mirror of
https://github.com/AvengeMedia/DankMaterialShell.git
synced 2026-01-24 21:42:51 -05:00
qmlfmt with 4 space
This commit is contained in:
@@ -21,123 +21,124 @@ DankModal {
|
||||
property Component clipboardContent
|
||||
|
||||
function updateFilteredModel() {
|
||||
filteredClipboardModel.clear();
|
||||
filteredClipboardModel.clear()
|
||||
for (var i = 0; i < clipboardModel.count; i++) {
|
||||
const entry = clipboardModel.get(i).entry;
|
||||
const entry = clipboardModel.get(i).entry
|
||||
if (searchText.trim().length === 0) {
|
||||
filteredClipboardModel.append({
|
||||
"entry": entry
|
||||
});
|
||||
"entry": entry
|
||||
})
|
||||
} else {
|
||||
const content = getEntryPreview(entry).toLowerCase();
|
||||
const content = getEntryPreview(entry).toLowerCase()
|
||||
if (content.includes(searchText.toLowerCase()))
|
||||
filteredClipboardModel.append({
|
||||
"entry": entry
|
||||
});
|
||||
|
||||
"entry": entry
|
||||
})
|
||||
}
|
||||
}
|
||||
clipboardHistoryModal.totalCount = filteredClipboardModel.count;
|
||||
clipboardHistoryModal.totalCount = filteredClipboardModel.count
|
||||
// Clamp selectedIndex to valid range
|
||||
if (filteredClipboardModel.count === 0) {
|
||||
keyboardNavigationActive = false;
|
||||
selectedIndex = 0;
|
||||
keyboardNavigationActive = false
|
||||
selectedIndex = 0
|
||||
} else if (selectedIndex >= filteredClipboardModel.count) {
|
||||
selectedIndex = filteredClipboardModel.count - 1;
|
||||
selectedIndex = filteredClipboardModel.count - 1
|
||||
}
|
||||
}
|
||||
|
||||
function toggle() {
|
||||
if (shouldBeVisible)
|
||||
hide();
|
||||
hide()
|
||||
else
|
||||
show();
|
||||
show()
|
||||
}
|
||||
|
||||
function show() {
|
||||
open();
|
||||
clipboardHistoryModal.searchText = "";
|
||||
|
||||
initializeThumbnailSystem();
|
||||
refreshClipboard();
|
||||
keyboardController.reset();
|
||||
|
||||
Qt.callLater(function() {
|
||||
open()
|
||||
clipboardHistoryModal.searchText = ""
|
||||
|
||||
initializeThumbnailSystem()
|
||||
refreshClipboard()
|
||||
keyboardController.reset()
|
||||
|
||||
Qt.callLater(function () {
|
||||
if (contentLoader.item && contentLoader.item.searchField) {
|
||||
contentLoader.item.searchField.text = "";
|
||||
contentLoader.item.searchField.forceActiveFocus();
|
||||
contentLoader.item.searchField.text = ""
|
||||
contentLoader.item.searchField.forceActiveFocus()
|
||||
}
|
||||
});
|
||||
})
|
||||
}
|
||||
|
||||
function hide() {
|
||||
close();
|
||||
clipboardHistoryModal.searchText = "";
|
||||
|
||||
updateFilteredModel();
|
||||
keyboardController.reset();
|
||||
cleanupTempFiles();
|
||||
close()
|
||||
clipboardHistoryModal.searchText = ""
|
||||
|
||||
updateFilteredModel()
|
||||
keyboardController.reset()
|
||||
cleanupTempFiles()
|
||||
}
|
||||
|
||||
function initializeThumbnailSystem() {
|
||||
}
|
||||
function initializeThumbnailSystem() {}
|
||||
|
||||
function cleanupTempFiles() {
|
||||
Quickshell.execDetached(["sh", "-c", "rm -f /tmp/clipboard_*.png"]);
|
||||
Quickshell.execDetached(["sh", "-c", "rm -f /tmp/clipboard_*.png"])
|
||||
}
|
||||
|
||||
function generateThumbnails() {
|
||||
}
|
||||
function generateThumbnails() {}
|
||||
|
||||
function refreshClipboard() {
|
||||
clipboardProcess.running = true;
|
||||
clipboardProcess.running = true
|
||||
}
|
||||
|
||||
function copyEntry(entry) {
|
||||
const entryId = entry.split('\t')[0];
|
||||
Quickshell.execDetached(["sh", "-c", `cliphist decode ${entryId} | wl-copy`]);
|
||||
ToastService.showInfo("Copied to clipboard");
|
||||
hide();
|
||||
const entryId = entry.split('\t')[0]
|
||||
Quickshell.execDetached(
|
||||
["sh", "-c", `cliphist decode ${entryId} | wl-copy`])
|
||||
ToastService.showInfo("Copied to clipboard")
|
||||
hide()
|
||||
}
|
||||
|
||||
function deleteEntry(entry) {
|
||||
deleteProcess.deletedEntry = entry;
|
||||
deleteProcess.deletedEntry = entry
|
||||
deleteProcess.command = ["sh", "-c", `echo '${entry.replace(
|
||||
/'/g, "'\\''")}' | cliphist delete`];
|
||||
deleteProcess.running = true;
|
||||
/'/g, "'\\''")}' | cliphist delete`]
|
||||
deleteProcess.running = true
|
||||
}
|
||||
|
||||
function clearAll() {
|
||||
clearProcess.running = true;
|
||||
clearProcess.running = true
|
||||
}
|
||||
|
||||
function getEntryPreview(entry) {
|
||||
let content = entry.replace(/^\s*\d+\s+/, "");
|
||||
if (content.includes("image/") || content.includes("binary data") || /\.(png|jpg|jpeg|gif|bmp|webp)/i.test(content)) {
|
||||
const dimensionMatch = content.match(/(\d+)x(\d+)/);
|
||||
let content = entry.replace(/^\s*\d+\s+/, "")
|
||||
if (content.includes("image/") || content.includes("binary data")
|
||||
|| /\.(png|jpg|jpeg|gif|bmp|webp)/i.test(content)) {
|
||||
const dimensionMatch = content.match(/(\d+)x(\d+)/)
|
||||
if (dimensionMatch)
|
||||
return `Image ${dimensionMatch[1]}×${dimensionMatch[2]}`;
|
||||
return `Image ${dimensionMatch[1]}×${dimensionMatch[2]}`
|
||||
|
||||
const typeMatch = content.match(/\b(png|jpg|jpeg|gif|bmp|webp)\b/i);
|
||||
const typeMatch = content.match(/\b(png|jpg|jpeg|gif|bmp|webp)\b/i)
|
||||
if (typeMatch)
|
||||
return `Image (${typeMatch[1].toUpperCase()})`;
|
||||
return `Image (${typeMatch[1].toUpperCase()})`
|
||||
|
||||
return "Image";
|
||||
return "Image"
|
||||
}
|
||||
if (content.length > 100)
|
||||
return content.substring(0, 100) + "...";
|
||||
return content.substring(0, 100) + "..."
|
||||
|
||||
return content;
|
||||
return content
|
||||
}
|
||||
|
||||
function getEntryType(entry) {
|
||||
if (entry.includes("image/") || entry.includes("binary data") || /\.(png|jpg|jpeg|gif|bmp|webp)/i.test(entry) || /\b(png|jpg|jpeg|gif|bmp|webp)\b/i.test(entry))
|
||||
return "image";
|
||||
if (entry.includes("image/") || entry.includes("binary data")
|
||||
|| /\.(png|jpg|jpeg|gif|bmp|webp)/i.test(entry)
|
||||
|| /\b(png|jpg|jpeg|gif|bmp|webp)\b/i.test(entry))
|
||||
return "image"
|
||||
|
||||
if (entry.length > 200)
|
||||
return "long_text";
|
||||
return "long_text"
|
||||
|
||||
return "text";
|
||||
return "text"
|
||||
}
|
||||
|
||||
visible: false
|
||||
@@ -149,10 +150,10 @@ DankModal {
|
||||
borderWidth: 1
|
||||
enableShadow: true
|
||||
onBackgroundClicked: {
|
||||
hide();
|
||||
hide()
|
||||
}
|
||||
modalFocusScope.Keys.onPressed: function(event) {
|
||||
keyboardController.handleKey(event);
|
||||
modalFocusScope.Keys.onPressed: function (event) {
|
||||
keyboardController.handleKey(event)
|
||||
}
|
||||
content: clipboardContent
|
||||
|
||||
@@ -160,107 +161,116 @@ DankModal {
|
||||
id: keyboardController
|
||||
|
||||
function reset() {
|
||||
selectedIndex = 0;
|
||||
keyboardNavigationActive = false;
|
||||
showKeyboardHints = false;
|
||||
selectedIndex = 0
|
||||
keyboardNavigationActive = false
|
||||
showKeyboardHints = false
|
||||
if (typeof clipboardListView !== 'undefined' && clipboardListView)
|
||||
clipboardListView.keyboardActive = false;
|
||||
|
||||
clipboardListView.keyboardActive = false
|
||||
}
|
||||
|
||||
function selectNext() {
|
||||
if (filteredClipboardModel.count === 0)
|
||||
return ;
|
||||
return
|
||||
|
||||
keyboardNavigationActive = true;
|
||||
selectedIndex = Math.min(selectedIndex + 1, filteredClipboardModel.count - 1);
|
||||
keyboardNavigationActive = true
|
||||
selectedIndex = Math.min(selectedIndex + 1,
|
||||
filteredClipboardModel.count - 1)
|
||||
}
|
||||
|
||||
function selectPrevious() {
|
||||
if (filteredClipboardModel.count === 0)
|
||||
return ;
|
||||
return
|
||||
|
||||
keyboardNavigationActive = true;
|
||||
selectedIndex = Math.max(selectedIndex - 1, 0);
|
||||
keyboardNavigationActive = true
|
||||
selectedIndex = Math.max(selectedIndex - 1, 0)
|
||||
}
|
||||
|
||||
function copySelected() {
|
||||
if (filteredClipboardModel.count === 0 || selectedIndex < 0 || selectedIndex >= filteredClipboardModel.count)
|
||||
return ;
|
||||
if (filteredClipboardModel.count === 0 || selectedIndex < 0
|
||||
|| selectedIndex >= filteredClipboardModel.count)
|
||||
return
|
||||
|
||||
var selectedEntry = filteredClipboardModel.get(selectedIndex).entry;
|
||||
copyEntry(selectedEntry);
|
||||
var selectedEntry = filteredClipboardModel.get(selectedIndex).entry
|
||||
copyEntry(selectedEntry)
|
||||
}
|
||||
|
||||
function deleteSelected() {
|
||||
if (filteredClipboardModel.count === 0 || selectedIndex < 0 || selectedIndex >= filteredClipboardModel.count)
|
||||
return ;
|
||||
if (filteredClipboardModel.count === 0 || selectedIndex < 0
|
||||
|| selectedIndex >= filteredClipboardModel.count)
|
||||
return
|
||||
|
||||
var selectedEntry = filteredClipboardModel.get(selectedIndex).entry;
|
||||
deleteEntry(selectedEntry);
|
||||
var selectedEntry = filteredClipboardModel.get(selectedIndex).entry
|
||||
deleteEntry(selectedEntry)
|
||||
}
|
||||
|
||||
function handleKey(event) {
|
||||
if (event.key === Qt.Key_Escape) {
|
||||
if (keyboardNavigationActive) {
|
||||
keyboardNavigationActive = false;
|
||||
if (typeof clipboardListView !== 'undefined' && clipboardListView)
|
||||
clipboardListView.keyboardActive = false;
|
||||
keyboardNavigationActive = false
|
||||
if (typeof clipboardListView !== 'undefined'
|
||||
&& clipboardListView)
|
||||
clipboardListView.keyboardActive = false
|
||||
|
||||
event.accepted = true;
|
||||
event.accepted = true
|
||||
} else {
|
||||
hide();
|
||||
event.accepted = true;
|
||||
hide()
|
||||
event.accepted = true
|
||||
}
|
||||
} else if (event.key === Qt.Key_Down) {
|
||||
if (!keyboardNavigationActive) {
|
||||
keyboardNavigationActive = true;
|
||||
selectedIndex = 0;
|
||||
if (typeof clipboardListView !== 'undefined' && clipboardListView)
|
||||
clipboardListView.keyboardActive = true;
|
||||
keyboardNavigationActive = true
|
||||
selectedIndex = 0
|
||||
if (typeof clipboardListView !== 'undefined'
|
||||
&& clipboardListView)
|
||||
clipboardListView.keyboardActive = true
|
||||
|
||||
event.accepted = true;
|
||||
event.accepted = true
|
||||
} else {
|
||||
selectNext();
|
||||
event.accepted = true;
|
||||
selectNext()
|
||||
event.accepted = true
|
||||
}
|
||||
} else if (event.key === Qt.Key_Up) {
|
||||
if (!keyboardNavigationActive) {
|
||||
keyboardNavigationActive = true;
|
||||
selectedIndex = 0;
|
||||
if (typeof clipboardListView !== 'undefined' && clipboardListView)
|
||||
clipboardListView.keyboardActive = true;
|
||||
keyboardNavigationActive = true
|
||||
selectedIndex = 0
|
||||
if (typeof clipboardListView !== 'undefined'
|
||||
&& clipboardListView)
|
||||
clipboardListView.keyboardActive = true
|
||||
|
||||
event.accepted = true;
|
||||
event.accepted = true
|
||||
} else if (selectedIndex === 0) {
|
||||
keyboardNavigationActive = false;
|
||||
if (typeof clipboardListView !== 'undefined' && clipboardListView)
|
||||
clipboardListView.keyboardActive = false;
|
||||
keyboardNavigationActive = false
|
||||
if (typeof clipboardListView !== 'undefined'
|
||||
&& clipboardListView)
|
||||
clipboardListView.keyboardActive = false
|
||||
|
||||
event.accepted = true;
|
||||
event.accepted = true
|
||||
} else {
|
||||
selectPrevious();
|
||||
event.accepted = true;
|
||||
selectPrevious()
|
||||
event.accepted = true
|
||||
}
|
||||
} else if (event.key === Qt.Key_Delete && (event.modifiers & Qt.ShiftModifier)) {
|
||||
clearAll();
|
||||
hide();
|
||||
event.accepted = true;
|
||||
} else if (event.key === Qt.Key_Delete
|
||||
&& (event.modifiers & Qt.ShiftModifier)) {
|
||||
clearAll()
|
||||
hide()
|
||||
event.accepted = true
|
||||
} else if (keyboardNavigationActive) {
|
||||
if ((event.key === Qt.Key_C && (event.modifiers & Qt.ControlModifier)) || event.key === Qt.Key_Return || event.key === Qt.Key_Enter) {
|
||||
copySelected();
|
||||
event.accepted = true;
|
||||
if ((event.key === Qt.Key_C
|
||||
&& (event.modifiers & Qt.ControlModifier))
|
||||
|| event.key === Qt.Key_Return
|
||||
|| event.key === Qt.Key_Enter) {
|
||||
copySelected()
|
||||
event.accepted = true
|
||||
} else if (event.key === Qt.Key_Delete) {
|
||||
deleteSelected();
|
||||
event.accepted = true;
|
||||
deleteSelected()
|
||||
event.accepted = true
|
||||
}
|
||||
}
|
||||
if (event.key === Qt.Key_F10) {
|
||||
showKeyboardHints = !showKeyboardHints;
|
||||
event.accepted = true;
|
||||
showKeyboardHints = !showKeyboardHints
|
||||
event.accepted = true
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
DankModal {
|
||||
@@ -269,8 +279,8 @@ DankModal {
|
||||
visible: showClearConfirmation
|
||||
width: 350
|
||||
height: 150
|
||||
onBackgroundClicked: {
|
||||
showClearConfirmation = false;
|
||||
onBackgroundClicked: {
|
||||
showClearConfirmation = false
|
||||
}
|
||||
|
||||
content: Component {
|
||||
@@ -326,7 +336,6 @@ DankModal {
|
||||
cursorShape: Qt.PointingHandCursor
|
||||
onClicked: showClearConfirmation = false
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
@@ -350,22 +359,16 @@ DankModal {
|
||||
hoverEnabled: true
|
||||
cursorShape: Qt.PointingHandCursor
|
||||
onClicked: {
|
||||
clearAll();
|
||||
showClearConfirmation = false;
|
||||
hide();
|
||||
clearAll()
|
||||
showClearConfirmation = false
|
||||
hide()
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
ListModel {
|
||||
@@ -384,19 +387,17 @@ DankModal {
|
||||
|
||||
stdout: StdioCollector {
|
||||
onStreamFinished: {
|
||||
clipboardModel.clear();
|
||||
const lines = text.trim().split('\n');
|
||||
clipboardModel.clear()
|
||||
const lines = text.trim().split('\n')
|
||||
for (const line of lines) {
|
||||
if (line.trim().length > 0)
|
||||
clipboardModel.append({
|
||||
"entry": line
|
||||
});
|
||||
|
||||
"entry": line
|
||||
})
|
||||
}
|
||||
updateFilteredModel();
|
||||
updateFilteredModel()
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Process {
|
||||
@@ -405,33 +406,35 @@ DankModal {
|
||||
property string deletedEntry: ""
|
||||
|
||||
running: false
|
||||
onExited: (exitCode) => {
|
||||
if (exitCode === 0) {
|
||||
// Just remove the item from models instead of re-fetching everything
|
||||
for (var i = 0; i < clipboardModel.count; i++) {
|
||||
if (clipboardModel.get(i).entry === deleteProcess.deletedEntry) {
|
||||
clipboardModel.remove(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
for (var j = 0; j < filteredClipboardModel.count; j++) {
|
||||
if (filteredClipboardModel.get(j).entry === deleteProcess.deletedEntry) {
|
||||
filteredClipboardModel.remove(j);
|
||||
break;
|
||||
}
|
||||
}
|
||||
clipboardHistoryModal.totalCount = filteredClipboardModel.count;
|
||||
// Clamp selectedIndex to valid range
|
||||
if (filteredClipboardModel.count === 0) {
|
||||
keyboardNavigationActive = false;
|
||||
selectedIndex = 0;
|
||||
} else if (selectedIndex >= filteredClipboardModel.count) {
|
||||
selectedIndex = filteredClipboardModel.count - 1;
|
||||
}
|
||||
} else {
|
||||
console.warn("Failed to delete clipboard entry");
|
||||
}
|
||||
}
|
||||
onExited: exitCode => {
|
||||
if (exitCode === 0) {
|
||||
// Just remove the item from models instead of re-fetching everything
|
||||
for (var i = 0; i < clipboardModel.count; i++) {
|
||||
if (clipboardModel.get(
|
||||
i).entry === deleteProcess.deletedEntry) {
|
||||
clipboardModel.remove(i)
|
||||
break
|
||||
}
|
||||
}
|
||||
for (var j = 0; j < filteredClipboardModel.count; j++) {
|
||||
if (filteredClipboardModel.get(
|
||||
j).entry === deleteProcess.deletedEntry) {
|
||||
filteredClipboardModel.remove(j)
|
||||
break
|
||||
}
|
||||
}
|
||||
clipboardHistoryModal.totalCount = filteredClipboardModel.count
|
||||
// Clamp selectedIndex to valid range
|
||||
if (filteredClipboardModel.count === 0) {
|
||||
keyboardNavigationActive = false
|
||||
selectedIndex = 0
|
||||
} else if (selectedIndex >= filteredClipboardModel.count) {
|
||||
selectedIndex = filteredClipboardModel.count - 1
|
||||
}
|
||||
} else {
|
||||
console.warn("Failed to delete clipboard entry")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Process {
|
||||
@@ -439,30 +442,31 @@ DankModal {
|
||||
|
||||
command: ["cliphist", "wipe"]
|
||||
running: false
|
||||
onExited: (exitCode) => {
|
||||
if (exitCode === 0) {
|
||||
clipboardModel.clear();
|
||||
filteredClipboardModel.clear();
|
||||
totalCount = 0;
|
||||
} else {
|
||||
}
|
||||
}
|
||||
onExited: exitCode => {
|
||||
if (exitCode === 0) {
|
||||
clipboardModel.clear()
|
||||
filteredClipboardModel.clear()
|
||||
totalCount = 0
|
||||
} else {
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
IpcHandler {
|
||||
function open() {
|
||||
clipboardHistoryModal.show();
|
||||
return "CLIPBOARD_OPEN_SUCCESS";
|
||||
clipboardHistoryModal.show()
|
||||
return "CLIPBOARD_OPEN_SUCCESS"
|
||||
}
|
||||
|
||||
function close() {
|
||||
hide();
|
||||
return "CLIPBOARD_CLOSE_SUCCESS";
|
||||
hide()
|
||||
return "CLIPBOARD_CLOSE_SUCCESS"
|
||||
}
|
||||
|
||||
function toggle() {
|
||||
clipboardHistoryModal.toggle();
|
||||
return "CLIPBOARD_TOGGLE_SUCCESS";
|
||||
clipboardHistoryModal.toggle()
|
||||
return "CLIPBOARD_TOGGLE_SUCCESS"
|
||||
}
|
||||
|
||||
target: "clipboard"
|
||||
@@ -472,7 +476,7 @@ DankModal {
|
||||
Item {
|
||||
id: clipboardContent
|
||||
property alias searchField: searchField
|
||||
|
||||
|
||||
anchors.fill: parent
|
||||
|
||||
Column {
|
||||
@@ -504,7 +508,6 @@ DankModal {
|
||||
font.weight: Font.Medium
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Row {
|
||||
@@ -518,7 +521,7 @@ DankModal {
|
||||
iconColor: showKeyboardHints ? Theme.primary : Theme.surfaceText
|
||||
hoverColor: Theme.primaryHover
|
||||
onClicked: {
|
||||
showKeyboardHints = !showKeyboardHints;
|
||||
showKeyboardHints = !showKeyboardHints
|
||||
}
|
||||
}
|
||||
|
||||
@@ -528,7 +531,7 @@ DankModal {
|
||||
iconColor: Theme.error
|
||||
hoverColor: Theme.errorHover
|
||||
onClicked: {
|
||||
showClearConfirmation = true;
|
||||
showClearConfirmation = true
|
||||
}
|
||||
}
|
||||
|
||||
@@ -539,9 +542,7 @@ DankModal {
|
||||
hoverColor: Theme.errorHover
|
||||
onClicked: hide()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
DankTextField {
|
||||
@@ -555,25 +556,25 @@ DankModal {
|
||||
ignoreLeftRightKeys: true
|
||||
keyForwardTargets: [modalFocusScope]
|
||||
onTextChanged: {
|
||||
clipboardHistoryModal.searchText = text;
|
||||
updateFilteredModel();
|
||||
clipboardHistoryModal.searchText = text
|
||||
updateFilteredModel()
|
||||
}
|
||||
Keys.onEscapePressed: function(event) {
|
||||
hide();
|
||||
event.accepted = true;
|
||||
Keys.onEscapePressed: function (event) {
|
||||
hide()
|
||||
event.accepted = true
|
||||
}
|
||||
Component.onCompleted: {
|
||||
Qt.callLater(function() {
|
||||
forceActiveFocus();
|
||||
});
|
||||
Qt.callLater(function () {
|
||||
forceActiveFocus()
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
Connections {
|
||||
target: clipboardHistoryModal
|
||||
function onOpened() {
|
||||
Qt.callLater(function() {
|
||||
searchField.forceActiveFocus();
|
||||
});
|
||||
Qt.callLater(function () {
|
||||
searchField.forceActiveFocus()
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -592,15 +593,15 @@ DankModal {
|
||||
|
||||
function ensureVisible(index) {
|
||||
if (index < 0 || index >= count)
|
||||
return ;
|
||||
return
|
||||
|
||||
var itemHeight = 72 + spacing;
|
||||
var itemY = index * itemHeight;
|
||||
var itemBottom = itemY + itemHeight;
|
||||
var itemHeight = 72 + spacing
|
||||
var itemY = index * itemHeight
|
||||
var itemBottom = itemY + itemHeight
|
||||
if (itemY < contentY)
|
||||
contentY = itemY;
|
||||
contentY = itemY
|
||||
else if (itemBottom > contentY + height)
|
||||
contentY = itemBottom - height;
|
||||
contentY = itemBottom - height
|
||||
}
|
||||
|
||||
anchors.fill: parent
|
||||
@@ -618,8 +619,7 @@ DankModal {
|
||||
flickableDirection: Flickable.VerticalFlick
|
||||
onCurrentIndexChanged: {
|
||||
if (keyboardNavigationActive && currentIndex >= 0)
|
||||
ensureVisible(currentIndex);
|
||||
|
||||
ensureVisible(currentIndex)
|
||||
}
|
||||
|
||||
StyledText {
|
||||
@@ -640,7 +640,8 @@ DankModal {
|
||||
|
||||
delegate: Rectangle {
|
||||
property string entryType: getEntryType(model.entry)
|
||||
property string entryPreview: getEntryPreview(model.entry)
|
||||
property string entryPreview: getEntryPreview(
|
||||
model.entry)
|
||||
property int entryIndex: index + 1
|
||||
property string entryData: model.entry
|
||||
property alias thumbnailImageSource: thumbnailImageSource
|
||||
@@ -649,18 +650,25 @@ DankModal {
|
||||
height: 72
|
||||
radius: Theme.cornerRadius
|
||||
color: {
|
||||
if (keyboardNavigationActive && index === selectedIndex)
|
||||
return Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, 0.2);
|
||||
if (keyboardNavigationActive
|
||||
&& index === selectedIndex)
|
||||
return Qt.rgba(Theme.surfaceVariant.r,
|
||||
Theme.surfaceVariant.g,
|
||||
Theme.surfaceVariant.b, 0.2)
|
||||
|
||||
return mouseArea.containsMouse ? Theme.primaryHover : Theme.primaryBackground;
|
||||
return mouseArea.containsMouse ? Theme.primaryHover : Theme.primaryBackground
|
||||
}
|
||||
border.color: {
|
||||
if (keyboardNavigationActive && index === selectedIndex)
|
||||
return Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.5);
|
||||
if (keyboardNavigationActive
|
||||
&& index === selectedIndex)
|
||||
return Qt.rgba(Theme.primary.r,
|
||||
Theme.primary.g,
|
||||
Theme.primary.b, 0.5)
|
||||
|
||||
return Theme.outlineStrong;
|
||||
return Theme.outlineStrong
|
||||
}
|
||||
border.width: keyboardNavigationActive && index === selectedIndex ? 1.5 : 1
|
||||
border.width: keyboardNavigationActive
|
||||
&& index === selectedIndex ? 1.5 : 1
|
||||
|
||||
Row {
|
||||
anchors.fill: parent
|
||||
@@ -682,7 +690,6 @@ DankModal {
|
||||
font.weight: Font.Bold
|
||||
color: Theme.primary
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Row {
|
||||
@@ -698,10 +705,12 @@ DankModal {
|
||||
CachingImage {
|
||||
id: thumbnailImageSource
|
||||
|
||||
property string entryId: model.entry.split('\t')[0]
|
||||
property string entryId: model.entry.split(
|
||||
'\t')[0]
|
||||
|
||||
anchors.fill: parent
|
||||
source: entryType === "image" && imageLoader.imageData ? `data:image/png;base64,${imageLoader.imageData}` : ""
|
||||
source: entryType === "image"
|
||||
&& imageLoader.imageData ? `data:image/png;base64,${imageLoader.imageData}` : ""
|
||||
fillMode: Image.PreserveAspectCrop
|
||||
smooth: true
|
||||
cache: true
|
||||
@@ -718,12 +727,10 @@ DankModal {
|
||||
|
||||
stdout: StdioCollector {
|
||||
onStreamFinished: {
|
||||
imageLoader.imageData = text.trim();
|
||||
imageLoader.imageData = text.trim()
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
MultiEffect {
|
||||
@@ -732,7 +739,8 @@ DankModal {
|
||||
source: thumbnailImageSource
|
||||
maskEnabled: true
|
||||
maskSource: clipboardCircularMask
|
||||
visible: entryType === "image" && thumbnailImageSource.status === Image.Ready
|
||||
visible: entryType === "image"
|
||||
&& thumbnailImageSource.status === Image.Ready
|
||||
maskThresholdMin: 0.5
|
||||
maskSpreadAtMin: 1
|
||||
}
|
||||
@@ -752,25 +760,25 @@ DankModal {
|
||||
color: "black"
|
||||
antialiasing: true
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
DankIcon {
|
||||
visible: !(entryType === "image" && thumbnailImageSource.status === Image.Ready)
|
||||
visible: !(entryType === "image"
|
||||
&& thumbnailImageSource.status
|
||||
=== Image.Ready)
|
||||
name: {
|
||||
if (entryType === "image")
|
||||
return "image";
|
||||
return "image"
|
||||
|
||||
if (entryType === "long_text")
|
||||
return "subject";
|
||||
return "subject"
|
||||
|
||||
return "content_copy";
|
||||
return "content_copy"
|
||||
}
|
||||
size: Theme.iconSize
|
||||
color: Theme.primary
|
||||
anchors.centerIn: parent
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Column {
|
||||
@@ -782,11 +790,11 @@ DankModal {
|
||||
text: {
|
||||
switch (entryType) {
|
||||
case "image":
|
||||
return "Image • " + entryPreview;
|
||||
return "Image • " + entryPreview
|
||||
case "long_text":
|
||||
return "Long Text";
|
||||
return "Long Text"
|
||||
default:
|
||||
return "Text";
|
||||
return "Text"
|
||||
}
|
||||
}
|
||||
font.pixelSize: Theme.fontSizeSmall
|
||||
@@ -807,11 +815,8 @@ DankModal {
|
||||
maximumLineCount: entryType === "long_text" ? 3 : 1
|
||||
elide: Text.ElideRight
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
DankActionButton {
|
||||
@@ -823,7 +828,7 @@ DankModal {
|
||||
iconColor: Theme.error
|
||||
hoverColor: Theme.errorHover
|
||||
onClicked: {
|
||||
deleteEntry(model.entry);
|
||||
deleteEntry(model.entry)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -836,11 +841,8 @@ DankModal {
|
||||
cursorShape: Qt.PointingHandCursor
|
||||
onClicked: copyEntry(model.entry)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Item {
|
||||
@@ -852,11 +854,8 @@ DankModal {
|
||||
duration: Theme.shortDuration
|
||||
easing.type: Theme.standardEasing
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
@@ -866,7 +865,9 @@ DankModal {
|
||||
anchors.margins: Theme.spacingL
|
||||
height: 80
|
||||
radius: Theme.cornerRadius
|
||||
color: Qt.rgba(Theme.surfaceContainer.r, Theme.surfaceContainer.g, Theme.surfaceContainer.b, 0.95)
|
||||
color: Qt.rgba(Theme.surfaceContainer.r,
|
||||
Theme.surfaceContainer.g,
|
||||
Theme.surfaceContainer.b, 0.95)
|
||||
border.color: Theme.primary
|
||||
border.width: 2
|
||||
opacity: showKeyboardHints ? 1 : 0
|
||||
@@ -889,7 +890,6 @@ DankModal {
|
||||
color: Theme.surfaceText
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Behavior on opacity {
|
||||
@@ -897,13 +897,8 @@ DankModal {
|
||||
duration: Theme.shortDuration
|
||||
easing.type: Theme.standardEasing
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -34,10 +34,10 @@ PanelWindow {
|
||||
property bool allowFocusOverride: false
|
||||
property bool allowStacking: false
|
||||
|
||||
signal opened()
|
||||
signal dialogClosed()
|
||||
signal backgroundClicked()
|
||||
|
||||
signal opened
|
||||
signal dialogClosed
|
||||
signal backgroundClicked
|
||||
|
||||
Connections {
|
||||
target: ModalManager
|
||||
function onCloseAllModalsExcept(excludedModal) {
|
||||
@@ -49,25 +49,24 @@ PanelWindow {
|
||||
|
||||
function open() {
|
||||
ModalManager.openModal(root)
|
||||
closeTimer.stop();
|
||||
shouldBeVisible = true;
|
||||
visible = true;
|
||||
focusScope.forceActiveFocus();
|
||||
closeTimer.stop()
|
||||
shouldBeVisible = true
|
||||
visible = true
|
||||
focusScope.forceActiveFocus()
|
||||
}
|
||||
|
||||
function close() {
|
||||
shouldBeVisible = false;
|
||||
closeTimer.restart();
|
||||
shouldBeVisible = false
|
||||
closeTimer.restart()
|
||||
}
|
||||
|
||||
function toggle() {
|
||||
if (shouldBeVisible)
|
||||
close();
|
||||
close()
|
||||
else
|
||||
open();
|
||||
open()
|
||||
}
|
||||
|
||||
|
||||
visible: shouldBeVisible
|
||||
color: "transparent"
|
||||
WlrLayershell.layer: WlrLayershell.Overlay
|
||||
@@ -75,13 +74,13 @@ PanelWindow {
|
||||
WlrLayershell.keyboardFocus: shouldHaveFocus ? WlrKeyboardFocus.Exclusive : WlrKeyboardFocus.None
|
||||
onVisibleChanged: {
|
||||
if (root.visible) {
|
||||
opened();
|
||||
opened()
|
||||
} else {
|
||||
if (Qt.inputMethod) {
|
||||
Qt.inputMethod.hide();
|
||||
Qt.inputMethod.reset();
|
||||
Qt.inputMethod.hide()
|
||||
Qt.inputMethod.reset()
|
||||
}
|
||||
dialogClosed();
|
||||
dialogClosed()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -90,12 +89,10 @@ PanelWindow {
|
||||
|
||||
interval: animationDuration + 50
|
||||
onTriggered: {
|
||||
visible = false;
|
||||
visible = false
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
anchors {
|
||||
top: true
|
||||
left: true
|
||||
@@ -114,12 +111,15 @@ PanelWindow {
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
enabled: root.closeOnBackgroundClick
|
||||
onClicked: (mouse) => {
|
||||
var localPos = mapToItem(contentContainer, mouse.x, mouse.y);
|
||||
if (localPos.x < 0 || localPos.x > contentContainer.width || localPos.y < 0 || localPos.y > contentContainer.height)
|
||||
root.backgroundClicked();
|
||||
|
||||
}
|
||||
onClicked: mouse => {
|
||||
var localPos = mapToItem(contentContainer,
|
||||
mouse.x, mouse.y)
|
||||
if (localPos.x < 0
|
||||
|| localPos.x > contentContainer.width
|
||||
|| localPos.y < 0
|
||||
|| localPos.y > contentContainer.height)
|
||||
root.backgroundClicked()
|
||||
}
|
||||
}
|
||||
|
||||
Behavior on opacity {
|
||||
@@ -127,9 +127,7 @@ PanelWindow {
|
||||
duration: root.animationDuration
|
||||
easing.type: root.animationEasing
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
@@ -140,17 +138,18 @@ PanelWindow {
|
||||
anchors.centerIn: positioning === "center" ? parent : undefined
|
||||
x: {
|
||||
if (positioning === "top-right")
|
||||
return Math.max(Theme.spacingL, root.screenWidth - width - Theme.spacingL);
|
||||
return Math.max(Theme.spacingL,
|
||||
root.screenWidth - width - Theme.spacingL)
|
||||
else if (positioning === "custom")
|
||||
return root.customPosition.x;
|
||||
return 0; // Will be overridden by anchors.centerIn when positioning === "center"
|
||||
return root.customPosition.x
|
||||
return 0 // Will be overridden by anchors.centerIn when positioning === "center"
|
||||
}
|
||||
y: {
|
||||
if (positioning === "top-right")
|
||||
return Theme.barHeight + Theme.spacingXS;
|
||||
return Theme.barHeight + Theme.spacingXS
|
||||
else if (positioning === "custom")
|
||||
return root.customPosition.y;
|
||||
return 0; // Will be overridden by anchors.centerIn when positioning === "center"
|
||||
return root.customPosition.y
|
||||
return 0 // Will be overridden by anchors.centerIn when positioning === "center"
|
||||
}
|
||||
color: root.backgroundColor
|
||||
radius: root.cornerRadius
|
||||
@@ -160,9 +159,9 @@ PanelWindow {
|
||||
opacity: root.shouldBeVisible ? 1 : 0
|
||||
scale: {
|
||||
if (root.animationType === "scale")
|
||||
return root.shouldBeVisible ? 1 : 0.9;
|
||||
return root.shouldBeVisible ? 1 : 0.9
|
||||
|
||||
return 1;
|
||||
return 1
|
||||
}
|
||||
transform: root.animationType === "slide" ? slideTransform : null
|
||||
|
||||
@@ -186,7 +185,6 @@ PanelWindow {
|
||||
duration: root.animationDuration
|
||||
easing.type: root.animationEasing
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Behavior on scale {
|
||||
@@ -196,7 +194,6 @@ PanelWindow {
|
||||
duration: root.animationDuration
|
||||
easing.type: root.animationEasing
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
layer.effect: MultiEffect {
|
||||
@@ -207,7 +204,6 @@ PanelWindow {
|
||||
shadowColor: Theme.shadowStrong
|
||||
shadowOpacity: 0.3
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
FocusScope {
|
||||
@@ -217,31 +213,35 @@ PanelWindow {
|
||||
anchors.fill: parent
|
||||
visible: root.visible // Only active when the modal is visible
|
||||
focus: root.visible
|
||||
Keys.onEscapePressed: (event) => {
|
||||
console.log("DankModal escape pressed - shouldHaveFocus:", shouldHaveFocus, "closeOnEscapeKey:", root.closeOnEscapeKey, "objectName:", root.objectName || "unnamed");
|
||||
if (root.closeOnEscapeKey && shouldHaveFocus) {
|
||||
console.log("DankModal handling escape");
|
||||
root.close();
|
||||
event.accepted = true;
|
||||
}
|
||||
}
|
||||
Keys.onEscapePressed: event => {
|
||||
console.log(
|
||||
"DankModal escape pressed - shouldHaveFocus:",
|
||||
shouldHaveFocus, "closeOnEscapeKey:",
|
||||
root.closeOnEscapeKey, "objectName:",
|
||||
root.objectName || "unnamed")
|
||||
if (root.closeOnEscapeKey
|
||||
&& shouldHaveFocus) {
|
||||
console.log("DankModal handling escape")
|
||||
root.close()
|
||||
event.accepted = true
|
||||
}
|
||||
}
|
||||
onVisibleChanged: {
|
||||
if (visible && shouldHaveFocus)
|
||||
Qt.callLater(function() {
|
||||
focusScope.forceActiveFocus();
|
||||
});
|
||||
Qt.callLater(function () {
|
||||
focusScope.forceActiveFocus()
|
||||
})
|
||||
}
|
||||
|
||||
Connections {
|
||||
target: root
|
||||
function onShouldHaveFocusChanged() {
|
||||
if (shouldHaveFocus && visible) {
|
||||
Qt.callLater(function() {
|
||||
focusScope.forceActiveFocus();
|
||||
});
|
||||
Qt.callLater(function () {
|
||||
focusScope.forceActiveFocus()
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -9,290 +9,291 @@ import qs.Common
|
||||
import qs.Widgets
|
||||
|
||||
DankModal {
|
||||
id: fileBrowserModal
|
||||
objectName: "fileBrowserModal"
|
||||
allowStacking: true
|
||||
id: fileBrowserModal
|
||||
objectName: "fileBrowserModal"
|
||||
allowStacking: true
|
||||
|
||||
signal fileSelected(string path)
|
||||
signal fileSelected(string path)
|
||||
|
||||
property string homeDir: StandardPaths.writableLocation(
|
||||
StandardPaths.HomeLocation)
|
||||
property string currentPath: ""
|
||||
property var fileExtensions: ["*.*"]
|
||||
property string browserTitle: "Select File"
|
||||
property string browserIcon: "folder_open"
|
||||
property string browserType: "generic" // "wallpaper" or "profile" for last path memory
|
||||
property string homeDir: StandardPaths.writableLocation(
|
||||
StandardPaths.HomeLocation)
|
||||
property string currentPath: ""
|
||||
property var fileExtensions: ["*.*"]
|
||||
property string browserTitle: "Select File"
|
||||
property string browserIcon: "folder_open"
|
||||
property string browserType: "generic" // "wallpaper" or "profile" for last path memory
|
||||
|
||||
FolderListModel {
|
||||
id: folderModel
|
||||
showDirsFirst: true
|
||||
showDotAndDotDot: false
|
||||
showHidden: false
|
||||
nameFilters: fileExtensions
|
||||
showFiles: true
|
||||
showDirs: true
|
||||
folder: currentPath ? "file://" + currentPath : "file://" + homeDir
|
||||
}
|
||||
|
||||
function isImageFile(fileName) {
|
||||
if (!fileName)
|
||||
return false
|
||||
var ext = fileName.toLowerCase().split('.').pop()
|
||||
return ['jpg', 'jpeg', 'png', 'gif', 'bmp', 'webp', 'svg'].includes(ext)
|
||||
}
|
||||
|
||||
function getLastPath() {
|
||||
var lastPath = ""
|
||||
if (browserType === "wallpaper") {
|
||||
lastPath = SessionData.wallpaperLastPath
|
||||
} else if (browserType === "profile") {
|
||||
lastPath = SessionData.profileLastPath
|
||||
FolderListModel {
|
||||
id: folderModel
|
||||
showDirsFirst: true
|
||||
showDotAndDotDot: false
|
||||
showHidden: false
|
||||
nameFilters: fileExtensions
|
||||
showFiles: true
|
||||
showDirs: true
|
||||
folder: currentPath ? "file://" + currentPath : "file://" + homeDir
|
||||
}
|
||||
|
||||
if (lastPath && lastPath !== "") {
|
||||
return lastPath
|
||||
}
|
||||
return homeDir
|
||||
}
|
||||
|
||||
function saveLastPath(path) {
|
||||
if (browserType === "wallpaper") {
|
||||
SessionData.setWallpaperLastPath(path)
|
||||
} else if (browserType === "profile") {
|
||||
SessionData.setProfileLastPath(path)
|
||||
}
|
||||
}
|
||||
|
||||
Component.onCompleted: {
|
||||
currentPath = getLastPath()
|
||||
}
|
||||
|
||||
width: 800
|
||||
height: 600
|
||||
enableShadow: true
|
||||
visible: false
|
||||
|
||||
onBackgroundClicked: close()
|
||||
|
||||
onVisibleChanged: {
|
||||
if (visible) {
|
||||
var startPath = getLastPath()
|
||||
currentPath = startPath
|
||||
}
|
||||
}
|
||||
|
||||
onCurrentPathChanged: {
|
||||
|
||||
}
|
||||
|
||||
function navigateUp() {
|
||||
var path = currentPath
|
||||
|
||||
if (path === homeDir) {
|
||||
return
|
||||
function isImageFile(fileName) {
|
||||
if (!fileName)
|
||||
return false
|
||||
var ext = fileName.toLowerCase().split('.').pop()
|
||||
return ['jpg', 'jpeg', 'png', 'gif', 'bmp', 'webp', 'svg'].includes(ext)
|
||||
}
|
||||
|
||||
var lastSlash = path.lastIndexOf('/')
|
||||
if (lastSlash > 0) {
|
||||
var newPath = path.substring(0, lastSlash)
|
||||
if (newPath.length < homeDir.length) {
|
||||
currentPath = homeDir
|
||||
saveLastPath(homeDir)
|
||||
} else {
|
||||
currentPath = newPath
|
||||
saveLastPath(newPath)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function navigateTo(path) {
|
||||
currentPath = path
|
||||
saveLastPath(path) // Save the path when navigating
|
||||
}
|
||||
|
||||
content: Component {
|
||||
Column {
|
||||
anchors.fill: parent
|
||||
anchors.margins: Theme.spacingM
|
||||
spacing: Theme.spacingS
|
||||
|
||||
Item {
|
||||
width: parent.width
|
||||
height: 40
|
||||
|
||||
Row {
|
||||
spacing: Theme.spacingM
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
|
||||
DankIcon {
|
||||
name: browserIcon
|
||||
size: Theme.iconSizeLarge
|
||||
color: Theme.primary
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
}
|
||||
|
||||
StyledText {
|
||||
text: browserTitle
|
||||
font.pixelSize: Theme.fontSizeXLarge
|
||||
color: Theme.surfaceText
|
||||
font.weight: Font.Medium
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
}
|
||||
function getLastPath() {
|
||||
var lastPath = ""
|
||||
if (browserType === "wallpaper") {
|
||||
lastPath = SessionData.wallpaperLastPath
|
||||
} else if (browserType === "profile") {
|
||||
lastPath = SessionData.profileLastPath
|
||||
}
|
||||
|
||||
DankActionButton {
|
||||
circular: false
|
||||
iconName: "close"
|
||||
iconSize: Theme.iconSize - 4
|
||||
iconColor: Theme.surfaceText
|
||||
hoverColor: Theme.errorHover
|
||||
onClicked: fileBrowserModal.close()
|
||||
anchors.right: parent.right
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
if (lastPath && lastPath !== "") {
|
||||
return lastPath
|
||||
}
|
||||
}
|
||||
return homeDir
|
||||
}
|
||||
|
||||
Row {
|
||||
width: parent.width
|
||||
spacing: Theme.spacingS
|
||||
function saveLastPath(path) {
|
||||
if (browserType === "wallpaper") {
|
||||
SessionData.setWallpaperLastPath(path)
|
||||
} else if (browserType === "profile") {
|
||||
SessionData.setProfileLastPath(path)
|
||||
}
|
||||
}
|
||||
|
||||
StyledRect {
|
||||
width: 32
|
||||
height: 32
|
||||
radius: Theme.cornerRadius
|
||||
color: mouseArea.containsMouse
|
||||
&& currentPath !== homeDir ? Theme.surfaceVariant : "transparent"
|
||||
opacity: currentPath !== homeDir ? 1.0 : 0.0
|
||||
Component.onCompleted: {
|
||||
currentPath = getLastPath()
|
||||
}
|
||||
|
||||
DankIcon {
|
||||
anchors.centerIn: parent
|
||||
name: "arrow_back"
|
||||
size: Theme.iconSizeSmall
|
||||
color: Theme.surfaceText
|
||||
}
|
||||
width: 800
|
||||
height: 600
|
||||
enableShadow: true
|
||||
visible: false
|
||||
|
||||
MouseArea {
|
||||
id: mouseArea
|
||||
onBackgroundClicked: close()
|
||||
|
||||
onVisibleChanged: {
|
||||
if (visible) {
|
||||
var startPath = getLastPath()
|
||||
currentPath = startPath
|
||||
}
|
||||
}
|
||||
|
||||
onCurrentPathChanged: {
|
||||
|
||||
}
|
||||
|
||||
function navigateUp() {
|
||||
var path = currentPath
|
||||
|
||||
if (path === homeDir) {
|
||||
return
|
||||
}
|
||||
|
||||
var lastSlash = path.lastIndexOf('/')
|
||||
if (lastSlash > 0) {
|
||||
var newPath = path.substring(0, lastSlash)
|
||||
if (newPath.length < homeDir.length) {
|
||||
currentPath = homeDir
|
||||
saveLastPath(homeDir)
|
||||
} else {
|
||||
currentPath = newPath
|
||||
saveLastPath(newPath)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function navigateTo(path) {
|
||||
currentPath = path
|
||||
saveLastPath(path) // Save the path when navigating
|
||||
}
|
||||
|
||||
content: Component {
|
||||
Column {
|
||||
anchors.fill: parent
|
||||
hoverEnabled: currentPath !== homeDir
|
||||
cursorShape: currentPath !== homeDir ? Qt.PointingHandCursor : Qt.ArrowCursor
|
||||
enabled: currentPath !== homeDir
|
||||
onClicked: navigateUp()
|
||||
}
|
||||
}
|
||||
|
||||
StyledText {
|
||||
text: fileBrowserModal.currentPath.replace("file://", "")
|
||||
font.pixelSize: Theme.fontSizeMedium
|
||||
color: Theme.surfaceText
|
||||
font.weight: Font.Medium
|
||||
width: parent.width - 40 - Theme.spacingS
|
||||
elide: Text.ElideMiddle
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
maximumLineCount: 1
|
||||
wrapMode: Text.NoWrap
|
||||
}
|
||||
}
|
||||
|
||||
DankGridView {
|
||||
id: fileGrid
|
||||
|
||||
width: parent.width
|
||||
height: parent.height - 80
|
||||
clip: true
|
||||
cellWidth: 150
|
||||
cellHeight: 130
|
||||
cacheBuffer: 260
|
||||
|
||||
model: folderModel
|
||||
|
||||
ScrollBar.vertical: ScrollBar {
|
||||
policy: ScrollBar.AsNeeded
|
||||
}
|
||||
ScrollBar.horizontal: ScrollBar {
|
||||
policy: ScrollBar.AlwaysOff
|
||||
}
|
||||
|
||||
delegate: StyledRect {
|
||||
id: delegateRoot
|
||||
|
||||
required property bool fileIsDir
|
||||
required property string filePath
|
||||
required property string fileName
|
||||
required property url fileURL
|
||||
|
||||
width: 140
|
||||
height: 120
|
||||
radius: Theme.cornerRadius
|
||||
color: mouseArea.containsMouse ? Theme.surfaceVariant : "transparent"
|
||||
border.color: Theme.outline
|
||||
border.width: mouseArea.containsMouse ? 1 : 0
|
||||
|
||||
Column {
|
||||
anchors.centerIn: parent
|
||||
spacing: Theme.spacingXS
|
||||
anchors.margins: Theme.spacingM
|
||||
spacing: Theme.spacingS
|
||||
|
||||
Item {
|
||||
width: 80
|
||||
height: 60
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
width: parent.width
|
||||
height: 40
|
||||
|
||||
CachingImage {
|
||||
anchors.fill: parent
|
||||
imagePath: !delegateRoot.fileIsDir ? delegateRoot.filePath : ""
|
||||
fillMode: Image.PreserveAspectCrop
|
||||
visible: !delegateRoot.fileIsDir && isImageFile(
|
||||
delegateRoot.fileName)
|
||||
maxCacheSize: 80
|
||||
}
|
||||
Row {
|
||||
spacing: Theme.spacingM
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
|
||||
DankIcon {
|
||||
anchors.centerIn: parent
|
||||
name: "description"
|
||||
size: Theme.iconSizeLarge
|
||||
color: Theme.primary
|
||||
visible: !delegateRoot.fileIsDir && !isImageFile(
|
||||
delegateRoot.fileName)
|
||||
}
|
||||
DankIcon {
|
||||
name: browserIcon
|
||||
size: Theme.iconSizeLarge
|
||||
color: Theme.primary
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
}
|
||||
|
||||
DankIcon {
|
||||
anchors.centerIn: parent
|
||||
name: "folder"
|
||||
size: Theme.iconSizeLarge
|
||||
color: Theme.primary
|
||||
visible: delegateRoot.fileIsDir
|
||||
}
|
||||
StyledText {
|
||||
text: browserTitle
|
||||
font.pixelSize: Theme.fontSizeXLarge
|
||||
color: Theme.surfaceText
|
||||
font.weight: Font.Medium
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
}
|
||||
}
|
||||
|
||||
DankActionButton {
|
||||
circular: false
|
||||
iconName: "close"
|
||||
iconSize: Theme.iconSize - 4
|
||||
iconColor: Theme.surfaceText
|
||||
hoverColor: Theme.errorHover
|
||||
onClicked: fileBrowserModal.close()
|
||||
anchors.right: parent.right
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
}
|
||||
}
|
||||
|
||||
StyledText {
|
||||
text: delegateRoot.fileName || ""
|
||||
font.pixelSize: Theme.fontSizeSmall
|
||||
color: Theme.surfaceText
|
||||
width: 120
|
||||
elide: Text.ElideMiddle
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
maximumLineCount: 2
|
||||
wrapMode: Text.WordWrap
|
||||
}
|
||||
}
|
||||
Row {
|
||||
width: parent.width
|
||||
spacing: Theme.spacingS
|
||||
|
||||
MouseArea {
|
||||
id: mouseArea
|
||||
anchors.fill: parent
|
||||
hoverEnabled: true
|
||||
cursorShape: Qt.PointingHandCursor
|
||||
StyledRect {
|
||||
width: 32
|
||||
height: 32
|
||||
radius: Theme.cornerRadius
|
||||
color: mouseArea.containsMouse
|
||||
&& currentPath !== homeDir ? Theme.surfaceVariant : "transparent"
|
||||
opacity: currentPath !== homeDir ? 1.0 : 0.0
|
||||
|
||||
onClicked: {
|
||||
if (delegateRoot.fileIsDir) {
|
||||
navigateTo(delegateRoot.filePath)
|
||||
} else {
|
||||
fileSelected(delegateRoot.filePath)
|
||||
}
|
||||
DankIcon {
|
||||
anchors.centerIn: parent
|
||||
name: "arrow_back"
|
||||
size: Theme.iconSizeSmall
|
||||
color: Theme.surfaceText
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
id: mouseArea
|
||||
anchors.fill: parent
|
||||
hoverEnabled: currentPath !== homeDir
|
||||
cursorShape: currentPath
|
||||
!== homeDir ? Qt.PointingHandCursor : Qt.ArrowCursor
|
||||
enabled: currentPath !== homeDir
|
||||
onClicked: navigateUp()
|
||||
}
|
||||
}
|
||||
|
||||
StyledText {
|
||||
text: fileBrowserModal.currentPath.replace("file://", "")
|
||||
font.pixelSize: Theme.fontSizeMedium
|
||||
color: Theme.surfaceText
|
||||
font.weight: Font.Medium
|
||||
width: parent.width - 40 - Theme.spacingS
|
||||
elide: Text.ElideMiddle
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
maximumLineCount: 1
|
||||
wrapMode: Text.NoWrap
|
||||
}
|
||||
}
|
||||
|
||||
DankGridView {
|
||||
id: fileGrid
|
||||
|
||||
width: parent.width
|
||||
height: parent.height - 80
|
||||
clip: true
|
||||
cellWidth: 150
|
||||
cellHeight: 130
|
||||
cacheBuffer: 260
|
||||
|
||||
model: folderModel
|
||||
|
||||
ScrollBar.vertical: ScrollBar {
|
||||
policy: ScrollBar.AsNeeded
|
||||
}
|
||||
ScrollBar.horizontal: ScrollBar {
|
||||
policy: ScrollBar.AlwaysOff
|
||||
}
|
||||
|
||||
delegate: StyledRect {
|
||||
id: delegateRoot
|
||||
|
||||
required property bool fileIsDir
|
||||
required property string filePath
|
||||
required property string fileName
|
||||
required property url fileURL
|
||||
|
||||
width: 140
|
||||
height: 120
|
||||
radius: Theme.cornerRadius
|
||||
color: mouseArea.containsMouse ? Theme.surfaceVariant : "transparent"
|
||||
border.color: Theme.outline
|
||||
border.width: mouseArea.containsMouse ? 1 : 0
|
||||
|
||||
Column {
|
||||
anchors.centerIn: parent
|
||||
spacing: Theme.spacingXS
|
||||
|
||||
Item {
|
||||
width: 80
|
||||
height: 60
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
|
||||
CachingImage {
|
||||
anchors.fill: parent
|
||||
imagePath: !delegateRoot.fileIsDir ? delegateRoot.filePath : ""
|
||||
fillMode: Image.PreserveAspectCrop
|
||||
visible: !delegateRoot.fileIsDir && isImageFile(
|
||||
delegateRoot.fileName)
|
||||
maxCacheSize: 80
|
||||
}
|
||||
|
||||
DankIcon {
|
||||
anchors.centerIn: parent
|
||||
name: "description"
|
||||
size: Theme.iconSizeLarge
|
||||
color: Theme.primary
|
||||
visible: !delegateRoot.fileIsDir
|
||||
&& !isImageFile(delegateRoot.fileName)
|
||||
}
|
||||
|
||||
DankIcon {
|
||||
anchors.centerIn: parent
|
||||
name: "folder"
|
||||
size: Theme.iconSizeLarge
|
||||
color: Theme.primary
|
||||
visible: delegateRoot.fileIsDir
|
||||
}
|
||||
}
|
||||
|
||||
StyledText {
|
||||
text: delegateRoot.fileName || ""
|
||||
font.pixelSize: Theme.fontSizeSmall
|
||||
color: Theme.surfaceText
|
||||
width: 120
|
||||
elide: Text.ElideMiddle
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
maximumLineCount: 2
|
||||
wrapMode: Text.WordWrap
|
||||
}
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
id: mouseArea
|
||||
anchors.fill: parent
|
||||
hoverEnabled: true
|
||||
cursorShape: Qt.PointingHandCursor
|
||||
|
||||
onClicked: {
|
||||
if (delegateRoot.fileIsDir) {
|
||||
navigateTo(delegateRoot.filePath)
|
||||
} else {
|
||||
fileSelected(delegateRoot.filePath)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,195 +8,202 @@ import qs.Services
|
||||
import qs.Widgets
|
||||
|
||||
DankModal {
|
||||
id: root
|
||||
id: root
|
||||
|
||||
property bool networkInfoModalVisible: false
|
||||
property string networkSSID: ""
|
||||
property var networkData: null
|
||||
property string networkDetails: ""
|
||||
property bool networkInfoModalVisible: false
|
||||
property string networkSSID: ""
|
||||
property var networkData: null
|
||||
property string networkDetails: ""
|
||||
|
||||
function showNetworkInfo(ssid, data) {
|
||||
networkSSID = ssid
|
||||
networkData = data
|
||||
networkInfoModalVisible = true
|
||||
open()
|
||||
NetworkService.fetchNetworkInfo(ssid)
|
||||
}
|
||||
|
||||
function hideDialog() {
|
||||
networkInfoModalVisible = false
|
||||
close()
|
||||
networkSSID = ""
|
||||
networkData = null
|
||||
networkDetails = ""
|
||||
}
|
||||
|
||||
visible: networkInfoModalVisible
|
||||
width: 600
|
||||
height: 500
|
||||
enableShadow: true
|
||||
onBackgroundClicked: {
|
||||
hideDialog()
|
||||
}
|
||||
onVisibleChanged: {
|
||||
if (!visible) {
|
||||
networkSSID = ""
|
||||
networkData = null
|
||||
networkDetails = ""
|
||||
function showNetworkInfo(ssid, data) {
|
||||
networkSSID = ssid
|
||||
networkData = data
|
||||
networkInfoModalVisible = true
|
||||
open()
|
||||
NetworkService.fetchNetworkInfo(ssid)
|
||||
}
|
||||
}
|
||||
|
||||
content: Component {
|
||||
Item {
|
||||
anchors.fill: parent
|
||||
function hideDialog() {
|
||||
networkInfoModalVisible = false
|
||||
close()
|
||||
networkSSID = ""
|
||||
networkData = null
|
||||
networkDetails = ""
|
||||
}
|
||||
|
||||
Column {
|
||||
anchors.fill: parent
|
||||
anchors.margins: Theme.spacingL
|
||||
spacing: Theme.spacingL
|
||||
|
||||
Row {
|
||||
width: parent.width
|
||||
|
||||
Column {
|
||||
width: parent.width - 40
|
||||
spacing: Theme.spacingXS
|
||||
|
||||
StyledText {
|
||||
text: "Network Information"
|
||||
font.pixelSize: Theme.fontSizeLarge
|
||||
color: Theme.surfaceText
|
||||
font.weight: Font.Medium
|
||||
}
|
||||
|
||||
StyledText {
|
||||
text: "Details for \"" + networkSSID + "\""
|
||||
font.pixelSize: Theme.fontSizeMedium
|
||||
color: Theme.surfaceTextMedium
|
||||
width: parent.width
|
||||
elide: Text.ElideRight
|
||||
}
|
||||
}
|
||||
|
||||
DankActionButton {
|
||||
iconName: "close"
|
||||
iconSize: Theme.iconSize - 4
|
||||
iconColor: Theme.surfaceText
|
||||
hoverColor: Theme.errorHover
|
||||
onClicked: {
|
||||
root.hideDialog()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Flickable {
|
||||
width: parent.width
|
||||
height: parent.height - 140
|
||||
clip: true
|
||||
contentWidth: width
|
||||
contentHeight: detailsRect.height
|
||||
|
||||
// Qt 6.9+ scrolling: flickDeceleration/maximumFlickVelocity only affect touch now
|
||||
interactive: true
|
||||
flickDeceleration: 1500
|
||||
maximumFlickVelocity: 2000
|
||||
boundsBehavior: Flickable.DragAndOvershootBounds
|
||||
boundsMovement: Flickable.FollowBoundsBehavior
|
||||
pressDelay: 0
|
||||
flickableDirection: Flickable.VerticalFlick
|
||||
|
||||
// Custom wheel handler for Qt 6.9+ responsive mouse wheel scrolling
|
||||
WheelHandler {
|
||||
acceptedDevices: PointerDevice.Mouse | PointerDevice.TouchPad
|
||||
onWheel: event => {
|
||||
let delta = event.pixelDelta.y
|
||||
!== 0 ? event.pixelDelta.y * 1.8 : event.angleDelta.y / 120 * 60
|
||||
let newY = parent.contentY - delta
|
||||
newY = Math.max(0, Math.min(
|
||||
parent.contentHeight - parent.height,
|
||||
newY))
|
||||
parent.contentY = newY
|
||||
event.accepted = true
|
||||
}
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
id: detailsRect
|
||||
|
||||
width: parent.width
|
||||
height: Math.max(parent.parent.height,
|
||||
detailsText.contentHeight + Theme.spacingM * 2)
|
||||
radius: Theme.cornerRadius
|
||||
color: Theme.surfaceHover
|
||||
border.color: Theme.outlineStrong
|
||||
border.width: 1
|
||||
|
||||
StyledText {
|
||||
id: detailsText
|
||||
|
||||
anchors.fill: parent
|
||||
anchors.margins: Theme.spacingM
|
||||
text: NetworkService.networkInfoDetails.replace(/\\n/g, '\n')
|
||||
|| "No information available"
|
||||
font.pixelSize: Theme.fontSizeMedium
|
||||
color: Theme.surfaceText
|
||||
wrapMode: Text.WordWrap
|
||||
lineHeight: 1.5
|
||||
}
|
||||
}
|
||||
|
||||
ScrollBar.vertical: ScrollBar {
|
||||
policy: ScrollBar.AsNeeded
|
||||
}
|
||||
|
||||
ScrollBar.horizontal: ScrollBar {
|
||||
policy: ScrollBar.AlwaysOff
|
||||
}
|
||||
visible: networkInfoModalVisible
|
||||
width: 600
|
||||
height: 500
|
||||
enableShadow: true
|
||||
onBackgroundClicked: {
|
||||
hideDialog()
|
||||
}
|
||||
onVisibleChanged: {
|
||||
if (!visible) {
|
||||
networkSSID = ""
|
||||
networkData = null
|
||||
networkDetails = ""
|
||||
}
|
||||
}
|
||||
|
||||
content: Component {
|
||||
Item {
|
||||
width: parent.width
|
||||
height: 40
|
||||
anchors.fill: parent
|
||||
|
||||
Rectangle {
|
||||
anchors.right: parent.right
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
width: Math.max(70, closeText.contentWidth + Theme.spacingM * 2)
|
||||
height: 36
|
||||
radius: Theme.cornerRadius
|
||||
color: closeArea.containsMouse ? Qt.darker(Theme.primary,
|
||||
1.1) : Theme.primary
|
||||
Column {
|
||||
anchors.fill: parent
|
||||
anchors.margins: Theme.spacingL
|
||||
spacing: Theme.spacingL
|
||||
|
||||
StyledText {
|
||||
id: closeText
|
||||
Row {
|
||||
width: parent.width
|
||||
|
||||
anchors.centerIn: parent
|
||||
text: "Close"
|
||||
font.pixelSize: Theme.fontSizeMedium
|
||||
color: Theme.background
|
||||
font.weight: Font.Medium
|
||||
Column {
|
||||
width: parent.width - 40
|
||||
spacing: Theme.spacingXS
|
||||
|
||||
StyledText {
|
||||
text: "Network Information"
|
||||
font.pixelSize: Theme.fontSizeLarge
|
||||
color: Theme.surfaceText
|
||||
font.weight: Font.Medium
|
||||
}
|
||||
|
||||
StyledText {
|
||||
text: "Details for \"" + networkSSID + "\""
|
||||
font.pixelSize: Theme.fontSizeMedium
|
||||
color: Theme.surfaceTextMedium
|
||||
width: parent.width
|
||||
elide: Text.ElideRight
|
||||
}
|
||||
}
|
||||
|
||||
DankActionButton {
|
||||
iconName: "close"
|
||||
iconSize: Theme.iconSize - 4
|
||||
iconColor: Theme.surfaceText
|
||||
hoverColor: Theme.errorHover
|
||||
onClicked: {
|
||||
root.hideDialog()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Flickable {
|
||||
width: parent.width
|
||||
height: parent.height - 140
|
||||
clip: true
|
||||
contentWidth: width
|
||||
contentHeight: detailsRect.height
|
||||
|
||||
// Qt 6.9+ scrolling: flickDeceleration/maximumFlickVelocity only affect touch now
|
||||
interactive: true
|
||||
flickDeceleration: 1500
|
||||
maximumFlickVelocity: 2000
|
||||
boundsBehavior: Flickable.DragAndOvershootBounds
|
||||
boundsMovement: Flickable.FollowBoundsBehavior
|
||||
pressDelay: 0
|
||||
flickableDirection: Flickable.VerticalFlick
|
||||
|
||||
// Custom wheel handler for Qt 6.9+ responsive mouse wheel scrolling
|
||||
WheelHandler {
|
||||
acceptedDevices: PointerDevice.Mouse | PointerDevice.TouchPad
|
||||
onWheel: event => {
|
||||
let delta = event.pixelDelta.y
|
||||
!== 0 ? event.pixelDelta.y
|
||||
* 1.8 : event.angleDelta.y / 120 * 60
|
||||
let newY = parent.contentY - delta
|
||||
newY = Math.max(
|
||||
0, Math.min(
|
||||
parent.contentHeight - parent.height,
|
||||
newY))
|
||||
parent.contentY = newY
|
||||
event.accepted = true
|
||||
}
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
id: detailsRect
|
||||
|
||||
width: parent.width
|
||||
height: Math.max(
|
||||
parent.parent.height,
|
||||
detailsText.contentHeight + Theme.spacingM * 2)
|
||||
radius: Theme.cornerRadius
|
||||
color: Theme.surfaceHover
|
||||
border.color: Theme.outlineStrong
|
||||
border.width: 1
|
||||
|
||||
StyledText {
|
||||
id: detailsText
|
||||
|
||||
anchors.fill: parent
|
||||
anchors.margins: Theme.spacingM
|
||||
text: NetworkService.networkInfoDetails.replace(
|
||||
/\\n/g,
|
||||
'\n') || "No information available"
|
||||
font.pixelSize: Theme.fontSizeMedium
|
||||
color: Theme.surfaceText
|
||||
wrapMode: Text.WordWrap
|
||||
lineHeight: 1.5
|
||||
}
|
||||
}
|
||||
|
||||
ScrollBar.vertical: ScrollBar {
|
||||
policy: ScrollBar.AsNeeded
|
||||
}
|
||||
|
||||
ScrollBar.horizontal: ScrollBar {
|
||||
policy: ScrollBar.AlwaysOff
|
||||
}
|
||||
}
|
||||
|
||||
Item {
|
||||
width: parent.width
|
||||
height: 40
|
||||
|
||||
Rectangle {
|
||||
anchors.right: parent.right
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
width: Math.max(
|
||||
70,
|
||||
closeText.contentWidth + Theme.spacingM * 2)
|
||||
height: 36
|
||||
radius: Theme.cornerRadius
|
||||
color: closeArea.containsMouse ? Qt.darker(
|
||||
Theme.primary,
|
||||
1.1) : Theme.primary
|
||||
|
||||
StyledText {
|
||||
id: closeText
|
||||
|
||||
anchors.centerIn: parent
|
||||
text: "Close"
|
||||
font.pixelSize: Theme.fontSizeMedium
|
||||
color: Theme.background
|
||||
font.weight: Font.Medium
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
id: closeArea
|
||||
|
||||
anchors.fill: parent
|
||||
hoverEnabled: true
|
||||
cursorShape: Qt.PointingHandCursor
|
||||
onClicked: {
|
||||
root.hideDialog()
|
||||
}
|
||||
}
|
||||
|
||||
Behavior on color {
|
||||
ColorAnimation {
|
||||
duration: Theme.shortDuration
|
||||
easing.type: Theme.standardEasing
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
id: closeArea
|
||||
|
||||
anchors.fill: parent
|
||||
hoverEnabled: true
|
||||
cursorShape: Qt.PointingHandCursor
|
||||
onClicked: {
|
||||
root.hideDialog()
|
||||
}
|
||||
}
|
||||
|
||||
Behavior on color {
|
||||
ColorAnimation {
|
||||
duration: Theme.shortDuration
|
||||
easing.type: Theme.standardEasing
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,7 +11,7 @@ import qs.Widgets
|
||||
|
||||
DankModal {
|
||||
id: notificationModal
|
||||
|
||||
|
||||
width: 500
|
||||
height: 700
|
||||
visible: false
|
||||
@@ -20,28 +20,28 @@ DankModal {
|
||||
notificationModalOpen = false
|
||||
modalKeyboardController.reset()
|
||||
}
|
||||
|
||||
modalFocusScope.Keys.onPressed: function(event) {
|
||||
|
||||
modalFocusScope.Keys.onPressed: function (event) {
|
||||
modalKeyboardController.handleKey(event)
|
||||
}
|
||||
|
||||
|
||||
NotificationKeyboardController {
|
||||
id: modalKeyboardController
|
||||
listView: null
|
||||
isOpen: notificationModal.notificationModalOpen
|
||||
onClose: function() { notificationModal.hide() }
|
||||
onClose: function () {
|
||||
notificationModal.hide()
|
||||
}
|
||||
}
|
||||
|
||||
property bool notificationModalOpen: false
|
||||
property var notificationListRef: null
|
||||
|
||||
|
||||
|
||||
function show() {
|
||||
notificationModalOpen = true
|
||||
open()
|
||||
modalKeyboardController.reset()
|
||||
|
||||
|
||||
if (modalKeyboardController && notificationListRef) {
|
||||
modalKeyboardController.listView = notificationListRef
|
||||
modalKeyboardController.rebuildFlatNavigation()
|
||||
@@ -61,7 +61,6 @@ DankModal {
|
||||
show()
|
||||
}
|
||||
|
||||
|
||||
IpcHandler {
|
||||
function open() {
|
||||
notificationModal.show()
|
||||
@@ -96,7 +95,7 @@ DankModal {
|
||||
id: notificationHeader
|
||||
keyboardController: modalKeyboardController
|
||||
}
|
||||
|
||||
|
||||
NotificationSettings {
|
||||
id: notificationSettings
|
||||
expanded: notificationHeader.showSettings
|
||||
@@ -104,11 +103,11 @@ DankModal {
|
||||
|
||||
KeyboardNavigatedNotificationList {
|
||||
id: notificationList
|
||||
|
||||
|
||||
width: parent.width
|
||||
height: parent.height - y
|
||||
keyboardController: modalKeyboardController
|
||||
|
||||
|
||||
Component.onCompleted: {
|
||||
notificationModal.notificationListRef = notificationList
|
||||
if (modalKeyboardController) {
|
||||
@@ -117,7 +116,6 @@ DankModal {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
NotificationKeyboardHints {
|
||||
@@ -128,9 +126,8 @@ DankModal {
|
||||
anchors.margins: Theme.spacingL
|
||||
showHints: modalKeyboardController.showKeyboardHints
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
content: notificationContent
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,159 +7,160 @@ import qs.Services
|
||||
import qs.Widgets
|
||||
|
||||
DankModal {
|
||||
id: root
|
||||
id: root
|
||||
|
||||
property string powerConfirmAction: ""
|
||||
property string powerConfirmTitle: ""
|
||||
property string powerConfirmMessage: ""
|
||||
property string powerConfirmAction: ""
|
||||
property string powerConfirmTitle: ""
|
||||
property string powerConfirmMessage: ""
|
||||
|
||||
function show(action, title, message) {
|
||||
powerConfirmAction = action
|
||||
powerConfirmTitle = title
|
||||
powerConfirmMessage = message
|
||||
open()
|
||||
}
|
||||
|
||||
function executePowerAction(action) {
|
||||
switch (action) {
|
||||
case "logout":
|
||||
NiriService.quit()
|
||||
break
|
||||
case "suspend":
|
||||
Quickshell.execDetached(["systemctl", "suspend"])
|
||||
break
|
||||
case "reboot":
|
||||
Quickshell.execDetached(["systemctl", "reboot"])
|
||||
break
|
||||
case "poweroff":
|
||||
Quickshell.execDetached(["systemctl", "poweroff"])
|
||||
break
|
||||
function show(action, title, message) {
|
||||
powerConfirmAction = action
|
||||
powerConfirmTitle = title
|
||||
powerConfirmMessage = message
|
||||
open()
|
||||
}
|
||||
}
|
||||
|
||||
shouldBeVisible: false
|
||||
width: 350
|
||||
height: 160
|
||||
enableShadow: false
|
||||
onBackgroundClicked: {
|
||||
close()
|
||||
}
|
||||
|
||||
content: Component {
|
||||
Item {
|
||||
anchors.fill: parent
|
||||
|
||||
Column {
|
||||
anchors.centerIn: parent
|
||||
width: parent.width - Theme.spacingM * 2
|
||||
spacing: Theme.spacingM
|
||||
|
||||
StyledText {
|
||||
text: powerConfirmTitle
|
||||
font.pixelSize: Theme.fontSizeLarge
|
||||
color: {
|
||||
switch (powerConfirmAction) {
|
||||
case "poweroff":
|
||||
return Theme.error
|
||||
case "reboot":
|
||||
return Theme.warning
|
||||
default:
|
||||
return Theme.surfaceText
|
||||
}
|
||||
}
|
||||
font.weight: Font.Medium
|
||||
width: parent.width
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
function executePowerAction(action) {
|
||||
switch (action) {
|
||||
case "logout":
|
||||
NiriService.quit()
|
||||
break
|
||||
case "suspend":
|
||||
Quickshell.execDetached(["systemctl", "suspend"])
|
||||
break
|
||||
case "reboot":
|
||||
Quickshell.execDetached(["systemctl", "reboot"])
|
||||
break
|
||||
case "poweroff":
|
||||
Quickshell.execDetached(["systemctl", "poweroff"])
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
StyledText {
|
||||
text: powerConfirmMessage
|
||||
font.pixelSize: Theme.fontSizeMedium
|
||||
color: Theme.surfaceText
|
||||
width: parent.width
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
wrapMode: Text.WordWrap
|
||||
}
|
||||
shouldBeVisible: false
|
||||
width: 350
|
||||
height: 160
|
||||
enableShadow: false
|
||||
onBackgroundClicked: {
|
||||
close()
|
||||
}
|
||||
|
||||
content: Component {
|
||||
Item {
|
||||
height: Theme.spacingS
|
||||
anchors.fill: parent
|
||||
|
||||
Column {
|
||||
anchors.centerIn: parent
|
||||
width: parent.width - Theme.spacingM * 2
|
||||
spacing: Theme.spacingM
|
||||
|
||||
StyledText {
|
||||
text: powerConfirmTitle
|
||||
font.pixelSize: Theme.fontSizeLarge
|
||||
color: {
|
||||
switch (powerConfirmAction) {
|
||||
case "poweroff":
|
||||
return Theme.error
|
||||
case "reboot":
|
||||
return Theme.warning
|
||||
default:
|
||||
return Theme.surfaceText
|
||||
}
|
||||
}
|
||||
font.weight: Font.Medium
|
||||
width: parent.width
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
}
|
||||
|
||||
StyledText {
|
||||
text: powerConfirmMessage
|
||||
font.pixelSize: Theme.fontSizeMedium
|
||||
color: Theme.surfaceText
|
||||
width: parent.width
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
wrapMode: Text.WordWrap
|
||||
}
|
||||
|
||||
Item {
|
||||
height: Theme.spacingS
|
||||
}
|
||||
|
||||
Row {
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
spacing: Theme.spacingM
|
||||
|
||||
Rectangle {
|
||||
width: 120
|
||||
height: 40
|
||||
radius: Theme.cornerRadius
|
||||
color: cancelButton.containsMouse ? Theme.surfaceTextPressed : Theme.surfaceVariantAlpha
|
||||
|
||||
StyledText {
|
||||
text: "Cancel"
|
||||
font.pixelSize: Theme.fontSizeMedium
|
||||
color: Theme.surfaceText
|
||||
font.weight: Font.Medium
|
||||
anchors.centerIn: parent
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
id: cancelButton
|
||||
|
||||
anchors.fill: parent
|
||||
hoverEnabled: true
|
||||
cursorShape: Qt.PointingHandCursor
|
||||
onClicked: {
|
||||
close()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
width: 120
|
||||
height: 40
|
||||
radius: Theme.cornerRadius
|
||||
color: {
|
||||
let baseColor
|
||||
switch (powerConfirmAction) {
|
||||
case "poweroff":
|
||||
baseColor = Theme.error
|
||||
break
|
||||
case "reboot":
|
||||
baseColor = Theme.warning
|
||||
break
|
||||
default:
|
||||
baseColor = Theme.primary
|
||||
break
|
||||
}
|
||||
return confirmButton.containsMouse ? Qt.rgba(
|
||||
baseColor.r,
|
||||
baseColor.g,
|
||||
baseColor.b,
|
||||
0.9) : baseColor
|
||||
}
|
||||
|
||||
StyledText {
|
||||
text: "Confirm"
|
||||
font.pixelSize: Theme.fontSizeMedium
|
||||
color: Theme.primaryText
|
||||
font.weight: Font.Medium
|
||||
anchors.centerIn: parent
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
id: confirmButton
|
||||
|
||||
anchors.fill: parent
|
||||
hoverEnabled: true
|
||||
cursorShape: Qt.PointingHandCursor
|
||||
onClicked: {
|
||||
close()
|
||||
executePowerAction(powerConfirmAction)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Row {
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
spacing: Theme.spacingM
|
||||
|
||||
Rectangle {
|
||||
width: 120
|
||||
height: 40
|
||||
radius: Theme.cornerRadius
|
||||
color: cancelButton.containsMouse ? Theme.surfaceTextPressed : Theme.surfaceVariantAlpha
|
||||
|
||||
StyledText {
|
||||
text: "Cancel"
|
||||
font.pixelSize: Theme.fontSizeMedium
|
||||
color: Theme.surfaceText
|
||||
font.weight: Font.Medium
|
||||
anchors.centerIn: parent
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
id: cancelButton
|
||||
|
||||
anchors.fill: parent
|
||||
hoverEnabled: true
|
||||
cursorShape: Qt.PointingHandCursor
|
||||
onClicked: {
|
||||
close()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
width: 120
|
||||
height: 40
|
||||
radius: Theme.cornerRadius
|
||||
color: {
|
||||
let baseColor
|
||||
switch (powerConfirmAction) {
|
||||
case "poweroff":
|
||||
baseColor = Theme.error
|
||||
break
|
||||
case "reboot":
|
||||
baseColor = Theme.warning
|
||||
break
|
||||
default:
|
||||
baseColor = Theme.primary
|
||||
break
|
||||
}
|
||||
return confirmButton.containsMouse ? Qt.rgba(baseColor.r,
|
||||
baseColor.g,
|
||||
baseColor.b,
|
||||
0.9) : baseColor
|
||||
}
|
||||
|
||||
StyledText {
|
||||
text: "Confirm"
|
||||
font.pixelSize: Theme.fontSizeMedium
|
||||
color: Theme.primaryText
|
||||
font.weight: Font.Medium
|
||||
anchors.centerIn: parent
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
id: confirmButton
|
||||
|
||||
anchors.fill: parent
|
||||
hoverEnabled: true
|
||||
cursorShape: Qt.PointingHandCursor
|
||||
onClicked: {
|
||||
close()
|
||||
executePowerAction(powerConfirmAction)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,29 +19,28 @@ DankModal {
|
||||
|
||||
function show() {
|
||||
if (!DgopService.dgopAvailable) {
|
||||
console.warn("ProcessListModal: dgop is not available");
|
||||
return ;
|
||||
console.warn("ProcessListModal: dgop is not available")
|
||||
return
|
||||
}
|
||||
open();
|
||||
UserInfoService.getUptime();
|
||||
open()
|
||||
UserInfoService.getUptime()
|
||||
}
|
||||
|
||||
function hide() {
|
||||
close();
|
||||
close()
|
||||
if (processContextMenu.visible)
|
||||
processContextMenu.close();
|
||||
|
||||
processContextMenu.close()
|
||||
}
|
||||
|
||||
function toggle() {
|
||||
if (!DgopService.dgopAvailable) {
|
||||
console.warn("ProcessListModal: dgop is not available");
|
||||
return ;
|
||||
console.warn("ProcessListModal: dgop is not available")
|
||||
return
|
||||
}
|
||||
if (shouldBeVisible)
|
||||
hide();
|
||||
hide()
|
||||
else
|
||||
show();
|
||||
show()
|
||||
}
|
||||
|
||||
width: 900
|
||||
@@ -58,23 +57,18 @@ DankModal {
|
||||
ProcessesTab {
|
||||
contextMenu: processContextMenu
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Component {
|
||||
id: performanceTabComponent
|
||||
|
||||
PerformanceTab {
|
||||
}
|
||||
|
||||
PerformanceTab {}
|
||||
}
|
||||
|
||||
Component {
|
||||
id: systemTabComponent
|
||||
|
||||
SystemTab {
|
||||
}
|
||||
|
||||
SystemTab {}
|
||||
}
|
||||
|
||||
ProcessContextMenu {
|
||||
@@ -85,19 +79,19 @@ DankModal {
|
||||
Item {
|
||||
anchors.fill: parent
|
||||
focus: true
|
||||
Keys.onPressed: function(event) {
|
||||
Keys.onPressed: function (event) {
|
||||
if (event.key === Qt.Key_Escape) {
|
||||
processListModal.hide();
|
||||
event.accepted = true;
|
||||
processListModal.hide()
|
||||
event.accepted = true
|
||||
} else if (event.key === Qt.Key_1) {
|
||||
currentTab = 0;
|
||||
event.accepted = true;
|
||||
currentTab = 0
|
||||
event.accepted = true
|
||||
} else if (event.key === Qt.Key_2) {
|
||||
currentTab = 1;
|
||||
event.accepted = true;
|
||||
currentTab = 1
|
||||
event.accepted = true
|
||||
} else if (event.key === Qt.Key_3) {
|
||||
currentTab = 2;
|
||||
event.accepted = true;
|
||||
currentTab = 2
|
||||
event.accepted = true
|
||||
}
|
||||
}
|
||||
|
||||
@@ -139,9 +133,7 @@ DankModal {
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
wrapMode: Text.WordWrap
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
ColumnLayout {
|
||||
@@ -175,7 +167,6 @@ DankModal {
|
||||
onClicked: processListModal.hide()
|
||||
Layout.alignment: Qt.AlignVCenter
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
@@ -210,17 +201,18 @@ DankModal {
|
||||
name: {
|
||||
switch (index) {
|
||||
case 0:
|
||||
return "list_alt";
|
||||
return "list_alt"
|
||||
case 1:
|
||||
return "analytics";
|
||||
return "analytics"
|
||||
case 2:
|
||||
return "settings";
|
||||
return "settings"
|
||||
default:
|
||||
return "tab";
|
||||
return "tab"
|
||||
}
|
||||
}
|
||||
size: Theme.iconSize - 2
|
||||
color: currentTab === index ? Theme.primary : Theme.surfaceText
|
||||
color: currentTab
|
||||
=== index ? Theme.primary : Theme.surfaceText
|
||||
opacity: currentTab === index ? 1 : 0.7
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
|
||||
@@ -228,16 +220,15 @@ DankModal {
|
||||
ColorAnimation {
|
||||
duration: Theme.shortDuration
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
StyledText {
|
||||
text: modelData
|
||||
font.pixelSize: Theme.fontSizeLarge
|
||||
font.weight: Font.Medium
|
||||
color: currentTab === index ? Theme.primary : Theme.surfaceText
|
||||
color: currentTab
|
||||
=== index ? Theme.primary : Theme.surfaceText
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
anchors.verticalCenterOffset: -1
|
||||
|
||||
@@ -245,11 +236,8 @@ DankModal {
|
||||
ColorAnimation {
|
||||
duration: Theme.shortDuration
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
@@ -259,7 +247,7 @@ DankModal {
|
||||
hoverEnabled: true
|
||||
cursorShape: Qt.PointingHandCursor
|
||||
onClicked: {
|
||||
currentTab = index;
|
||||
currentTab = index
|
||||
}
|
||||
}
|
||||
|
||||
@@ -267,22 +255,16 @@ DankModal {
|
||||
ColorAnimation {
|
||||
duration: Theme.shortDuration
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Behavior on border.color {
|
||||
ColorAnimation {
|
||||
duration: Theme.shortDuration
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
@@ -308,9 +290,7 @@ DankModal {
|
||||
duration: Theme.mediumDuration
|
||||
easing.type: Theme.emphasizedEasing
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Loader {
|
||||
@@ -328,9 +308,7 @@ DankModal {
|
||||
duration: Theme.mediumDuration
|
||||
easing.type: Theme.emphasizedEasing
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Loader {
|
||||
@@ -348,17 +326,10 @@ DankModal {
|
||||
duration: Theme.mediumDuration
|
||||
easing.type: Theme.emphasizedEasing
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -14,21 +14,21 @@ DankModal {
|
||||
|
||||
property Component settingsContent
|
||||
|
||||
signal closingModal()
|
||||
signal closingModal
|
||||
|
||||
function show() {
|
||||
open();
|
||||
open()
|
||||
}
|
||||
|
||||
function hide() {
|
||||
close();
|
||||
close()
|
||||
}
|
||||
|
||||
function toggle() {
|
||||
if (shouldBeVisible)
|
||||
hide();
|
||||
hide()
|
||||
else
|
||||
show();
|
||||
show()
|
||||
}
|
||||
|
||||
objectName: "settingsModal"
|
||||
@@ -40,18 +40,18 @@ DankModal {
|
||||
|
||||
IpcHandler {
|
||||
function open() {
|
||||
settingsModal.show();
|
||||
return "SETTINGS_OPEN_SUCCESS";
|
||||
settingsModal.show()
|
||||
return "SETTINGS_OPEN_SUCCESS"
|
||||
}
|
||||
|
||||
function close() {
|
||||
settingsModal.hide();
|
||||
return "SETTINGS_CLOSE_SUCCESS";
|
||||
settingsModal.hide()
|
||||
return "SETTINGS_CLOSE_SUCCESS"
|
||||
}
|
||||
|
||||
function toggle() {
|
||||
settingsModal.toggle();
|
||||
return "SETTINGS_TOGGLE_SUCCESS";
|
||||
settingsModal.toggle()
|
||||
return "SETTINGS_TOGGLE_SUCCESS"
|
||||
}
|
||||
|
||||
target: "settings"
|
||||
@@ -103,7 +103,6 @@ DankModal {
|
||||
hoverColor: Theme.errorHover
|
||||
onClicked: settingsModal.hide()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Main content with side navigation
|
||||
@@ -153,7 +152,8 @@ DankModal {
|
||||
height: 80
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
|
||||
property bool hasImage: profileImageSource.status === Image.Ready
|
||||
property bool hasImage: profileImageSource.status
|
||||
=== Image.Ready
|
||||
|
||||
Rectangle {
|
||||
anchors.fill: parent
|
||||
@@ -168,10 +168,11 @@ DankModal {
|
||||
id: profileImageSource
|
||||
source: {
|
||||
if (PortalService.profileImage === "")
|
||||
return "";
|
||||
if (PortalService.profileImage.startsWith("/"))
|
||||
return "file://" + PortalService.profileImage;
|
||||
return PortalService.profileImage;
|
||||
return ""
|
||||
if (PortalService.profileImage.startsWith(
|
||||
"/"))
|
||||
return "file://" + PortalService.profileImage
|
||||
return PortalService.profileImage
|
||||
}
|
||||
smooth: true
|
||||
asynchronous: true
|
||||
@@ -226,7 +227,8 @@ DankModal {
|
||||
name: "warning"
|
||||
size: Theme.iconSizeLarge
|
||||
color: Theme.error
|
||||
visible: PortalService.profileImage !== "" && profileImageSource.status === Image.Error
|
||||
visible: PortalService.profileImage !== ""
|
||||
&& profileImageSource.status === Image.Error
|
||||
}
|
||||
|
||||
// Hover overlay with edit and clear buttons
|
||||
@@ -235,54 +237,58 @@ DankModal {
|
||||
radius: width / 2
|
||||
color: Qt.rgba(0, 0, 0, 0.7)
|
||||
visible: profileMouseArea.containsMouse
|
||||
|
||||
|
||||
Row {
|
||||
anchors.centerIn: parent
|
||||
spacing: 4
|
||||
|
||||
|
||||
Rectangle {
|
||||
width: 28
|
||||
height: 28
|
||||
radius: 14
|
||||
color: Qt.rgba(255, 255, 255, 0.9)
|
||||
|
||||
color: Qt.rgba(255, 255,
|
||||
255, 0.9)
|
||||
|
||||
DankIcon {
|
||||
anchors.centerIn: parent
|
||||
name: "edit"
|
||||
size: 16
|
||||
color: "black"
|
||||
}
|
||||
|
||||
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
cursorShape: Qt.PointingHandCursor
|
||||
onClicked: {
|
||||
settingsModal.allowFocusOverride = true;
|
||||
settingsModal.shouldHaveFocus = false;
|
||||
profileBrowser.open();
|
||||
settingsModal.allowFocusOverride = true
|
||||
settingsModal.shouldHaveFocus = false
|
||||
profileBrowser.open(
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Rectangle {
|
||||
width: 28
|
||||
height: 28
|
||||
radius: 14
|
||||
color: Qt.rgba(255, 255, 255, 0.9)
|
||||
color: Qt.rgba(255, 255,
|
||||
255, 0.9)
|
||||
visible: profileImageContainer.hasImage
|
||||
|
||||
|
||||
DankIcon {
|
||||
anchors.centerIn: parent
|
||||
name: "close"
|
||||
size: 16
|
||||
color: "black"
|
||||
}
|
||||
|
||||
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
cursorShape: Qt.PointingHandCursor
|
||||
onClicked: {
|
||||
PortalService.setProfileImage("");
|
||||
PortalService.setProfileImage(
|
||||
"")
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -306,7 +312,8 @@ DankModal {
|
||||
spacing: Theme.spacingXS
|
||||
|
||||
StyledText {
|
||||
text: UserInfoService.fullName || "User"
|
||||
text: UserInfoService.fullName
|
||||
|| "User"
|
||||
font.pixelSize: Theme.fontSizeLarge
|
||||
font.weight: Font.Medium
|
||||
color: Theme.surfaceText
|
||||
@@ -315,7 +322,8 @@ DankModal {
|
||||
}
|
||||
|
||||
StyledText {
|
||||
text: DgopService.distribution || "Linux"
|
||||
text: DgopService.distribution
|
||||
|| "Linux"
|
||||
font.pixelSize: Theme.fontSizeMedium
|
||||
color: Theme.surfaceVariantText
|
||||
elide: Text.ElideRight
|
||||
@@ -341,33 +349,33 @@ DankModal {
|
||||
id: sidebarRepeater
|
||||
|
||||
model: [{
|
||||
"text": "Personalization",
|
||||
"icon": "person"
|
||||
}, {
|
||||
"text": "Time & Date",
|
||||
"icon": "schedule"
|
||||
}, {
|
||||
"text": "Weather",
|
||||
"icon": "cloud"
|
||||
}, {
|
||||
"text": "Top Bar",
|
||||
"icon": "toolbar"
|
||||
}, {
|
||||
"text": "Widgets",
|
||||
"icon": "widgets"
|
||||
}, {
|
||||
"text": "Dock",
|
||||
"icon": "dock_to_bottom"
|
||||
}, {
|
||||
"text": "Recent Apps",
|
||||
"icon": "history"
|
||||
}, {
|
||||
"text": "Theme & Colors",
|
||||
"icon": "palette"
|
||||
}, {
|
||||
"text": "About",
|
||||
"icon": "info"
|
||||
}]
|
||||
"text": "Personalization",
|
||||
"icon": "person"
|
||||
}, {
|
||||
"text": "Time & Date",
|
||||
"icon": "schedule"
|
||||
}, {
|
||||
"text": "Weather",
|
||||
"icon": "cloud"
|
||||
}, {
|
||||
"text": "Top Bar",
|
||||
"icon": "toolbar"
|
||||
}, {
|
||||
"text": "Widgets",
|
||||
"icon": "widgets"
|
||||
}, {
|
||||
"text": "Dock",
|
||||
"icon": "dock_to_bottom"
|
||||
}, {
|
||||
"text": "Recent Apps",
|
||||
"icon": "history"
|
||||
}, {
|
||||
"text": "Theme & Colors",
|
||||
"icon": "palette"
|
||||
}, {
|
||||
"text": "About",
|
||||
"icon": "info"
|
||||
}]
|
||||
|
||||
Rectangle {
|
||||
property bool isActive: sidebarContainer.currentIndex === index
|
||||
@@ -397,7 +405,6 @@ DankModal {
|
||||
font.weight: parent.parent.isActive ? Font.Medium : Font.Normal
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
@@ -407,7 +414,7 @@ DankModal {
|
||||
hoverEnabled: true
|
||||
cursorShape: Qt.PointingHandCursor
|
||||
onClicked: {
|
||||
sidebarContainer.currentIndex = index;
|
||||
sidebarContainer.currentIndex = index
|
||||
}
|
||||
}
|
||||
|
||||
@@ -416,15 +423,10 @@ DankModal {
|
||||
duration: Theme.shortDuration
|
||||
easing.type: Theme.standardEasing
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Main content area
|
||||
@@ -452,9 +454,7 @@ DankModal {
|
||||
PersonalizationTab {
|
||||
parentModal: settingsModal
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Loader {
|
||||
@@ -509,11 +509,8 @@ DankModal {
|
||||
asynchronous: true
|
||||
|
||||
sourceComponent: Component {
|
||||
DockTab {
|
||||
}
|
||||
|
||||
DockTab {}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Loader {
|
||||
@@ -545,210 +542,224 @@ DankModal {
|
||||
asynchronous: true
|
||||
sourceComponent: AboutTab {}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Footer
|
||||
Row {
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
spacing: Theme.spacingXS
|
||||
|
||||
|
||||
// Dank logo
|
||||
Item {
|
||||
width: 68
|
||||
height: 16
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
|
||||
|
||||
Image {
|
||||
anchors.fill: parent
|
||||
source: Qt.resolvedUrl(".").toString().replace("file://", "").replace("/Modals/", "") + "/assets/dank.svg"
|
||||
source: Qt.resolvedUrl(".").toString().replace(
|
||||
"file://",
|
||||
"").replace("/Modals/",
|
||||
"") + "/assets/dank.svg"
|
||||
sourceSize: Qt.size(68, 16)
|
||||
smooth: true
|
||||
fillMode: Image.PreserveAspectFit
|
||||
layer.enabled: true
|
||||
|
||||
|
||||
layer.effect: MultiEffect {
|
||||
colorization: 1
|
||||
colorizationColor: Theme.primary
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
cursorShape: Qt.PointingHandCursor
|
||||
onClicked: Qt.openUrlExternally("https://github.com/AvengeMedia/DankMaterialShell")
|
||||
onClicked: Qt.openUrlExternally(
|
||||
"https://github.com/AvengeMedia/DankMaterialShell")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
StyledText {
|
||||
text: "•"
|
||||
font.pixelSize: Theme.fontSizeSmall
|
||||
color: Theme.surfaceVariantText
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
}
|
||||
|
||||
|
||||
Rectangle {
|
||||
width: Theme.spacingXS
|
||||
height: 1
|
||||
color: "transparent"
|
||||
}
|
||||
|
||||
|
||||
// Niri logo
|
||||
Item {
|
||||
width: 24
|
||||
height: 24
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
|
||||
|
||||
Image {
|
||||
anchors.fill: parent
|
||||
source: Qt.resolvedUrl(".").toString().replace("file://", "").replace("/Modals/", "") + "/assets/niri.svg"
|
||||
source: Qt.resolvedUrl(".").toString().replace(
|
||||
"file://",
|
||||
"").replace("/Modals/",
|
||||
"") + "/assets/niri.svg"
|
||||
sourceSize: Qt.size(24, 24)
|
||||
smooth: true
|
||||
fillMode: Image.PreserveAspectFit
|
||||
}
|
||||
|
||||
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
cursorShape: Qt.PointingHandCursor
|
||||
onClicked: Qt.openUrlExternally("https://github.com/YaLTeR/niri")
|
||||
onClicked: Qt.openUrlExternally(
|
||||
"https://github.com/YaLTeR/niri")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Rectangle {
|
||||
width: Theme.spacingXS
|
||||
height: 1
|
||||
color: "transparent"
|
||||
}
|
||||
|
||||
|
||||
StyledText {
|
||||
text: "•"
|
||||
font.pixelSize: Theme.fontSizeSmall
|
||||
color: Theme.surfaceVariantText
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
}
|
||||
|
||||
|
||||
Rectangle {
|
||||
width: Theme.spacingM
|
||||
height: 1
|
||||
color: "transparent"
|
||||
}
|
||||
|
||||
|
||||
// Matrix button
|
||||
Item {
|
||||
width: 32
|
||||
height: 20
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
|
||||
|
||||
Image {
|
||||
anchors.fill: parent
|
||||
source: Qt.resolvedUrl(".").toString().replace("file://", "").replace("/Modals/", "") + "/assets/matrix-logo-white.svg"
|
||||
source: Qt.resolvedUrl(".").toString().replace(
|
||||
"file://", "").replace(
|
||||
"/Modals/",
|
||||
"") + "/assets/matrix-logo-white.svg"
|
||||
sourceSize: Qt.size(32, 20)
|
||||
smooth: true
|
||||
fillMode: Image.PreserveAspectFit
|
||||
layer.enabled: true
|
||||
|
||||
|
||||
layer.effect: MultiEffect {
|
||||
colorization: 1
|
||||
colorizationColor: Theme.surfaceText
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
cursorShape: Qt.PointingHandCursor
|
||||
onClicked: Qt.openUrlExternally("https://matrix.to/#/#niri:matrix.org")
|
||||
onClicked: Qt.openUrlExternally(
|
||||
"https://matrix.to/#/#niri:matrix.org")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Rectangle {
|
||||
width: Theme.spacingM
|
||||
height: 1
|
||||
color: "transparent"
|
||||
}
|
||||
|
||||
|
||||
StyledText {
|
||||
text: "•"
|
||||
font.pixelSize: Theme.fontSizeSmall
|
||||
color: Theme.surfaceVariantText
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
}
|
||||
|
||||
|
||||
Rectangle {
|
||||
width: Theme.spacingM
|
||||
height: 1
|
||||
color: "transparent"
|
||||
}
|
||||
|
||||
|
||||
// Discord button
|
||||
Item {
|
||||
width: 16
|
||||
height: 16
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
|
||||
|
||||
Image {
|
||||
anchors.fill: parent
|
||||
source: Qt.resolvedUrl(".").toString().replace("file://", "").replace("/Modals/", "") + "/assets/discord.svg"
|
||||
source: Qt.resolvedUrl(".").toString().replace(
|
||||
"file://",
|
||||
"").replace("/Modals/",
|
||||
"") + "/assets/discord.svg"
|
||||
sourceSize: Qt.size(16, 16)
|
||||
smooth: true
|
||||
fillMode: Image.PreserveAspectFit
|
||||
}
|
||||
|
||||
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
cursorShape: Qt.PointingHandCursor
|
||||
onClicked: Qt.openUrlExternally("https://discord.gg/vT8Sfjy7sx")
|
||||
onClicked: Qt.openUrlExternally(
|
||||
"https://discord.gg/vT8Sfjy7sx")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Rectangle {
|
||||
width: Theme.spacingM
|
||||
height: 1
|
||||
color: "transparent"
|
||||
}
|
||||
|
||||
|
||||
StyledText {
|
||||
text: "•"
|
||||
font.pixelSize: Theme.fontSizeSmall
|
||||
color: Theme.surfaceVariantText
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
}
|
||||
|
||||
|
||||
Rectangle {
|
||||
width: Theme.spacingM
|
||||
height: 1
|
||||
color: "transparent"
|
||||
}
|
||||
|
||||
|
||||
// Reddit button
|
||||
Item {
|
||||
width: 18
|
||||
height: 18
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
|
||||
|
||||
Image {
|
||||
anchors.fill: parent
|
||||
source: Qt.resolvedUrl(".").toString().replace("file://", "").replace("/Modals/", "") + "/assets/reddit.svg"
|
||||
source: Qt.resolvedUrl(".").toString().replace(
|
||||
"file://",
|
||||
"").replace("/Modals/",
|
||||
"") + "/assets/reddit.svg"
|
||||
sourceSize: Qt.size(18, 18)
|
||||
smooth: true
|
||||
fillMode: Image.PreserveAspectFit
|
||||
}
|
||||
|
||||
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
cursorShape: Qt.PointingHandCursor
|
||||
onClicked: Qt.openUrlExternally("https://reddit.com/r/niri")
|
||||
onClicked: Qt.openUrlExternally(
|
||||
"https://reddit.com/r/niri")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
FileBrowserModal {
|
||||
@@ -758,18 +769,17 @@ DankModal {
|
||||
browserIcon: "person"
|
||||
browserType: "profile"
|
||||
fileExtensions: ["*.jpg", "*.jpeg", "*.png", "*.bmp", "*.gif", "*.webp"]
|
||||
onFileSelected: (path) => {
|
||||
PortalService.setProfileImage(path);
|
||||
close();
|
||||
}
|
||||
onFileSelected: path => {
|
||||
PortalService.setProfileImage(path)
|
||||
close()
|
||||
}
|
||||
onDialogClosed: {
|
||||
if (settingsModal) {
|
||||
settingsModal.allowFocusOverride = false;
|
||||
settingsModal.allowFocusOverride = false
|
||||
settingsModal.shouldHaveFocus = Qt.binding(() => {
|
||||
return settingsModal.shouldBeVisible;
|
||||
});
|
||||
return settingsModal.shouldBeVisible
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -16,41 +16,41 @@ DankModal {
|
||||
property Component spotlightContent
|
||||
|
||||
function show() {
|
||||
spotlightOpen = true;
|
||||
open();
|
||||
spotlightOpen = true
|
||||
open()
|
||||
if (contentLoader.item && contentLoader.item.appLauncher)
|
||||
contentLoader.item.appLauncher.searchQuery = "";
|
||||
contentLoader.item.appLauncher.searchQuery = ""
|
||||
|
||||
Qt.callLater(function() {
|
||||
Qt.callLater(function () {
|
||||
if (contentLoader.item && contentLoader.item.searchField)
|
||||
contentLoader.item.searchField.forceActiveFocus();
|
||||
|
||||
});
|
||||
contentLoader.item.searchField.forceActiveFocus()
|
||||
})
|
||||
}
|
||||
|
||||
function hide() {
|
||||
spotlightOpen = false;
|
||||
close();
|
||||
spotlightOpen = false
|
||||
close()
|
||||
if (contentLoader.item && contentLoader.item.appLauncher) {
|
||||
contentLoader.item.appLauncher.searchQuery = "";
|
||||
contentLoader.item.appLauncher.selectedIndex = 0;
|
||||
contentLoader.item.appLauncher.setCategory("All");
|
||||
contentLoader.item.appLauncher.searchQuery = ""
|
||||
contentLoader.item.appLauncher.selectedIndex = 0
|
||||
contentLoader.item.appLauncher.setCategory("All")
|
||||
}
|
||||
}
|
||||
|
||||
function toggle() {
|
||||
if (spotlightOpen)
|
||||
hide();
|
||||
hide()
|
||||
else
|
||||
show();
|
||||
show()
|
||||
}
|
||||
|
||||
shouldBeVisible: spotlightOpen
|
||||
|
||||
|
||||
Connections {
|
||||
target: ModalManager
|
||||
function onCloseAllModalsExcept(excludedModal) {
|
||||
if (excludedModal !== spotlightModal && !allowStacking && spotlightOpen) {
|
||||
if (excludedModal !== spotlightModal && !allowStacking
|
||||
&& spotlightOpen) {
|
||||
spotlightOpen = false
|
||||
}
|
||||
}
|
||||
@@ -64,43 +64,41 @@ DankModal {
|
||||
enableShadow: true
|
||||
onVisibleChanged: {
|
||||
if (visible && !spotlightOpen)
|
||||
show();
|
||||
show()
|
||||
|
||||
if (visible && contentLoader.item)
|
||||
Qt.callLater(function() {
|
||||
Qt.callLater(function () {
|
||||
if (contentLoader.item.searchField)
|
||||
contentLoader.item.searchField.forceActiveFocus();
|
||||
|
||||
});
|
||||
|
||||
contentLoader.item.searchField.forceActiveFocus()
|
||||
})
|
||||
}
|
||||
onBackgroundClicked: {
|
||||
hide();
|
||||
hide()
|
||||
}
|
||||
Component.onCompleted: {
|
||||
|
||||
}
|
||||
content: spotlightContent
|
||||
|
||||
IpcHandler {
|
||||
function open() {
|
||||
spotlightModal.show();
|
||||
return "SPOTLIGHT_OPEN_SUCCESS";
|
||||
spotlightModal.show()
|
||||
return "SPOTLIGHT_OPEN_SUCCESS"
|
||||
}
|
||||
|
||||
function close() {
|
||||
spotlightModal.hide();
|
||||
return "SPOTLIGHT_CLOSE_SUCCESS";
|
||||
spotlightModal.hide()
|
||||
return "SPOTLIGHT_CLOSE_SUCCESS"
|
||||
}
|
||||
|
||||
function toggle() {
|
||||
spotlightModal.toggle();
|
||||
return "SPOTLIGHT_TOGGLE_SUCCESS";
|
||||
spotlightModal.toggle()
|
||||
return "SPOTLIGHT_TOGGLE_SUCCESS"
|
||||
}
|
||||
|
||||
target: "spotlight"
|
||||
}
|
||||
|
||||
|
||||
spotlightContent: Component {
|
||||
Item {
|
||||
id: spotlightKeyHandler
|
||||
@@ -110,29 +108,34 @@ DankModal {
|
||||
|
||||
anchors.fill: parent
|
||||
focus: true
|
||||
Keys.onPressed: function(event) {
|
||||
Keys.onPressed: function (event) {
|
||||
if (event.key === Qt.Key_Escape) {
|
||||
hide();
|
||||
event.accepted = true;
|
||||
hide()
|
||||
event.accepted = true
|
||||
} else if (event.key === Qt.Key_Down) {
|
||||
appLauncher.selectNext();
|
||||
event.accepted = true;
|
||||
appLauncher.selectNext()
|
||||
event.accepted = true
|
||||
} else if (event.key === Qt.Key_Up) {
|
||||
appLauncher.selectPrevious();
|
||||
event.accepted = true;
|
||||
} else if (event.key === Qt.Key_Right && appLauncher.viewMode === "grid") {
|
||||
appLauncher.selectNextInRow();
|
||||
event.accepted = true;
|
||||
} else if (event.key === Qt.Key_Left && appLauncher.viewMode === "grid") {
|
||||
appLauncher.selectPreviousInRow();
|
||||
event.accepted = true;
|
||||
} else if (event.key === Qt.Key_Return || event.key === Qt.Key_Enter) {
|
||||
appLauncher.launchSelected();
|
||||
event.accepted = true;
|
||||
} else if (!searchField.activeFocus && event.text && event.text.length > 0 && event.text.match(/[a-zA-Z0-9\\s]/)) {
|
||||
searchField.forceActiveFocus();
|
||||
searchField.insertText(event.text);
|
||||
event.accepted = true;
|
||||
appLauncher.selectPrevious()
|
||||
event.accepted = true
|
||||
} else if (event.key === Qt.Key_Right
|
||||
&& appLauncher.viewMode === "grid") {
|
||||
appLauncher.selectNextInRow()
|
||||
event.accepted = true
|
||||
} else if (event.key === Qt.Key_Left
|
||||
&& appLauncher.viewMode === "grid") {
|
||||
appLauncher.selectPreviousInRow()
|
||||
event.accepted = true
|
||||
} else if (event.key === Qt.Key_Return
|
||||
|| event.key === Qt.Key_Enter) {
|
||||
appLauncher.launchSelected()
|
||||
event.accepted = true
|
||||
} else if (!searchField.activeFocus && event.text
|
||||
&& event.text.length > 0 && event.text.match(
|
||||
/[a-zA-Z0-9\\s]/)) {
|
||||
searchField.forceActiveFocus()
|
||||
searchField.insertText(event.text)
|
||||
event.accepted = true
|
||||
}
|
||||
}
|
||||
|
||||
@@ -142,8 +145,8 @@ DankModal {
|
||||
viewMode: SettingsData.spotlightModalViewMode
|
||||
gridColumns: 4
|
||||
onAppLaunched: hide()
|
||||
onViewModeSelected: function(mode) {
|
||||
SettingsData.setSpotlightModalViewMode(mode);
|
||||
onViewModeSelected: function (mode) {
|
||||
SettingsData.setSpotlightModalViewMode(mode)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -159,7 +162,8 @@ DankModal {
|
||||
color: Theme.surfaceVariantAlpha
|
||||
border.color: Theme.outlineMedium
|
||||
border.width: 1
|
||||
visible: appLauncher.categories.length > 1 || appLauncher.model.count > 0
|
||||
visible: appLauncher.categories.length > 1
|
||||
|| appLauncher.model.count > 0
|
||||
|
||||
CategorySelector {
|
||||
id: categorySelector
|
||||
@@ -169,11 +173,11 @@ DankModal {
|
||||
categories: appLauncher.categories
|
||||
selectedCategory: appLauncher.selectedCategory
|
||||
compact: false
|
||||
onCategorySelected: (category) => {
|
||||
return appLauncher.setCategory(category);
|
||||
}
|
||||
onCategorySelected: category => {
|
||||
return appLauncher.setCategory(
|
||||
category)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Row {
|
||||
@@ -183,10 +187,16 @@ DankModal {
|
||||
DankTextField {
|
||||
id: searchField
|
||||
|
||||
width: parent.width - 80 - Theme.spacingM // Leave space for view toggle buttons
|
||||
width: parent.width - 80
|
||||
- Theme.spacingM // Leave space for view toggle buttons
|
||||
height: 56
|
||||
cornerRadius: Theme.cornerRadius
|
||||
backgroundColor: Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, Theme.getContentBackgroundAlpha() * 0.7)
|
||||
backgroundColor: Qt.rgba(
|
||||
Theme.surfaceVariant.r,
|
||||
Theme.surfaceVariant.g,
|
||||
Theme.surfaceVariant.b,
|
||||
Theme.getContentBackgroundAlpha(
|
||||
) * 0.7)
|
||||
normalBorderColor: Theme.outlineMedium
|
||||
focusedBorderColor: Theme.primary
|
||||
leftIconName: "search"
|
||||
@@ -202,22 +212,26 @@ DankModal {
|
||||
keyForwardTargets: [spotlightKeyHandler]
|
||||
text: appLauncher.searchQuery
|
||||
onTextEdited: {
|
||||
appLauncher.searchQuery = text;
|
||||
}
|
||||
Keys.onPressed: (event) => {
|
||||
if (event.key === Qt.Key_Escape) {
|
||||
hide();
|
||||
event.accepted = true;
|
||||
} else if ((event.key === Qt.Key_Return || event.key === Qt.Key_Enter) && text.length > 0) {
|
||||
if (appLauncher.keyboardNavigationActive && appLauncher.model.count > 0)
|
||||
appLauncher.launchSelected();
|
||||
else if (appLauncher.model.count > 0)
|
||||
appLauncher.launchApp(appLauncher.model.get(0));
|
||||
event.accepted = true;
|
||||
} else if (event.key === Qt.Key_Down || event.key === Qt.Key_Up || event.key === Qt.Key_Left || event.key === Qt.Key_Right || ((event.key === Qt.Key_Return || event.key === Qt.Key_Enter) && text.length === 0)) {
|
||||
event.accepted = false;
|
||||
}
|
||||
appLauncher.searchQuery = text
|
||||
}
|
||||
Keys.onPressed: event => {
|
||||
if (event.key === Qt.Key_Escape) {
|
||||
hide()
|
||||
event.accepted = true
|
||||
} else if ((event.key === Qt.Key_Return
|
||||
|| event.key === Qt.Key_Enter)
|
||||
&& text.length > 0) {
|
||||
if (appLauncher.keyboardNavigationActive
|
||||
&& appLauncher.model.count > 0)
|
||||
appLauncher.launchSelected()
|
||||
else if (appLauncher.model.count > 0)
|
||||
appLauncher.launchApp(
|
||||
appLauncher.model.get(0))
|
||||
event.accepted = true
|
||||
} else if (event.key === Qt.Key_Down || event.key === Qt.Key_Up || event.key === Qt.Key_Left || event.key === Qt.Key_Right || ((event.key === Qt.Key_Return || event.key === Qt.Key_Enter) && text.length === 0)) {
|
||||
event.accepted = false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Row {
|
||||
@@ -230,14 +244,16 @@ DankModal {
|
||||
height: 36
|
||||
radius: Theme.cornerRadius
|
||||
color: appLauncher.viewMode === "list" ? Theme.primaryHover : listViewArea.containsMouse ? Theme.surfaceHover : "transparent"
|
||||
border.color: appLauncher.viewMode === "list" ? Theme.primarySelected : "transparent"
|
||||
border.color: appLauncher.viewMode
|
||||
=== "list" ? Theme.primarySelected : "transparent"
|
||||
border.width: 1
|
||||
|
||||
DankIcon {
|
||||
anchors.centerIn: parent
|
||||
name: "view_list"
|
||||
size: 18
|
||||
color: appLauncher.viewMode === "list" ? Theme.primary : Theme.surfaceText
|
||||
color: appLauncher.viewMode
|
||||
=== "list" ? Theme.primary : Theme.surfaceText
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
@@ -247,10 +263,9 @@ DankModal {
|
||||
hoverEnabled: true
|
||||
cursorShape: Qt.PointingHandCursor
|
||||
onClicked: {
|
||||
appLauncher.setViewMode("list");
|
||||
appLauncher.setViewMode("list")
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
@@ -258,14 +273,16 @@ DankModal {
|
||||
height: 36
|
||||
radius: Theme.cornerRadius
|
||||
color: appLauncher.viewMode === "grid" ? Theme.primaryHover : gridViewArea.containsMouse ? Theme.surfaceHover : "transparent"
|
||||
border.color: appLauncher.viewMode === "grid" ? Theme.primarySelected : "transparent"
|
||||
border.color: appLauncher.viewMode
|
||||
=== "grid" ? Theme.primarySelected : "transparent"
|
||||
border.width: 1
|
||||
|
||||
DankIcon {
|
||||
anchors.centerIn: parent
|
||||
name: "grid_view"
|
||||
size: 18
|
||||
color: appLauncher.viewMode === "grid" ? Theme.primary : Theme.surfaceText
|
||||
color: appLauncher.viewMode
|
||||
=== "grid" ? Theme.primary : Theme.surfaceText
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
@@ -275,14 +292,11 @@ DankModal {
|
||||
hoverEnabled: true
|
||||
cursorShape: Qt.PointingHandCursor
|
||||
onClicked: {
|
||||
appLauncher.setViewMode("grid");
|
||||
appLauncher.setViewMode("grid")
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
@@ -305,20 +319,20 @@ DankModal {
|
||||
property bool hoverUpdatesSelection: false
|
||||
property bool keyboardNavigationActive: appLauncher.keyboardNavigationActive
|
||||
|
||||
signal keyboardNavigationReset()
|
||||
signal keyboardNavigationReset
|
||||
signal itemClicked(int index, var modelData)
|
||||
signal itemRightClicked(int index, var modelData, real mouseX, real mouseY)
|
||||
|
||||
function ensureVisible(index) {
|
||||
if (index < 0 || index >= count)
|
||||
return ;
|
||||
return
|
||||
|
||||
var itemY = index * (itemHeight + itemSpacing);
|
||||
var itemBottom = itemY + itemHeight;
|
||||
var itemY = index * (itemHeight + itemSpacing)
|
||||
var itemBottom = itemY + itemHeight
|
||||
if (itemY < contentY)
|
||||
contentY = itemY;
|
||||
contentY = itemY
|
||||
else if (itemBottom > contentY + height)
|
||||
contentY = itemBottom - height;
|
||||
contentY = itemBottom - height
|
||||
}
|
||||
|
||||
anchors.fill: parent
|
||||
@@ -334,17 +348,16 @@ DankModal {
|
||||
reuseItems: true
|
||||
onCurrentIndexChanged: {
|
||||
if (keyboardNavigationActive)
|
||||
ensureVisible(currentIndex);
|
||||
|
||||
ensureVisible(currentIndex)
|
||||
}
|
||||
onItemClicked: function(index, modelData) {
|
||||
appLauncher.launchApp(modelData);
|
||||
onItemClicked: function (index, modelData) {
|
||||
appLauncher.launchApp(modelData)
|
||||
}
|
||||
onItemRightClicked: function(index, modelData, mouseX, mouseY) {
|
||||
contextMenu.show(mouseX, mouseY, modelData);
|
||||
onItemRightClicked: function (index, modelData, mouseX, mouseY) {
|
||||
contextMenu.show(mouseX, mouseY, modelData)
|
||||
}
|
||||
onKeyboardNavigationReset: {
|
||||
appLauncher.keyboardNavigationActive = false;
|
||||
appLauncher.keyboardNavigationActive = false
|
||||
}
|
||||
|
||||
ScrollBar.vertical: ScrollBar {
|
||||
@@ -377,7 +390,9 @@ DankModal {
|
||||
id: listIconImg
|
||||
|
||||
anchors.fill: parent
|
||||
source: (model.icon) ? Quickshell.iconPath(model.icon, SettingsData.iconTheme === "System Default" ? "" : SettingsData.iconTheme) : ""
|
||||
source: (model.icon) ? Quickshell.iconPath(
|
||||
model.icon,
|
||||
SettingsData.iconTheme === "System Default" ? "" : SettingsData.iconTheme) : ""
|
||||
smooth: true
|
||||
asynchronous: true
|
||||
visible: status === Image.Ready
|
||||
@@ -393,14 +408,16 @@ DankModal {
|
||||
|
||||
StyledText {
|
||||
anchors.centerIn: parent
|
||||
text: (model.name && model.name.length > 0) ? model.name.charAt(0).toUpperCase() : "A"
|
||||
text: (model.name
|
||||
&& model.name.length
|
||||
> 0) ? model.name.charAt(
|
||||
0).toUpperCase(
|
||||
) : "A"
|
||||
font.pixelSize: resultsList.iconSize * 0.4
|
||||
color: Theme.primary
|
||||
font.weight: Font.Bold
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Column {
|
||||
@@ -423,11 +440,11 @@ DankModal {
|
||||
font.pixelSize: Theme.fontSizeMedium
|
||||
color: Theme.surfaceVariantText
|
||||
elide: Text.ElideRight
|
||||
visible: resultsList.showDescription && model.comment && model.comment.length > 0
|
||||
visible: resultsList.showDescription
|
||||
&& model.comment
|
||||
&& model.comment.length > 0
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
@@ -439,25 +456,28 @@ DankModal {
|
||||
acceptedButtons: Qt.LeftButton | Qt.RightButton
|
||||
z: 10
|
||||
onEntered: {
|
||||
if (resultsList.hoverUpdatesSelection && !resultsList.keyboardNavigationActive)
|
||||
resultsList.currentIndex = index;
|
||||
|
||||
if (resultsList.hoverUpdatesSelection
|
||||
&& !resultsList.keyboardNavigationActive)
|
||||
resultsList.currentIndex = index
|
||||
}
|
||||
onPositionChanged: {
|
||||
resultsList.keyboardNavigationReset();
|
||||
}
|
||||
onClicked: (mouse) => {
|
||||
if (mouse.button === Qt.LeftButton) {
|
||||
resultsList.itemClicked(index, model);
|
||||
} else if (mouse.button === Qt.RightButton) {
|
||||
var modalPos = mapToItem(spotlightKeyHandler, mouse.x, mouse.y);
|
||||
resultsList.itemRightClicked(index, model, modalPos.x, modalPos.y);
|
||||
}
|
||||
resultsList.keyboardNavigationReset()
|
||||
}
|
||||
onClicked: mouse => {
|
||||
if (mouse.button === Qt.LeftButton) {
|
||||
resultsList.itemClicked(
|
||||
index, model)
|
||||
} else if (mouse.button === Qt.RightButton) {
|
||||
var modalPos = mapToItem(
|
||||
spotlightKeyHandler,
|
||||
mouse.x, mouse.y)
|
||||
resultsList.itemRightClicked(
|
||||
index, model,
|
||||
modalPos.x, modalPos.y)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
DankGridView {
|
||||
@@ -474,25 +494,30 @@ DankModal {
|
||||
property int minIconSize: 32
|
||||
property bool hoverUpdatesSelection: false
|
||||
property bool keyboardNavigationActive: appLauncher.keyboardNavigationActive
|
||||
property int baseCellWidth: adaptiveColumns ? Math.max(minCellWidth, Math.min(maxCellWidth, width / columns)) : (width - Theme.spacingS * 2) / columns
|
||||
property int baseCellWidth: adaptiveColumns ? Math.max(
|
||||
minCellWidth,
|
||||
Math.min(maxCellWidth, width / columns)) : (width - Theme.spacingS * 2) / columns
|
||||
property int baseCellHeight: baseCellWidth + 20
|
||||
property int actualColumns: adaptiveColumns ? Math.floor(width / cellWidth) : columns
|
||||
property int actualColumns: adaptiveColumns ? Math.floor(
|
||||
width
|
||||
/ cellWidth) : columns
|
||||
property int remainingSpace: width - (actualColumns * cellWidth)
|
||||
|
||||
signal keyboardNavigationReset()
|
||||
signal keyboardNavigationReset
|
||||
signal itemClicked(int index, var modelData)
|
||||
signal itemRightClicked(int index, var modelData, real mouseX, real mouseY)
|
||||
|
||||
function ensureVisible(index) {
|
||||
if (index < 0 || index >= count)
|
||||
return ;
|
||||
return
|
||||
|
||||
var itemY = Math.floor(index / actualColumns) * cellHeight;
|
||||
var itemBottom = itemY + cellHeight;
|
||||
var itemY = Math.floor(
|
||||
index / actualColumns) * cellHeight
|
||||
var itemBottom = itemY + cellHeight
|
||||
if (itemY < contentY)
|
||||
contentY = itemY;
|
||||
contentY = itemY
|
||||
else if (itemBottom > contentY + height)
|
||||
contentY = itemBottom - height;
|
||||
contentY = itemBottom - height
|
||||
}
|
||||
|
||||
anchors.fill: parent
|
||||
@@ -510,17 +535,16 @@ DankModal {
|
||||
reuseItems: true
|
||||
onCurrentIndexChanged: {
|
||||
if (keyboardNavigationActive)
|
||||
ensureVisible(currentIndex);
|
||||
|
||||
ensureVisible(currentIndex)
|
||||
}
|
||||
onItemClicked: function(index, modelData) {
|
||||
appLauncher.launchApp(modelData);
|
||||
onItemClicked: function (index, modelData) {
|
||||
appLauncher.launchApp(modelData)
|
||||
}
|
||||
onItemRightClicked: function(index, modelData, mouseX, mouseY) {
|
||||
contextMenu.show(mouseX, mouseY, modelData);
|
||||
onItemRightClicked: function (index, modelData, mouseX, mouseY) {
|
||||
contextMenu.show(mouseX, mouseY, modelData)
|
||||
}
|
||||
onKeyboardNavigationReset: {
|
||||
appLauncher.keyboardNavigationActive = false;
|
||||
appLauncher.keyboardNavigationActive = false
|
||||
}
|
||||
|
||||
ScrollBar.vertical: ScrollBar {
|
||||
@@ -536,7 +560,8 @@ DankModal {
|
||||
height: resultsGrid.cellHeight - resultsGrid.cellPadding
|
||||
radius: Theme.cornerRadius
|
||||
color: resultsGrid.currentIndex === index ? Theme.primaryPressed : gridMouseArea.containsMouse ? Theme.primaryHoverLight : Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, 0.03)
|
||||
border.color: resultsGrid.currentIndex === index ? Theme.primarySelected : Theme.outlineMedium
|
||||
border.color: resultsGrid.currentIndex
|
||||
=== index ? Theme.primarySelected : Theme.outlineMedium
|
||||
border.width: resultsGrid.currentIndex === index ? 2 : 1
|
||||
|
||||
Column {
|
||||
@@ -544,7 +569,12 @@ DankModal {
|
||||
spacing: Theme.spacingS
|
||||
|
||||
Item {
|
||||
property int iconSize: Math.min(resultsGrid.maxIconSize, Math.max(resultsGrid.minIconSize, resultsGrid.cellWidth * resultsGrid.iconSizeRatio))
|
||||
property int iconSize: Math.min(
|
||||
resultsGrid.maxIconSize,
|
||||
Math.max(
|
||||
resultsGrid.minIconSize,
|
||||
resultsGrid.cellWidth
|
||||
* resultsGrid.iconSizeRatio))
|
||||
|
||||
width: iconSize
|
||||
height: iconSize
|
||||
@@ -554,7 +584,9 @@ DankModal {
|
||||
id: gridIconImg
|
||||
|
||||
anchors.fill: parent
|
||||
source: (model.icon) ? Quickshell.iconPath(model.icon, SettingsData.iconTheme === "System Default" ? "" : SettingsData.iconTheme) : ""
|
||||
source: (model.icon) ? Quickshell.iconPath(
|
||||
model.icon,
|
||||
SettingsData.iconTheme === "System Default" ? "" : SettingsData.iconTheme) : ""
|
||||
smooth: true
|
||||
asynchronous: true
|
||||
visible: status === Image.Ready
|
||||
@@ -570,14 +602,18 @@ DankModal {
|
||||
|
||||
StyledText {
|
||||
anchors.centerIn: parent
|
||||
text: (model.name && model.name.length > 0) ? model.name.charAt(0).toUpperCase() : "A"
|
||||
font.pixelSize: Math.min(28, parent.width * 0.5)
|
||||
text: (model.name
|
||||
&& model.name.length
|
||||
> 0) ? model.name.charAt(
|
||||
0).toUpperCase(
|
||||
) : "A"
|
||||
font.pixelSize: Math.min(
|
||||
28,
|
||||
parent.width * 0.5)
|
||||
color: Theme.primary
|
||||
font.weight: Font.Bold
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
StyledText {
|
||||
@@ -592,7 +628,6 @@ DankModal {
|
||||
maximumLineCount: 2
|
||||
wrapMode: Text.WordWrap
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
@@ -604,29 +639,30 @@ DankModal {
|
||||
acceptedButtons: Qt.LeftButton | Qt.RightButton
|
||||
z: 10
|
||||
onEntered: {
|
||||
if (resultsGrid.hoverUpdatesSelection && !resultsGrid.keyboardNavigationActive)
|
||||
resultsGrid.currentIndex = index;
|
||||
|
||||
if (resultsGrid.hoverUpdatesSelection
|
||||
&& !resultsGrid.keyboardNavigationActive)
|
||||
resultsGrid.currentIndex = index
|
||||
}
|
||||
onPositionChanged: {
|
||||
resultsGrid.keyboardNavigationReset();
|
||||
}
|
||||
onClicked: (mouse) => {
|
||||
if (mouse.button === Qt.LeftButton) {
|
||||
resultsGrid.itemClicked(index, model);
|
||||
} else if (mouse.button === Qt.RightButton) {
|
||||
var modalPos = mapToItem(spotlightKeyHandler, mouse.x, mouse.y);
|
||||
resultsGrid.itemRightClicked(index, model, modalPos.x, modalPos.y);
|
||||
}
|
||||
resultsGrid.keyboardNavigationReset()
|
||||
}
|
||||
onClicked: mouse => {
|
||||
if (mouse.button === Qt.LeftButton) {
|
||||
resultsGrid.itemClicked(
|
||||
index, model)
|
||||
} else if (mouse.button === Qt.RightButton) {
|
||||
var modalPos = mapToItem(
|
||||
spotlightKeyHandler,
|
||||
mouse.x, mouse.y)
|
||||
resultsGrid.itemRightClicked(
|
||||
index, model,
|
||||
modalPos.x, modalPos.y)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
@@ -637,23 +673,29 @@ DankModal {
|
||||
|
||||
function show(x, y, app) {
|
||||
currentApp = app
|
||||
|
||||
|
||||
const menuWidth = 180
|
||||
const menuHeight = menuColumn.implicitHeight + Theme.spacingS * 2
|
||||
let finalX = x + 8
|
||||
let finalY = y + 8
|
||||
|
||||
|
||||
if (finalX + menuWidth > spotlightKeyHandler.width) {
|
||||
finalX = x - menuWidth - 8
|
||||
}
|
||||
|
||||
|
||||
if (finalY + menuHeight > spotlightKeyHandler.height) {
|
||||
finalY = y - menuHeight - 8
|
||||
}
|
||||
|
||||
finalX = Math.max(8, Math.min(finalX, spotlightKeyHandler.width - menuWidth - 8))
|
||||
finalY = Math.max(8, Math.min(finalY, spotlightKeyHandler.height - menuHeight - 8))
|
||||
|
||||
|
||||
finalX = Math.max(
|
||||
8, Math.min(
|
||||
finalX,
|
||||
spotlightKeyHandler.width - menuWidth - 8))
|
||||
finalY = Math.max(
|
||||
8, Math.min(
|
||||
finalY,
|
||||
spotlightKeyHandler.height - menuHeight - 8))
|
||||
|
||||
contextMenu.x = finalX
|
||||
contextMenu.y = finalY
|
||||
contextMenu.visible = true
|
||||
@@ -663,8 +705,8 @@ DankModal {
|
||||
function close() {
|
||||
contextMenu.menuVisible = false
|
||||
Qt.callLater(() => {
|
||||
contextMenu.visible = false
|
||||
})
|
||||
contextMenu.visible = false
|
||||
})
|
||||
}
|
||||
|
||||
visible: false
|
||||
@@ -672,7 +714,8 @@ DankModal {
|
||||
height: menuColumn.implicitHeight + Theme.spacingS * 2
|
||||
radius: Theme.cornerRadius
|
||||
color: Theme.popupBackground()
|
||||
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.08)
|
||||
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g,
|
||||
Theme.outline.b, 0.08)
|
||||
border.width: 1
|
||||
z: 1000
|
||||
opacity: menuVisible ? 1 : 0
|
||||
@@ -700,7 +743,11 @@ DankModal {
|
||||
width: parent.width
|
||||
height: 32
|
||||
radius: Theme.cornerRadius
|
||||
color: pinMouseArea.containsMouse ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.12) : "transparent"
|
||||
color: pinMouseArea.containsMouse ? Qt.rgba(
|
||||
Theme.primary.r,
|
||||
Theme.primary.g,
|
||||
Theme.primary.b,
|
||||
0.12) : "transparent"
|
||||
|
||||
Row {
|
||||
anchors.left: parent.left
|
||||
@@ -710,11 +757,15 @@ DankModal {
|
||||
|
||||
DankIcon {
|
||||
name: {
|
||||
if (!contextMenu.currentApp || !contextMenu.currentApp.desktopEntry)
|
||||
if (!contextMenu.currentApp
|
||||
|| !contextMenu.currentApp.desktopEntry)
|
||||
return "push_pin"
|
||||
|
||||
var appId = contextMenu.currentApp.desktopEntry.id || contextMenu.currentApp.desktopEntry.execString || ""
|
||||
return SessionData.isPinnedApp(appId) ? "keep_off" : "push_pin"
|
||||
var appId = contextMenu.currentApp.desktopEntry.id
|
||||
|| contextMenu.currentApp.desktopEntry.execString
|
||||
|| ""
|
||||
return SessionData.isPinnedApp(
|
||||
appId) ? "keep_off" : "push_pin"
|
||||
}
|
||||
size: Theme.iconSize - 2
|
||||
color: Theme.surfaceText
|
||||
@@ -724,11 +775,15 @@ DankModal {
|
||||
|
||||
StyledText {
|
||||
text: {
|
||||
if (!contextMenu.currentApp || !contextMenu.currentApp.desktopEntry)
|
||||
if (!contextMenu.currentApp
|
||||
|| !contextMenu.currentApp.desktopEntry)
|
||||
return "Pin to Dock"
|
||||
|
||||
var appId = contextMenu.currentApp.desktopEntry.id || contextMenu.currentApp.desktopEntry.execString || ""
|
||||
return SessionData.isPinnedApp(appId) ? "Unpin from Dock" : "Pin to Dock"
|
||||
var appId = contextMenu.currentApp.desktopEntry.id
|
||||
|| contextMenu.currentApp.desktopEntry.execString
|
||||
|| ""
|
||||
return SessionData.isPinnedApp(
|
||||
appId) ? "Unpin from Dock" : "Pin to Dock"
|
||||
}
|
||||
font.pixelSize: Theme.fontSizeSmall
|
||||
color: Theme.surfaceText
|
||||
@@ -744,10 +799,13 @@ DankModal {
|
||||
hoverEnabled: true
|
||||
cursorShape: Qt.PointingHandCursor
|
||||
onClicked: {
|
||||
if (!contextMenu.currentApp || !contextMenu.currentApp.desktopEntry)
|
||||
if (!contextMenu.currentApp
|
||||
|| !contextMenu.currentApp.desktopEntry)
|
||||
return
|
||||
|
||||
var appId = contextMenu.currentApp.desktopEntry.id || contextMenu.currentApp.desktopEntry.execString || ""
|
||||
var appId = contextMenu.currentApp.desktopEntry.id
|
||||
|| contextMenu.currentApp.desktopEntry.execString
|
||||
|| ""
|
||||
if (SessionData.isPinnedApp(appId))
|
||||
SessionData.removePinnedApp(appId)
|
||||
else
|
||||
@@ -767,7 +825,8 @@ DankModal {
|
||||
anchors.centerIn: parent
|
||||
width: parent.width
|
||||
height: 1
|
||||
color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.2)
|
||||
color: Qt.rgba(Theme.outline.r, Theme.outline.g,
|
||||
Theme.outline.b, 0.2)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -775,7 +834,11 @@ DankModal {
|
||||
width: parent.width
|
||||
height: 32
|
||||
radius: Theme.cornerRadius
|
||||
color: launchMouseArea.containsMouse ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.12) : "transparent"
|
||||
color: launchMouseArea.containsMouse ? Qt.rgba(
|
||||
Theme.primary.r,
|
||||
Theme.primary.g,
|
||||
Theme.primary.b,
|
||||
0.12) : "transparent"
|
||||
|
||||
Row {
|
||||
anchors.left: parent.left
|
||||
@@ -808,7 +871,8 @@ DankModal {
|
||||
cursorShape: Qt.PointingHandCursor
|
||||
onClicked: {
|
||||
if (contextMenu.currentApp)
|
||||
appLauncher.launchApp(contextMenu.currentApp)
|
||||
appLauncher.launchApp(
|
||||
contextMenu.currentApp)
|
||||
|
||||
contextMenu.close()
|
||||
}
|
||||
@@ -845,13 +909,11 @@ DankModal {
|
||||
width: contextMenu.width
|
||||
height: contextMenu.height
|
||||
onClicked: {
|
||||
|
||||
// Prevent closing when clicking on the menu itself
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -5,300 +5,306 @@ import qs.Services
|
||||
import qs.Widgets
|
||||
|
||||
DankModal {
|
||||
id: root
|
||||
id: root
|
||||
|
||||
property string wifiPasswordSSID: ""
|
||||
property string wifiPasswordInput: ""
|
||||
property string wifiPasswordSSID: ""
|
||||
property string wifiPasswordInput: ""
|
||||
|
||||
function show(ssid) {
|
||||
wifiPasswordSSID = ssid
|
||||
wifiPasswordInput = ""
|
||||
open()
|
||||
Qt.callLater(function() {
|
||||
if (contentLoader.item && contentLoader.item.passwordInput) {
|
||||
contentLoader.item.passwordInput.forceActiveFocus()
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
shouldBeVisible: false
|
||||
width: 420
|
||||
height: 230
|
||||
onShouldBeVisibleChanged: {
|
||||
if (!shouldBeVisible)
|
||||
wifiPasswordInput = ""
|
||||
}
|
||||
onOpened: {
|
||||
Qt.callLater(function() {
|
||||
if (contentLoader.item && contentLoader.item.passwordInput) {
|
||||
contentLoader.item.passwordInput.forceActiveFocus()
|
||||
}
|
||||
})
|
||||
}
|
||||
onBackgroundClicked: {
|
||||
close()
|
||||
wifiPasswordInput = ""
|
||||
}
|
||||
|
||||
Connections {
|
||||
function onPasswordDialogShouldReopenChanged() {
|
||||
if (NetworkService.passwordDialogShouldReopen
|
||||
&& NetworkService.connectingSSID !== "") {
|
||||
wifiPasswordSSID = NetworkService.connectingSSID
|
||||
function show(ssid) {
|
||||
wifiPasswordSSID = ssid
|
||||
wifiPasswordInput = ""
|
||||
open()
|
||||
NetworkService.passwordDialogShouldReopen = false
|
||||
}
|
||||
Qt.callLater(function () {
|
||||
if (contentLoader.item && contentLoader.item.passwordInput) {
|
||||
contentLoader.item.passwordInput.forceActiveFocus()
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
target: NetworkService
|
||||
}
|
||||
|
||||
content: Component {
|
||||
FocusScope {
|
||||
id: wifiContent
|
||||
property alias passwordInput: passwordInput
|
||||
|
||||
anchors.fill: parent
|
||||
focus: true
|
||||
Keys.onEscapePressed: function(event) {
|
||||
shouldBeVisible: false
|
||||
width: 420
|
||||
height: 230
|
||||
onShouldBeVisibleChanged: {
|
||||
if (!shouldBeVisible)
|
||||
wifiPasswordInput = ""
|
||||
}
|
||||
onOpened: {
|
||||
Qt.callLater(function () {
|
||||
if (contentLoader.item && contentLoader.item.passwordInput) {
|
||||
contentLoader.item.passwordInput.forceActiveFocus()
|
||||
}
|
||||
})
|
||||
}
|
||||
onBackgroundClicked: {
|
||||
close()
|
||||
wifiPasswordInput = ""
|
||||
event.accepted = true
|
||||
}
|
||||
|
||||
Column {
|
||||
anchors.centerIn: parent
|
||||
width: parent.width - Theme.spacingM * 2
|
||||
spacing: Theme.spacingM
|
||||
|
||||
Row {
|
||||
width: parent.width
|
||||
|
||||
Column {
|
||||
width: parent.width - 40
|
||||
spacing: Theme.spacingXS
|
||||
|
||||
StyledText {
|
||||
text: "Connect to Wi-Fi"
|
||||
font.pixelSize: Theme.fontSizeLarge
|
||||
color: Theme.surfaceText
|
||||
font.weight: Font.Medium
|
||||
}
|
||||
|
||||
StyledText {
|
||||
text: "Enter password for \"" + wifiPasswordSSID + "\""
|
||||
font.pixelSize: Theme.fontSizeMedium
|
||||
color: Theme.surfaceTextMedium
|
||||
width: parent.width
|
||||
elide: Text.ElideRight
|
||||
}
|
||||
}
|
||||
|
||||
DankActionButton {
|
||||
iconName: "close"
|
||||
iconSize: Theme.iconSize - 4
|
||||
iconColor: Theme.surfaceText
|
||||
hoverColor: Theme.errorHover
|
||||
onClicked: {
|
||||
close()
|
||||
wifiPasswordInput = ""
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
width: parent.width
|
||||
height: 50
|
||||
radius: Theme.cornerRadius
|
||||
color: Theme.surfaceHover
|
||||
border.color: passwordInput.activeFocus ? Theme.primary : Theme.outlineStrong
|
||||
border.width: passwordInput.activeFocus ? 2 : 1
|
||||
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
onClicked: {
|
||||
passwordInput.forceActiveFocus()
|
||||
}
|
||||
}
|
||||
|
||||
DankTextField {
|
||||
id: passwordInput
|
||||
|
||||
anchors.fill: parent
|
||||
font.pixelSize: Theme.fontSizeMedium
|
||||
textColor: Theme.surfaceText
|
||||
text: wifiPasswordInput
|
||||
echoMode: showPasswordCheckbox.checked ? TextInput.Normal : TextInput.Password
|
||||
placeholderText: ""
|
||||
backgroundColor: "transparent"
|
||||
focus: true
|
||||
enabled: root.shouldBeVisible
|
||||
onTextEdited: {
|
||||
wifiPasswordInput = text
|
||||
}
|
||||
onAccepted: {
|
||||
NetworkService.connectToWifiWithPassword(wifiPasswordSSID,
|
||||
passwordInput.text)
|
||||
close()
|
||||
wifiPasswordInput = ""
|
||||
passwordInput.text = ""
|
||||
}
|
||||
|
||||
Component.onCompleted: {
|
||||
if (root.shouldBeVisible) {
|
||||
focusDelayTimer.start()
|
||||
}
|
||||
}
|
||||
|
||||
Timer {
|
||||
id: focusDelayTimer
|
||||
interval: 100
|
||||
repeat: false
|
||||
onTriggered: {
|
||||
if (root.shouldBeVisible) {
|
||||
passwordInput.forceActiveFocus()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Connections {
|
||||
target: root
|
||||
function onShouldBeVisibleChanged() {
|
||||
if (root.shouldBeVisible) {
|
||||
focusDelayTimer.start()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Row {
|
||||
spacing: Theme.spacingS
|
||||
|
||||
Rectangle {
|
||||
id: showPasswordCheckbox
|
||||
|
||||
property bool checked: false
|
||||
|
||||
width: 20
|
||||
height: 20
|
||||
radius: 4
|
||||
color: checked ? Theme.primary : "transparent"
|
||||
border.color: checked ? Theme.primary : Theme.outlineButton
|
||||
border.width: 2
|
||||
|
||||
DankIcon {
|
||||
anchors.centerIn: parent
|
||||
name: "check"
|
||||
size: 12
|
||||
color: Theme.background
|
||||
visible: parent.checked
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
hoverEnabled: true
|
||||
cursorShape: Qt.PointingHandCursor
|
||||
onClicked: {
|
||||
showPasswordCheckbox.checked = !showPasswordCheckbox.checked
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
StyledText {
|
||||
text: "Show password"
|
||||
font.pixelSize: Theme.fontSizeMedium
|
||||
color: Theme.surfaceText
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
}
|
||||
}
|
||||
|
||||
Item {
|
||||
width: parent.width
|
||||
height: 40
|
||||
|
||||
Row {
|
||||
anchors.right: parent.right
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
spacing: Theme.spacingM
|
||||
|
||||
Rectangle {
|
||||
width: Math.max(70, cancelText.contentWidth + Theme.spacingM * 2)
|
||||
height: 36
|
||||
radius: Theme.cornerRadius
|
||||
color: cancelArea.containsMouse ? Theme.surfaceTextHover : "transparent"
|
||||
border.color: Theme.surfaceVariantAlpha
|
||||
border.width: 1
|
||||
|
||||
StyledText {
|
||||
id: cancelText
|
||||
|
||||
anchors.centerIn: parent
|
||||
text: "Cancel"
|
||||
font.pixelSize: Theme.fontSizeMedium
|
||||
color: Theme.surfaceText
|
||||
font.weight: Font.Medium
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
id: cancelArea
|
||||
|
||||
anchors.fill: parent
|
||||
hoverEnabled: true
|
||||
cursorShape: Qt.PointingHandCursor
|
||||
onClicked: {
|
||||
close()
|
||||
wifiPasswordInput = ""
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
width: Math.max(80, connectText.contentWidth + Theme.spacingM * 2)
|
||||
height: 36
|
||||
radius: Theme.cornerRadius
|
||||
color: connectArea.containsMouse ? Qt.darker(Theme.primary,
|
||||
1.1) : Theme.primary
|
||||
enabled: passwordInput.text.length > 0
|
||||
opacity: enabled ? 1 : 0.5
|
||||
|
||||
StyledText {
|
||||
id: connectText
|
||||
|
||||
anchors.centerIn: parent
|
||||
text: "Connect"
|
||||
font.pixelSize: Theme.fontSizeMedium
|
||||
color: Theme.background
|
||||
font.weight: Font.Medium
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
id: connectArea
|
||||
|
||||
anchors.fill: parent
|
||||
hoverEnabled: true
|
||||
cursorShape: Qt.PointingHandCursor
|
||||
enabled: parent.enabled
|
||||
onClicked: {
|
||||
NetworkService.connectToWifiWithPassword(wifiPasswordSSID,
|
||||
passwordInput.text)
|
||||
close()
|
||||
wifiPasswordInput = ""
|
||||
passwordInput.text = ""
|
||||
}
|
||||
}
|
||||
|
||||
Behavior on color {
|
||||
ColorAnimation {
|
||||
duration: Theme.shortDuration
|
||||
easing.type: Theme.standardEasing
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Connections {
|
||||
function onPasswordDialogShouldReopenChanged() {
|
||||
if (NetworkService.passwordDialogShouldReopen
|
||||
&& NetworkService.connectingSSID !== "") {
|
||||
wifiPasswordSSID = NetworkService.connectingSSID
|
||||
wifiPasswordInput = ""
|
||||
open()
|
||||
NetworkService.passwordDialogShouldReopen = false
|
||||
}
|
||||
}
|
||||
|
||||
target: NetworkService
|
||||
}
|
||||
|
||||
content: Component {
|
||||
FocusScope {
|
||||
id: wifiContent
|
||||
property alias passwordInput: passwordInput
|
||||
|
||||
anchors.fill: parent
|
||||
focus: true
|
||||
Keys.onEscapePressed: function (event) {
|
||||
close()
|
||||
wifiPasswordInput = ""
|
||||
event.accepted = true
|
||||
}
|
||||
|
||||
Column {
|
||||
anchors.centerIn: parent
|
||||
width: parent.width - Theme.spacingM * 2
|
||||
spacing: Theme.spacingM
|
||||
|
||||
Row {
|
||||
width: parent.width
|
||||
|
||||
Column {
|
||||
width: parent.width - 40
|
||||
spacing: Theme.spacingXS
|
||||
|
||||
StyledText {
|
||||
text: "Connect to Wi-Fi"
|
||||
font.pixelSize: Theme.fontSizeLarge
|
||||
color: Theme.surfaceText
|
||||
font.weight: Font.Medium
|
||||
}
|
||||
|
||||
StyledText {
|
||||
text: "Enter password for \"" + wifiPasswordSSID + "\""
|
||||
font.pixelSize: Theme.fontSizeMedium
|
||||
color: Theme.surfaceTextMedium
|
||||
width: parent.width
|
||||
elide: Text.ElideRight
|
||||
}
|
||||
}
|
||||
|
||||
DankActionButton {
|
||||
iconName: "close"
|
||||
iconSize: Theme.iconSize - 4
|
||||
iconColor: Theme.surfaceText
|
||||
hoverColor: Theme.errorHover
|
||||
onClicked: {
|
||||
close()
|
||||
wifiPasswordInput = ""
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
width: parent.width
|
||||
height: 50
|
||||
radius: Theme.cornerRadius
|
||||
color: Theme.surfaceHover
|
||||
border.color: passwordInput.activeFocus ? Theme.primary : Theme.outlineStrong
|
||||
border.width: passwordInput.activeFocus ? 2 : 1
|
||||
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
onClicked: {
|
||||
passwordInput.forceActiveFocus()
|
||||
}
|
||||
}
|
||||
|
||||
DankTextField {
|
||||
id: passwordInput
|
||||
|
||||
anchors.fill: parent
|
||||
font.pixelSize: Theme.fontSizeMedium
|
||||
textColor: Theme.surfaceText
|
||||
text: wifiPasswordInput
|
||||
echoMode: showPasswordCheckbox.checked ? TextInput.Normal : TextInput.Password
|
||||
placeholderText: ""
|
||||
backgroundColor: "transparent"
|
||||
focus: true
|
||||
enabled: root.shouldBeVisible
|
||||
onTextEdited: {
|
||||
wifiPasswordInput = text
|
||||
}
|
||||
onAccepted: {
|
||||
NetworkService.connectToWifiWithPassword(
|
||||
wifiPasswordSSID, passwordInput.text)
|
||||
close()
|
||||
wifiPasswordInput = ""
|
||||
passwordInput.text = ""
|
||||
}
|
||||
|
||||
Component.onCompleted: {
|
||||
if (root.shouldBeVisible) {
|
||||
focusDelayTimer.start()
|
||||
}
|
||||
}
|
||||
|
||||
Timer {
|
||||
id: focusDelayTimer
|
||||
interval: 100
|
||||
repeat: false
|
||||
onTriggered: {
|
||||
if (root.shouldBeVisible) {
|
||||
passwordInput.forceActiveFocus()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Connections {
|
||||
target: root
|
||||
function onShouldBeVisibleChanged() {
|
||||
if (root.shouldBeVisible) {
|
||||
focusDelayTimer.start()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Row {
|
||||
spacing: Theme.spacingS
|
||||
|
||||
Rectangle {
|
||||
id: showPasswordCheckbox
|
||||
|
||||
property bool checked: false
|
||||
|
||||
width: 20
|
||||
height: 20
|
||||
radius: 4
|
||||
color: checked ? Theme.primary : "transparent"
|
||||
border.color: checked ? Theme.primary : Theme.outlineButton
|
||||
border.width: 2
|
||||
|
||||
DankIcon {
|
||||
anchors.centerIn: parent
|
||||
name: "check"
|
||||
size: 12
|
||||
color: Theme.background
|
||||
visible: parent.checked
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
hoverEnabled: true
|
||||
cursorShape: Qt.PointingHandCursor
|
||||
onClicked: {
|
||||
showPasswordCheckbox.checked = !showPasswordCheckbox.checked
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
StyledText {
|
||||
text: "Show password"
|
||||
font.pixelSize: Theme.fontSizeMedium
|
||||
color: Theme.surfaceText
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
}
|
||||
}
|
||||
|
||||
Item {
|
||||
width: parent.width
|
||||
height: 40
|
||||
|
||||
Row {
|
||||
anchors.right: parent.right
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
spacing: Theme.spacingM
|
||||
|
||||
Rectangle {
|
||||
width: Math.max(
|
||||
70,
|
||||
cancelText.contentWidth + Theme.spacingM * 2)
|
||||
height: 36
|
||||
radius: Theme.cornerRadius
|
||||
color: cancelArea.containsMouse ? Theme.surfaceTextHover : "transparent"
|
||||
border.color: Theme.surfaceVariantAlpha
|
||||
border.width: 1
|
||||
|
||||
StyledText {
|
||||
id: cancelText
|
||||
|
||||
anchors.centerIn: parent
|
||||
text: "Cancel"
|
||||
font.pixelSize: Theme.fontSizeMedium
|
||||
color: Theme.surfaceText
|
||||
font.weight: Font.Medium
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
id: cancelArea
|
||||
|
||||
anchors.fill: parent
|
||||
hoverEnabled: true
|
||||
cursorShape: Qt.PointingHandCursor
|
||||
onClicked: {
|
||||
close()
|
||||
wifiPasswordInput = ""
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
width: Math.max(
|
||||
80,
|
||||
connectText.contentWidth + Theme.spacingM * 2)
|
||||
height: 36
|
||||
radius: Theme.cornerRadius
|
||||
color: connectArea.containsMouse ? Qt.darker(
|
||||
Theme.primary,
|
||||
1.1) : Theme.primary
|
||||
enabled: passwordInput.text.length > 0
|
||||
opacity: enabled ? 1 : 0.5
|
||||
|
||||
StyledText {
|
||||
id: connectText
|
||||
|
||||
anchors.centerIn: parent
|
||||
text: "Connect"
|
||||
font.pixelSize: Theme.fontSizeMedium
|
||||
color: Theme.background
|
||||
font.weight: Font.Medium
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
id: connectArea
|
||||
|
||||
anchors.fill: parent
|
||||
hoverEnabled: true
|
||||
cursorShape: Qt.PointingHandCursor
|
||||
enabled: parent.enabled
|
||||
onClicked: {
|
||||
NetworkService.connectToWifiWithPassword(
|
||||
wifiPasswordSSID,
|
||||
passwordInput.text)
|
||||
close()
|
||||
wifiPasswordInput = ""
|
||||
passwordInput.text = ""
|
||||
}
|
||||
}
|
||||
|
||||
Behavior on color {
|
||||
ColorAnimation {
|
||||
duration: Theme.shortDuration
|
||||
easing.type: Theme.standardEasing
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user