mirror of
https://github.com/AvengeMedia/DankMaterialShell.git
synced 2026-08-10 07:28:30 -04:00
qs: launcher optimizations and weather tab optimizations
This commit is contained in:
@@ -0,0 +1,324 @@
|
|||||||
|
import QtQuick
|
||||||
|
import qs.Common
|
||||||
|
import qs.Services
|
||||||
|
import qs.Widgets
|
||||||
|
|
||||||
|
FocusScope {
|
||||||
|
id: root
|
||||||
|
|
||||||
|
property var editingApp: null
|
||||||
|
property string editAppId: ""
|
||||||
|
|
||||||
|
signal closeRequested
|
||||||
|
|
||||||
|
function loadOverride() {
|
||||||
|
var existing = SessionData.getAppOverride(editAppId);
|
||||||
|
editNameField.text = existing?.name || "";
|
||||||
|
editIconField.text = existing?.icon || "";
|
||||||
|
editCommentField.text = existing?.comment || "";
|
||||||
|
editEnvVarsField.text = existing?.envVars || "";
|
||||||
|
editExtraFlagsField.text = existing?.extraFlags || "";
|
||||||
|
Qt.callLater(() => editNameField.forceActiveFocus());
|
||||||
|
}
|
||||||
|
|
||||||
|
function saveAppOverride() {
|
||||||
|
var override = {};
|
||||||
|
if (editNameField.text.trim())
|
||||||
|
override.name = editNameField.text.trim();
|
||||||
|
if (editIconField.text.trim())
|
||||||
|
override.icon = editIconField.text.trim();
|
||||||
|
if (editCommentField.text.trim())
|
||||||
|
override.comment = editCommentField.text.trim();
|
||||||
|
if (editEnvVarsField.text.trim())
|
||||||
|
override.envVars = editEnvVarsField.text.trim();
|
||||||
|
if (editExtraFlagsField.text.trim())
|
||||||
|
override.extraFlags = editExtraFlagsField.text.trim();
|
||||||
|
SessionData.setAppOverride(editAppId, override);
|
||||||
|
closeRequested();
|
||||||
|
}
|
||||||
|
|
||||||
|
function resetAppOverride() {
|
||||||
|
SessionData.clearAppOverride(editAppId);
|
||||||
|
closeRequested();
|
||||||
|
}
|
||||||
|
|
||||||
|
Keys.onPressed: event => {
|
||||||
|
if (event.key === Qt.Key_Escape) {
|
||||||
|
closeRequested();
|
||||||
|
event.accepted = true;
|
||||||
|
} else if (event.key === Qt.Key_Return || event.key === Qt.Key_Enter) {
|
||||||
|
if (event.modifiers & Qt.ControlModifier) {
|
||||||
|
saveAppOverride();
|
||||||
|
event.accepted = true;
|
||||||
|
}
|
||||||
|
} else if (event.key === Qt.Key_S && event.modifiers & Qt.ControlModifier) {
|
||||||
|
saveAppOverride();
|
||||||
|
event.accepted = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Column {
|
||||||
|
anchors.fill: parent
|
||||||
|
spacing: Theme.spacingM
|
||||||
|
|
||||||
|
Row {
|
||||||
|
width: parent.width
|
||||||
|
spacing: Theme.spacingM
|
||||||
|
|
||||||
|
Rectangle {
|
||||||
|
width: 40
|
||||||
|
height: 40
|
||||||
|
radius: Theme.cornerRadius
|
||||||
|
color: backButtonArea.containsMouse ? Theme.surfaceHover : Theme.withAlpha(Theme.surfaceHover, 0)
|
||||||
|
|
||||||
|
DankIcon {
|
||||||
|
anchors.centerIn: parent
|
||||||
|
name: "arrow_back"
|
||||||
|
size: 20
|
||||||
|
color: Theme.surfaceText
|
||||||
|
}
|
||||||
|
|
||||||
|
MouseArea {
|
||||||
|
id: backButtonArea
|
||||||
|
anchors.fill: parent
|
||||||
|
hoverEnabled: true
|
||||||
|
cursorShape: Qt.PointingHandCursor
|
||||||
|
onClicked: root.closeRequested()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Image {
|
||||||
|
width: 40
|
||||||
|
height: 40
|
||||||
|
source: Paths.resolveIconUrl(root.editingApp?.icon || "application-x-executable")
|
||||||
|
sourceSize.width: 40
|
||||||
|
sourceSize.height: 40
|
||||||
|
fillMode: Image.PreserveAspectFit
|
||||||
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
}
|
||||||
|
|
||||||
|
Column {
|
||||||
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
spacing: Theme.spacingXXS
|
||||||
|
|
||||||
|
StyledText {
|
||||||
|
text: I18n.tr("Edit App")
|
||||||
|
font.pixelSize: Theme.fontSizeLarge
|
||||||
|
color: Theme.surfaceText
|
||||||
|
font.weight: Font.Medium
|
||||||
|
}
|
||||||
|
|
||||||
|
StyledText {
|
||||||
|
text: root.editingApp?.name || ""
|
||||||
|
font.pixelSize: Theme.fontSizeSmall
|
||||||
|
color: Theme.surfaceVariantText
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Rectangle {
|
||||||
|
width: parent.width
|
||||||
|
height: 1
|
||||||
|
color: Theme.outlineMedium
|
||||||
|
}
|
||||||
|
|
||||||
|
Flickable {
|
||||||
|
width: parent.width
|
||||||
|
height: parent.height - y - buttonsRow.height - Theme.spacingM
|
||||||
|
contentHeight: editFieldsColumn.height
|
||||||
|
clip: true
|
||||||
|
boundsBehavior: Flickable.StopAtBounds
|
||||||
|
|
||||||
|
Column {
|
||||||
|
id: editFieldsColumn
|
||||||
|
width: parent.width
|
||||||
|
spacing: Theme.spacingS
|
||||||
|
|
||||||
|
Column {
|
||||||
|
width: parent.width
|
||||||
|
spacing: Theme.spacingXS
|
||||||
|
|
||||||
|
StyledText {
|
||||||
|
text: I18n.tr("Name")
|
||||||
|
font.pixelSize: Theme.fontSizeSmall
|
||||||
|
color: Theme.surfaceText
|
||||||
|
font.weight: Font.Medium
|
||||||
|
}
|
||||||
|
|
||||||
|
DankTextField {
|
||||||
|
id: editNameField
|
||||||
|
width: parent.width
|
||||||
|
placeholderText: root.editingApp?.name || ""
|
||||||
|
keyNavigationTab: editIconField
|
||||||
|
keyNavigationBacktab: editExtraFlagsField
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Column {
|
||||||
|
width: parent.width
|
||||||
|
spacing: Theme.spacingXS
|
||||||
|
|
||||||
|
StyledText {
|
||||||
|
text: I18n.tr("Icon")
|
||||||
|
font.pixelSize: Theme.fontSizeSmall
|
||||||
|
color: Theme.surfaceText
|
||||||
|
font.weight: Font.Medium
|
||||||
|
}
|
||||||
|
|
||||||
|
DankTextField {
|
||||||
|
id: editIconField
|
||||||
|
width: parent.width
|
||||||
|
placeholderText: root.editingApp?.icon || ""
|
||||||
|
keyNavigationTab: editCommentField
|
||||||
|
keyNavigationBacktab: editNameField
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Column {
|
||||||
|
width: parent.width
|
||||||
|
spacing: Theme.spacingXS
|
||||||
|
|
||||||
|
StyledText {
|
||||||
|
text: I18n.tr("Description")
|
||||||
|
font.pixelSize: Theme.fontSizeSmall
|
||||||
|
color: Theme.surfaceText
|
||||||
|
font.weight: Font.Medium
|
||||||
|
}
|
||||||
|
|
||||||
|
DankTextField {
|
||||||
|
id: editCommentField
|
||||||
|
width: parent.width
|
||||||
|
placeholderText: root.editingApp?.comment || ""
|
||||||
|
keyNavigationTab: editEnvVarsField
|
||||||
|
keyNavigationBacktab: editIconField
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Column {
|
||||||
|
width: parent.width
|
||||||
|
spacing: Theme.spacingXS
|
||||||
|
|
||||||
|
StyledText {
|
||||||
|
text: I18n.tr("Environment Variables")
|
||||||
|
font.pixelSize: Theme.fontSizeSmall
|
||||||
|
color: Theme.surfaceText
|
||||||
|
font.weight: Font.Medium
|
||||||
|
}
|
||||||
|
|
||||||
|
StyledText {
|
||||||
|
text: "KEY=value KEY2=value2"
|
||||||
|
font.pixelSize: Theme.fontSizeSmall - 1
|
||||||
|
color: Theme.surfaceVariantText
|
||||||
|
}
|
||||||
|
|
||||||
|
DankTextField {
|
||||||
|
id: editEnvVarsField
|
||||||
|
width: parent.width
|
||||||
|
placeholderText: "VAR=value"
|
||||||
|
keyNavigationTab: editExtraFlagsField
|
||||||
|
keyNavigationBacktab: editCommentField
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Column {
|
||||||
|
width: parent.width
|
||||||
|
spacing: Theme.spacingXS
|
||||||
|
|
||||||
|
StyledText {
|
||||||
|
text: I18n.tr("Extra Arguments")
|
||||||
|
font.pixelSize: Theme.fontSizeSmall
|
||||||
|
color: Theme.surfaceText
|
||||||
|
font.weight: Font.Medium
|
||||||
|
}
|
||||||
|
|
||||||
|
DankTextField {
|
||||||
|
id: editExtraFlagsField
|
||||||
|
width: parent.width
|
||||||
|
placeholderText: "--flag --option=value"
|
||||||
|
keyNavigationTab: editNameField
|
||||||
|
keyNavigationBacktab: editEnvVarsField
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Row {
|
||||||
|
id: buttonsRow
|
||||||
|
anchors.horizontalCenter: parent.horizontalCenter
|
||||||
|
spacing: Theme.spacingM
|
||||||
|
|
||||||
|
Rectangle {
|
||||||
|
id: resetButton
|
||||||
|
width: 90
|
||||||
|
height: 40
|
||||||
|
radius: Theme.cornerRadius
|
||||||
|
color: resetButtonArea.containsMouse ? Theme.surfacePressed : Theme.surfaceVariantAlpha
|
||||||
|
visible: SessionData.getAppOverride(root.editAppId) !== null
|
||||||
|
|
||||||
|
StyledText {
|
||||||
|
text: I18n.tr("Reset")
|
||||||
|
font.pixelSize: Theme.fontSizeMedium
|
||||||
|
color: Theme.error
|
||||||
|
font.weight: Font.Medium
|
||||||
|
anchors.centerIn: parent
|
||||||
|
}
|
||||||
|
|
||||||
|
MouseArea {
|
||||||
|
id: resetButtonArea
|
||||||
|
anchors.fill: parent
|
||||||
|
hoverEnabled: true
|
||||||
|
cursorShape: Qt.PointingHandCursor
|
||||||
|
onClicked: root.resetAppOverride()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Rectangle {
|
||||||
|
id: cancelButton
|
||||||
|
width: 90
|
||||||
|
height: 40
|
||||||
|
radius: Theme.cornerRadius
|
||||||
|
color: cancelButtonArea.containsMouse ? Theme.surfacePressed : Theme.surfaceVariantAlpha
|
||||||
|
|
||||||
|
StyledText {
|
||||||
|
text: I18n.tr("Cancel")
|
||||||
|
font.pixelSize: Theme.fontSizeMedium
|
||||||
|
color: Theme.surfaceText
|
||||||
|
font.weight: Font.Medium
|
||||||
|
anchors.centerIn: parent
|
||||||
|
}
|
||||||
|
|
||||||
|
MouseArea {
|
||||||
|
id: cancelButtonArea
|
||||||
|
anchors.fill: parent
|
||||||
|
hoverEnabled: true
|
||||||
|
cursorShape: Qt.PointingHandCursor
|
||||||
|
onClicked: root.closeRequested()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Rectangle {
|
||||||
|
id: saveButton
|
||||||
|
width: 90
|
||||||
|
height: 40
|
||||||
|
radius: Theme.cornerRadius
|
||||||
|
color: saveButtonArea.containsMouse ? Theme.withAlpha(Theme.primary, 0.9) : Theme.primary
|
||||||
|
|
||||||
|
StyledText {
|
||||||
|
text: I18n.tr("Save")
|
||||||
|
font.pixelSize: Theme.fontSizeMedium
|
||||||
|
color: Theme.primaryText
|
||||||
|
font.weight: Font.Medium
|
||||||
|
anchors.centerIn: parent
|
||||||
|
}
|
||||||
|
|
||||||
|
MouseArea {
|
||||||
|
id: saveButtonArea
|
||||||
|
anchors.fill: parent
|
||||||
|
hoverEnabled: true
|
||||||
|
cursorShape: Qt.PointingHandCursor
|
||||||
|
onClicked: root.saveAppOverride()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -930,23 +930,10 @@ Item {
|
|||||||
searchCompleted();
|
searchCompleted();
|
||||||
return;
|
return;
|
||||||
} else if (!searchQuery) {
|
} else if (!searchQuery) {
|
||||||
var emptyTriggerOrdered = getEmptyTriggerPluginsOrdered();
|
_pluginPhasePending = true;
|
||||||
for (var i = 0; i < emptyTriggerOrdered.length; i++) {
|
_phase1Items = allItems.slice();
|
||||||
var plugin = emptyTriggerOrdered[i];
|
_pluginPhaseForceFirst = shouldResetSelection;
|
||||||
if (plugin.isBuiltIn) {
|
pluginPhaseTimer.restart();
|
||||||
var blItems = AppSearchService.getBuiltInLauncherItems(plugin.id, searchQuery);
|
|
||||||
for (var j = 0; j < blItems.length; j++)
|
|
||||||
allItems.push(transformBuiltInSearchItem(blItems[j], plugin.id));
|
|
||||||
} else {
|
|
||||||
var pItems = getPluginItems(plugin.id, searchQuery);
|
|
||||||
for (var j = 0; j < pItems.length; j++)
|
|
||||||
allItems.push(pItems[j]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var browseItems = getPluginBrowseItems();
|
|
||||||
for (var i = 0; i < browseItems.length; i++)
|
|
||||||
allItems.push(browseItems[i]);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -977,11 +964,6 @@ Item {
|
|||||||
flatModel = Scorer.flattenSections(newSections);
|
flatModel = Scorer.flattenSections(newSections);
|
||||||
sections = newSections;
|
sections = newSections;
|
||||||
|
|
||||||
if (!AppSearchService.isCacheValid() && !searchQuery && searchMode === "all" && !pluginFilter) {
|
|
||||||
AppSearchService.setCachedDefaultSections(sections, flatModel);
|
|
||||||
_saveDiskCache(sections);
|
|
||||||
}
|
|
||||||
|
|
||||||
selectedFlatIndex = restoreSelection(flatModel);
|
selectedFlatIndex = restoreSelection(flatModel);
|
||||||
updateSelectedItem();
|
updateSelectedItem();
|
||||||
|
|
||||||
@@ -991,7 +973,9 @@ Item {
|
|||||||
|
|
||||||
function _performPluginPhase() {
|
function _performPluginPhase() {
|
||||||
_pluginPhasePending = false;
|
_pluginPhasePending = false;
|
||||||
if (!searchQuery || searchQuery.length < 2 || searchMode !== "all")
|
if (searchMode !== "all")
|
||||||
|
return;
|
||||||
|
if (searchQuery && searchQuery.length < 2)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
var currentVersion = _searchVersion;
|
var currentVersion = _searchVersion;
|
||||||
@@ -999,27 +983,49 @@ Item {
|
|||||||
var allItems = _phase1Items;
|
var allItems = _phase1Items;
|
||||||
_phase1Items = [];
|
_phase1Items = [];
|
||||||
|
|
||||||
var allPluginsOrdered = getAllVisiblePluginsOrdered();
|
if (!searchQuery) {
|
||||||
var maxPerPlugin = 10;
|
var emptyTriggerOrdered = getEmptyTriggerPluginsOrdered();
|
||||||
for (var i = 0; i < allPluginsOrdered.length; i++) {
|
for (var i = 0; i < emptyTriggerOrdered.length; i++) {
|
||||||
if (currentVersion !== _searchVersion)
|
if (currentVersion !== _searchVersion)
|
||||||
return;
|
return;
|
||||||
var plugin = allPluginsOrdered[i];
|
var plugin = emptyTriggerOrdered[i];
|
||||||
if (plugin.isBuiltIn && (plugin.id === "dms_settings_search" || plugin.id === "dms_clipboard_search"))
|
if (plugin.isBuiltIn) {
|
||||||
continue;
|
var blItems = AppSearchService.getBuiltInLauncherItems(plugin.id, searchQuery);
|
||||||
if (plugin.isBuiltIn) {
|
for (var j = 0; j < blItems.length; j++)
|
||||||
var blItems = AppSearchService.getBuiltInLauncherItems(plugin.id, searchQuery);
|
allItems.push(transformBuiltInSearchItem(blItems[j], plugin.id));
|
||||||
var blLimit = Math.min(blItems.length, maxPerPlugin);
|
} else {
|
||||||
for (var j = 0; j < blLimit; j++) {
|
var pItems = getPluginItems(plugin.id, searchQuery);
|
||||||
var item = transformBuiltInSearchItem(blItems[j], plugin.id);
|
for (var j = 0; j < pItems.length; j++)
|
||||||
item._preScored = 900 - j;
|
allItems.push(pItems[j]);
|
||||||
allItems.push(item);
|
|
||||||
}
|
}
|
||||||
} else {
|
}
|
||||||
var pItems = getPluginItems(plugin.id, searchQuery, maxPerPlugin);
|
|
||||||
for (var j = 0; j < pItems.length; j++) {
|
var browseItems = getPluginBrowseItems();
|
||||||
pItems[j]._preScored = 900 - j;
|
for (var i = 0; i < browseItems.length; i++)
|
||||||
allItems.push(pItems[j]);
|
allItems.push(browseItems[i]);
|
||||||
|
} else {
|
||||||
|
var allPluginsOrdered = getAllVisiblePluginsOrdered();
|
||||||
|
var maxPerPlugin = 10;
|
||||||
|
for (var i = 0; i < allPluginsOrdered.length; i++) {
|
||||||
|
if (currentVersion !== _searchVersion)
|
||||||
|
return;
|
||||||
|
var plugin = allPluginsOrdered[i];
|
||||||
|
if (plugin.isBuiltIn && (plugin.id === "dms_settings_search" || plugin.id === "dms_clipboard_search"))
|
||||||
|
continue;
|
||||||
|
if (plugin.isBuiltIn) {
|
||||||
|
var blItems = AppSearchService.getBuiltInLauncherItems(plugin.id, searchQuery);
|
||||||
|
var blLimit = Math.min(blItems.length, maxPerPlugin);
|
||||||
|
for (var j = 0; j < blLimit; j++) {
|
||||||
|
var item = transformBuiltInSearchItem(blItems[j], plugin.id);
|
||||||
|
item._preScored = 900 - j;
|
||||||
|
allItems.push(item);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
var pItems = getPluginItems(plugin.id, searchQuery, maxPerPlugin);
|
||||||
|
for (var j = 0; j < pItems.length; j++) {
|
||||||
|
pItems[j]._preScored = 900 - j;
|
||||||
|
allItems.push(pItems[j]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1029,7 +1035,8 @@ Item {
|
|||||||
|
|
||||||
var dynamicDefs = buildDynamicSectionDefs(allItems);
|
var dynamicDefs = buildDynamicSectionDefs(allItems);
|
||||||
var scoredItems = Scorer.scoreItems(allItems, searchQuery, getFrecencyForItem);
|
var scoredItems = Scorer.scoreItems(allItems, searchQuery, getFrecencyForItem);
|
||||||
var newSections = Scorer.groupBySection(scoredItems, dynamicDefs, false, 50);
|
var sortAlpha = !searchQuery && SettingsData.sortAppsAlphabetically;
|
||||||
|
var newSections = Scorer.groupBySection(scoredItems, dynamicDefs, sortAlpha, searchQuery ? 50 : 500);
|
||||||
|
|
||||||
if (currentVersion !== _searchVersion)
|
if (currentVersion !== _searchVersion)
|
||||||
return;
|
return;
|
||||||
@@ -1043,6 +1050,12 @@ Item {
|
|||||||
_applyHighlights(newSections, searchQuery);
|
_applyHighlights(newSections, searchQuery);
|
||||||
flatModel = Scorer.flattenSections(newSections);
|
flatModel = Scorer.flattenSections(newSections);
|
||||||
sections = newSections;
|
sections = newSections;
|
||||||
|
|
||||||
|
if (!AppSearchService.isCacheValid() && !searchQuery && !pluginFilter) {
|
||||||
|
AppSearchService.setCachedDefaultSections(sections, flatModel);
|
||||||
|
_saveDiskCache(sections);
|
||||||
|
}
|
||||||
|
|
||||||
selectedFlatIndex = restoreSelection(flatModel);
|
selectedFlatIndex = restoreSelection(flatModel);
|
||||||
updateSelectedItem();
|
updateSelectedItem();
|
||||||
isSearching = false;
|
isSearching = false;
|
||||||
|
|||||||
@@ -54,14 +54,7 @@ FocusScope {
|
|||||||
return;
|
return;
|
||||||
editingApp = app;
|
editingApp = app;
|
||||||
editAppId = app.id || app.execString || app.exec || "";
|
editAppId = app.id || app.execString || app.exec || "";
|
||||||
var existing = SessionData.getAppOverride(editAppId);
|
|
||||||
editNameField.text = existing?.name || "";
|
|
||||||
editIconField.text = existing?.icon || "";
|
|
||||||
editCommentField.text = existing?.comment || "";
|
|
||||||
editEnvVarsField.text = existing?.envVars || "";
|
|
||||||
editExtraFlagsField.text = existing?.extraFlags || "";
|
|
||||||
editMode = true;
|
editMode = true;
|
||||||
Qt.callLater(() => editNameField.forceActiveFocus());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function closeEditMode() {
|
function closeEditMode() {
|
||||||
@@ -71,27 +64,6 @@ FocusScope {
|
|||||||
Qt.callLater(() => searchField.forceActiveFocus());
|
Qt.callLater(() => searchField.forceActiveFocus());
|
||||||
}
|
}
|
||||||
|
|
||||||
function saveAppOverride() {
|
|
||||||
var override = {};
|
|
||||||
if (editNameField.text.trim())
|
|
||||||
override.name = editNameField.text.trim();
|
|
||||||
if (editIconField.text.trim())
|
|
||||||
override.icon = editIconField.text.trim();
|
|
||||||
if (editCommentField.text.trim())
|
|
||||||
override.comment = editCommentField.text.trim();
|
|
||||||
if (editEnvVarsField.text.trim())
|
|
||||||
override.envVars = editEnvVarsField.text.trim();
|
|
||||||
if (editExtraFlagsField.text.trim())
|
|
||||||
override.extraFlags = editExtraFlagsField.text.trim();
|
|
||||||
SessionData.setAppOverride(editAppId, override);
|
|
||||||
closeEditMode();
|
|
||||||
}
|
|
||||||
|
|
||||||
function resetAppOverride() {
|
|
||||||
SessionData.clearAppOverride(editAppId);
|
|
||||||
closeEditMode();
|
|
||||||
}
|
|
||||||
|
|
||||||
function showContextMenu(item, x, y, fromKeyboard) {
|
function showContextMenu(item, x, y, fromKeyboard) {
|
||||||
if (!item)
|
if (!item)
|
||||||
return;
|
return;
|
||||||
@@ -817,291 +789,21 @@ FocusScope {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
FocusScope {
|
Loader {
|
||||||
id: editView
|
id: editLoader
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
anchors.margins: Theme.spacingM
|
anchors.margins: Theme.spacingM
|
||||||
visible: editMode
|
active: root.editMode
|
||||||
focus: editMode
|
visible: active
|
||||||
|
focus: root.editMode
|
||||||
|
|
||||||
Keys.onPressed: event => {
|
sourceComponent: AppEditView {
|
||||||
if (event.key === Qt.Key_Escape) {
|
focus: true
|
||||||
closeEditMode();
|
editingApp: root.editingApp
|
||||||
event.accepted = true;
|
editAppId: root.editAppId
|
||||||
} else if (event.key === Qt.Key_Return || event.key === Qt.Key_Enter) {
|
onCloseRequested: root.closeEditMode()
|
||||||
if (event.modifiers & Qt.ControlModifier) {
|
|
||||||
saveAppOverride();
|
|
||||||
event.accepted = true;
|
|
||||||
}
|
|
||||||
} else if (event.key === Qt.Key_S && event.modifiers & Qt.ControlModifier) {
|
|
||||||
saveAppOverride();
|
|
||||||
event.accepted = true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Column {
|
onLoaded: item.loadOverride()
|
||||||
anchors.fill: parent
|
|
||||||
spacing: Theme.spacingM
|
|
||||||
|
|
||||||
Row {
|
|
||||||
width: parent.width
|
|
||||||
spacing: Theme.spacingM
|
|
||||||
|
|
||||||
Rectangle {
|
|
||||||
width: 40
|
|
||||||
height: 40
|
|
||||||
radius: Theme.cornerRadius
|
|
||||||
color: backButtonArea.containsMouse ? Theme.surfaceHover : Theme.withAlpha(Theme.surfaceHover, 0)
|
|
||||||
|
|
||||||
DankIcon {
|
|
||||||
anchors.centerIn: parent
|
|
||||||
name: "arrow_back"
|
|
||||||
size: 20
|
|
||||||
color: Theme.surfaceText
|
|
||||||
}
|
|
||||||
|
|
||||||
MouseArea {
|
|
||||||
id: backButtonArea
|
|
||||||
anchors.fill: parent
|
|
||||||
hoverEnabled: true
|
|
||||||
cursorShape: Qt.PointingHandCursor
|
|
||||||
onClicked: closeEditMode()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Image {
|
|
||||||
width: 40
|
|
||||||
height: 40
|
|
||||||
source: Paths.resolveIconUrl(editingApp?.icon || "application-x-executable")
|
|
||||||
sourceSize.width: 40
|
|
||||||
sourceSize.height: 40
|
|
||||||
fillMode: Image.PreserveAspectFit
|
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
|
||||||
}
|
|
||||||
|
|
||||||
Column {
|
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
|
||||||
spacing: Theme.spacingXXS
|
|
||||||
|
|
||||||
StyledText {
|
|
||||||
text: I18n.tr("Edit App")
|
|
||||||
font.pixelSize: Theme.fontSizeLarge
|
|
||||||
color: Theme.surfaceText
|
|
||||||
font.weight: Font.Medium
|
|
||||||
}
|
|
||||||
|
|
||||||
StyledText {
|
|
||||||
text: editingApp?.name || ""
|
|
||||||
font.pixelSize: Theme.fontSizeSmall
|
|
||||||
color: Theme.surfaceVariantText
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Rectangle {
|
|
||||||
width: parent.width
|
|
||||||
height: 1
|
|
||||||
color: Theme.outlineMedium
|
|
||||||
}
|
|
||||||
|
|
||||||
Flickable {
|
|
||||||
width: parent.width
|
|
||||||
height: parent.height - y - buttonsRow.height - Theme.spacingM
|
|
||||||
contentHeight: editFieldsColumn.height
|
|
||||||
clip: true
|
|
||||||
boundsBehavior: Flickable.StopAtBounds
|
|
||||||
|
|
||||||
Column {
|
|
||||||
id: editFieldsColumn
|
|
||||||
width: parent.width
|
|
||||||
spacing: Theme.spacingS
|
|
||||||
|
|
||||||
Column {
|
|
||||||
width: parent.width
|
|
||||||
spacing: Theme.spacingXS
|
|
||||||
|
|
||||||
StyledText {
|
|
||||||
text: I18n.tr("Name")
|
|
||||||
font.pixelSize: Theme.fontSizeSmall
|
|
||||||
color: Theme.surfaceText
|
|
||||||
font.weight: Font.Medium
|
|
||||||
}
|
|
||||||
|
|
||||||
DankTextField {
|
|
||||||
id: editNameField
|
|
||||||
width: parent.width
|
|
||||||
placeholderText: editingApp?.name || ""
|
|
||||||
keyNavigationTab: editIconField
|
|
||||||
keyNavigationBacktab: editExtraFlagsField
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Column {
|
|
||||||
width: parent.width
|
|
||||||
spacing: Theme.spacingXS
|
|
||||||
|
|
||||||
StyledText {
|
|
||||||
text: I18n.tr("Icon")
|
|
||||||
font.pixelSize: Theme.fontSizeSmall
|
|
||||||
color: Theme.surfaceText
|
|
||||||
font.weight: Font.Medium
|
|
||||||
}
|
|
||||||
|
|
||||||
DankTextField {
|
|
||||||
id: editIconField
|
|
||||||
width: parent.width
|
|
||||||
placeholderText: editingApp?.icon || ""
|
|
||||||
keyNavigationTab: editCommentField
|
|
||||||
keyNavigationBacktab: editNameField
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Column {
|
|
||||||
width: parent.width
|
|
||||||
spacing: Theme.spacingXS
|
|
||||||
|
|
||||||
StyledText {
|
|
||||||
text: I18n.tr("Description")
|
|
||||||
font.pixelSize: Theme.fontSizeSmall
|
|
||||||
color: Theme.surfaceText
|
|
||||||
font.weight: Font.Medium
|
|
||||||
}
|
|
||||||
|
|
||||||
DankTextField {
|
|
||||||
id: editCommentField
|
|
||||||
width: parent.width
|
|
||||||
placeholderText: editingApp?.comment || ""
|
|
||||||
keyNavigationTab: editEnvVarsField
|
|
||||||
keyNavigationBacktab: editIconField
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Column {
|
|
||||||
width: parent.width
|
|
||||||
spacing: Theme.spacingXS
|
|
||||||
|
|
||||||
StyledText {
|
|
||||||
text: I18n.tr("Environment Variables")
|
|
||||||
font.pixelSize: Theme.fontSizeSmall
|
|
||||||
color: Theme.surfaceText
|
|
||||||
font.weight: Font.Medium
|
|
||||||
}
|
|
||||||
|
|
||||||
StyledText {
|
|
||||||
text: "KEY=value KEY2=value2"
|
|
||||||
font.pixelSize: Theme.fontSizeSmall - 1
|
|
||||||
color: Theme.surfaceVariantText
|
|
||||||
}
|
|
||||||
|
|
||||||
DankTextField {
|
|
||||||
id: editEnvVarsField
|
|
||||||
width: parent.width
|
|
||||||
placeholderText: "VAR=value"
|
|
||||||
keyNavigationTab: editExtraFlagsField
|
|
||||||
keyNavigationBacktab: editCommentField
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Column {
|
|
||||||
width: parent.width
|
|
||||||
spacing: Theme.spacingXS
|
|
||||||
|
|
||||||
StyledText {
|
|
||||||
text: I18n.tr("Extra Arguments")
|
|
||||||
font.pixelSize: Theme.fontSizeSmall
|
|
||||||
color: Theme.surfaceText
|
|
||||||
font.weight: Font.Medium
|
|
||||||
}
|
|
||||||
|
|
||||||
DankTextField {
|
|
||||||
id: editExtraFlagsField
|
|
||||||
width: parent.width
|
|
||||||
placeholderText: "--flag --option=value"
|
|
||||||
keyNavigationTab: editNameField
|
|
||||||
keyNavigationBacktab: editEnvVarsField
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Row {
|
|
||||||
id: buttonsRow
|
|
||||||
anchors.horizontalCenter: parent.horizontalCenter
|
|
||||||
spacing: Theme.spacingM
|
|
||||||
|
|
||||||
Rectangle {
|
|
||||||
id: resetButton
|
|
||||||
width: 90
|
|
||||||
height: 40
|
|
||||||
radius: Theme.cornerRadius
|
|
||||||
color: resetButtonArea.containsMouse ? Theme.surfacePressed : Theme.surfaceVariantAlpha
|
|
||||||
visible: SessionData.getAppOverride(editAppId) !== null
|
|
||||||
|
|
||||||
StyledText {
|
|
||||||
text: I18n.tr("Reset")
|
|
||||||
font.pixelSize: Theme.fontSizeMedium
|
|
||||||
color: Theme.error
|
|
||||||
font.weight: Font.Medium
|
|
||||||
anchors.centerIn: parent
|
|
||||||
}
|
|
||||||
|
|
||||||
MouseArea {
|
|
||||||
id: resetButtonArea
|
|
||||||
anchors.fill: parent
|
|
||||||
hoverEnabled: true
|
|
||||||
cursorShape: Qt.PointingHandCursor
|
|
||||||
onClicked: resetAppOverride()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Rectangle {
|
|
||||||
id: cancelButton
|
|
||||||
width: 90
|
|
||||||
height: 40
|
|
||||||
radius: Theme.cornerRadius
|
|
||||||
color: cancelButtonArea.containsMouse ? Theme.surfacePressed : Theme.surfaceVariantAlpha
|
|
||||||
|
|
||||||
StyledText {
|
|
||||||
text: I18n.tr("Cancel")
|
|
||||||
font.pixelSize: Theme.fontSizeMedium
|
|
||||||
color: Theme.surfaceText
|
|
||||||
font.weight: Font.Medium
|
|
||||||
anchors.centerIn: parent
|
|
||||||
}
|
|
||||||
|
|
||||||
MouseArea {
|
|
||||||
id: cancelButtonArea
|
|
||||||
anchors.fill: parent
|
|
||||||
hoverEnabled: true
|
|
||||||
cursorShape: Qt.PointingHandCursor
|
|
||||||
onClicked: closeEditMode()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Rectangle {
|
|
||||||
id: saveButton
|
|
||||||
width: 90
|
|
||||||
height: 40
|
|
||||||
radius: Theme.cornerRadius
|
|
||||||
color: saveButtonArea.containsMouse ? Theme.withAlpha(Theme.primary, 0.9) : Theme.primary
|
|
||||||
|
|
||||||
StyledText {
|
|
||||||
text: I18n.tr("Save")
|
|
||||||
font.pixelSize: Theme.fontSizeMedium
|
|
||||||
color: Theme.primaryText
|
|
||||||
font.weight: Font.Medium
|
|
||||||
anchors.centerIn: parent
|
|
||||||
}
|
|
||||||
|
|
||||||
MouseArea {
|
|
||||||
id: saveButtonArea
|
|
||||||
anchors.fill: parent
|
|
||||||
hoverEnabled: true
|
|
||||||
cursorShape: Qt.PointingHandCursor
|
|
||||||
onClicked: saveAppOverride()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -241,107 +241,124 @@ Item {
|
|||||||
required property var modelData
|
required property var modelData
|
||||||
required property int index
|
required property int index
|
||||||
|
|
||||||
|
readonly property string rowType: modelData?.type ?? ""
|
||||||
|
|
||||||
width: mainListView.width
|
width: mainListView.width
|
||||||
height: modelData?.height ?? 52
|
height: modelData?.height ?? 52
|
||||||
|
|
||||||
SectionHeader {
|
Loader {
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
visible: delegateRoot.modelData?.type === "header"
|
active: delegateRoot.rowType === "header"
|
||||||
section: delegateRoot.modelData?.section ?? null
|
visible: active
|
||||||
controller: root.controller
|
sourceComponent: SectionHeader {
|
||||||
viewMode: {
|
section: delegateRoot.modelData?.section ?? null
|
||||||
var vt = root.controller?.viewModeVersion ?? 0;
|
controller: root.controller
|
||||||
void (vt);
|
viewMode: {
|
||||||
return root.controller?.getSectionViewMode(delegateRoot.modelData?.sectionId ?? "") ?? "list";
|
var vt = root.controller?.viewModeVersion ?? 0;
|
||||||
|
void (vt);
|
||||||
|
return root.controller?.getSectionViewMode(delegateRoot.modelData?.sectionId ?? "") ?? "list";
|
||||||
|
}
|
||||||
|
canChangeViewMode: {
|
||||||
|
var vt = root.controller?.viewModeVersion ?? 0;
|
||||||
|
void (vt);
|
||||||
|
return root.controller?.canChangeSectionViewMode(delegateRoot.modelData?.sectionId ?? "") ?? false;
|
||||||
|
}
|
||||||
|
canCollapse: root.controller?.canCollapseSection(delegateRoot.modelData?.sectionId ?? "") ?? false
|
||||||
|
transientSurfaceTracker: root.transientSurfaceTracker
|
||||||
}
|
}
|
||||||
canChangeViewMode: {
|
|
||||||
var vt = root.controller?.viewModeVersion ?? 0;
|
|
||||||
void (vt);
|
|
||||||
return root.controller?.canChangeSectionViewMode(delegateRoot.modelData?.sectionId ?? "") ?? false;
|
|
||||||
}
|
|
||||||
canCollapse: root.controller?.canCollapseSection(delegateRoot.modelData?.sectionId ?? "") ?? false
|
|
||||||
transientSurfaceTracker: root.transientSurfaceTracker
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ResultItem {
|
Loader {
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
anchors.topMargin: 2
|
anchors.topMargin: 2
|
||||||
anchors.bottomMargin: 2
|
anchors.bottomMargin: 2
|
||||||
visible: delegateRoot.modelData?.type === "list_item"
|
active: delegateRoot.rowType === "list_item"
|
||||||
item: delegateRoot.modelData?.type === "list_item" ? (delegateRoot.modelData?.item ?? null) : null
|
visible: active
|
||||||
isSelected: delegateRoot.modelData?.type === "list_item" && (delegateRoot.modelData?.flatIndex ?? -1) === root.controller?.selectedFlatIndex
|
sourceComponent: ResultItem {
|
||||||
controller: root.controller
|
item: delegateRoot.modelData?.item ?? null
|
||||||
flatIndex: delegateRoot.modelData?.type === "list_item" ? (delegateRoot.modelData?.flatIndex ?? -1) : -1
|
isSelected: (delegateRoot.modelData?.flatIndex ?? -1) === root.controller?.selectedFlatIndex
|
||||||
|
controller: root.controller
|
||||||
|
flatIndex: delegateRoot.modelData?.flatIndex ?? -1
|
||||||
|
|
||||||
onClicked: {
|
onClicked: {
|
||||||
if (root.controller && delegateRoot.modelData?.item) {
|
if (root.controller && delegateRoot.modelData?.item) {
|
||||||
root.controller.executeItem(delegateRoot.modelData.item);
|
root.controller.executeItem(delegateRoot.modelData.item);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
onRightClicked: (mouseX, mouseY) => {
|
onRightClicked: (mouseX, mouseY) => {
|
||||||
root.itemRightClicked(delegateRoot.modelData?.flatIndex ?? -1, delegateRoot.modelData?.item ?? null, mouseX, mouseY);
|
root.itemRightClicked(delegateRoot.modelData?.flatIndex ?? -1, delegateRoot.modelData?.item ?? null, mouseX, mouseY);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Row {
|
Loader {
|
||||||
id: gridRowContent
|
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
visible: delegateRoot.modelData?.type === "grid_row"
|
active: delegateRoot.rowType === "grid_row"
|
||||||
|
visible: active
|
||||||
|
sourceComponent: Row {
|
||||||
|
Repeater {
|
||||||
|
model: delegateRoot.modelData?.items ?? []
|
||||||
|
|
||||||
Repeater {
|
Item {
|
||||||
model: delegateRoot.modelData?.type === "grid_row" ? (delegateRoot.modelData?.items ?? []) : []
|
id: gridCellDelegate
|
||||||
|
required property var modelData
|
||||||
|
required property int index
|
||||||
|
|
||||||
Item {
|
readonly property bool isTile: delegateRoot.modelData?.viewMode === "tile"
|
||||||
id: gridCellDelegate
|
readonly property real cellWidth: isTile ? Math.floor(delegateRoot.width / 3) : Math.floor(delegateRoot.width / (delegateRoot.modelData?.cols ?? root.gridColumns))
|
||||||
required property var modelData
|
|
||||||
required property int index
|
|
||||||
|
|
||||||
readonly property real cellWidth: delegateRoot.modelData?.viewMode === "tile" ? Math.floor(delegateRoot.width / 3) : Math.floor(delegateRoot.width / (delegateRoot.modelData?.cols ?? root.gridColumns))
|
width: cellWidth
|
||||||
|
height: delegateRoot.height
|
||||||
|
|
||||||
width: cellWidth
|
Loader {
|
||||||
height: delegateRoot.height
|
width: parent.width - 4
|
||||||
|
height: parent.height - 4
|
||||||
|
anchors.centerIn: parent
|
||||||
|
sourceComponent: gridCellDelegate.isTile ? tileCellComponent : gridCellComponent
|
||||||
|
|
||||||
GridItem {
|
Component {
|
||||||
width: parent.width - 4
|
id: gridCellComponent
|
||||||
height: parent.height - 4
|
|
||||||
anchors.centerIn: parent
|
|
||||||
visible: delegateRoot.modelData?.viewMode === "grid"
|
|
||||||
item: gridCellDelegate.modelData?.item ?? null
|
|
||||||
isSelected: (gridCellDelegate.modelData?.flatIndex ?? -1) === root.controller?.selectedFlatIndex
|
|
||||||
controller: root.controller
|
|
||||||
flatIndex: gridCellDelegate.modelData?.flatIndex ?? -1
|
|
||||||
|
|
||||||
onClicked: {
|
GridItem {
|
||||||
if (root.controller && gridCellDelegate.modelData?.item) {
|
item: gridCellDelegate.modelData?.item ?? null
|
||||||
root.controller.executeItem(gridCellDelegate.modelData.item);
|
isSelected: (gridCellDelegate.modelData?.flatIndex ?? -1) === root.controller?.selectedFlatIndex
|
||||||
|
controller: root.controller
|
||||||
|
flatIndex: gridCellDelegate.modelData?.flatIndex ?? -1
|
||||||
|
|
||||||
|
onClicked: {
|
||||||
|
if (root.controller && gridCellDelegate.modelData?.item) {
|
||||||
|
root.controller.executeItem(gridCellDelegate.modelData.item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
onRightClicked: (mouseX, mouseY) => {
|
||||||
|
root.itemRightClicked(gridCellDelegate.modelData?.flatIndex ?? -1, gridCellDelegate.modelData?.item ?? null, mouseX, mouseY);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
onRightClicked: (mouseX, mouseY) => {
|
Component {
|
||||||
root.itemRightClicked(gridCellDelegate.modelData?.flatIndex ?? -1, gridCellDelegate.modelData?.item ?? null, mouseX, mouseY);
|
id: tileCellComponent
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
TileItem {
|
TileItem {
|
||||||
width: parent.width - 4
|
item: gridCellDelegate.modelData?.item ?? null
|
||||||
height: parent.height - 4
|
isSelected: (gridCellDelegate.modelData?.flatIndex ?? -1) === root.controller?.selectedFlatIndex
|
||||||
anchors.centerIn: parent
|
controller: root.controller
|
||||||
visible: delegateRoot.modelData?.viewMode === "tile"
|
flatIndex: gridCellDelegate.modelData?.flatIndex ?? -1
|
||||||
item: gridCellDelegate.modelData?.item ?? null
|
|
||||||
isSelected: (gridCellDelegate.modelData?.flatIndex ?? -1) === root.controller?.selectedFlatIndex
|
|
||||||
controller: root.controller
|
|
||||||
flatIndex: gridCellDelegate.modelData?.flatIndex ?? -1
|
|
||||||
|
|
||||||
onClicked: {
|
onClicked: {
|
||||||
if (root.controller && gridCellDelegate.modelData?.item) {
|
if (root.controller && gridCellDelegate.modelData?.item) {
|
||||||
root.controller.executeItem(gridCellDelegate.modelData.item);
|
root.controller.executeItem(gridCellDelegate.modelData.item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
onRightClicked: (mouseX, mouseY) => {
|
||||||
|
root.itemRightClicked(gridCellDelegate.modelData?.flatIndex ?? -1, gridCellDelegate.modelData?.item ?? null, mouseX, mouseY);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
onRightClicked: (mouseX, mouseY) => {
|
|
||||||
root.itemRightClicked(gridCellDelegate.modelData?.flatIndex ?? -1, gridCellDelegate.modelData?.item ?? null, mouseX, mouseY);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -550,276 +550,288 @@ Item {
|
|||||||
|
|
||||||
color: "transparent"
|
color: "transparent"
|
||||||
|
|
||||||
Rectangle {
|
|
||||||
anchors.fill: parent
|
|
||||||
opacity: skyBox.backgroundOpacity
|
|
||||||
|
|
||||||
gradient: Gradient {
|
|
||||||
GradientStop {
|
|
||||||
position: 0.0
|
|
||||||
color: Theme.withAlpha(skyBox.blackColor, 0.0)
|
|
||||||
}
|
|
||||||
GradientStop {
|
|
||||||
position: 0.05
|
|
||||||
color: skyBox.topColor
|
|
||||||
}
|
|
||||||
GradientStop {
|
|
||||||
position: 0.3
|
|
||||||
color: skyBox.topColor
|
|
||||||
}
|
|
||||||
GradientStop {
|
|
||||||
position: 0.5
|
|
||||||
color: skyBox.topColor
|
|
||||||
}
|
|
||||||
GradientStop {
|
|
||||||
position: 0.501
|
|
||||||
color: skyBox.blackColor
|
|
||||||
}
|
|
||||||
GradientStop {
|
|
||||||
position: 0.9
|
|
||||||
color: skyBox.blackColor
|
|
||||||
}
|
|
||||||
GradientStop {
|
|
||||||
position: 1.0
|
|
||||||
color: Theme.withAlpha(skyBox.blackColor, 0.0)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
property var currentDate: dateStepper.currentDate
|
property var currentDate: dateStepper.currentDate
|
||||||
property var hMargin: 0
|
property var hMargin: 0
|
||||||
property var vMargin: Theme.spacingM
|
property var vMargin: Theme.spacingM
|
||||||
property var effectiveHeight: skyBox.height - 2 * vMargin
|
property var effectiveHeight: skyBox.height - 2 * vMargin
|
||||||
property var effectiveWidth: skyBox.width - 2 * hMargin
|
property var effectiveWidth: skyBox.width - 2 * hMargin
|
||||||
|
|
||||||
StyledText {
|
|
||||||
text: parent.sunTime?.period ?? ""
|
|
||||||
font.pixelSize: Theme.fontSizeSmall
|
|
||||||
color: Theme.withAlpha(Theme.surfaceText, 0.7)
|
|
||||||
x: 0
|
|
||||||
y: 0
|
|
||||||
}
|
|
||||||
|
|
||||||
Shape {
|
|
||||||
id: skyShape
|
|
||||||
anchors.left: parent.left
|
|
||||||
anchors.top: parent.top
|
|
||||||
anchors.right: parent.right
|
|
||||||
height: parent.height / 2
|
|
||||||
opacity: skyBox.backgroundOpacity
|
|
||||||
|
|
||||||
ShapePath {
|
|
||||||
strokeColor: "transparent"
|
|
||||||
fillGradient: RadialGradient {
|
|
||||||
centerX: skyBox.hMargin + sun.x + sun.width / 2
|
|
||||||
centerY: skyBox.vMargin + sun.y + 30
|
|
||||||
centerRadius: {
|
|
||||||
const a = Math.abs((skyBox.sunTime?.dayPercent ?? 0) - 0.5);
|
|
||||||
const out = 200 * (0.5 - a * a);
|
|
||||||
return out;
|
|
||||||
}
|
|
||||||
focalX: skyBox.hMargin + sun.x + sun.width / 2
|
|
||||||
focalY: skyBox.vMargin + sun.y
|
|
||||||
GradientStop {
|
|
||||||
position: 0
|
|
||||||
color: skyBox.sunColor
|
|
||||||
}
|
|
||||||
GradientStop {
|
|
||||||
position: 0.3
|
|
||||||
color: Theme.blendAlpha(skyBox.sunColor, 0.5)
|
|
||||||
}
|
|
||||||
GradientStop {
|
|
||||||
position: 1
|
|
||||||
color: "transparent"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
PathLine {
|
|
||||||
x: 0
|
|
||||||
y: 0
|
|
||||||
}
|
|
||||||
PathLine {
|
|
||||||
x: skyShape.width
|
|
||||||
y: 0
|
|
||||||
}
|
|
||||||
PathLine {
|
|
||||||
x: skyShape.width
|
|
||||||
y: skyShape.height
|
|
||||||
}
|
|
||||||
PathLine {
|
|
||||||
x: 0
|
|
||||||
y: skyShape.height
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ShapePath {
|
|
||||||
strokeColor: "transparent"
|
|
||||||
fillGradient: RadialGradient {
|
|
||||||
centerX: sun.x
|
|
||||||
centerY: sun.y
|
|
||||||
centerRadius: 500
|
|
||||||
focalX: centerX
|
|
||||||
focalY: centerY + 0.99 * (centerRadius - focalRadius)
|
|
||||||
focalRadius: 10
|
|
||||||
GradientStop {
|
|
||||||
position: 0
|
|
||||||
color: skyBox.sunColor
|
|
||||||
}
|
|
||||||
GradientStop {
|
|
||||||
position: 0.45
|
|
||||||
color: skyBox.sunColor
|
|
||||||
}
|
|
||||||
GradientStop {
|
|
||||||
position: 0.55
|
|
||||||
color: "transparent"
|
|
||||||
}
|
|
||||||
GradientStop {
|
|
||||||
position: 1
|
|
||||||
color: "transparent"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
PathLine {
|
|
||||||
x: 0
|
|
||||||
y: 0
|
|
||||||
}
|
|
||||||
PathLine {
|
|
||||||
x: skyShape.width
|
|
||||||
y: 0
|
|
||||||
}
|
|
||||||
PathLine {
|
|
||||||
x: skyShape.width
|
|
||||||
y: skyShape.height
|
|
||||||
}
|
|
||||||
PathLine {
|
|
||||||
x: 0
|
|
||||||
y: skyShape.height
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Canvas {
|
|
||||||
id: ecliptic
|
|
||||||
anchors.fill: parent
|
|
||||||
property var points: WeatherService.getEcliptic(dateStepper.currentDate)
|
|
||||||
|
|
||||||
function getX(index) {
|
|
||||||
return points[index].h * skyBox.effectiveWidth + skyBox.hMargin;
|
|
||||||
}
|
|
||||||
function getY(index) {
|
|
||||||
return points[index].v * -(skyBox.effectiveHeight / 2) + skyBox.effectiveHeight / 2 + skyBox.vMargin;
|
|
||||||
}
|
|
||||||
|
|
||||||
onPointsChanged: requestPaint()
|
|
||||||
|
|
||||||
onPaint: {
|
|
||||||
var ctx = getContext("2d");
|
|
||||||
ctx.clearRect(0, 0, width, height);
|
|
||||||
if (!points || points.length === 0)
|
|
||||||
return;
|
|
||||||
ctx.beginPath();
|
|
||||||
ctx.moveTo(getX(0), getY(0));
|
|
||||||
for (var i = 1; i < points.length; i++) {
|
|
||||||
ctx.lineTo(getX(i), getY(i));
|
|
||||||
}
|
|
||||||
ctx.strokeStyle = Theme.withAlpha(Theme.outline, 0.2);
|
|
||||||
ctx.stroke();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
property real latitude: WeatherService.getLocation()?.latitude ?? 0
|
property real latitude: WeatherService.getLocation()?.latitude ?? 0
|
||||||
property real sunDeclination: WeatherService.getSunDeclination(dateStepper.currentDate)
|
property real sunDeclination: WeatherService.getSunDeclination(dateStepper.currentDate)
|
||||||
|
|
||||||
readonly property bool solarNoonIsSouth: latitude > sunDeclination
|
readonly property bool solarNoonIsSouth: latitude > sunDeclination
|
||||||
|
|
||||||
StyledText {
|
Loader {
|
||||||
id: middle
|
anchors.fill: parent
|
||||||
text: skyBox.solarNoonIsSouth ? "S" : "N"
|
asynchronous: true
|
||||||
font.pixelSize: Theme.fontSizeSmall
|
sourceComponent: skyContentComponent
|
||||||
color: Theme.primary
|
opacity: status === Loader.Ready ? 1 : 0
|
||||||
x: skyBox.width / 2 - middle.width / 2
|
|
||||||
y: skyBox.height / 2 - middle.height / 2
|
Behavior on opacity {
|
||||||
|
NumberAnimation {
|
||||||
|
duration: Theme.shortDuration
|
||||||
|
easing.type: Theme.standardEasing
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
StyledText {
|
Component {
|
||||||
id: left
|
id: skyContentComponent
|
||||||
text: skyBox.solarNoonIsSouth ? "E" : "W"
|
|
||||||
font.pixelSize: Theme.fontSizeSmall
|
|
||||||
color: Theme.primary
|
|
||||||
x: skyBox.width / 4 - left.width / 2
|
|
||||||
y: skyBox.height / 2 - left.height / 2
|
|
||||||
}
|
|
||||||
|
|
||||||
StyledText {
|
Item {
|
||||||
id: right
|
Rectangle {
|
||||||
text: skyBox.solarNoonIsSouth ? "W" : "E"
|
anchors.fill: parent
|
||||||
font.pixelSize: Theme.fontSizeSmall
|
opacity: skyBox.backgroundOpacity
|
||||||
color: Theme.primary
|
|
||||||
x: 3 * skyBox.width / 4 - right.width / 2
|
|
||||||
y: skyBox.height / 2 - right.height / 2
|
|
||||||
}
|
|
||||||
|
|
||||||
Rectangle {
|
gradient: Gradient {
|
||||||
height: 1
|
GradientStop {
|
||||||
anchors.leftMargin: Theme.spacingS
|
position: 0.0
|
||||||
anchors.rightMargin: Theme.spacingS
|
color: Theme.withAlpha(skyBox.blackColor, 0.0)
|
||||||
anchors.left: right.right
|
}
|
||||||
anchors.right: skyBox.right
|
GradientStop {
|
||||||
anchors.verticalCenter: middle.verticalCenter
|
position: 0.05
|
||||||
color: Theme.outline
|
color: skyBox.topColor
|
||||||
}
|
}
|
||||||
|
GradientStop {
|
||||||
|
position: 0.3
|
||||||
|
color: skyBox.topColor
|
||||||
|
}
|
||||||
|
GradientStop {
|
||||||
|
position: 0.5
|
||||||
|
color: skyBox.topColor
|
||||||
|
}
|
||||||
|
GradientStop {
|
||||||
|
position: 0.501
|
||||||
|
color: skyBox.blackColor
|
||||||
|
}
|
||||||
|
GradientStop {
|
||||||
|
position: 0.9
|
||||||
|
color: skyBox.blackColor
|
||||||
|
}
|
||||||
|
GradientStop {
|
||||||
|
position: 1.0
|
||||||
|
color: Theme.withAlpha(skyBox.blackColor, 0.0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Rectangle {
|
StyledText {
|
||||||
height: 1
|
text: skyBox.sunTime?.period ?? ""
|
||||||
anchors.leftMargin: Theme.spacingS
|
font.pixelSize: Theme.fontSizeSmall
|
||||||
anchors.rightMargin: Theme.spacingS
|
color: Theme.withAlpha(Theme.surfaceText, 0.7)
|
||||||
anchors.left: middle.right
|
x: 0
|
||||||
anchors.right: right.left
|
y: 0
|
||||||
anchors.verticalCenter: middle.verticalCenter
|
}
|
||||||
color: Theme.outline
|
|
||||||
}
|
|
||||||
|
|
||||||
Rectangle {
|
Shape {
|
||||||
height: 1
|
id: skyShape
|
||||||
anchors.leftMargin: Theme.spacingS
|
anchors.left: parent.left
|
||||||
anchors.rightMargin: Theme.spacingS
|
anchors.top: parent.top
|
||||||
anchors.left: left.right
|
anchors.right: parent.right
|
||||||
anchors.right: middle.left
|
height: parent.height / 2
|
||||||
anchors.verticalCenter: middle.verticalCenter
|
opacity: skyBox.backgroundOpacity
|
||||||
color: Theme.outline
|
|
||||||
}
|
|
||||||
|
|
||||||
Rectangle {
|
ShapePath {
|
||||||
height: 1
|
strokeColor: "transparent"
|
||||||
anchors.leftMargin: Theme.spacingS
|
fillGradient: RadialGradient {
|
||||||
anchors.rightMargin: Theme.spacingS
|
centerX: skyBox.hMargin + sun.x + sun.width / 2
|
||||||
anchors.left: skyBox.left
|
centerY: skyBox.vMargin + sun.y + 30
|
||||||
anchors.right: left.left
|
centerRadius: {
|
||||||
anchors.verticalCenter: middle.verticalCenter
|
const a = Math.abs((skyBox.sunTime?.dayPercent ?? 0) - 0.5);
|
||||||
color: Theme.outline
|
const out = 200 * (0.5 - a * a);
|
||||||
}
|
return out;
|
||||||
|
}
|
||||||
|
focalX: skyBox.hMargin + sun.x + sun.width / 2
|
||||||
|
focalY: skyBox.vMargin + sun.y
|
||||||
|
GradientStop {
|
||||||
|
position: 0
|
||||||
|
color: skyBox.sunColor
|
||||||
|
}
|
||||||
|
GradientStop {
|
||||||
|
position: 0.3
|
||||||
|
color: Theme.blendAlpha(skyBox.sunColor, 0.5)
|
||||||
|
}
|
||||||
|
GradientStop {
|
||||||
|
position: 1
|
||||||
|
color: "transparent"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
PathLine {
|
||||||
|
x: 0
|
||||||
|
y: 0
|
||||||
|
}
|
||||||
|
PathLine {
|
||||||
|
x: skyShape.width
|
||||||
|
y: 0
|
||||||
|
}
|
||||||
|
PathLine {
|
||||||
|
x: skyShape.width
|
||||||
|
y: skyShape.height
|
||||||
|
}
|
||||||
|
PathLine {
|
||||||
|
x: 0
|
||||||
|
y: skyShape.height
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
DankNFIcon {
|
ShapePath {
|
||||||
id: moonPhase
|
strokeColor: "transparent"
|
||||||
name: WeatherService.getMoonPhase(skyBox.currentDate) || ""
|
fillGradient: RadialGradient {
|
||||||
size: Theme.fontSizeXLarge
|
centerX: sun.x
|
||||||
color: Theme.withAlpha(Theme.surfaceText, 0.7)
|
centerY: sun.y
|
||||||
rotation: (WeatherService.getMoonAngle(skyBox.currentDate) || 0) / Math.PI * 180
|
centerRadius: 500
|
||||||
visible: !!pos
|
focalX: centerX
|
||||||
|
focalY: centerY + 0.99 * (centerRadius - focalRadius)
|
||||||
|
focalRadius: 10
|
||||||
|
GradientStop {
|
||||||
|
position: 0
|
||||||
|
color: skyBox.sunColor
|
||||||
|
}
|
||||||
|
GradientStop {
|
||||||
|
position: 0.45
|
||||||
|
color: skyBox.sunColor
|
||||||
|
}
|
||||||
|
GradientStop {
|
||||||
|
position: 0.55
|
||||||
|
color: "transparent"
|
||||||
|
}
|
||||||
|
GradientStop {
|
||||||
|
position: 1
|
||||||
|
color: "transparent"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
PathLine {
|
||||||
|
x: 0
|
||||||
|
y: 0
|
||||||
|
}
|
||||||
|
PathLine {
|
||||||
|
x: skyShape.width
|
||||||
|
y: 0
|
||||||
|
}
|
||||||
|
PathLine {
|
||||||
|
x: skyShape.width
|
||||||
|
y: skyShape.height
|
||||||
|
}
|
||||||
|
PathLine {
|
||||||
|
x: 0
|
||||||
|
y: skyShape.height
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
property var pos: WeatherService.getSkyArcPosition(skyBox.currentDate, false)
|
Shape {
|
||||||
x: (pos?.h ?? 0) * skyBox.effectiveWidth - (moonPhase.width / 2) + skyBox.hMargin
|
anchors.fill: parent
|
||||||
y: (pos?.v ?? 0) * -(skyBox.effectiveHeight / 2) + skyBox.effectiveHeight / 2 - (moonPhase.height / 2) + skyBox.vMargin
|
|
||||||
}
|
|
||||||
|
|
||||||
DankIcon {
|
ShapePath {
|
||||||
id: sun
|
strokeColor: Theme.withAlpha(Theme.outline, 0.2)
|
||||||
name: "light_mode"
|
strokeWidth: 1
|
||||||
size: Theme.fontSizeXLarge
|
fillColor: "transparent"
|
||||||
color: Theme.primary
|
|
||||||
visible: !!pos
|
|
||||||
|
|
||||||
property var pos: WeatherService.getSkyArcPosition(skyBox.currentDate, true)
|
PathPolyline {
|
||||||
x: (pos?.h ?? 0) * skyBox.effectiveWidth - (sun.width / 2) + skyBox.hMargin
|
path: {
|
||||||
y: (pos?.v ?? 0) * -(skyBox.effectiveHeight / 2) + skyBox.effectiveHeight / 2 - (sun.height / 2) + skyBox.vMargin
|
const points = WeatherService.getEcliptic(dateStepper.currentDate) ?? [];
|
||||||
|
const out = [];
|
||||||
|
for (let i = 0; i < points.length; i++) {
|
||||||
|
out.push(Qt.point(points[i].h * skyBox.effectiveWidth + skyBox.hMargin, points[i].v * -(skyBox.effectiveHeight / 2) + skyBox.effectiveHeight / 2 + skyBox.vMargin));
|
||||||
|
}
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
StyledText {
|
||||||
|
id: middle
|
||||||
|
text: skyBox.solarNoonIsSouth ? "S" : "N"
|
||||||
|
font.pixelSize: Theme.fontSizeSmall
|
||||||
|
color: Theme.primary
|
||||||
|
x: skyBox.width / 2 - middle.width / 2
|
||||||
|
y: skyBox.height / 2 - middle.height / 2
|
||||||
|
}
|
||||||
|
|
||||||
|
StyledText {
|
||||||
|
id: left
|
||||||
|
text: skyBox.solarNoonIsSouth ? "E" : "W"
|
||||||
|
font.pixelSize: Theme.fontSizeSmall
|
||||||
|
color: Theme.primary
|
||||||
|
x: skyBox.width / 4 - left.width / 2
|
||||||
|
y: skyBox.height / 2 - left.height / 2
|
||||||
|
}
|
||||||
|
|
||||||
|
StyledText {
|
||||||
|
id: right
|
||||||
|
text: skyBox.solarNoonIsSouth ? "W" : "E"
|
||||||
|
font.pixelSize: Theme.fontSizeSmall
|
||||||
|
color: Theme.primary
|
||||||
|
x: 3 * skyBox.width / 4 - right.width / 2
|
||||||
|
y: skyBox.height / 2 - right.height / 2
|
||||||
|
}
|
||||||
|
|
||||||
|
Rectangle {
|
||||||
|
height: 1
|
||||||
|
anchors.leftMargin: Theme.spacingS
|
||||||
|
anchors.rightMargin: Theme.spacingS
|
||||||
|
anchors.left: right.right
|
||||||
|
anchors.right: parent.right
|
||||||
|
anchors.verticalCenter: middle.verticalCenter
|
||||||
|
color: Theme.outline
|
||||||
|
}
|
||||||
|
|
||||||
|
Rectangle {
|
||||||
|
height: 1
|
||||||
|
anchors.leftMargin: Theme.spacingS
|
||||||
|
anchors.rightMargin: Theme.spacingS
|
||||||
|
anchors.left: middle.right
|
||||||
|
anchors.right: right.left
|
||||||
|
anchors.verticalCenter: middle.verticalCenter
|
||||||
|
color: Theme.outline
|
||||||
|
}
|
||||||
|
|
||||||
|
Rectangle {
|
||||||
|
height: 1
|
||||||
|
anchors.leftMargin: Theme.spacingS
|
||||||
|
anchors.rightMargin: Theme.spacingS
|
||||||
|
anchors.left: left.right
|
||||||
|
anchors.right: middle.left
|
||||||
|
anchors.verticalCenter: middle.verticalCenter
|
||||||
|
color: Theme.outline
|
||||||
|
}
|
||||||
|
|
||||||
|
Rectangle {
|
||||||
|
height: 1
|
||||||
|
anchors.leftMargin: Theme.spacingS
|
||||||
|
anchors.rightMargin: Theme.spacingS
|
||||||
|
anchors.left: parent.left
|
||||||
|
anchors.right: left.left
|
||||||
|
anchors.verticalCenter: middle.verticalCenter
|
||||||
|
color: Theme.outline
|
||||||
|
}
|
||||||
|
|
||||||
|
DankNFIcon {
|
||||||
|
id: moonPhase
|
||||||
|
name: WeatherService.getMoonPhase(skyBox.currentDate) || ""
|
||||||
|
size: Theme.fontSizeXLarge
|
||||||
|
color: Theme.withAlpha(Theme.surfaceText, 0.7)
|
||||||
|
rotation: (WeatherService.getMoonAngle(skyBox.currentDate) || 0) / Math.PI * 180
|
||||||
|
visible: !!pos
|
||||||
|
|
||||||
|
property var pos: WeatherService.getSkyArcPosition(skyBox.currentDate, false)
|
||||||
|
x: (pos?.h ?? 0) * skyBox.effectiveWidth - (moonPhase.width / 2) + skyBox.hMargin
|
||||||
|
y: (pos?.v ?? 0) * -(skyBox.effectiveHeight / 2) + skyBox.effectiveHeight / 2 - (moonPhase.height / 2) + skyBox.vMargin
|
||||||
|
}
|
||||||
|
|
||||||
|
DankIcon {
|
||||||
|
id: sun
|
||||||
|
name: "light_mode"
|
||||||
|
size: Theme.fontSizeXLarge
|
||||||
|
color: Theme.primary
|
||||||
|
visible: !!pos
|
||||||
|
|
||||||
|
property var pos: WeatherService.getSkyArcPosition(skyBox.currentDate, true)
|
||||||
|
x: (pos?.h ?? 0) * skyBox.effectiveWidth - (sun.width / 2) + skyBox.hMargin
|
||||||
|
y: (pos?.v ?? 0) * -(skyBox.effectiveHeight / 2) + skyBox.effectiveHeight / 2 - (sun.height / 2) + skyBox.vMargin
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user