mirror of
https://github.com/AvengeMedia/DankMaterialShell.git
synced 2025-12-06 21:45:38 -05:00
uncomment toast, and format
This commit is contained in:
@@ -6,9 +6,9 @@ import Quickshell.Io
|
||||
import Quickshell.Wayland
|
||||
import Quickshell.Widgets
|
||||
import qs.Common
|
||||
import qs.Modules.AppDrawer
|
||||
import qs.Services
|
||||
import qs.Widgets
|
||||
import qs.Modules.AppDrawer
|
||||
|
||||
PanelWindow {
|
||||
id: appDrawerPopout
|
||||
@@ -50,10 +50,9 @@ PanelWindow {
|
||||
// App launcher logic
|
||||
AppLauncher {
|
||||
id: appLauncher
|
||||
|
||||
|
||||
viewMode: Prefs.appLauncherViewMode
|
||||
gridColumns: 4
|
||||
|
||||
onAppLaunched: appDrawerPopout.hide()
|
||||
onViewModeSelected: function(mode) {
|
||||
Prefs.setAppLauncherViewMode(mode);
|
||||
@@ -67,48 +66,48 @@ PanelWindow {
|
||||
onClicked: function(mouse) {
|
||||
// Only close if click is outside the launcher panel
|
||||
var localPos = mapToItem(launcherLoader, mouse.x, mouse.y);
|
||||
if (localPos.x < 0 || localPos.x > launcherLoader.width ||
|
||||
localPos.y < 0 || localPos.y > launcherLoader.height) {
|
||||
if (localPos.x < 0 || localPos.x > launcherLoader.width || localPos.y < 0 || localPos.y > launcherLoader.height)
|
||||
appDrawerPopout.hide();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// Main launcher panel with asynchronous loading
|
||||
Loader {
|
||||
id: launcherLoader
|
||||
|
||||
asynchronous: true
|
||||
active: appDrawerPopout.isVisible
|
||||
|
||||
width: 520
|
||||
height: 600
|
||||
x: Theme.spacingL
|
||||
y: Theme.barHeight + Theme.spacingXS
|
||||
|
||||
opacity: appDrawerPopout.isVisible ? 1 : 0
|
||||
scale: appDrawerPopout.isVisible ? 1 : 0.9
|
||||
|
||||
|
||||
Behavior on opacity {
|
||||
NumberAnimation {
|
||||
duration: Anims.durMed
|
||||
easing.type: Easing.BezierSpline
|
||||
easing.bezierCurve: Anims.emphasized
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
Behavior on scale {
|
||||
NumberAnimation {
|
||||
duration: Anims.durMed
|
||||
easing.type: Easing.BezierSpline
|
||||
easing.bezierCurve: Anims.emphasized
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
sourceComponent: Rectangle {
|
||||
id: launcherPanel
|
||||
|
||||
color: Theme.popupBackground()
|
||||
radius: Theme.cornerRadiusXLarge
|
||||
|
||||
// Remove layer rendering for better performance
|
||||
antialiasing: true
|
||||
smooth: true
|
||||
@@ -146,13 +145,14 @@ PanelWindow {
|
||||
// Content with focus management
|
||||
Item {
|
||||
id: keyHandler
|
||||
|
||||
anchors.fill: parent
|
||||
focus: true
|
||||
Component.onCompleted: {
|
||||
if (appDrawerPopout.isVisible)
|
||||
forceActiveFocus();
|
||||
|
||||
}
|
||||
|
||||
// Handle keyboard shortcuts
|
||||
Keys.onPressed: function(event) {
|
||||
if (event.key === Qt.Key_Escape) {
|
||||
@@ -214,6 +214,7 @@ PanelWindow {
|
||||
font.pixelSize: Theme.fontSizeMedium
|
||||
color: Theme.surfaceVariantText
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Enhanced search field
|
||||
@@ -252,26 +253,25 @@ PanelWindow {
|
||||
event.accepted = false;
|
||||
}
|
||||
}
|
||||
|
||||
Component.onCompleted: {
|
||||
if (appDrawerPopout.isVisible) {
|
||||
if (appDrawerPopout.isVisible)
|
||||
searchField.forceActiveFocus();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Connections {
|
||||
function onIsVisibleChanged() {
|
||||
if (appDrawerPopout.isVisible) {
|
||||
if (appDrawerPopout.isVisible)
|
||||
Qt.callLater(function() {
|
||||
searchField.forceActiveFocus();
|
||||
});
|
||||
} else {
|
||||
else
|
||||
searchField.clearFocus();
|
||||
}
|
||||
}
|
||||
|
||||
target: appDrawerPopout
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Category filter and view mode controls
|
||||
@@ -285,7 +285,7 @@ PanelWindow {
|
||||
Item {
|
||||
width: 200
|
||||
height: 36
|
||||
|
||||
|
||||
DankDropdown {
|
||||
anchors.fill: parent
|
||||
text: ""
|
||||
@@ -296,6 +296,7 @@ PanelWindow {
|
||||
appLauncher.setCategory(value);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Item {
|
||||
@@ -335,7 +336,9 @@ PanelWindow {
|
||||
appLauncher.setViewMode("grid");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// App grid/list container
|
||||
@@ -399,10 +402,15 @@ PanelWindow {
|
||||
appLauncher.keyboardNavigationActive = false;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -18,62 +18,35 @@ Item {
|
||||
property bool debounceSearch: true
|
||||
property int debounceInterval: 50
|
||||
property bool keyboardNavigationActive: false
|
||||
|
||||
// Categories (computed from AppSearchService)
|
||||
property var categories: {
|
||||
var allCategories = AppSearchService.getAllCategories().filter(cat => {
|
||||
var allCategories = AppSearchService.getAllCategories().filter((cat) => {
|
||||
return cat !== "Education" && cat !== "Science";
|
||||
});
|
||||
var result = ["All"];
|
||||
return result.concat(allCategories.filter(cat => {
|
||||
return result.concat(allCategories.filter((cat) => {
|
||||
return cat !== "All";
|
||||
}));
|
||||
}
|
||||
|
||||
// Category icons (computed from AppSearchService)
|
||||
property var categoryIcons: categories.map(category => AppSearchService.getCategoryIcon(category))
|
||||
|
||||
property var categoryIcons: categories.map((category) => {
|
||||
return AppSearchService.getCategoryIcon(category);
|
||||
})
|
||||
// App usage ranking helper
|
||||
property var appUsageRanking: Prefs.appUsageRanking
|
||||
// Internal model
|
||||
property alias model: filteredModel
|
||||
|
||||
// Signals
|
||||
signal appLaunched(var app)
|
||||
signal categorySelected(string category)
|
||||
signal viewModeSelected(string mode)
|
||||
|
||||
// Internal model
|
||||
property alias model: filteredModel
|
||||
|
||||
ListModel {
|
||||
id: filteredModel
|
||||
}
|
||||
|
||||
// Search debouncing
|
||||
Timer {
|
||||
id: searchDebounceTimer
|
||||
interval: root.debounceInterval
|
||||
repeat: false
|
||||
onTriggered: updateFilteredModel()
|
||||
}
|
||||
|
||||
// Watch for changes
|
||||
onSearchQueryChanged: {
|
||||
if (debounceSearch) {
|
||||
searchDebounceTimer.restart();
|
||||
} else {
|
||||
updateFilteredModel();
|
||||
}
|
||||
}
|
||||
onSelectedCategoryChanged: updateFilteredModel()
|
||||
onAppUsageRankingChanged: updateFilteredModel()
|
||||
|
||||
function updateFilteredModel() {
|
||||
filteredModel.clear();
|
||||
selectedIndex = 0;
|
||||
keyboardNavigationActive = false;
|
||||
|
||||
var apps = [];
|
||||
|
||||
if (searchQuery.length === 0) {
|
||||
// Show apps from category
|
||||
if (selectedCategory === "All") {
|
||||
@@ -90,8 +63,10 @@ Item {
|
||||
var categoryApps = AppSearchService.getAppsInCategory(selectedCategory);
|
||||
if (categoryApps.length > 0) {
|
||||
var allSearchResults = AppSearchService.searchApplications(searchQuery);
|
||||
var categoryNames = new Set(categoryApps.map(app => app.name));
|
||||
apps = allSearchResults.filter(searchApp => {
|
||||
var categoryNames = new Set(categoryApps.map((app) => {
|
||||
return app.name;
|
||||
}));
|
||||
apps = allSearchResults.filter((searchApp) => {
|
||||
return categoryNames.has(searchApp.name);
|
||||
}).slice(0, maxResults);
|
||||
} else {
|
||||
@@ -99,25 +74,20 @@ Item {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Sort apps by usage ranking, then alphabetically
|
||||
apps = apps.sort(function(a, b) {
|
||||
var aId = a.id || (a.execString || a.exec || "");
|
||||
var bId = b.id || (b.execString || b.exec || "");
|
||||
|
||||
var aUsage = appUsageRanking[aId] ? appUsageRanking[aId].usageCount : 0;
|
||||
var bUsage = appUsageRanking[bId] ? appUsageRanking[bId].usageCount : 0;
|
||||
|
||||
if (aUsage !== bUsage) {
|
||||
if (aUsage !== bUsage)
|
||||
return bUsage - aUsage; // Higher usage first
|
||||
}
|
||||
|
||||
|
||||
return (a.name || "").localeCompare(b.name || ""); // Alphabetical fallback
|
||||
});
|
||||
|
||||
// Convert to model format and populate
|
||||
apps.forEach(app => {
|
||||
if (app) {
|
||||
apps.forEach((app) => {
|
||||
if (app)
|
||||
filteredModel.append({
|
||||
"name": app.name || "",
|
||||
"exec": app.execString || "",
|
||||
@@ -126,7 +96,7 @@ Item {
|
||||
"categories": app.categories || [],
|
||||
"desktopEntry": app
|
||||
});
|
||||
}
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
@@ -180,9 +150,8 @@ Item {
|
||||
function launchApp(appData) {
|
||||
if (!appData) {
|
||||
console.warn("AppLauncher: No app data provided");
|
||||
return;
|
||||
return ;
|
||||
}
|
||||
|
||||
appData.desktopEntry.execute();
|
||||
appLaunched(appData);
|
||||
Prefs.addAppUsage(appData.desktopEntry);
|
||||
@@ -200,8 +169,31 @@ Item {
|
||||
viewModeSelected(mode);
|
||||
}
|
||||
|
||||
// Watch for changes
|
||||
onSearchQueryChanged: {
|
||||
if (debounceSearch)
|
||||
searchDebounceTimer.restart();
|
||||
else
|
||||
updateFilteredModel();
|
||||
}
|
||||
onSelectedCategoryChanged: updateFilteredModel()
|
||||
onAppUsageRankingChanged: updateFilteredModel()
|
||||
// Initialize
|
||||
Component.onCompleted: {
|
||||
updateFilteredModel();
|
||||
}
|
||||
}
|
||||
|
||||
ListModel {
|
||||
id: filteredModel
|
||||
}
|
||||
|
||||
// Search debouncing
|
||||
Timer {
|
||||
id: searchDebounceTimer
|
||||
|
||||
interval: root.debounceInterval
|
||||
repeat: false
|
||||
onTriggered: updateFilteredModel()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -48,8 +48,11 @@ Item {
|
||||
categorySelected(modelData);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Two-row layout (for SpotlightModal organized style)
|
||||
@@ -66,7 +69,7 @@ Item {
|
||||
spacing: Theme.spacingS
|
||||
|
||||
Repeater {
|
||||
model: parent.topRowCategories.filter(cat => {
|
||||
model: parent.topRowCategories.filter((cat) => {
|
||||
return categories.includes(cat);
|
||||
})
|
||||
|
||||
@@ -95,8 +98,11 @@ Item {
|
||||
categorySelected(modelData);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Bottom row: Internet, Media, Office, Settings, System (5 items)
|
||||
@@ -107,7 +113,7 @@ Item {
|
||||
spacing: Theme.spacingS
|
||||
|
||||
Repeater {
|
||||
model: parent.bottomRowCategories.filter(cat => {
|
||||
model: parent.bottomRowCategories.filter((cat) => {
|
||||
return categories.includes(cat);
|
||||
})
|
||||
|
||||
@@ -136,8 +142,13 @@ Item {
|
||||
categorySelected(modelData);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -6,8 +6,8 @@ import Quickshell.Services.Mpris
|
||||
import Quickshell.Wayland
|
||||
import Quickshell.Widgets
|
||||
import qs.Common
|
||||
import qs.Services
|
||||
import qs.Modules.CentcomCenter
|
||||
import qs.Services
|
||||
|
||||
PanelWindow {
|
||||
id: root
|
||||
@@ -17,25 +17,25 @@ PanelWindow {
|
||||
property bool internalVisible: false
|
||||
|
||||
visible: internalVisible
|
||||
|
||||
onCalendarVisibleChanged: {
|
||||
if (calendarVisible) {
|
||||
internalVisible = true
|
||||
internalVisible = true;
|
||||
Qt.callLater(() => {
|
||||
// This ensures opacity changes after window is visible
|
||||
internalVisible = true // Force re-trigger if needed
|
||||
internalVisible = true;
|
||||
// Force re-trigger if needed
|
||||
// Ensure events are loaded for current display month
|
||||
calendarGrid.loadEventsForMonth()
|
||||
})
|
||||
calendarGrid.loadEventsForMonth();
|
||||
});
|
||||
} else {
|
||||
internalVisible = false
|
||||
internalVisible = false;
|
||||
}
|
||||
}
|
||||
onVisibleChanged: {
|
||||
if (visible && calendarGrid)
|
||||
calendarGrid.loadEventsForMonth();
|
||||
|
||||
}
|
||||
|
||||
implicitWidth: 480
|
||||
implicitHeight: 600
|
||||
WlrLayershell.layer: WlrLayershell.Overlay
|
||||
@@ -53,6 +53,8 @@ PanelWindow {
|
||||
Rectangle {
|
||||
id: mainContainer
|
||||
|
||||
readonly property real targetWidth: Math.min(Screen.width * 0.9, 600)
|
||||
|
||||
function calculateWidth() {
|
||||
let baseWidth = 320;
|
||||
if (leftWidgets.hasAnyWidgets)
|
||||
@@ -80,7 +82,6 @@ PanelWindow {
|
||||
return Math.min(contentHeight, parent.height * 0.9);
|
||||
}
|
||||
|
||||
readonly property real targetWidth: Math.min(Screen.width * 0.9, 600)
|
||||
width: targetWidth
|
||||
height: calculateHeight()
|
||||
color: Theme.surfaceContainer
|
||||
@@ -92,44 +93,27 @@ PanelWindow {
|
||||
scale: calendarVisible ? 1 : 0.9
|
||||
x: (Screen.width - targetWidth) / 2
|
||||
y: Theme.barHeight + 4
|
||||
|
||||
Behavior on opacity {
|
||||
NumberAnimation {
|
||||
duration: Anims.durMed
|
||||
easing.type: Easing.BezierSpline
|
||||
easing.bezierCurve: Anims.emphasized
|
||||
}
|
||||
}
|
||||
|
||||
Behavior on scale {
|
||||
NumberAnimation {
|
||||
duration: Anims.durMed
|
||||
easing.type: Easing.BezierSpline
|
||||
easing.bezierCurve: Anims.emphasized
|
||||
}
|
||||
}
|
||||
|
||||
// Only resize after animation is complete
|
||||
onOpacityChanged: {
|
||||
if (opacity === 1) {
|
||||
if (opacity === 1)
|
||||
// Animation finished, now we can safely resize
|
||||
Qt.callLater(() => {
|
||||
height = calculateHeight();
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Connections {
|
||||
function onEventsByDateChanged() {
|
||||
if (mainContainer.opacity === 1) {
|
||||
if (mainContainer.opacity === 1)
|
||||
mainContainer.height = mainContainer.calculateHeight();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
function onKhalAvailableChanged() {
|
||||
if (mainContainer.opacity === 1) {
|
||||
if (mainContainer.opacity === 1)
|
||||
mainContainer.height = mainContainer.calculateHeight();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
target: CalendarService
|
||||
@@ -138,9 +122,9 @@ PanelWindow {
|
||||
|
||||
Connections {
|
||||
function onSelectedDateEventsChanged() {
|
||||
if (mainContainer.opacity === 1) {
|
||||
if (mainContainer.opacity === 1)
|
||||
mainContainer.height = mainContainer.calculateHeight();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
target: events
|
||||
@@ -172,8 +156,6 @@ PanelWindow {
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
Column {
|
||||
anchors.fill: parent
|
||||
anchors.margins: Theme.spacingM
|
||||
@@ -236,6 +218,24 @@ PanelWindow {
|
||||
|
||||
}
|
||||
|
||||
Behavior on opacity {
|
||||
NumberAnimation {
|
||||
duration: Anims.durMed
|
||||
easing.type: Easing.BezierSpline
|
||||
easing.bezierCurve: Anims.emphasized
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Behavior on scale {
|
||||
NumberAnimation {
|
||||
duration: Anims.durMed
|
||||
easing.type: Easing.BezierSpline
|
||||
easing.bezierCurve: Anims.emphasized
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
layer.effect: MultiEffect {
|
||||
shadowEnabled: true
|
||||
shadowHorizontalOffset: 0
|
||||
@@ -245,8 +245,6 @@ PanelWindow {
|
||||
shadowOpacity: 0.15
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
@@ -256,10 +254,9 @@ PanelWindow {
|
||||
onClicked: function(mouse) {
|
||||
// Only close if click is outside the main container
|
||||
var localPos = mapToItem(mainContainer, mouse.x, mouse.y);
|
||||
if (localPos.x < 0 || localPos.x > mainContainer.width ||
|
||||
localPos.y < 0 || localPos.y > mainContainer.height) {
|
||||
if (localPos.x < 0 || localPos.x > mainContainer.width || localPos.y < 0 || localPos.y > mainContainer.height)
|
||||
calendarVisible = false;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@ Rectangle {
|
||||
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.08)
|
||||
border.width: 1
|
||||
layer.enabled: true
|
||||
|
||||
|
||||
Ref {
|
||||
service: WeatherService
|
||||
}
|
||||
|
||||
@@ -16,7 +16,7 @@ PanelWindow {
|
||||
|
||||
visible: notificationHistoryVisible
|
||||
implicitWidth: 400
|
||||
implicitHeight: Math.min(Screen.height * 0.60, Math.max(580, (notificationsList.contentHeight || 0) + 140))
|
||||
implicitHeight: Math.min(Screen.height * 0.6, Math.max(580, (notificationsList.contentHeight || 0) + 140))
|
||||
WlrLayershell.layer: WlrLayershell.Overlay
|
||||
WlrLayershell.exclusiveZone: -1
|
||||
WlrLayershell.keyboardFocus: WlrKeyboardFocus.None
|
||||
@@ -39,7 +39,7 @@ PanelWindow {
|
||||
|
||||
Rectangle {
|
||||
width: 400
|
||||
height: Math.min(Screen.height * 0.60, Math.max(580, (notificationsList.contentHeight || 0) + 140))
|
||||
height: Math.min(Screen.height * 0.6, Math.max(580, (notificationsList.contentHeight || 0) + 140))
|
||||
x: Screen.width - width - Theme.spacingL
|
||||
y: Theme.barHeight + Theme.spacingXS
|
||||
color: Theme.popupBackground()
|
||||
@@ -710,7 +710,6 @@ PanelWindow {
|
||||
|
||||
delegate: Rectangle {
|
||||
required property var modelData
|
||||
|
||||
readonly property bool messageExpanded: NotificationService.expandedMessages[modelData.notification.id] || false
|
||||
|
||||
width: parent.width
|
||||
@@ -726,7 +725,7 @@ PanelWindow {
|
||||
|
||||
Rectangle {
|
||||
id: messageIcon
|
||||
|
||||
|
||||
readonly property bool hasNotificationImage: modelData.image && modelData.image !== ""
|
||||
|
||||
width: 32
|
||||
@@ -830,7 +829,6 @@ PanelWindow {
|
||||
bodyText = bodyText.length > 500 ? bodyText.substring(0, 497) + "..." : bodyText;
|
||||
else
|
||||
bodyText = bodyText.length > 80 ? bodyText.substring(0, 77) + "..." : bodyText;
|
||||
|
||||
// Auto-detect and make URLs clickable
|
||||
const urlRegex = /(https?:\/\/[^\s]+)/g;
|
||||
return bodyText.replace(urlRegex, '<a href="$1" style="color: ' + Theme.primary + '; text-decoration: underline;">$1</a>');
|
||||
@@ -916,7 +914,6 @@ PanelWindow {
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1114,6 +1111,7 @@ PanelWindow {
|
||||
duration: Theme.shortDuration
|
||||
easing.type: Theme.standardEasing
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Behavior on opacity {
|
||||
|
||||
@@ -16,7 +16,7 @@ PanelWindow {
|
||||
WlrLayershell.keyboardFocus: WlrKeyboardFocus.None
|
||||
color: "transparent"
|
||||
implicitWidth: 400
|
||||
implicitHeight: Math.min(Screen.height * 0.60, Math.max(400, (notificationsList.contentHeight || 0) + 32))
|
||||
implicitHeight: Math.min(Screen.height * 0.6, Math.max(400, (notificationsList.contentHeight || 0) + 32))
|
||||
|
||||
anchors {
|
||||
top: true
|
||||
@@ -35,18 +35,11 @@ PanelWindow {
|
||||
anchors.rightMargin: 16
|
||||
anchors.bottomMargin: 16
|
||||
width: 380
|
||||
height: Math.min(Screen.height * 0.60 - 32, Math.max(368, (notificationsList.contentHeight || 0) + 32))
|
||||
height: Math.min(Screen.height * 0.6 - 32, Math.max(368, (notificationsList.contentHeight || 0) + 32))
|
||||
color: "transparent"
|
||||
radius: 12
|
||||
clip: true
|
||||
|
||||
Behavior on height {
|
||||
NumberAnimation {
|
||||
duration: Theme.shortDuration
|
||||
easing.type: Theme.standardEasing
|
||||
}
|
||||
}
|
||||
|
||||
ScrollView {
|
||||
anchors.fill: parent
|
||||
clip: true
|
||||
@@ -607,6 +600,7 @@ PanelWindow {
|
||||
// Body text with expand capability
|
||||
Text {
|
||||
id: bodyText
|
||||
|
||||
property bool hasUrls: {
|
||||
const urlRegex = /(https?:\/\/[^\s]+)/g;
|
||||
return urlRegex.test(modelData.body || "");
|
||||
@@ -908,6 +902,14 @@ PanelWindow {
|
||||
|
||||
}
|
||||
|
||||
Behavior on height {
|
||||
NumberAnimation {
|
||||
duration: Theme.shortDuration
|
||||
easing.type: Theme.standardEasing
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Behavior on implicitHeight {
|
||||
|
||||
@@ -7,18 +7,19 @@ import qs.Widgets
|
||||
|
||||
ScrollView {
|
||||
id: appearanceTab
|
||||
|
||||
|
||||
contentWidth: availableWidth
|
||||
contentHeight: column.implicitHeight + Theme.spacingXL
|
||||
clip: true
|
||||
|
||||
|
||||
Column {
|
||||
id: column
|
||||
|
||||
width: parent.width
|
||||
spacing: Theme.spacingXL
|
||||
topPadding: Theme.spacingL
|
||||
bottomPadding: Theme.spacingXL
|
||||
|
||||
|
||||
// Display Settings Section
|
||||
StyledRect {
|
||||
width: parent.width
|
||||
@@ -27,24 +28,25 @@ ScrollView {
|
||||
color: Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, 0.3)
|
||||
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.2)
|
||||
border.width: 1
|
||||
|
||||
|
||||
Column {
|
||||
id: displaySection
|
||||
|
||||
anchors.fill: parent
|
||||
anchors.margins: Theme.spacingL
|
||||
spacing: Theme.spacingM
|
||||
|
||||
|
||||
Row {
|
||||
width: parent.width
|
||||
spacing: Theme.spacingM
|
||||
|
||||
|
||||
DankIcon {
|
||||
name: "monitor"
|
||||
size: Theme.iconSize
|
||||
color: Theme.primary
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
}
|
||||
|
||||
|
||||
StyledText {
|
||||
text: "Display Settings"
|
||||
font.pixelSize: Theme.fontSizeLarge
|
||||
@@ -52,8 +54,9 @@ ScrollView {
|
||||
color: Theme.surfaceText
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
DankToggle {
|
||||
width: parent.width
|
||||
text: "Night Mode"
|
||||
@@ -67,7 +70,7 @@ ScrollView {
|
||||
nightModeDisableProcess.running = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
DankToggle {
|
||||
width: parent.width
|
||||
text: "Light Mode"
|
||||
@@ -78,7 +81,7 @@ ScrollView {
|
||||
Theme.isLightMode = checked;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
DankDropdown {
|
||||
width: parent.width
|
||||
text: "Icon Theme"
|
||||
@@ -89,9 +92,11 @@ ScrollView {
|
||||
Prefs.setIconTheme(value);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
// Transparency Settings Section
|
||||
StyledRect {
|
||||
width: parent.width
|
||||
@@ -100,24 +105,25 @@ ScrollView {
|
||||
color: Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, 0.3)
|
||||
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.2)
|
||||
border.width: 1
|
||||
|
||||
|
||||
Column {
|
||||
id: transparencySection
|
||||
|
||||
anchors.fill: parent
|
||||
anchors.margins: Theme.spacingL
|
||||
spacing: Theme.spacingM
|
||||
|
||||
|
||||
Row {
|
||||
width: parent.width
|
||||
spacing: Theme.spacingM
|
||||
|
||||
|
||||
DankIcon {
|
||||
name: "opacity"
|
||||
size: Theme.iconSize
|
||||
color: Theme.primary
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
}
|
||||
|
||||
|
||||
StyledText {
|
||||
text: "Transparency Settings"
|
||||
font.pixelSize: Theme.fontSizeLarge
|
||||
@@ -125,19 +131,20 @@ ScrollView {
|
||||
color: Theme.surfaceText
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
Column {
|
||||
width: parent.width
|
||||
spacing: Theme.spacingS
|
||||
|
||||
|
||||
StyledText {
|
||||
text: "Top Bar Transparency"
|
||||
font.pixelSize: Theme.fontSizeSmall
|
||||
color: Theme.surfaceText
|
||||
font.weight: Font.Medium
|
||||
}
|
||||
|
||||
|
||||
DankSlider {
|
||||
width: parent.width
|
||||
height: 24
|
||||
@@ -150,19 +157,20 @@ ScrollView {
|
||||
Prefs.setTopBarTransparency(newValue / 100);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
Column {
|
||||
width: parent.width
|
||||
spacing: Theme.spacingS
|
||||
|
||||
|
||||
StyledText {
|
||||
text: "Popup Transparency"
|
||||
font.pixelSize: Theme.fontSizeSmall
|
||||
color: Theme.surfaceText
|
||||
font.weight: Font.Medium
|
||||
}
|
||||
|
||||
|
||||
DankSlider {
|
||||
width: parent.width
|
||||
height: 24
|
||||
@@ -175,10 +183,13 @@ ScrollView {
|
||||
Prefs.setPopupTransparency(newValue / 100);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
// Theme Picker Section
|
||||
StyledRect {
|
||||
width: parent.width
|
||||
@@ -187,24 +198,25 @@ ScrollView {
|
||||
color: Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, 0.3)
|
||||
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.2)
|
||||
border.width: 1
|
||||
|
||||
|
||||
Column {
|
||||
id: themeSection
|
||||
|
||||
anchors.fill: parent
|
||||
anchors.margins: Theme.spacingL
|
||||
spacing: Theme.spacingM
|
||||
|
||||
|
||||
Row {
|
||||
width: parent.width
|
||||
spacing: Theme.spacingM
|
||||
|
||||
|
||||
DankIcon {
|
||||
name: "palette"
|
||||
size: Theme.iconSize
|
||||
color: Theme.primary
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
}
|
||||
|
||||
|
||||
StyledText {
|
||||
text: "Theme Color"
|
||||
font.pixelSize: Theme.fontSizeLarge
|
||||
@@ -212,12 +224,13 @@ ScrollView {
|
||||
color: Theme.surfaceText
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
Column {
|
||||
width: parent.width
|
||||
spacing: Theme.spacingS
|
||||
|
||||
|
||||
StyledText {
|
||||
text: "Current Theme: " + (Theme.isDynamicTheme ? "Auto" : (Theme.currentThemeIndex < Theme.themes.length ? Theme.themes[Theme.currentThemeIndex].name : "Blue"))
|
||||
font.pixelSize: Theme.fontSizeMedium
|
||||
@@ -225,12 +238,12 @@ ScrollView {
|
||||
font.weight: Font.Medium
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
}
|
||||
|
||||
|
||||
StyledText {
|
||||
text: {
|
||||
if (Theme.isDynamicTheme)
|
||||
return "Wallpaper-based dynamic colors";
|
||||
|
||||
|
||||
var descriptions = ["Material blue inspired by modern interfaces", "Deep blue inspired by material 3", "Rich purple tones for BB elegance", "Natural green for productivity", "Energetic orange for creativity", "Bold red for impact", "Cool cyan for tranquility", "Vibrant pink for expression", "Warm amber for comfort", "Soft coral for gentle warmth"];
|
||||
return descriptions[Theme.currentThemeIndex] || "Select a theme";
|
||||
}
|
||||
@@ -241,21 +254,22 @@ ScrollView {
|
||||
width: Math.min(parent.width, 400)
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
// Theme Grid
|
||||
Column {
|
||||
spacing: Theme.spacingS
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
|
||||
|
||||
// First row - Blue, Deep Blue, Purple, Green, Orange
|
||||
Row {
|
||||
spacing: Theme.spacingM
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
|
||||
|
||||
Repeater {
|
||||
model: 5
|
||||
|
||||
|
||||
Rectangle {
|
||||
width: 32
|
||||
height: 32
|
||||
@@ -264,7 +278,7 @@ ScrollView {
|
||||
border.color: Theme.outline
|
||||
border.width: (Theme.currentThemeIndex === index && !Theme.isDynamicTheme) ? 2 : 1
|
||||
scale: (Theme.currentThemeIndex === index && !Theme.isDynamicTheme) ? 1.1 : 1
|
||||
|
||||
|
||||
// Theme name tooltip
|
||||
Rectangle {
|
||||
width: nameText.contentWidth + Theme.spacingS * 2
|
||||
@@ -277,18 +291,21 @@ ScrollView {
|
||||
anchors.bottomMargin: Theme.spacingXS
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
visible: mouseArea.containsMouse
|
||||
|
||||
|
||||
StyledText {
|
||||
id: nameText
|
||||
|
||||
text: Theme.themes[index].name
|
||||
font.pixelSize: Theme.fontSizeSmall
|
||||
color: Theme.surfaceText
|
||||
anchors.centerIn: parent
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
MouseArea {
|
||||
id: mouseArea
|
||||
|
||||
anchors.fill: parent
|
||||
hoverEnabled: true
|
||||
cursorShape: Qt.PointingHandCursor
|
||||
@@ -296,35 +313,40 @@ ScrollView {
|
||||
Theme.switchTheme(index, false);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Behavior on scale {
|
||||
NumberAnimation {
|
||||
duration: Theme.shortDuration
|
||||
easing.type: Theme.emphasizedEasing
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
Behavior on border.width {
|
||||
NumberAnimation {
|
||||
duration: Theme.shortDuration
|
||||
easing.type: Theme.emphasizedEasing
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
// Second row - Red, Cyan, Pink, Amber, Coral
|
||||
Row {
|
||||
spacing: Theme.spacingM
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
|
||||
|
||||
Repeater {
|
||||
model: 5
|
||||
|
||||
|
||||
Rectangle {
|
||||
property int themeIndex: index + 5
|
||||
|
||||
|
||||
width: 32
|
||||
height: 32
|
||||
radius: 16
|
||||
@@ -333,7 +355,7 @@ ScrollView {
|
||||
border.width: Theme.currentThemeIndex === themeIndex ? 2 : 1
|
||||
visible: themeIndex < Theme.themes.length
|
||||
scale: Theme.currentThemeIndex === themeIndex ? 1.1 : 1
|
||||
|
||||
|
||||
// Theme name tooltip
|
||||
Rectangle {
|
||||
width: nameText2.contentWidth + Theme.spacingS * 2
|
||||
@@ -346,50 +368,59 @@ ScrollView {
|
||||
anchors.bottomMargin: Theme.spacingXS
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
visible: mouseArea2.containsMouse && themeIndex < Theme.themes.length
|
||||
|
||||
|
||||
StyledText {
|
||||
id: nameText2
|
||||
|
||||
text: themeIndex < Theme.themes.length ? Theme.themes[themeIndex].name : ""
|
||||
font.pixelSize: Theme.fontSizeSmall
|
||||
color: Theme.surfaceText
|
||||
anchors.centerIn: parent
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
MouseArea {
|
||||
id: mouseArea2
|
||||
|
||||
anchors.fill: parent
|
||||
hoverEnabled: true
|
||||
cursorShape: Qt.PointingHandCursor
|
||||
onClicked: {
|
||||
if (themeIndex < Theme.themes.length)
|
||||
Theme.switchTheme(themeIndex);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Behavior on scale {
|
||||
NumberAnimation {
|
||||
duration: Theme.shortDuration
|
||||
easing.type: Theme.emphasizedEasing
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
Behavior on border.width {
|
||||
NumberAnimation {
|
||||
duration: Theme.shortDuration
|
||||
easing.type: Theme.emphasizedEasing
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
// Spacer
|
||||
Item {
|
||||
width: 1
|
||||
height: Theme.spacingM
|
||||
}
|
||||
|
||||
|
||||
// Auto theme button
|
||||
Rectangle {
|
||||
width: 120
|
||||
@@ -412,11 +443,11 @@ ScrollView {
|
||||
}
|
||||
border.width: Theme.isDynamicTheme ? 2 : 1
|
||||
scale: Theme.isDynamicTheme ? 1.1 : (autoMouseArea.containsMouse ? 1.02 : 1)
|
||||
|
||||
|
||||
Row {
|
||||
anchors.centerIn: parent
|
||||
spacing: Theme.spacingS
|
||||
|
||||
|
||||
DankIcon {
|
||||
name: {
|
||||
if (ToastService.wallpaperErrorStatus === "error" || ToastService.wallpaperErrorStatus === "matugen_missing")
|
||||
@@ -433,7 +464,7 @@ ScrollView {
|
||||
}
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
}
|
||||
|
||||
|
||||
StyledText {
|
||||
text: {
|
||||
if (ToastService.wallpaperErrorStatus === "error")
|
||||
@@ -453,24 +484,25 @@ ScrollView {
|
||||
font.weight: Font.Medium
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
MouseArea {
|
||||
id: autoMouseArea
|
||||
|
||||
anchors.fill: parent
|
||||
hoverEnabled: true
|
||||
cursorShape: Qt.PointingHandCursor
|
||||
onClicked: {
|
||||
if (ToastService.wallpaperErrorStatus === "matugen_missing") {
|
||||
if (ToastService.wallpaperErrorStatus === "matugen_missing")
|
||||
ToastService.showError("matugen not found - install matugen package for dynamic theming");
|
||||
} else if (ToastService.wallpaperErrorStatus === "error") {
|
||||
else if (ToastService.wallpaperErrorStatus === "error")
|
||||
ToastService.showError("Wallpaper processing failed - check wallpaper path");
|
||||
} else {
|
||||
else
|
||||
Theme.switchTheme(10, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Tooltip for Auto button
|
||||
Rectangle {
|
||||
width: autoTooltipText.contentWidth + Theme.spacingM * 2
|
||||
@@ -483,9 +515,10 @@ ScrollView {
|
||||
anchors.bottomMargin: Theme.spacingS
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
visible: autoMouseArea.containsMouse && (!Theme.isDynamicTheme || ToastService.wallpaperErrorStatus === "error" || ToastService.wallpaperErrorStatus === "matugen_missing")
|
||||
|
||||
|
||||
StyledText {
|
||||
id: autoTooltipText
|
||||
|
||||
text: {
|
||||
if (ToastService.wallpaperErrorStatus === "error")
|
||||
return "Wallpaper symlink missing at ~/quickshell/current_wallpaper";
|
||||
@@ -501,37 +534,47 @@ ScrollView {
|
||||
width: Math.min(implicitWidth, 250)
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
Behavior on scale {
|
||||
NumberAnimation {
|
||||
duration: Theme.shortDuration
|
||||
easing.type: Theme.emphasizedEasing
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
Behavior on color {
|
||||
ColorAnimation {
|
||||
duration: Theme.mediumDuration
|
||||
easing.type: Theme.standardEasing
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
Behavior on border.color {
|
||||
ColorAnimation {
|
||||
duration: Theme.mediumDuration
|
||||
easing.type: Theme.standardEasing
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
// Night mode processes
|
||||
Process {
|
||||
id: nightModeEnableProcess
|
||||
|
||||
command: ["bash", "-c", "if command -v wlsunset > /dev/null; then pkill wlsunset; wlsunset -t 3000 & elif command -v redshift > /dev/null; then pkill redshift; redshift -P -O 3000 & else echo 'No night mode tool available'; fi"]
|
||||
running: false
|
||||
onExited: (exitCode) => {
|
||||
@@ -541,14 +584,17 @@ ScrollView {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Process {
|
||||
id: nightModeDisableProcess
|
||||
|
||||
command: ["bash", "-c", "pkill wlsunset; pkill redshift; if command -v wlsunset > /dev/null; then wlsunset -t 6500 -T 6500 & sleep 1; pkill wlsunset; elif command -v redshift > /dev/null; then redshift -P -O 6500; redshift -x; fi"]
|
||||
running: false
|
||||
onExited: (exitCode) => {
|
||||
if (exitCode !== 0)
|
||||
console.warn("Failed to disable night mode");
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -296,18 +296,26 @@ ScrollView {
|
||||
|
||||
StyledText {
|
||||
text: {
|
||||
if (!modelData.lastUsed) return "Never used";
|
||||
if (!modelData.lastUsed)
|
||||
return "Never used";
|
||||
|
||||
var date = new Date(modelData.lastUsed);
|
||||
var now = new Date();
|
||||
var diffMs = now - date;
|
||||
var diffMins = Math.floor(diffMs / (1000 * 60));
|
||||
var diffHours = Math.floor(diffMs / (1000 * 60 * 60));
|
||||
var diffDays = Math.floor(diffMs / (1000 * 60 * 60 * 24));
|
||||
|
||||
if (diffMins < 1) return "Last launched just now";
|
||||
if (diffMins < 60) return "Last launched " + diffMins + " minute" + (diffMins === 1 ? "" : "s") + " ago";
|
||||
if (diffHours < 24) return "Last launched " + diffHours + " hour" + (diffHours === 1 ? "" : "s") + " ago";
|
||||
if (diffDays < 7) return "Last launched " + diffDays + " day" + (diffDays === 1 ? "" : "s") + " ago";
|
||||
if (diffMins < 1)
|
||||
return "Last launched just now";
|
||||
|
||||
if (diffMins < 60)
|
||||
return "Last launched " + diffMins + " minute" + (diffMins === 1 ? "" : "s") + " ago";
|
||||
|
||||
if (diffHours < 24)
|
||||
return "Last launched " + diffHours + " hour" + (diffHours === 1 ? "" : "s") + " ago";
|
||||
|
||||
if (diffDays < 7)
|
||||
return "Last launched " + diffDays + " day" + (diffDays === 1 ? "" : "s") + " ago";
|
||||
|
||||
return "Last launched " + date.toLocaleDateString();
|
||||
}
|
||||
@@ -329,7 +337,8 @@ ScrollView {
|
||||
iconColor: Theme.error
|
||||
hoverColor: Qt.rgba(Theme.error.r, Theme.error.g, Theme.error.b, 0.12)
|
||||
onClicked: {
|
||||
var currentRanking = Object.assign({}, Prefs.appUsageRanking);
|
||||
var currentRanking = Object.assign({
|
||||
}, Prefs.appUsageRanking);
|
||||
delete currentRanking[modelData.id];
|
||||
Prefs.appUsageRanking = currentRanking;
|
||||
Prefs.saveSettings();
|
||||
|
||||
@@ -3,22 +3,26 @@ import QtQuick.Controls
|
||||
import QtQuick.Effects
|
||||
import Quickshell
|
||||
import qs.Common
|
||||
import qs.Modals
|
||||
import qs.Services
|
||||
import qs.Widgets
|
||||
import qs.Modals
|
||||
|
||||
ScrollView {
|
||||
id: personalizationTab
|
||||
|
||||
|
||||
property alias profileBrowser: profileBrowserLoader.item
|
||||
property alias wallpaperBrowser: wallpaperBrowserLoader.item
|
||||
|
||||
contentWidth: availableWidth
|
||||
contentHeight: column.implicitHeight
|
||||
clip: true
|
||||
|
||||
|
||||
Column {
|
||||
id: column
|
||||
|
||||
width: parent.width
|
||||
spacing: Theme.spacingXL
|
||||
|
||||
|
||||
// Profile Section
|
||||
StyledRect {
|
||||
width: parent.width
|
||||
@@ -27,24 +31,25 @@ ScrollView {
|
||||
color: Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, 0.3)
|
||||
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.2)
|
||||
border.width: 1
|
||||
|
||||
|
||||
Column {
|
||||
id: profileSection
|
||||
|
||||
anchors.fill: parent
|
||||
anchors.margins: Theme.spacingL
|
||||
spacing: Theme.spacingM
|
||||
|
||||
|
||||
Row {
|
||||
width: parent.width
|
||||
spacing: Theme.spacingM
|
||||
|
||||
|
||||
DankIcon {
|
||||
name: "person"
|
||||
size: Theme.iconSize
|
||||
color: Theme.primary
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
}
|
||||
|
||||
|
||||
StyledText {
|
||||
text: "Profile Image"
|
||||
font.pixelSize: Theme.fontSizeLarge
|
||||
@@ -52,21 +57,22 @@ ScrollView {
|
||||
color: Theme.surfaceText
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
Row {
|
||||
width: parent.width
|
||||
spacing: Theme.spacingL
|
||||
|
||||
|
||||
// Circular profile image preview
|
||||
Item {
|
||||
id: avatarContainer
|
||||
|
||||
|
||||
property bool hasImage: avatarImageSource.status === Image.Ready
|
||||
|
||||
|
||||
width: 80
|
||||
height: 80
|
||||
|
||||
|
||||
Rectangle {
|
||||
anchors.fill: parent
|
||||
radius: width / 2
|
||||
@@ -75,17 +81,17 @@ ScrollView {
|
||||
border.width: 1
|
||||
visible: parent.hasImage
|
||||
}
|
||||
|
||||
|
||||
Image {
|
||||
id: avatarImageSource
|
||||
|
||||
|
||||
source: {
|
||||
if (Prefs.profileImage === "")
|
||||
return "";
|
||||
|
||||
|
||||
if (Prefs.profileImage.startsWith("/"))
|
||||
return "file://" + Prefs.profileImage;
|
||||
|
||||
|
||||
return Prefs.profileImage;
|
||||
}
|
||||
smooth: true
|
||||
@@ -94,7 +100,7 @@ ScrollView {
|
||||
cache: true
|
||||
visible: false
|
||||
}
|
||||
|
||||
|
||||
MultiEffect {
|
||||
anchors.fill: parent
|
||||
anchors.margins: 5
|
||||
@@ -105,38 +111,40 @@ ScrollView {
|
||||
maskThresholdMin: 0.5
|
||||
maskSpreadAtMin: 1
|
||||
}
|
||||
|
||||
|
||||
Item {
|
||||
id: settingsCircularMask
|
||||
|
||||
|
||||
width: 70
|
||||
height: 70
|
||||
layer.enabled: true
|
||||
layer.smooth: true
|
||||
visible: false
|
||||
|
||||
|
||||
Rectangle {
|
||||
anchors.fill: parent
|
||||
radius: width / 2
|
||||
color: "black"
|
||||
antialiasing: true
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
Rectangle {
|
||||
anchors.fill: parent
|
||||
radius: width / 2
|
||||
color: Theme.primary
|
||||
visible: !parent.hasImage
|
||||
|
||||
|
||||
DankIcon {
|
||||
anchors.centerIn: parent
|
||||
name: "person"
|
||||
size: Theme.iconSizeLarge + 8
|
||||
color: Theme.primaryText
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
DankIcon {
|
||||
anchors.centerIn: parent
|
||||
name: "warning"
|
||||
@@ -144,13 +152,14 @@ ScrollView {
|
||||
color: Theme.error
|
||||
visible: Prefs.profileImage !== "" && avatarImageSource.status === Image.Error
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
Column {
|
||||
width: parent.width - 80 - Theme.spacingL
|
||||
spacing: Theme.spacingS
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
|
||||
|
||||
StyledText {
|
||||
text: Prefs.profileImage ? Prefs.profileImage.split('/').pop() : "No profile image selected"
|
||||
font.pixelSize: Theme.fontSizeLarge
|
||||
@@ -158,7 +167,7 @@ ScrollView {
|
||||
elide: Text.ElideMiddle
|
||||
width: parent.width
|
||||
}
|
||||
|
||||
|
||||
StyledText {
|
||||
text: Prefs.profileImage ? Prefs.profileImage : ""
|
||||
font.pixelSize: Theme.fontSizeSmall
|
||||
@@ -167,35 +176,36 @@ ScrollView {
|
||||
width: parent.width
|
||||
visible: Prefs.profileImage !== ""
|
||||
}
|
||||
|
||||
|
||||
Row {
|
||||
spacing: Theme.spacingS
|
||||
|
||||
|
||||
StyledRect {
|
||||
width: 100
|
||||
height: 32
|
||||
radius: Theme.cornerRadius
|
||||
color: Theme.primary
|
||||
|
||||
|
||||
Row {
|
||||
anchors.centerIn: parent
|
||||
spacing: Theme.spacingXS
|
||||
|
||||
|
||||
DankIcon {
|
||||
name: "folder_open"
|
||||
size: Theme.iconSizeSmall
|
||||
color: Theme.primaryText
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
}
|
||||
|
||||
|
||||
StyledText {
|
||||
text: "Browse"
|
||||
color: Theme.primaryText
|
||||
font.pixelSize: Theme.fontSizeSmall
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
cursorShape: Qt.PointingHandCursor
|
||||
@@ -204,34 +214,36 @@ ScrollView {
|
||||
profileBrowser.visible = true;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
StyledRect {
|
||||
width: 80
|
||||
height: 32
|
||||
radius: Theme.cornerRadius
|
||||
color: Theme.surfaceVariant
|
||||
opacity: Prefs.profileImage !== "" ? 1.0 : 0.5
|
||||
|
||||
opacity: Prefs.profileImage !== "" ? 1 : 0.5
|
||||
|
||||
Row {
|
||||
anchors.centerIn: parent
|
||||
spacing: Theme.spacingXS
|
||||
|
||||
|
||||
DankIcon {
|
||||
name: "clear"
|
||||
size: Theme.iconSizeSmall
|
||||
color: Theme.surfaceVariantText
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
}
|
||||
|
||||
|
||||
StyledText {
|
||||
text: "Clear"
|
||||
color: Theme.surfaceVariantText
|
||||
font.pixelSize: Theme.fontSizeSmall
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
enabled: Prefs.profileImage !== ""
|
||||
@@ -240,13 +252,19 @@ ScrollView {
|
||||
Prefs.setProfileImage("");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
// Wallpaper Section
|
||||
StyledRect {
|
||||
width: parent.width
|
||||
@@ -255,24 +273,25 @@ ScrollView {
|
||||
color: Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, 0.3)
|
||||
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.2)
|
||||
border.width: 1
|
||||
|
||||
|
||||
Column {
|
||||
id: wallpaperSection
|
||||
|
||||
anchors.fill: parent
|
||||
anchors.margins: Theme.spacingL
|
||||
spacing: Theme.spacingM
|
||||
|
||||
|
||||
Row {
|
||||
width: parent.width
|
||||
spacing: Theme.spacingM
|
||||
|
||||
|
||||
DankIcon {
|
||||
name: "wallpaper"
|
||||
size: Theme.iconSize
|
||||
color: Theme.primary
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
}
|
||||
|
||||
|
||||
StyledText {
|
||||
text: "Wallpaper"
|
||||
font.pixelSize: Theme.fontSizeLarge
|
||||
@@ -280,12 +299,13 @@ ScrollView {
|
||||
color: Theme.surfaceText
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
Row {
|
||||
width: parent.width
|
||||
spacing: Theme.spacingL
|
||||
|
||||
|
||||
// Wallpaper Preview
|
||||
StyledRect {
|
||||
width: 160
|
||||
@@ -294,7 +314,7 @@ ScrollView {
|
||||
color: Theme.surfaceVariant
|
||||
border.color: Theme.outline
|
||||
border.width: 1
|
||||
|
||||
|
||||
CachingImage {
|
||||
anchors.fill: parent
|
||||
anchors.margins: 1
|
||||
@@ -303,16 +323,19 @@ ScrollView {
|
||||
visible: Prefs.wallpaperPath !== ""
|
||||
maxCacheSize: 160
|
||||
layer.enabled: true
|
||||
|
||||
layer.effect: MultiEffect {
|
||||
maskEnabled: true
|
||||
maskSource: wallpaperMask
|
||||
maskThresholdMin: 0.5
|
||||
maskSpreadAtMin: 1.0
|
||||
maskSpreadAtMin: 1
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
Rectangle {
|
||||
id: wallpaperMask
|
||||
|
||||
anchors.fill: parent
|
||||
anchors.margins: 1
|
||||
radius: Theme.cornerRadius - 1
|
||||
@@ -320,7 +343,7 @@ ScrollView {
|
||||
visible: false
|
||||
layer.enabled: true
|
||||
}
|
||||
|
||||
|
||||
DankIcon {
|
||||
anchors.centerIn: parent
|
||||
name: "image"
|
||||
@@ -328,13 +351,14 @@ ScrollView {
|
||||
color: Theme.surfaceVariantText
|
||||
visible: Prefs.wallpaperPath === ""
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
Column {
|
||||
width: parent.width - 160 - Theme.spacingL
|
||||
spacing: Theme.spacingS
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
|
||||
|
||||
StyledText {
|
||||
text: Prefs.wallpaperPath ? Prefs.wallpaperPath.split('/').pop() : "No wallpaper selected"
|
||||
font.pixelSize: Theme.fontSizeLarge
|
||||
@@ -342,7 +366,7 @@ ScrollView {
|
||||
elide: Text.ElideMiddle
|
||||
width: parent.width
|
||||
}
|
||||
|
||||
|
||||
StyledText {
|
||||
text: Prefs.wallpaperPath ? Prefs.wallpaperPath : ""
|
||||
font.pixelSize: Theme.fontSizeSmall
|
||||
@@ -351,35 +375,36 @@ ScrollView {
|
||||
width: parent.width
|
||||
visible: Prefs.wallpaperPath !== ""
|
||||
}
|
||||
|
||||
|
||||
Row {
|
||||
spacing: Theme.spacingS
|
||||
|
||||
|
||||
StyledRect {
|
||||
width: 100
|
||||
height: 32
|
||||
radius: Theme.cornerRadius
|
||||
color: Theme.primary
|
||||
|
||||
|
||||
Row {
|
||||
anchors.centerIn: parent
|
||||
spacing: Theme.spacingXS
|
||||
|
||||
|
||||
DankIcon {
|
||||
name: "folder_open"
|
||||
size: Theme.iconSizeSmall
|
||||
color: Theme.primaryText
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
}
|
||||
|
||||
|
||||
StyledText {
|
||||
text: "Browse"
|
||||
color: Theme.primaryText
|
||||
font.pixelSize: Theme.fontSizeSmall
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
cursorShape: Qt.PointingHandCursor
|
||||
@@ -388,34 +413,36 @@ ScrollView {
|
||||
wallpaperBrowser.visible = true;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
StyledRect {
|
||||
width: 80
|
||||
height: 32
|
||||
radius: Theme.cornerRadius
|
||||
color: Theme.surfaceVariant
|
||||
opacity: Prefs.wallpaperPath !== "" ? 1.0 : 0.5
|
||||
|
||||
opacity: Prefs.wallpaperPath !== "" ? 1 : 0.5
|
||||
|
||||
Row {
|
||||
anchors.centerIn: parent
|
||||
spacing: Theme.spacingXS
|
||||
|
||||
|
||||
DankIcon {
|
||||
name: "clear"
|
||||
size: Theme.iconSizeSmall
|
||||
color: Theme.surfaceVariantText
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
}
|
||||
|
||||
|
||||
StyledText {
|
||||
text: "Clear"
|
||||
color: Theme.surfaceVariantText
|
||||
font.pixelSize: Theme.fontSizeSmall
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
enabled: Prefs.wallpaperPath !== ""
|
||||
@@ -424,13 +451,19 @@ ScrollView {
|
||||
Prefs.setWallpaperPath("");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
// Dynamic Theming Section
|
||||
StyledRect {
|
||||
width: parent.width
|
||||
@@ -439,36 +472,37 @@ ScrollView {
|
||||
color: Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, 0.3)
|
||||
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.2)
|
||||
border.width: 1
|
||||
|
||||
|
||||
Column {
|
||||
id: dynamicThemeSection
|
||||
|
||||
anchors.fill: parent
|
||||
anchors.margins: Theme.spacingL
|
||||
spacing: Theme.spacingM
|
||||
|
||||
|
||||
Row {
|
||||
width: parent.width
|
||||
spacing: Theme.spacingM
|
||||
|
||||
|
||||
DankIcon {
|
||||
name: "palette"
|
||||
size: Theme.iconSize
|
||||
color: Theme.primary
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
}
|
||||
|
||||
|
||||
Column {
|
||||
width: parent.width - Theme.iconSize - Theme.spacingM - toggle.width - Theme.spacingM
|
||||
spacing: Theme.spacingXS
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
|
||||
|
||||
StyledText {
|
||||
text: "Dynamic Theming"
|
||||
font.pixelSize: Theme.fontSizeLarge
|
||||
font.weight: Font.Medium
|
||||
color: Theme.surfaceText
|
||||
}
|
||||
|
||||
|
||||
StyledText {
|
||||
text: "Automatically extract colors from wallpaper"
|
||||
font.pixelSize: Theme.fontSizeSmall
|
||||
@@ -476,23 +510,25 @@ ScrollView {
|
||||
wrapMode: Text.WordWrap
|
||||
width: parent.width
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
DankToggle {
|
||||
id: toggle
|
||||
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
checked: Theme.isDynamicTheme
|
||||
enabled: ToastService.wallpaperErrorStatus !== "matugen_missing"
|
||||
onToggled: (toggled) => {
|
||||
if (toggled) {
|
||||
Theme.switchTheme(10, true)
|
||||
} else {
|
||||
Theme.switchTheme(0)
|
||||
}
|
||||
if (toggled)
|
||||
Theme.switchTheme(10, true);
|
||||
else
|
||||
Theme.switchTheme(0);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
StyledText {
|
||||
text: "matugen not detected - dynamic theming unavailable"
|
||||
font.pixelSize: Theme.fontSizeSmall
|
||||
@@ -501,16 +537,21 @@ ScrollView {
|
||||
width: parent.width
|
||||
leftPadding: Theme.iconSize + Theme.spacingM
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
LazyLoader {
|
||||
id: profileBrowserLoader
|
||||
|
||||
active: false
|
||||
|
||||
|
||||
FileBrowserModal {
|
||||
id: profileBrowser
|
||||
|
||||
browserTitle: "Select Profile Image"
|
||||
browserIcon: "person"
|
||||
browserType: "profile"
|
||||
@@ -520,14 +561,17 @@ ScrollView {
|
||||
visible = false;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
LazyLoader {
|
||||
id: wallpaperBrowserLoader
|
||||
|
||||
active: false
|
||||
|
||||
|
||||
FileBrowserModal {
|
||||
id: wallpaperBrowser
|
||||
|
||||
browserTitle: "Select Wallpaper"
|
||||
browserIcon: "wallpaper"
|
||||
browserType: "wallpaper"
|
||||
@@ -537,8 +581,7 @@ ScrollView {
|
||||
visible = false;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
property alias profileBrowser: profileBrowserLoader.item
|
||||
property alias wallpaperBrowser: wallpaperBrowserLoader.item
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -16,6 +16,11 @@ Column {
|
||||
|
||||
width: parent.width
|
||||
spacing: expanded ? Theme.spacingM : 0
|
||||
Component.onCompleted: {
|
||||
if (!collapsible)
|
||||
expanded = true;
|
||||
|
||||
}
|
||||
|
||||
// Section header
|
||||
MouseArea {
|
||||
@@ -23,7 +28,12 @@ Column {
|
||||
height: headerRow.height
|
||||
enabled: collapsible
|
||||
hoverEnabled: collapsible
|
||||
|
||||
onClicked: {
|
||||
if (collapsible)
|
||||
expanded = !expanded;
|
||||
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
anchors.fill: parent
|
||||
color: parent.containsMouse ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.08) : "transparent"
|
||||
@@ -32,7 +42,7 @@ Column {
|
||||
|
||||
Row {
|
||||
id: headerRow
|
||||
|
||||
|
||||
width: parent.width
|
||||
spacing: Theme.spacingS
|
||||
topPadding: Theme.spacingS
|
||||
@@ -43,14 +53,16 @@ Column {
|
||||
size: Theme.iconSize - 2
|
||||
color: Theme.primary
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
|
||||
|
||||
Behavior on rotation {
|
||||
NumberAnimation {
|
||||
duration: Appearance.anim.durations.fast
|
||||
easing.type: Easing.BezierSpline
|
||||
easing.bezierCurve: Appearance.anim.curves.standard
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
DankIcon {
|
||||
@@ -68,13 +80,9 @@ Column {
|
||||
font.weight: Font.Medium
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
onClicked: {
|
||||
if (collapsible) {
|
||||
expanded = !expanded
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Divider
|
||||
@@ -93,21 +101,17 @@ Column {
|
||||
active: lazyLoad ? expanded || !collapsible : true
|
||||
visible: expanded || !collapsible
|
||||
asynchronous: true
|
||||
|
||||
opacity: visible ? 1 : 0
|
||||
|
||||
Behavior on opacity {
|
||||
NumberAnimation {
|
||||
duration: Appearance.anim.durations.normal
|
||||
easing.type: Easing.BezierSpline
|
||||
easing.bezierCurve: Appearance.anim.curves.standard
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
opacity: visible ? 1 : 0
|
||||
|
||||
}
|
||||
|
||||
Component.onCompleted: {
|
||||
if (!collapsible) {
|
||||
expanded = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,16 +5,17 @@ import qs.Widgets
|
||||
|
||||
ScrollView {
|
||||
id: timeWeatherTab
|
||||
|
||||
|
||||
contentWidth: availableWidth
|
||||
contentHeight: column.implicitHeight
|
||||
clip: true
|
||||
|
||||
|
||||
Column {
|
||||
id: column
|
||||
|
||||
width: parent.width
|
||||
spacing: Theme.spacingXL
|
||||
|
||||
|
||||
// Time Settings Section
|
||||
StyledRect {
|
||||
width: parent.width
|
||||
@@ -23,24 +24,25 @@ ScrollView {
|
||||
color: Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, 0.3)
|
||||
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.2)
|
||||
border.width: 1
|
||||
|
||||
|
||||
Column {
|
||||
id: timeSection
|
||||
|
||||
anchors.fill: parent
|
||||
anchors.margins: Theme.spacingL
|
||||
spacing: Theme.spacingM
|
||||
|
||||
|
||||
Row {
|
||||
width: parent.width
|
||||
spacing: Theme.spacingM
|
||||
|
||||
|
||||
DankIcon {
|
||||
name: "schedule"
|
||||
size: Theme.iconSize
|
||||
color: Theme.primary
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
}
|
||||
|
||||
|
||||
StyledText {
|
||||
text: "Time Format"
|
||||
font.pixelSize: Theme.fontSizeLarge
|
||||
@@ -48,8 +50,9 @@ ScrollView {
|
||||
color: Theme.surfaceText
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
DankToggle {
|
||||
width: parent.width
|
||||
text: "24-Hour Format"
|
||||
@@ -59,9 +62,11 @@ ScrollView {
|
||||
return Prefs.setClockFormat(checked);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
// Weather Settings Section
|
||||
StyledRect {
|
||||
width: parent.width
|
||||
@@ -70,24 +75,25 @@ ScrollView {
|
||||
color: Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, 0.3)
|
||||
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.2)
|
||||
border.width: 1
|
||||
|
||||
|
||||
Column {
|
||||
id: weatherSection
|
||||
|
||||
anchors.fill: parent
|
||||
anchors.margins: Theme.spacingL
|
||||
spacing: Theme.spacingM
|
||||
|
||||
|
||||
Row {
|
||||
width: parent.width
|
||||
spacing: Theme.spacingM
|
||||
|
||||
|
||||
DankIcon {
|
||||
name: "cloud"
|
||||
size: Theme.iconSize
|
||||
color: Theme.primary
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
}
|
||||
|
||||
|
||||
StyledText {
|
||||
text: "Weather"
|
||||
font.pixelSize: Theme.fontSizeLarge
|
||||
@@ -95,8 +101,9 @@ ScrollView {
|
||||
color: Theme.surfaceText
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
DankToggle {
|
||||
width: parent.width
|
||||
text: "Fahrenheit"
|
||||
@@ -106,7 +113,7 @@ ScrollView {
|
||||
return Prefs.setTemperatureUnit(checked);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
DankToggle {
|
||||
width: parent.width
|
||||
text: "Override Location"
|
||||
@@ -116,21 +123,21 @@ ScrollView {
|
||||
return Prefs.setWeatherLocationOverrideEnabled(checked);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Location input - only visible when override is enabled
|
||||
Column {
|
||||
width: parent.width
|
||||
spacing: Theme.spacingS
|
||||
visible: Prefs.weatherLocationOverrideEnabled
|
||||
opacity: visible ? 1 : 0
|
||||
|
||||
|
||||
StyledText {
|
||||
text: "Location"
|
||||
font.pixelSize: Theme.fontSizeMedium
|
||||
color: Theme.surfaceText
|
||||
font.weight: Font.Medium
|
||||
}
|
||||
|
||||
|
||||
DankLocationSearch {
|
||||
width: parent.width
|
||||
currentLocation: Prefs.weatherLocationOverride
|
||||
@@ -139,7 +146,7 @@ ScrollView {
|
||||
Prefs.setWeatherLocationOverride(coordinates);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
StyledText {
|
||||
text: "Examples: \"New York\", \"Tokyo\", \"90210\""
|
||||
font.pixelSize: Theme.fontSizeSmall
|
||||
@@ -147,15 +154,21 @@ ScrollView {
|
||||
wrapMode: Text.WordWrap
|
||||
width: parent.width
|
||||
}
|
||||
|
||||
|
||||
Behavior on opacity {
|
||||
NumberAnimation {
|
||||
duration: Theme.mediumDuration
|
||||
easing.type: Theme.emphasizedEasing
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -5,18 +5,19 @@ import qs.Widgets
|
||||
|
||||
ScrollView {
|
||||
id: widgetsTab
|
||||
|
||||
|
||||
contentWidth: availableWidth
|
||||
contentHeight: column.implicitHeight + Theme.spacingXL
|
||||
clip: true
|
||||
|
||||
|
||||
Column {
|
||||
id: column
|
||||
|
||||
width: parent.width
|
||||
spacing: Theme.spacingXL
|
||||
topPadding: Theme.spacingL
|
||||
bottomPadding: Theme.spacingXL
|
||||
|
||||
|
||||
// Top Bar Widgets Section
|
||||
StyledRect {
|
||||
width: parent.width
|
||||
@@ -25,24 +26,25 @@ ScrollView {
|
||||
color: Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, 0.3)
|
||||
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.2)
|
||||
border.width: 1
|
||||
|
||||
|
||||
Column {
|
||||
id: topBarSection
|
||||
|
||||
anchors.fill: parent
|
||||
anchors.margins: Theme.spacingL
|
||||
spacing: Theme.spacingM
|
||||
|
||||
|
||||
Row {
|
||||
width: parent.width
|
||||
spacing: Theme.spacingM
|
||||
|
||||
|
||||
DankIcon {
|
||||
name: "widgets"
|
||||
size: Theme.iconSize
|
||||
color: Theme.primary
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
}
|
||||
|
||||
|
||||
StyledText {
|
||||
text: "Top Bar Widgets"
|
||||
font.pixelSize: Theme.fontSizeLarge
|
||||
@@ -50,8 +52,9 @@ ScrollView {
|
||||
color: Theme.surfaceText
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
DankToggle {
|
||||
width: parent.width
|
||||
text: "Focused Window"
|
||||
@@ -61,7 +64,7 @@ ScrollView {
|
||||
return Prefs.setShowFocusedWindow(checked);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
DankToggle {
|
||||
width: parent.width
|
||||
text: "Weather Widget"
|
||||
@@ -71,7 +74,7 @@ ScrollView {
|
||||
return Prefs.setShowWeather(checked);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
DankToggle {
|
||||
width: parent.width
|
||||
text: "Media Controls"
|
||||
@@ -81,7 +84,7 @@ ScrollView {
|
||||
return Prefs.setShowMusic(checked);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
DankToggle {
|
||||
width: parent.width
|
||||
text: "Clipboard Button"
|
||||
@@ -91,7 +94,7 @@ ScrollView {
|
||||
return Prefs.setShowClipboard(checked);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
DankToggle {
|
||||
width: parent.width
|
||||
text: "System Resources"
|
||||
@@ -101,7 +104,7 @@ ScrollView {
|
||||
return Prefs.setShowSystemResources(checked);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
DankToggle {
|
||||
width: parent.width
|
||||
text: "System Tray"
|
||||
@@ -111,9 +114,11 @@ ScrollView {
|
||||
return Prefs.setShowSystemTray(checked);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
// Workspace Section
|
||||
StyledRect {
|
||||
width: parent.width
|
||||
@@ -122,24 +127,25 @@ ScrollView {
|
||||
color: Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, 0.3)
|
||||
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.2)
|
||||
border.width: 1
|
||||
|
||||
|
||||
Column {
|
||||
id: workspaceSection
|
||||
|
||||
anchors.fill: parent
|
||||
anchors.margins: Theme.spacingL
|
||||
spacing: Theme.spacingM
|
||||
|
||||
|
||||
Row {
|
||||
width: parent.width
|
||||
spacing: Theme.spacingM
|
||||
|
||||
|
||||
DankIcon {
|
||||
name: "view_module"
|
||||
size: Theme.iconSize
|
||||
color: Theme.primary
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
}
|
||||
|
||||
|
||||
StyledText {
|
||||
text: "Workspace Settings"
|
||||
font.pixelSize: Theme.fontSizeLarge
|
||||
@@ -147,8 +153,9 @@ ScrollView {
|
||||
color: Theme.surfaceText
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
DankToggle {
|
||||
width: parent.width
|
||||
text: "Workspace Index Numbers"
|
||||
@@ -158,7 +165,7 @@ ScrollView {
|
||||
return Prefs.setShowWorkspaceIndex(checked);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
DankToggle {
|
||||
width: parent.width
|
||||
text: "Workspace Padding"
|
||||
@@ -168,7 +175,11 @@ ScrollView {
|
||||
return Prefs.setShowWorkspacePadding(checked);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -115,12 +115,12 @@ PanelWindow {
|
||||
readonly property int availableWidth: width
|
||||
// Use estimated fixed widths to break circular dependencies
|
||||
readonly property int launcherButtonWidth: 40
|
||||
readonly property int workspaceSwitcherWidth: 120 // Approximate
|
||||
readonly property int workspaceSwitcherWidth: 120 // Approximate
|
||||
readonly property int focusedAppMaxWidth: focusedApp.visible ? 456 : 0
|
||||
readonly property int estimatedLeftSectionWidth: launcherButtonWidth + workspaceSwitcherWidth + focusedAppMaxWidth + (Theme.spacingXS * 2)
|
||||
readonly property int rightSectionWidth: rightSection.width
|
||||
readonly property int clockWidth: clock.width
|
||||
readonly property int mediaMaxWidth: media.visible ? 280 : 0 // Normal max width
|
||||
readonly property int mediaMaxWidth: media.visible ? 280 : 0 // Normal max width
|
||||
readonly property int weatherWidth: weather.visible ? weather.width : 0
|
||||
readonly property bool validLayout: availableWidth > 100 && estimatedLeftSectionWidth > 0 && rightSectionWidth > 0
|
||||
readonly property int clockLeftEdge: (availableWidth - clockWidth) / 2
|
||||
|
||||
Reference in New Issue
Block a user