fedora
This commit is contained in:
@@ -0,0 +1,182 @@
|
||||
import QtQuick
|
||||
import QtQuick.Controls
|
||||
import Quickshell
|
||||
|
||||
import qs.Commons
|
||||
import qs.Modules.MainScreen
|
||||
import qs.Services.UI
|
||||
import qs.Widgets
|
||||
|
||||
SmartPanel {
|
||||
id: root
|
||||
|
||||
// Disable when overlay mode is enabled (LauncherOverlayWindow handles it)
|
||||
enabled: !Settings.data.appLauncher.overviewLayer
|
||||
visible: !Settings.data.appLauncher.overviewLayer
|
||||
|
||||
// Reference to core (set after panelContent loads)
|
||||
property var launcherCoreRef: null
|
||||
|
||||
// Expose core launcher for external access (e.g., IPC)
|
||||
readonly property string searchText: launcherCoreRef ? launcherCoreRef.searchText : ""
|
||||
readonly property int selectedIndex: launcherCoreRef ? launcherCoreRef.selectedIndex : 0
|
||||
readonly property var results: launcherCoreRef ? launcherCoreRef.results : []
|
||||
readonly property var activeProvider: launcherCoreRef ? launcherCoreRef.activeProvider : null
|
||||
readonly property var currentProvider: launcherCoreRef ? launcherCoreRef.currentProvider : null
|
||||
readonly property bool isGridView: launcherCoreRef ? launcherCoreRef.isGridView : false
|
||||
readonly property int gridColumns: launcherCoreRef ? launcherCoreRef.gridColumns : 5
|
||||
|
||||
function setSearchText(text) {
|
||||
if (launcherCoreRef)
|
||||
launcherCoreRef.setSearchText(text);
|
||||
}
|
||||
|
||||
// Preview panel support
|
||||
readonly property bool previewActive: {
|
||||
if (!launcherCoreRef)
|
||||
return false;
|
||||
var provider = launcherCoreRef.activeProvider;
|
||||
if (!provider || !provider.hasPreview)
|
||||
return false;
|
||||
if (!Settings.data.appLauncher.enableClipPreview)
|
||||
return false;
|
||||
return selectedIndex >= 0 && results && !!results[selectedIndex];
|
||||
}
|
||||
readonly property int previewPanelWidth: Math.round(400 * Style.uiScaleRatio)
|
||||
|
||||
// Panel sizing
|
||||
readonly property int listPanelWidth: Math.round(500 * Style.uiScaleRatio)
|
||||
readonly property int totalBaseWidth: listPanelWidth + Style.margin2L
|
||||
|
||||
preferredWidth: totalBaseWidth
|
||||
preferredHeight: Math.round(600 * Style.uiScaleRatio)
|
||||
preferredWidthRatio: 0.25
|
||||
preferredHeightRatio: 0.5
|
||||
|
||||
// Positioning
|
||||
readonly property string screenBarPosition: Settings.getBarPositionForScreen(screen?.name)
|
||||
readonly property string panelPosition: {
|
||||
if (Settings.data.appLauncher.position === "follow_bar") {
|
||||
if (screenBarPosition === "left" || screenBarPosition === "right") {
|
||||
return `center_${screenBarPosition}`;
|
||||
} else {
|
||||
return `${screenBarPosition}_center`;
|
||||
}
|
||||
} else {
|
||||
return Settings.data.appLauncher.position;
|
||||
}
|
||||
}
|
||||
panelAnchorHorizontalCenter: !root.useButtonPosition && (panelPosition === "center" || panelPosition.endsWith("_center"))
|
||||
panelAnchorVerticalCenter: !root.useButtonPosition && panelPosition === "center"
|
||||
panelAnchorLeft: !root.useButtonPosition && panelPosition !== "center" && panelPosition.endsWith("_left")
|
||||
panelAnchorRight: !root.useButtonPosition && panelPosition !== "center" && panelPosition.endsWith("_right")
|
||||
panelAnchorBottom: !root.useButtonPosition && panelPosition.startsWith("bottom_")
|
||||
panelAnchorTop: !root.useButtonPosition && panelPosition.startsWith("top_")
|
||||
|
||||
panelContent: Rectangle {
|
||||
id: ui
|
||||
color: "transparent"
|
||||
opacity: launcherCore.resultsReady ? 1.0 : 0.0
|
||||
|
||||
Component.onCompleted: root.launcherCoreRef = launcherCore
|
||||
|
||||
Behavior on opacity {
|
||||
NumberAnimation {
|
||||
duration: Style.animationFast
|
||||
easing.type: Easing.OutCirc
|
||||
}
|
||||
}
|
||||
|
||||
// Preview Panel (external) - uses provider's preview component
|
||||
NDropShadow {
|
||||
source: previewBox
|
||||
anchors.fill: previewBox
|
||||
autoPaddingEnabled: true
|
||||
visible: previewBox.visible
|
||||
z: previewBox.z - 1
|
||||
}
|
||||
|
||||
NBox {
|
||||
id: previewBox
|
||||
visible: root.previewActive
|
||||
width: root.previewPanelWidth
|
||||
height: Math.round(400 * Style.uiScaleRatio)
|
||||
forceOpaque: true // no blur for now
|
||||
x: root.panelAnchorRight ? -(root.previewPanelWidth + Style.marginM) : ui.width + Style.marginM
|
||||
y: {
|
||||
var view = launcherCore.resultsView;
|
||||
if (!view)
|
||||
return Style.marginL;
|
||||
var row = launcherCore.isGridView ? Math.floor(launcherCore.selectedIndex / launcherCore.gridColumns) : launcherCore.selectedIndex;
|
||||
var gridCellSize = Math.floor((root.listPanelWidth - (2 * Style.marginXS) - ((launcherCore.targetGridColumns - 1) * Style.marginS)) / launcherCore.targetGridColumns);
|
||||
var itemHeight = launcherCore.isGridView ? (gridCellSize + Style.marginXXS) : (launcherCore.entryHeight + (view.spacing || 0));
|
||||
var yPos = row * itemHeight - (view.contentY || 0);
|
||||
var mapped = view.mapToItem(ui, 0, yPos);
|
||||
return Math.max(Style.marginL, Math.min(mapped.y, ui.height - previewBox.height - Style.marginL));
|
||||
}
|
||||
z: -1
|
||||
|
||||
opacity: visible ? 1.0 : 0.0
|
||||
Behavior on opacity {
|
||||
NumberAnimation {
|
||||
duration: Style.animationFast
|
||||
}
|
||||
}
|
||||
Behavior on y {
|
||||
NumberAnimation {
|
||||
duration: Style.animationFast
|
||||
easing.type: Easing.OutCubic
|
||||
}
|
||||
}
|
||||
|
||||
Loader {
|
||||
id: previewLoader
|
||||
anchors.fill: parent
|
||||
active: root.previewActive
|
||||
source: {
|
||||
if (!active)
|
||||
return "";
|
||||
var provider = launcherCore.activeProvider;
|
||||
if (provider && provider.previewComponentPath)
|
||||
return provider.previewComponentPath;
|
||||
return "";
|
||||
}
|
||||
|
||||
onLoaded: updatePreviewItem()
|
||||
onItemChanged: updatePreviewItem()
|
||||
|
||||
function updatePreviewItem() {
|
||||
if (!item || launcherCore.selectedIndex < 0 || !launcherCore.results[launcherCore.selectedIndex])
|
||||
return;
|
||||
var provider = launcherCore.activeProvider;
|
||||
if (provider && provider.getPreviewData) {
|
||||
item.currentItem = provider.getPreviewData(launcherCore.results[launcherCore.selectedIndex]);
|
||||
} else {
|
||||
item.currentItem = launcherCore.results[launcherCore.selectedIndex];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Core launcher (state, providers, UI)
|
||||
LauncherCore {
|
||||
id: launcherCore
|
||||
anchors.fill: parent
|
||||
screen: root.screen
|
||||
isOpen: root.isPanelOpen
|
||||
onRequestClose: root.close()
|
||||
// Defer so the signal emission completes before SmartPanel
|
||||
// sets isPanelOpen=false and the contentLoader destroys us.
|
||||
onRequestCloseImmediately: Qt.callLater(root.closeImmediately)
|
||||
}
|
||||
|
||||
// Update preview when selection changes
|
||||
Connections {
|
||||
target: launcherCore
|
||||
function onSelectedIndexChanged() {
|
||||
if (previewLoader.item)
|
||||
previewLoader.updatePreviewItem();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user