mirror of
https://github.com/AvengeMedia/DankMaterialShell.git
synced 2026-06-24 12:05:21 -04:00
99cc3b8449
- add sorting and clickable page jump - wrap-around page navigation
845 lines
29 KiB
QML
845 lines
29 KiB
QML
import Qt.labs.folderlistmodel
|
|
import QtCore
|
|
import QtQuick
|
|
import QtQuick.Effects
|
|
import qs.Common
|
|
import qs.Modals.FileBrowser
|
|
import qs.Widgets
|
|
|
|
Item {
|
|
id: root
|
|
|
|
LayoutMirroring.enabled: I18n.isRtl
|
|
LayoutMirroring.childrenInherit: true
|
|
|
|
implicitWidth: SettingsData.showWeekNumber ? 736 : 700
|
|
implicitHeight: 410
|
|
|
|
property string wallpaperDir: ""
|
|
property int currentPage: 0
|
|
property int itemsPerPage: 16
|
|
property int totalPages: Math.max(1, Math.ceil(wallpaperFolderModel.count / itemsPerPage))
|
|
property bool active: false
|
|
property Item focusTarget: wallpaperGrid
|
|
property Item tabBarItem: null
|
|
property int gridIndex: 0
|
|
property Item keyForwardTarget: null
|
|
property var parentPopout: null
|
|
property int lastPage: 0
|
|
property bool enableAnimation: false
|
|
property string homeDir: StandardPaths.writableLocation(StandardPaths.HomeLocation)
|
|
property string selectedFileName: ""
|
|
property var targetScreen: null
|
|
property string targetScreenName: targetScreen ? targetScreen.name : ""
|
|
// Shared with the wallpaper FileBrowser via CacheData.fileBrowserSettings["wallpaper"]
|
|
property string sortBy: "name"
|
|
property bool sortAscending: true
|
|
// Forces the page grid to rebuild when the folder model reorders in place.
|
|
property int gridRevision: 0
|
|
|
|
signal requestTabChange(int newIndex)
|
|
|
|
function refreshAfterSort() {
|
|
// Defer until FolderListModel finishes reordering.
|
|
Qt.callLater(() => {
|
|
gridRevision++;
|
|
if (visible && active) {
|
|
setInitialSelection();
|
|
}
|
|
updateSelectedFileName();
|
|
});
|
|
}
|
|
|
|
onSortByChanged: refreshAfterSort()
|
|
onSortAscendingChanged: refreshAfterSort()
|
|
|
|
function loadSort() {
|
|
const s = CacheData.fileBrowserSettings["wallpaper"];
|
|
if (s) {
|
|
sortBy = s.sortBy || "name";
|
|
sortAscending = s.sortAscending !== undefined ? s.sortAscending : true;
|
|
}
|
|
}
|
|
|
|
function persistSort() {
|
|
let settings = CacheData.fileBrowserSettings;
|
|
if (!settings["wallpaper"])
|
|
settings["wallpaper"] = {};
|
|
settings["wallpaper"].sortBy = sortBy;
|
|
settings["wallpaper"].sortAscending = sortAscending;
|
|
CacheData.fileBrowserSettings = settings;
|
|
CacheData.saveCache();
|
|
}
|
|
|
|
function getCurrentWallpaper() {
|
|
if (SessionData.perMonitorWallpaper && targetScreenName) {
|
|
return SessionData.getMonitorWallpaper(targetScreenName);
|
|
}
|
|
return SessionData.wallpaperPath;
|
|
}
|
|
|
|
function setCurrentWallpaper(path) {
|
|
if (SessionData.perMonitorWallpaper && targetScreenName) {
|
|
SessionData.setMonitorWallpaper(targetScreenName, path);
|
|
} else {
|
|
SessionData.setWallpaper(path);
|
|
}
|
|
}
|
|
|
|
onCurrentPageChanged: {
|
|
if (currentPage !== lastPage) {
|
|
enableAnimation = false;
|
|
lastPage = currentPage;
|
|
}
|
|
updateSelectedFileName();
|
|
}
|
|
|
|
onGridIndexChanged: {
|
|
updateSelectedFileName();
|
|
}
|
|
|
|
onVisibleChanged: {
|
|
if (visible && active) {
|
|
setInitialSelection();
|
|
}
|
|
}
|
|
|
|
Component.onCompleted: {
|
|
loadSort();
|
|
loadWallpaperDirectory();
|
|
}
|
|
|
|
Connections {
|
|
target: CacheData
|
|
function onFileBrowserSettingsChanged() {
|
|
loadSort();
|
|
}
|
|
}
|
|
|
|
onActiveChanged: {
|
|
if (active && visible) {
|
|
setInitialSelection();
|
|
}
|
|
}
|
|
|
|
function goToNextCell(visibleCount) {
|
|
if (gridIndex + 1 < visibleCount) {
|
|
gridIndex++;
|
|
} else if (currentPage < totalPages - 1) {
|
|
gridIndex = 0;
|
|
currentPage++;
|
|
} else if (totalPages > 1) {
|
|
gridIndex = 0;
|
|
currentPage = 0;
|
|
}
|
|
}
|
|
|
|
function goToPrevCell() {
|
|
if (gridIndex > 0) {
|
|
gridIndex--;
|
|
} else if (currentPage > 0) {
|
|
currentPage--;
|
|
const prevPageCount = Math.min(itemsPerPage, wallpaperFolderModel.count - currentPage * itemsPerPage);
|
|
gridIndex = prevPageCount - 1;
|
|
} else if (totalPages > 1) {
|
|
currentPage = totalPages - 1;
|
|
const lastPageCount = Math.min(itemsPerPage, wallpaperFolderModel.count - currentPage * itemsPerPage);
|
|
gridIndex = lastPageCount - 1;
|
|
}
|
|
}
|
|
|
|
function closeOverlays() {
|
|
if (sortMenu.visible || pageJumpPopup.visible) {
|
|
sortMenu.visible = false;
|
|
pageJumpPopup.visible = false;
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
function handleKeyEvent(event) {
|
|
if (event.key === Qt.Key_Escape) {
|
|
return closeOverlays();
|
|
}
|
|
const columns = 4;
|
|
const currentCol = gridIndex % columns;
|
|
const visibleCount = Math.min(itemsPerPage, wallpaperFolderModel.count - currentPage * itemsPerPage);
|
|
|
|
if (event.key === Qt.Key_Return || event.key === Qt.Key_Enter) {
|
|
if (gridIndex >= 0 && gridIndex < visibleCount) {
|
|
const absoluteIndex = currentPage * itemsPerPage + gridIndex;
|
|
if (absoluteIndex < wallpaperFolderModel.count) {
|
|
const filePath = wallpaperFolderModel.get(absoluteIndex, "filePath");
|
|
if (filePath) {
|
|
setCurrentWallpaper(filePath.toString().replace(/^file:\/\//, ''));
|
|
}
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
if (event.key === Qt.Key_Right || event.key === Qt.Key_L) {
|
|
if (I18n.isRtl) {
|
|
goToPrevCell();
|
|
} else {
|
|
goToNextCell(visibleCount);
|
|
}
|
|
return true;
|
|
}
|
|
|
|
if (event.key === Qt.Key_Left || event.key === Qt.Key_H) {
|
|
if (I18n.isRtl) {
|
|
goToNextCell(visibleCount);
|
|
} else {
|
|
goToPrevCell();
|
|
}
|
|
return true;
|
|
}
|
|
|
|
if (event.key === Qt.Key_Down || event.key === Qt.Key_J) {
|
|
if (gridIndex + columns < visibleCount) {
|
|
gridIndex += columns;
|
|
} else if (currentPage < totalPages - 1) {
|
|
gridIndex = currentCol;
|
|
currentPage++;
|
|
} else if (totalPages > 1) {
|
|
gridIndex = currentCol;
|
|
currentPage = 0;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
if (event.key === Qt.Key_Up || event.key === Qt.Key_K) {
|
|
if (gridIndex >= columns) {
|
|
gridIndex -= columns;
|
|
} else if (currentPage > 0) {
|
|
currentPage--;
|
|
const prevPageCount = Math.min(itemsPerPage, wallpaperFolderModel.count - currentPage * itemsPerPage);
|
|
const prevPageRows = Math.ceil(prevPageCount / columns);
|
|
gridIndex = (prevPageRows - 1) * columns + currentCol;
|
|
gridIndex = Math.min(gridIndex, prevPageCount - 1);
|
|
} else if (totalPages > 1) {
|
|
currentPage = totalPages - 1;
|
|
const lastPageCount = Math.min(itemsPerPage, wallpaperFolderModel.count - currentPage * itemsPerPage);
|
|
const lastPageRows = Math.ceil(lastPageCount / columns);
|
|
gridIndex = (lastPageRows - 1) * columns + currentCol;
|
|
gridIndex = Math.min(gridIndex, lastPageCount - 1);
|
|
}
|
|
return true;
|
|
}
|
|
|
|
if (event.key === Qt.Key_PageUp && totalPages > 1) {
|
|
gridIndex = 0;
|
|
currentPage = (currentPage - 1 + totalPages) % totalPages;
|
|
return true;
|
|
}
|
|
|
|
if (event.key === Qt.Key_PageDown && totalPages > 1) {
|
|
gridIndex = 0;
|
|
currentPage = (currentPage + 1) % totalPages;
|
|
return true;
|
|
}
|
|
|
|
if (event.key === Qt.Key_Home && event.modifiers & Qt.ControlModifier) {
|
|
gridIndex = 0;
|
|
currentPage = 0;
|
|
return true;
|
|
}
|
|
|
|
if (event.key === Qt.Key_End && event.modifiers & Qt.ControlModifier) {
|
|
currentPage = totalPages - 1;
|
|
const lastPageCount = Math.min(itemsPerPage, wallpaperFolderModel.count - currentPage * itemsPerPage);
|
|
gridIndex = Math.max(0, lastPageCount - 1);
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
function setInitialSelection() {
|
|
const currentWallpaper = getCurrentWallpaper();
|
|
if (!currentWallpaper || wallpaperFolderModel.count === 0) {
|
|
gridIndex = 0;
|
|
updateSelectedFileName();
|
|
Qt.callLater(() => {
|
|
enableAnimation = true;
|
|
});
|
|
return;
|
|
}
|
|
|
|
for (var i = 0; i < wallpaperFolderModel.count; i++) {
|
|
const filePath = wallpaperFolderModel.get(i, "filePath");
|
|
if (filePath && filePath.toString().replace(/^file:\/\//, '') === currentWallpaper) {
|
|
const targetPage = Math.floor(i / itemsPerPage);
|
|
const targetIndex = i % itemsPerPage;
|
|
currentPage = targetPage;
|
|
gridIndex = targetIndex;
|
|
updateSelectedFileName();
|
|
Qt.callLater(() => {
|
|
enableAnimation = true;
|
|
});
|
|
return;
|
|
}
|
|
}
|
|
gridIndex = 0;
|
|
updateSelectedFileName();
|
|
Qt.callLater(() => {
|
|
enableAnimation = true;
|
|
});
|
|
}
|
|
|
|
function loadWallpaperDirectory() {
|
|
const currentWallpaper = getCurrentWallpaper();
|
|
|
|
if (!currentWallpaper || currentWallpaper.startsWith("#")) {
|
|
if (CacheData.wallpaperLastPath && CacheData.wallpaperLastPath !== "") {
|
|
wallpaperDir = CacheData.wallpaperLastPath;
|
|
} else {
|
|
wallpaperDir = "";
|
|
}
|
|
return;
|
|
}
|
|
|
|
wallpaperDir = currentWallpaper.substring(0, currentWallpaper.lastIndexOf('/'));
|
|
}
|
|
|
|
function updateSelectedFileName() {
|
|
if (wallpaperFolderModel.count === 0) {
|
|
selectedFileName = "";
|
|
return;
|
|
}
|
|
|
|
const absoluteIndex = currentPage * itemsPerPage + gridIndex;
|
|
if (absoluteIndex < wallpaperFolderModel.count) {
|
|
const filePath = wallpaperFolderModel.get(absoluteIndex, "filePath");
|
|
if (filePath) {
|
|
const pathStr = filePath.toString().replace(/^file:\/\//, '');
|
|
selectedFileName = pathStr.substring(pathStr.lastIndexOf('/') + 1);
|
|
return;
|
|
}
|
|
}
|
|
selectedFileName = "";
|
|
}
|
|
|
|
Connections {
|
|
target: SessionData
|
|
function onWallpaperPathChanged() {
|
|
loadWallpaperDirectory();
|
|
if (visible && active) {
|
|
setInitialSelection();
|
|
}
|
|
}
|
|
function onMonitorWallpapersChanged() {
|
|
loadWallpaperDirectory();
|
|
if (visible && active) {
|
|
setInitialSelection();
|
|
}
|
|
}
|
|
function onPerMonitorWallpaperChanged() {
|
|
loadWallpaperDirectory();
|
|
if (visible && active) {
|
|
setInitialSelection();
|
|
}
|
|
}
|
|
}
|
|
|
|
onTargetScreenNameChanged: {
|
|
loadWallpaperDirectory();
|
|
if (visible && active) {
|
|
setInitialSelection();
|
|
}
|
|
}
|
|
|
|
function collectWallpaperPaths() {
|
|
const paths = [];
|
|
for (var i = 0; i < wallpaperFolderModel.count; i++) {
|
|
const filePath = wallpaperFolderModel.get(i, "filePath");
|
|
if (filePath) {
|
|
paths.push(filePath.toString().replace(/^file:\/\//, ''));
|
|
}
|
|
}
|
|
return paths;
|
|
}
|
|
|
|
Connections {
|
|
target: wallpaperFolderModel
|
|
function onCountChanged() {
|
|
if (wallpaperFolderModel.status === FolderListModel.Ready) {
|
|
if (visible && active) {
|
|
setInitialSelection();
|
|
}
|
|
updateSelectedFileName();
|
|
thumbnailPreloader.paths = collectWallpaperPaths();
|
|
}
|
|
}
|
|
function onStatusChanged() {
|
|
if (wallpaperFolderModel.status === FolderListModel.Ready && wallpaperFolderModel.count > 0) {
|
|
if (visible && active) {
|
|
setInitialSelection();
|
|
}
|
|
updateSelectedFileName();
|
|
thumbnailPreloader.paths = collectWallpaperPaths();
|
|
}
|
|
}
|
|
}
|
|
|
|
WallpaperThumbnailPreloader {
|
|
id: thumbnailPreloader
|
|
cacheSize: 256
|
|
}
|
|
|
|
FolderListModel {
|
|
id: wallpaperFolderModel
|
|
|
|
showDirsFirst: false
|
|
showDotAndDotDot: false
|
|
showHidden: false
|
|
caseSensitive: false
|
|
nameFilters: ["*.jpg", "*.jpeg", "*.png", "*.bmp", "*.gif", "*.webp", "*.jxl", "*.avif", "*.heif", "*.exr"]
|
|
showFiles: true
|
|
showDirs: false
|
|
sortField: {
|
|
switch (root.sortBy) {
|
|
case "size":
|
|
return FolderListModel.Size;
|
|
case "modified":
|
|
return FolderListModel.Time;
|
|
case "type":
|
|
return FolderListModel.Type;
|
|
default:
|
|
return FolderListModel.Name;
|
|
}
|
|
}
|
|
sortReversed: !root.sortAscending
|
|
folder: wallpaperDir ? "file://" + wallpaperDir.split('/').map(s => encodeURIComponent(s)).join('/') : ""
|
|
}
|
|
|
|
FileBrowserSurfaceModal {
|
|
id: wallpaperBrowser
|
|
|
|
browserTitle: I18n.tr("Select Wallpaper Directory", "wallpaper directory file browser title")
|
|
browserIcon: "folder_open"
|
|
browserType: "wallpaper"
|
|
showHiddenFiles: false
|
|
fileExtensions: ["*.jpg", "*.jpeg", "*.png", "*.bmp", "*.gif", "*.webp", "*.jxl", "*.avif", "*.heif", "*.exr"]
|
|
parentPopout: root.parentPopout
|
|
|
|
onFileSelected: path => {
|
|
const cleanPath = path.replace(/^file:\/\//, '');
|
|
setCurrentWallpaper(cleanPath);
|
|
|
|
const dirPath = cleanPath.substring(0, cleanPath.lastIndexOf('/'));
|
|
if (dirPath) {
|
|
wallpaperDir = dirPath;
|
|
CacheData.wallpaperLastPath = dirPath;
|
|
CacheData.saveCache();
|
|
}
|
|
close();
|
|
}
|
|
}
|
|
|
|
Column {
|
|
id: contentColumn
|
|
anchors.fill: parent
|
|
spacing: 0
|
|
|
|
Item {
|
|
width: parent.width
|
|
height: parent.height - 50
|
|
|
|
GridView {
|
|
id: wallpaperGrid
|
|
anchors.centerIn: parent
|
|
width: parent.width - Theme.spacingS
|
|
height: parent.height - Theme.spacingS
|
|
cellWidth: width / 4
|
|
cellHeight: height / 4
|
|
clip: true
|
|
enabled: root.active
|
|
interactive: root.active
|
|
boundsBehavior: Flickable.StopAtBounds
|
|
keyNavigationEnabled: false
|
|
activeFocusOnTab: false
|
|
highlightFollowsCurrentItem: true
|
|
highlightMoveDuration: enableAnimation ? Theme.shortDuration : 0
|
|
focus: false
|
|
|
|
highlight: Item {
|
|
z: 1000
|
|
Rectangle {
|
|
anchors.fill: parent
|
|
anchors.margins: Theme.spacingXS
|
|
color: "transparent"
|
|
border.width: 3
|
|
border.color: Theme.primary
|
|
radius: Theme.cornerRadius
|
|
}
|
|
}
|
|
|
|
model: {
|
|
root.gridRevision; // re-evaluate when sort order changes in place
|
|
const startIndex = currentPage * itemsPerPage;
|
|
const endIndex = Math.min(startIndex + itemsPerPage, wallpaperFolderModel.count);
|
|
const items = [];
|
|
for (var i = startIndex; i < endIndex; i++) {
|
|
const filePath = wallpaperFolderModel.get(i, "filePath");
|
|
if (filePath) {
|
|
items.push(filePath.toString().replace(/^file:\/\//, ''));
|
|
}
|
|
}
|
|
return items;
|
|
}
|
|
|
|
onModelChanged: {
|
|
const clampedIndex = model.length > 0 ? Math.min(Math.max(0, gridIndex), model.length - 1) : 0;
|
|
if (gridIndex !== clampedIndex) {
|
|
gridIndex = clampedIndex;
|
|
}
|
|
}
|
|
|
|
onCountChanged: {
|
|
if (count > 0) {
|
|
const clampedIndex = Math.min(gridIndex, count - 1);
|
|
currentIndex = clampedIndex;
|
|
positionViewAtIndex(clampedIndex, GridView.Contain);
|
|
}
|
|
Qt.callLater(() => {
|
|
enableAnimation = true;
|
|
});
|
|
}
|
|
|
|
Connections {
|
|
target: root
|
|
function onGridIndexChanged() {
|
|
if (wallpaperGrid.count > 0) {
|
|
wallpaperGrid.currentIndex = gridIndex;
|
|
if (!enableAnimation) {
|
|
wallpaperGrid.positionViewAtIndex(gridIndex, GridView.Contain);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
delegate: Item {
|
|
width: wallpaperGrid.cellWidth
|
|
height: wallpaperGrid.cellHeight
|
|
|
|
property string wallpaperPath: modelData || ""
|
|
property bool isSelected: getCurrentWallpaper() === modelData
|
|
|
|
Rectangle {
|
|
id: wallpaperCard
|
|
anchors.fill: parent
|
|
anchors.margins: Theme.spacingXS
|
|
color: Theme.withAlpha(Theme.surfaceContainerHighest, Theme.popupTransparency)
|
|
radius: Theme.cornerRadius
|
|
clip: true
|
|
|
|
Rectangle {
|
|
anchors.fill: parent
|
|
color: isSelected ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.15) : "transparent"
|
|
radius: parent.radius
|
|
|
|
Behavior on color {
|
|
ColorAnimation {
|
|
duration: Theme.shortDuration
|
|
easing.type: Theme.standardEasing
|
|
}
|
|
}
|
|
}
|
|
|
|
Rectangle {
|
|
id: maskRect
|
|
width: thumbnailImage.width
|
|
height: thumbnailImage.height
|
|
radius: Theme.cornerRadius
|
|
visible: false
|
|
layer.enabled: true
|
|
}
|
|
|
|
CachingImage {
|
|
id: thumbnailImage
|
|
anchors.fill: parent
|
|
imagePath: modelData || ""
|
|
maxCacheSize: 256
|
|
|
|
layer.enabled: true
|
|
layer.effect: MultiEffect {
|
|
maskEnabled: true
|
|
maskThresholdMin: 0.5
|
|
maskSpreadAtMin: 1.0
|
|
maskSource: maskRect
|
|
}
|
|
}
|
|
|
|
StateLayer {
|
|
anchors.fill: parent
|
|
cornerRadius: parent.radius
|
|
stateColor: Theme.primary
|
|
}
|
|
|
|
MouseArea {
|
|
id: wallpaperMouseArea
|
|
anchors.fill: parent
|
|
hoverEnabled: true
|
|
cursorShape: Qt.PointingHandCursor
|
|
|
|
onClicked: {
|
|
gridIndex = index;
|
|
if (modelData) {
|
|
setCurrentWallpaper(modelData);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
StyledText {
|
|
anchors.centerIn: parent
|
|
visible: wallpaperFolderModel.count === 0
|
|
text: I18n.tr("No wallpapers found\n\nClick the folder icon below to browse")
|
|
font.pixelSize: 14
|
|
color: Theme.outline
|
|
horizontalAlignment: Text.AlignHCenter
|
|
}
|
|
}
|
|
|
|
Column {
|
|
width: parent.width
|
|
height: 50
|
|
|
|
Row {
|
|
width: parent.width
|
|
height: 32
|
|
spacing: Theme.spacingS
|
|
|
|
Item {
|
|
width: (parent.width - controlsRow.width - sortButton.width - browseButton.width - Theme.spacingS * 3) / 2
|
|
height: parent.height
|
|
}
|
|
|
|
Row {
|
|
id: controlsRow
|
|
anchors.verticalCenter: parent.verticalCenter
|
|
spacing: Theme.spacingS
|
|
|
|
DankActionButton {
|
|
anchors.verticalCenter: parent.verticalCenter
|
|
iconName: "skip_previous"
|
|
iconSize: 20
|
|
buttonSize: 32
|
|
enabled: totalPages > 1
|
|
opacity: enabled ? 1.0 : 0.3
|
|
tooltipText: I18n.tr("Previous page")
|
|
tooltipSide: "top"
|
|
onClicked: {
|
|
if (totalPages > 1) {
|
|
currentPage = (currentPage - 1 + totalPages) % totalPages;
|
|
}
|
|
}
|
|
}
|
|
|
|
StyledText {
|
|
id: pageIndicator
|
|
anchors.verticalCenter: parent.verticalCenter
|
|
text: wallpaperFolderModel.count > 0 ? (wallpaperFolderModel.count === 1 ? I18n.tr("%1 wallpaper • %2 / %3").arg(wallpaperFolderModel.count).arg(currentPage + 1).arg(totalPages) : I18n.tr("%1 wallpapers • %2 / %3").arg(wallpaperFolderModel.count).arg(currentPage + 1).arg(totalPages)) : I18n.tr("No wallpapers")
|
|
font.pixelSize: 14
|
|
color: pageIndicatorMouseArea.containsMouse && pageIndicatorMouseArea.enabled ? Theme.primary : Theme.surfaceText
|
|
opacity: 0.7
|
|
|
|
MouseArea {
|
|
id: pageIndicatorMouseArea
|
|
anchors.fill: parent
|
|
enabled: totalPages > 1
|
|
hoverEnabled: true
|
|
cursorShape: enabled ? Qt.PointingHandCursor : Qt.ArrowCursor
|
|
onClicked: {
|
|
sortMenu.visible = false;
|
|
pageJumpPopup.visible = !pageJumpPopup.visible;
|
|
}
|
|
onEntered: if (enabled) pageJumpTooltip.show(I18n.tr("Jump to page"), pageIndicator, 0, 0, "top")
|
|
onExited: pageJumpTooltip.hide()
|
|
}
|
|
|
|
DankTooltipV2 {
|
|
id: pageJumpTooltip
|
|
}
|
|
}
|
|
|
|
DankActionButton {
|
|
anchors.verticalCenter: parent.verticalCenter
|
|
iconName: "skip_next"
|
|
iconSize: 20
|
|
buttonSize: 32
|
|
enabled: totalPages > 1
|
|
opacity: enabled ? 1.0 : 0.3
|
|
tooltipText: I18n.tr("Next page")
|
|
tooltipSide: "top"
|
|
onClicked: {
|
|
if (totalPages > 1) {
|
|
currentPage = (currentPage + 1) % totalPages;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
DankActionButton {
|
|
id: sortButton
|
|
anchors.verticalCenter: parent.verticalCenter
|
|
iconName: "sort"
|
|
iconSize: 20
|
|
buttonSize: 32
|
|
opacity: 0.7
|
|
enabled: wallpaperFolderModel.count > 0
|
|
tooltipText: I18n.tr("Sort wallpapers")
|
|
tooltipSide: "top"
|
|
onClicked: {
|
|
pageJumpPopup.visible = false;
|
|
sortMenu.visible = !sortMenu.visible;
|
|
}
|
|
}
|
|
|
|
DankActionButton {
|
|
id: browseButton
|
|
anchors.verticalCenter: parent.verticalCenter
|
|
iconName: "folder_open"
|
|
iconSize: 20
|
|
buttonSize: 32
|
|
opacity: 0.7
|
|
tooltipText: I18n.tr("Choose wallpaper folder")
|
|
tooltipSide: "top"
|
|
onClicked: wallpaperBrowser.open()
|
|
}
|
|
}
|
|
|
|
StyledText {
|
|
width: parent.width
|
|
height: 18
|
|
text: selectedFileName
|
|
font.pixelSize: 12
|
|
color: Theme.surfaceText
|
|
opacity: 0.5
|
|
visible: selectedFileName !== ""
|
|
elide: Text.ElideMiddle
|
|
horizontalAlignment: Text.AlignHCenter
|
|
}
|
|
}
|
|
}
|
|
|
|
function jumpToPage(value) {
|
|
const n = parseInt(value);
|
|
if (!isNaN(n)) {
|
|
currentPage = Math.max(0, Math.min(totalPages - 1, n - 1));
|
|
}
|
|
pageJumpPopup.visible = false;
|
|
}
|
|
|
|
// Click anywhere outside an open overlay to dismiss it.
|
|
MouseArea {
|
|
anchors.fill: parent
|
|
z: 99
|
|
visible: sortMenu.visible || pageJumpPopup.visible
|
|
enabled: visible
|
|
onClicked: closeOverlays()
|
|
}
|
|
|
|
BackdropBlur {
|
|
visible: sortMenu.visible
|
|
z: 100
|
|
width: sortMenu.width
|
|
height: sortMenu.height
|
|
anchors.right: parent.right
|
|
anchors.bottom: parent.bottom
|
|
anchors.rightMargin: Theme.spacingM
|
|
anchors.bottomMargin: 56
|
|
radius: Theme.cornerRadius
|
|
sourceItem: contentColumn
|
|
}
|
|
|
|
FileBrowserSortMenu {
|
|
id: sortMenu
|
|
anchors.right: parent.right
|
|
anchors.bottom: parent.bottom
|
|
anchors.rightMargin: Theme.spacingM
|
|
anchors.bottomMargin: 56
|
|
z: 101
|
|
surfaceColor: Theme.readableSurface
|
|
sortBy: root.sortBy
|
|
sortAscending: root.sortAscending
|
|
onSortBySelected: value => {
|
|
root.sortBy = value;
|
|
root.persistSort();
|
|
}
|
|
onSortOrderSelected: ascending => {
|
|
root.sortAscending = ascending;
|
|
root.persistSort();
|
|
}
|
|
}
|
|
|
|
BackdropBlur {
|
|
visible: pageJumpPopup.visible
|
|
z: 100
|
|
width: pageJumpPopup.width
|
|
height: pageJumpPopup.height
|
|
anchors.horizontalCenter: parent.horizontalCenter
|
|
anchors.bottom: parent.bottom
|
|
anchors.bottomMargin: 56
|
|
radius: Theme.cornerRadius
|
|
sourceItem: contentColumn
|
|
}
|
|
|
|
StyledRect {
|
|
id: pageJumpPopup
|
|
width: 180
|
|
height: jumpColumn.height + Theme.spacingM * 2
|
|
color: Theme.readableSurface
|
|
radius: Theme.cornerRadius
|
|
border.color: Theme.outlineMedium
|
|
border.width: 1
|
|
visible: false
|
|
z: 101
|
|
anchors.horizontalCenter: parent.horizontalCenter
|
|
anchors.bottom: parent.bottom
|
|
anchors.bottomMargin: 56
|
|
|
|
onVisibleChanged: {
|
|
if (visible) {
|
|
pageJumpField.text = (root.currentPage + 1).toString();
|
|
pageJumpField.forceActiveFocus();
|
|
pageJumpField.selectAll();
|
|
}
|
|
}
|
|
|
|
Column {
|
|
id: jumpColumn
|
|
anchors.left: parent.left
|
|
anchors.right: parent.right
|
|
anchors.top: parent.top
|
|
anchors.margins: Theme.spacingM
|
|
spacing: Theme.spacingXS
|
|
|
|
StyledText {
|
|
text: I18n.tr("Jump to page (1 - %1)").arg(root.totalPages)
|
|
font.pixelSize: Theme.fontSizeSmall
|
|
color: Theme.surfaceTextMedium
|
|
font.weight: Font.Medium
|
|
}
|
|
|
|
DankTextField {
|
|
id: pageJumpField
|
|
width: parent.width
|
|
placeholderText: "1 - " + root.totalPages
|
|
maximumLength: 6
|
|
topPadding: Theme.spacingS
|
|
bottomPadding: Theme.spacingS
|
|
validator: IntValidator {
|
|
bottom: 1
|
|
top: root.totalPages
|
|
}
|
|
onAccepted: root.jumpToPage(text)
|
|
}
|
|
}
|
|
}
|
|
}
|