forked from Shinonome/dots-hyprland
Merge branch 'end-4:main' into main
This commit is contained in:
@@ -8,3 +8,15 @@
|
|||||||
#env = SDL_IM_MODULE, fcitx
|
#env = SDL_IM_MODULE, fcitx
|
||||||
#env = GLFW_IM_MODULE, ibus
|
#env = GLFW_IM_MODULE, ibus
|
||||||
#env = INPUT_METHOD, fcitx
|
#env = INPUT_METHOD, fcitx
|
||||||
|
|
||||||
|
# ######## Wayland #########
|
||||||
|
# Tearing
|
||||||
|
# env = WLR_DRM_NO_ATOMIC, 1
|
||||||
|
# ?
|
||||||
|
# env = WLR_NO_HARDWARE_CURSORS, 1
|
||||||
|
|
||||||
|
# ######## EDITOR #########
|
||||||
|
#https://wiki.archlinux.org/title/Category:Text_editors
|
||||||
|
# for example: vi nano nvim ...
|
||||||
|
|
||||||
|
#env = EDITOR, vim
|
||||||
|
|||||||
@@ -1,2 +1,6 @@
|
|||||||
# Put general config stuff here
|
# Put general config stuff here
|
||||||
# Here's a list of every variable: https://wiki.hyprland.org/Configuring/Variables/
|
# Here's a list of every variable: https://wiki.hyprland.org/Configuring/Variables/
|
||||||
|
|
||||||
|
# monitor=,addreserved, 0, 0, 0, 0 # Custom reserved area
|
||||||
|
|
||||||
|
# HDMI port: mirror display. To see device name, use `hyprctl monitors`
|
||||||
|
|||||||
@@ -4,6 +4,19 @@
|
|||||||
bind = Ctrl+Super, Slash, exec, xdg-open ~/.config/illogical-impulse/config.json # Edit shell config
|
bind = Ctrl+Super, Slash, exec, xdg-open ~/.config/illogical-impulse/config.json # Edit shell config
|
||||||
bind = Ctrl+Super+Alt, Slash, exec, xdg-open ~/.config/hypr/custom/keybinds.conf # Edit extra keybinds
|
bind = Ctrl+Super+Alt, Slash, exec, xdg-open ~/.config/hypr/custom/keybinds.conf # Edit extra keybinds
|
||||||
|
|
||||||
|
##! Apps
|
||||||
|
# bind = Super, Return, exec, ~/.config/hypr/hyprland/scripts/launch_first_available.sh "${TERMINAL}" "kitty -1" "foot" "alacritty" "wezterm" "konsole" "kgx" "uxterm" "xterm" # Terminal
|
||||||
|
# bind = Super, T, exec, ~/.config/hypr/hyprland/scripts/launch_first_available.sh "${TERMINAL}" "kitty -1" "foot" "alacritty" "wezterm" "konsole" "kgx" "uxterm" "xterm" # [hidden] (terminal) (alt)
|
||||||
|
# bind = Ctrl+Alt, T, exec, ~/.config/hypr/hyprland/scripts/launch_first_available.sh "${TERMINAL}" "kitty -1" "foot" "alacritty" "wezterm" "konsole" "kgx" "uxterm" "xterm" # [hidden] (terminal) (for Ubuntu people)
|
||||||
|
# bind = Super, E, exec, ~/.config/hypr/hyprland/scripts/launch_first_available.sh "dolphin" "nautilus" "nemo" "thunar" "${TERMINAL}" "kitty -1 fish -c yazi" # File manager
|
||||||
|
# bind = Super, W, exec, ~/.config/hypr/hyprland/scripts/launch_first_available.sh "google-chrome-stable" "zen-browser" "firefox" "brave" "chromium" "microsoft-edge-stable" "opera" "librewolf" # Browser
|
||||||
|
# bind = Super, C, exec, ~/.config/hypr/hyprland/scripts/launch_first_available.sh "code" "codium" "cursor" "zed" "zedit" "zeditor" "kate" "gnome-text-editor" "emacs" "command -v nvim && kitty -1 nvim" "command -v micro && kitty -1 micro" # Code editor
|
||||||
|
# bind = Ctrl+Super+Shift+Alt, W, exec, ~/.config/hypr/hyprland/scripts/launch_first_available.sh "wps" "onlyoffice-desktopeditors" "libreoffice" # Office software
|
||||||
|
# bind = Super, X, exec, ~/.config/hypr/hyprland/scripts/launch_first_available.sh "kate" "gnome-text-editor" "emacs" # Text editor
|
||||||
|
# bind = Ctrl+Super, V, exec, ~/.config/hypr/hyprland/scripts/launch_first_available.sh "pavucontrol-qt" "pavucontrol" # Volume mixer
|
||||||
|
# bind = Super, I, exec, XDG_CURRENT_DESKTOP=gnome ~/.config/hypr/hyprland/scripts/launch_first_available.sh "qs -p ~/.config/quickshell/$qsConfig/settings.qml" "systemsettings" "gnome-control-center" "better-control" # Settings app
|
||||||
|
# bind = Ctrl+Shift, Escape, exec, ~/.config/hypr/hyprland/scripts/launch_first_available.sh "gnome-system-monitor" "plasma-systemmonitor --page-name Processes" "command -v btop && kitty -1 fish -c btop" # Task manager
|
||||||
|
|
||||||
# Add stuff here
|
# Add stuff here
|
||||||
# Use #! to add an extra column on the cheatsheet
|
# Use #! to add an extra column on the cheatsheet
|
||||||
# Use ##! to add a section in that column
|
# Use ##! to add a section in that column
|
||||||
|
|||||||
@@ -1,3 +1,11 @@
|
|||||||
# You can put custom rules here
|
# You can put custom rules here
|
||||||
# Window/layer rules: https://wiki.hyprland.org/Configuring/Window-Rules/
|
# Window/layer rules: https://wiki.hyprland.org/Configuring/Window-Rules/
|
||||||
# Workspace rules: https://wiki.hyprland.org/Configuring/Workspace-Rules/
|
# Workspace rules: https://wiki.hyprland.org/Configuring/Workspace-Rules/
|
||||||
|
|
||||||
|
# ######## Window rules ########
|
||||||
|
|
||||||
|
# Uncomment to apply global transparency to all windows:
|
||||||
|
# windowrulev2 = opacity 0.89 override 0.89 override, class:.*
|
||||||
|
|
||||||
|
# Disable blur for all xwayland apps
|
||||||
|
# windowrulev2 = noblur, xwayland:1
|
||||||
@@ -9,12 +9,6 @@ env = QT_QPA_PLATFORM, wayland
|
|||||||
env = QT_QPA_PLATFORMTHEME, kde
|
env = QT_QPA_PLATFORMTHEME, kde
|
||||||
env = XDG_MENU_PREFIX, plasma-
|
env = XDG_MENU_PREFIX, plasma-
|
||||||
|
|
||||||
# ######## Wayland #########
|
|
||||||
# Tearing
|
|
||||||
# env = WLR_DRM_NO_ATOMIC, 1
|
|
||||||
# ?
|
|
||||||
# env = WLR_NO_HARDWARE_CURSORS, 1
|
|
||||||
|
|
||||||
# ######## Virtual envrionment #########
|
# ######## Virtual envrionment #########
|
||||||
env = ILLOGICAL_IMPULSE_VIRTUAL_ENV, ~/.local/state/quickshell/.venv
|
env = ILLOGICAL_IMPULSE_VIRTUAL_ENV, ~/.local/state/quickshell/.venv
|
||||||
|
|
||||||
|
|||||||
@@ -1,9 +1,5 @@
|
|||||||
# MONITOR CONFIG
|
# MONITOR CONFIG
|
||||||
monitor=,preferred,auto,1
|
monitor=,preferred,auto,1
|
||||||
# monitor=,addreserved, 0, 0, 0, 0 # Custom reserved area
|
|
||||||
|
|
||||||
# HDMI port: mirror display. To see device name, use `hyprctl monitors`
|
|
||||||
# monitor=HDMI-A-1,1920x1080@60,1920x0,1,mirror,eDP-1
|
|
||||||
|
|
||||||
gesture = 3, swipe, move,
|
gesture = 3, swipe, move,
|
||||||
gesture = 3, pinch, float
|
gesture = 3, pinch, float
|
||||||
|
|||||||
@@ -1,12 +1,8 @@
|
|||||||
# ######## Window rules ########
|
# ######## Window rules ########
|
||||||
|
|
||||||
# Uncomment to apply global transparency to all windows:
|
|
||||||
# windowrulev2 = opacity 0.89 override 0.89 override, class:.*
|
|
||||||
|
|
||||||
# Disable blur for xwayland context menus
|
# Disable blur for xwayland context menus
|
||||||
windowrulev2 = noblur,class:^()$,title:^()$
|
windowrulev2 = noblur,class:^()$,title:^()$
|
||||||
# Disable blur for all xwayland apps
|
|
||||||
# windowrulev2 = noblur, xwayland:1
|
|
||||||
# Disable blur for every window
|
# Disable blur for every window
|
||||||
windowrulev2 = noblur, class:.*
|
windowrulev2 = noblur, class:.*
|
||||||
|
|
||||||
|
|||||||
@@ -590,8 +590,9 @@ Singleton {
|
|||||||
// false will make (some) stuff also be like that for accuracy.
|
// false will make (some) stuff also be like that for accuracy.
|
||||||
// Example: the right-click menu of the Start button
|
// Example: the right-click menu of the Start button
|
||||||
property JsonObject tweaks: JsonObject {
|
property JsonObject tweaks: JsonObject {
|
||||||
property bool smootherMenuAnimations: true
|
|
||||||
property bool switchHandlePositionFix: true
|
property bool switchHandlePositionFix: true
|
||||||
|
property bool smootherMenuAnimations: true
|
||||||
|
property bool smootherSearchBar: true
|
||||||
}
|
}
|
||||||
property JsonObject bar: JsonObject {
|
property JsonObject bar: JsonObject {
|
||||||
property bool bottom: true
|
property bool bottom: true
|
||||||
|
|||||||
@@ -0,0 +1,29 @@
|
|||||||
|
import QtQuick
|
||||||
|
import Quickshell
|
||||||
|
|
||||||
|
QtObject {
|
||||||
|
enum IconType { Material, Text, System, None }
|
||||||
|
enum FontType { Normal, Monospace }
|
||||||
|
|
||||||
|
// General stuff
|
||||||
|
property string type: ""
|
||||||
|
property var fontType: LauncherSearchResult.FontType.Normal
|
||||||
|
property string name: ""
|
||||||
|
property string rawValue: ""
|
||||||
|
property string iconName: ""
|
||||||
|
property var iconType: LauncherSearchResult.IconType.None
|
||||||
|
property string verb: ""
|
||||||
|
property bool blurImage: false
|
||||||
|
property var execute: () => {
|
||||||
|
print("Not implemented");
|
||||||
|
}
|
||||||
|
property var actions: []
|
||||||
|
|
||||||
|
// Stuff needed for DesktopEntry objects
|
||||||
|
property bool shown: true
|
||||||
|
property string comment: ""
|
||||||
|
property bool runInTerminal: false
|
||||||
|
property string genericName: ""
|
||||||
|
property list<string> keywords: []
|
||||||
|
|
||||||
|
}
|
||||||
@@ -278,7 +278,7 @@ Item {
|
|||||||
StyledToolTip {
|
StyledToolTip {
|
||||||
extraVisibleCondition: false
|
extraVisibleCondition: false
|
||||||
alternativeVisibleCondition: dragArea.containsMouse && !window.Drag.active
|
alternativeVisibleCondition: dragArea.containsMouse && !window.Drag.active
|
||||||
text: `${windowData.title}\n[${windowData.class}] ${windowData.xwayland ? "[XWayland] " : ""}`
|
text: `${windowData?.title}\n[${windowData?.class}] ${windowData?.xwayland ? "[XWayland] " : ""}`
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
import qs
|
import qs
|
||||||
import qs.services
|
import qs.services
|
||||||
import qs.modules.common
|
import qs.modules.common
|
||||||
|
import qs.modules.common.models
|
||||||
import qs.modules.common.widgets
|
import qs.modules.common.widgets
|
||||||
import qs.modules.common.functions
|
import qs.modules.common.functions
|
||||||
import QtQuick
|
import QtQuick
|
||||||
@@ -12,20 +13,27 @@ import Quickshell.Hyprland
|
|||||||
|
|
||||||
RippleButton {
|
RippleButton {
|
||||||
id: root
|
id: root
|
||||||
property var entry
|
property LauncherSearchResult entry
|
||||||
property string query
|
property string query
|
||||||
property bool entryShown: entry?.shown ?? true
|
property bool entryShown: entry?.shown ?? true
|
||||||
property string itemType: entry?.type ?? Translation.tr("App")
|
property string itemType: entry?.type ?? Translation.tr("App")
|
||||||
property string itemName: entry?.name ?? ""
|
property string itemName: entry?.name ?? ""
|
||||||
property string itemIcon: entry?.icon ?? ""
|
property var iconType: entry?.iconType
|
||||||
|
property string iconName: entry?.iconName ?? ""
|
||||||
property var itemExecute: entry?.execute
|
property var itemExecute: entry?.execute
|
||||||
property string fontType: entry?.fontType ?? "main"
|
property var fontType: switch(entry?.fontType) {
|
||||||
property string itemClickActionName: entry?.clickActionName ?? "Open"
|
case LauncherSearchResult.FontType.Monospace:
|
||||||
property string bigText: entry?.bigText ?? ""
|
return "monospace"
|
||||||
property string materialSymbol: entry?.materialSymbol ?? ""
|
case LauncherSearchResult.FontType.Normal:
|
||||||
property string cliphistRawString: entry?.cliphistRawString ?? ""
|
return "main"
|
||||||
|
default:
|
||||||
|
return "main"
|
||||||
|
}
|
||||||
|
property string itemClickActionName: entry?.verb ?? "Open"
|
||||||
|
property string bigText: entry?.iconType === LauncherSearchResult.IconType.Text ? entry?.iconName ?? "" : ""
|
||||||
|
property string materialSymbol: entry.iconType === LauncherSearchResult.IconType.Material ? entry?.iconName ?? "" : ""
|
||||||
|
property string cliphistRawString: entry?.rawValue ?? ""
|
||||||
property bool blurImage: entry?.blurImage ?? false
|
property bool blurImage: entry?.blurImage ?? false
|
||||||
property string blurImageText: entry?.blurImageText ?? "Image hidden"
|
|
||||||
|
|
||||||
visible: root.entryShown
|
visible: root.entryShown
|
||||||
property int horizontalMargin: 10
|
property int horizontalMargin: 10
|
||||||
@@ -97,7 +105,7 @@ RippleButton {
|
|||||||
}
|
}
|
||||||
Keys.onPressed: (event) => {
|
Keys.onPressed: (event) => {
|
||||||
if (event.key === Qt.Key_Delete && event.modifiers === Qt.ShiftModifier) {
|
if (event.key === Qt.Key_Delete && event.modifiers === Qt.ShiftModifier) {
|
||||||
const deleteAction = root.entry.actions.find(action => action.name == "Delete");
|
const deleteAction = root.entry.actions.find(action => action.name == Translation.tr("Delete"));
|
||||||
|
|
||||||
if (deleteAction) {
|
if (deleteAction) {
|
||||||
deleteAction.execute()
|
deleteAction.execute()
|
||||||
@@ -126,16 +134,24 @@ RippleButton {
|
|||||||
Loader {
|
Loader {
|
||||||
id: iconLoader
|
id: iconLoader
|
||||||
active: true
|
active: true
|
||||||
sourceComponent: root.materialSymbol !== "" ? materialSymbolComponent :
|
sourceComponent: switch(root.iconType) {
|
||||||
root.bigText ? bigTextComponent :
|
case LauncherSearchResult.IconType.Material:
|
||||||
root.itemIcon !== "" ? iconImageComponent :
|
return materialSymbolComponent
|
||||||
null
|
case LauncherSearchResult.IconType.Text:
|
||||||
|
return bigTextComponent
|
||||||
|
case LauncherSearchResult.IconType.System:
|
||||||
|
return iconImageComponent
|
||||||
|
case LauncherSearchResult.IconType.None:
|
||||||
|
return null
|
||||||
|
default:
|
||||||
|
return null
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Component {
|
Component {
|
||||||
id: iconImageComponent
|
id: iconImageComponent
|
||||||
IconImage {
|
IconImage {
|
||||||
source: Quickshell.iconPath(root.itemIcon, "image-missing")
|
source: Quickshell.iconPath(root.iconName, "image-missing")
|
||||||
width: 35
|
width: 35
|
||||||
height: 35
|
height: 35
|
||||||
}
|
}
|
||||||
@@ -217,7 +233,6 @@ RippleButton {
|
|||||||
maxWidth: contentColumn.width
|
maxWidth: contentColumn.width
|
||||||
maxHeight: 140
|
maxHeight: 140
|
||||||
blur: root.blurImage
|
blur: root.blurImage
|
||||||
blurText: root.blurImageText
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -243,8 +258,8 @@ RippleButton {
|
|||||||
delegate: RippleButton {
|
delegate: RippleButton {
|
||||||
id: actionButton
|
id: actionButton
|
||||||
required property var modelData
|
required property var modelData
|
||||||
property string iconName: modelData.icon ?? ""
|
property var iconType: modelData.iconType
|
||||||
property string materialIconName: modelData.materialIcon ?? ""
|
property string iconName: modelData.iconName ?? ""
|
||||||
implicitHeight: 34
|
implicitHeight: 34
|
||||||
implicitWidth: 34
|
implicitWidth: 34
|
||||||
|
|
||||||
@@ -256,16 +271,16 @@ RippleButton {
|
|||||||
anchors.centerIn: parent
|
anchors.centerIn: parent
|
||||||
Loader {
|
Loader {
|
||||||
anchors.centerIn: parent
|
anchors.centerIn: parent
|
||||||
active: !(actionButton.iconName !== "") || actionButton.materialIconName
|
active: actionButton.iconType === LauncherSearchResult.IconType.Material || actionButton.iconName === ""
|
||||||
sourceComponent: MaterialSymbol {
|
sourceComponent: MaterialSymbol {
|
||||||
text: actionButton.materialIconName || "video_settings"
|
text: actionButton.iconName || "video_settings"
|
||||||
font.pixelSize: Appearance.font.pixelSize.hugeass
|
font.pixelSize: Appearance.font.pixelSize.hugeass
|
||||||
color: Appearance.m3colors.m3onSurface
|
color: Appearance.m3colors.m3onSurface
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Loader {
|
Loader {
|
||||||
anchors.centerIn: parent
|
anchors.centerIn: parent
|
||||||
active: actionButton.materialIconName.length == 0 && actionButton.iconName && actionButton.iconName !== ""
|
active: actionButton.iconType === LauncherSearchResult.IconType.System && actionButton.iconName !== ""
|
||||||
sourceComponent: IconImage {
|
sourceComponent: IconImage {
|
||||||
source: Quickshell.iconPath(actionButton.iconName)
|
source: Quickshell.iconPath(actionButton.iconName)
|
||||||
implicitSize: 20
|
implicitSize: 20
|
||||||
|
|||||||
@@ -42,12 +42,6 @@ Item { // Wrapper
|
|||||||
LauncherSearch.query = text;
|
LauncherSearch.query = text;
|
||||||
}
|
}
|
||||||
|
|
||||||
function containsUnsafeLink(entry) {
|
|
||||||
if (entry == undefined) return false;
|
|
||||||
const unsafeKeywords = Config.options.workSafety.triggerCondition.linkKeywords;
|
|
||||||
return StringUtils.stringListContainsSubstring(entry.toLowerCase(), unsafeKeywords);
|
|
||||||
}
|
|
||||||
|
|
||||||
Keys.onPressed: event => {
|
Keys.onPressed: event => {
|
||||||
// Prevent Esc and Backspace from registering
|
// Prevent Esc and Backspace from registering
|
||||||
if (event.key === Qt.Key_Escape)
|
if (event.key === Qt.Key_Escape)
|
||||||
|
|||||||
@@ -64,7 +64,7 @@ Singleton {
|
|||||||
property color bg0: "#1C1C1C"
|
property color bg0: "#1C1C1C"
|
||||||
property color bg0Border: "#404040"
|
property color bg0Border: "#404040"
|
||||||
property color bg1Base: "#2C2C2C"
|
property color bg1Base: "#2C2C2C"
|
||||||
property color bg1: "#a8a8a8"
|
property color bg1: '#9f9f9f'
|
||||||
property color bg1Hover: "#b3b3b3"
|
property color bg1Hover: "#b3b3b3"
|
||||||
property color bg1Active: '#727272'
|
property color bg1Active: '#727272'
|
||||||
property color bg1Border: '#bebebe'
|
property color bg1Border: '#bebebe'
|
||||||
@@ -125,6 +125,7 @@ Singleton {
|
|||||||
property color accentUnfocused: root.dark ? root.darkColors.accentUnfocused : root.lightColors.accentUnfocused
|
property color accentUnfocused: root.dark ? root.darkColors.accentUnfocused : root.lightColors.accentUnfocused
|
||||||
property color accentFg: ColorUtils.isDark(accent) ? "#FFFFFF" : "#000000"
|
property color accentFg: ColorUtils.isDark(accent) ? "#FFFFFF" : "#000000"
|
||||||
property color selection: Appearance.colors.colPrimaryContainer
|
property color selection: Appearance.colors.colPrimaryContainer
|
||||||
|
property color selectionFg: Appearance.colors.colOnPrimaryContainer
|
||||||
}
|
}
|
||||||
|
|
||||||
radius: QtObject {
|
radius: QtObject {
|
||||||
|
|||||||
@@ -44,6 +44,7 @@ WButton {
|
|||||||
radius: Looks.radius.medium
|
radius: Looks.radius.medium
|
||||||
color: root.color
|
color: root.color
|
||||||
Behavior on color {
|
Behavior on color {
|
||||||
|
enabled: root.animateChoiceHighlight
|
||||||
animation: Looks.transition.color.createObject(this)
|
animation: Looks.transition.color.createObject(this)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -14,17 +14,18 @@ Menu {
|
|||||||
property bool downDirection: false
|
property bool downDirection: false
|
||||||
property bool hasIcons: false // TODO: implement
|
property bool hasIcons: false // TODO: implement
|
||||||
|
|
||||||
implicitWidth: background.implicitWidth + root.padding * 2
|
implicitWidth: background.implicitWidth + margins * 2
|
||||||
implicitHeight: background.implicitHeight + root.padding * 2
|
implicitHeight: background.implicitHeight + margins * 2
|
||||||
|
margins: 10
|
||||||
padding: 3
|
padding: 3
|
||||||
property real sourceEdgeMargin: -implicitHeight
|
property real sourceEdgeMargin: -implicitHeight
|
||||||
clip: true
|
clip: true
|
||||||
|
|
||||||
enter: Transition {
|
enter: Transition {
|
||||||
NumberAnimation {
|
NumberAnimation {
|
||||||
property: "sourceEdgeMargin"
|
property: "sourceEdgeMargin"
|
||||||
from: -root.implicitHeight
|
from: -root.implicitHeight
|
||||||
to: root.padding
|
to: root.margins
|
||||||
duration: 200
|
duration: 200
|
||||||
easing.type: Easing.BezierSpline
|
easing.type: Easing.BezierSpline
|
||||||
easing.bezierCurve: Looks.transition.easing.bezierCurve.easeIn
|
easing.bezierCurve: Looks.transition.easing.bezierCurve.easeIn
|
||||||
@@ -33,7 +34,7 @@ Menu {
|
|||||||
exit: Transition {
|
exit: Transition {
|
||||||
NumberAnimation {
|
NumberAnimation {
|
||||||
property: "sourceEdgeMargin"
|
property: "sourceEdgeMargin"
|
||||||
from: root.padding
|
from: root.margins
|
||||||
to: -root.implicitHeight
|
to: -root.implicitHeight
|
||||||
duration: 150
|
duration: 150
|
||||||
easing.type: Easing.BezierSpline
|
easing.type: Easing.BezierSpline
|
||||||
@@ -41,43 +42,55 @@ Menu {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
background: WPane {
|
background: Item {
|
||||||
anchors {
|
id: bgItem
|
||||||
left: parent.left
|
implicitWidth: bgPane.implicitWidth
|
||||||
right: parent.right
|
implicitHeight: bgPane.implicitHeight
|
||||||
top: root.downDirection ? parent.top : undefined
|
WPane {
|
||||||
bottom: root.downDirection ? undefined : parent.bottom
|
id: bgPane
|
||||||
margins: root.padding
|
anchors {
|
||||||
topMargin: root.downDirection ? root.sourceEdgeMargin : root.padding
|
left: parent.left
|
||||||
bottomMargin: root.downDirection ? root.padding : root.sourceEdgeMargin
|
right: parent.right
|
||||||
}
|
top: root.downDirection ? parent.top : undefined
|
||||||
contentItem: Rectangle {
|
bottom: root.downDirection ? undefined : parent.bottom
|
||||||
color: Looks.colors.bg1Base
|
margins: root.margins
|
||||||
implicitWidth: menuListView.implicitWidth + root.padding * 2
|
topMargin: root.downDirection ? root.sourceEdgeMargin : root.margins
|
||||||
implicitHeight: root.contentItem.implicitHeight + root.padding * 2
|
bottomMargin: root.downDirection ? root.margins : root.sourceEdgeMargin
|
||||||
|
}
|
||||||
|
contentItem: Rectangle {
|
||||||
|
color: Looks.colors.bg1Base
|
||||||
|
implicitWidth: menuListView.implicitWidth + root.padding * 2
|
||||||
|
implicitHeight: root.contentItem.implicitHeight + root.padding * 2
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
contentItem: ListView {
|
contentItem: Item {
|
||||||
id: menuListView
|
implicitWidth: menuListView.implicitWidth
|
||||||
anchors {
|
implicitHeight: menuListView.implicitHeight
|
||||||
left: parent.left
|
ListView {
|
||||||
right: parent.right
|
id: menuListView
|
||||||
top: root.downDirection ? parent.top : undefined
|
anchors {
|
||||||
bottom: root.downDirection ? undefined : parent.bottom
|
left: parent.left
|
||||||
margins: root.padding * 2
|
right: parent.right
|
||||||
topMargin: root.downDirection ? root.sourceEdgeMargin : root.padding
|
top: root.downDirection ? parent.top : undefined
|
||||||
bottomMargin: root.downDirection ? root.padding : root.sourceEdgeMargin
|
bottom: root.downDirection ? undefined : parent.bottom
|
||||||
}
|
margins: root.margins // ????
|
||||||
implicitHeight: contentHeight
|
topMargin: root.downDirection ? root.sourceEdgeMargin : root.margins
|
||||||
implicitWidth: Array.from({
|
bottomMargin: root.downDirection ? root.margins : root.sourceEdgeMargin
|
||||||
length: count
|
}
|
||||||
}, (_, i) => itemAtIndex(i)?.implicitWidth ?? 0).reduce((a, b) => a > b ? a : b)
|
implicitHeight: contentHeight
|
||||||
|
implicitWidth: Array.from({
|
||||||
|
length: count
|
||||||
|
}, (_, i) => itemAtIndex(i)?.implicitWidth ?? 0).reduce((a, b) => a > b ? a : b)
|
||||||
|
|
||||||
model: root.contentModel
|
model: root.contentModel
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
delegate: WMenuItem {
|
delegate: WMenuItem {
|
||||||
id: menuItemDelegate
|
id: menuItemDelegate
|
||||||
|
width: ListView.view?.width
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,14 +10,17 @@ WButton {
|
|||||||
id: root
|
id: root
|
||||||
|
|
||||||
property alias iconName: iconContent.icon
|
property alias iconName: iconContent.icon
|
||||||
|
property alias iconSize: iconContent.implicitSize
|
||||||
property alias monochrome: iconContent.monochrome
|
property alias monochrome: iconContent.monochrome
|
||||||
implicitWidth: 40
|
implicitWidth: 40
|
||||||
implicitHeight: 40
|
implicitHeight: 40
|
||||||
|
|
||||||
contentItem: FluentIcon {
|
contentItem: Item {
|
||||||
id: iconContent
|
FluentIcon {
|
||||||
anchors.centerIn: parent
|
id: iconContent
|
||||||
implicitSize: 18
|
anchors.centerIn: parent
|
||||||
icon: root.iconName
|
implicitSize: 18
|
||||||
|
icon: root.iconName
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,4 +15,5 @@ TextInput {
|
|||||||
}
|
}
|
||||||
|
|
||||||
selectionColor: Looks.colors.selection
|
selectionColor: Looks.colors.selection
|
||||||
|
selectedTextColor: Looks.colors.selectionFg
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,26 +12,36 @@ import qs.modules.waffle.looks
|
|||||||
FooterRectangle {
|
FooterRectangle {
|
||||||
id: root
|
id: root
|
||||||
|
|
||||||
|
property real horizontalPadding: 32
|
||||||
|
property real verticalPadding: 16
|
||||||
property bool searching: text.length > 0
|
property bool searching: text.length > 0
|
||||||
property alias text: searchInput.text
|
property alias text: searchInput.text
|
||||||
|
implicitHeight: outline.implicitHeight + verticalPadding * 2
|
||||||
|
|
||||||
Component.onCompleted: searchInput.forceActiveFocus()
|
Component.onCompleted: searchInput.forceActiveFocus()
|
||||||
|
|
||||||
focus: true
|
focus: true
|
||||||
color: searching ? Looks.colors.bgPanelBody : Looks.colors.bgPanelFooter
|
color: searching ? Looks.colors.bgPanelBody : Looks.colors.bgPanelFooter
|
||||||
|
|
||||||
implicitWidth: 832 // TODO: Make sizes naturally inferred
|
Behavior on horizontalPadding {
|
||||||
implicitHeight: 63
|
enabled: Config.options.waffles.tweaks.smootherSearchBar
|
||||||
|
animation: Looks.transition.move.createObject(this)
|
||||||
|
}
|
||||||
|
Behavior on verticalPadding {
|
||||||
|
enabled: Config.options.waffles.tweaks.smootherSearchBar
|
||||||
|
animation: Looks.transition.move.createObject(this)
|
||||||
|
}
|
||||||
|
|
||||||
Rectangle {
|
Rectangle {
|
||||||
id: outline
|
id: outline
|
||||||
anchors {
|
anchors {
|
||||||
fill: parent
|
left: parent.left
|
||||||
leftMargin: 32
|
right: parent.right
|
||||||
rightMargin: 32
|
leftMargin: root.horizontalPadding
|
||||||
topMargin: 16
|
rightMargin: root.horizontalPadding
|
||||||
bottomMargin: 15
|
verticalCenter: parent.verticalCenter
|
||||||
}
|
}
|
||||||
|
implicitHeight: 32
|
||||||
color: "transparent"
|
color: "transparent"
|
||||||
radius: height / 2
|
radius: height / 2
|
||||||
border.width: 1
|
border.width: 1
|
||||||
|
|||||||
@@ -12,5 +12,25 @@ import qs.modules.waffle.looks
|
|||||||
BodyRectangle {
|
BodyRectangle {
|
||||||
id: root
|
id: root
|
||||||
|
|
||||||
|
property string searchText: LauncherSearch.query
|
||||||
|
|
||||||
|
ColumnLayout {
|
||||||
|
anchors {
|
||||||
|
fill: parent
|
||||||
|
topMargin: 2
|
||||||
|
leftMargin: 24
|
||||||
|
rightMargin: 24
|
||||||
|
}
|
||||||
|
spacing: 12
|
||||||
|
|
||||||
|
TagStrip {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
Layout.fillHeight: false
|
||||||
|
}
|
||||||
|
|
||||||
|
SearchResults {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
Layout.fillHeight: true
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,60 @@
|
|||||||
|
import qs.modules.waffle.looks
|
||||||
|
import qs.modules.common.functions
|
||||||
|
import qs.modules.common
|
||||||
|
import qs.services
|
||||||
|
import qs
|
||||||
|
import Quickshell
|
||||||
|
import QtQuick.Layouts
|
||||||
|
import QtQuick.Controls
|
||||||
|
import QtQuick
|
||||||
|
pragma ComponentBehavior: Bound
|
||||||
|
|
||||||
|
RowLayout {
|
||||||
|
id: root
|
||||||
|
|
||||||
|
function focusFirstItem() {
|
||||||
|
resultList.currentIndex = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
ResultList {
|
||||||
|
id: resultList
|
||||||
|
Layout.fillHeight: true
|
||||||
|
Layout.fillWidth: true
|
||||||
|
}
|
||||||
|
ResultPreview {
|
||||||
|
Layout.preferredWidth: 386
|
||||||
|
Layout.leftMargin: 1
|
||||||
|
Layout.rightMargin: 1
|
||||||
|
}
|
||||||
|
|
||||||
|
component ResultList: ListView {
|
||||||
|
section {
|
||||||
|
criteria: ViewSection.FullString
|
||||||
|
property: "type"
|
||||||
|
}
|
||||||
|
clip: true
|
||||||
|
spacing: 4
|
||||||
|
model: ScriptModel {
|
||||||
|
values: {
|
||||||
|
// TODO: categorize and have max per category
|
||||||
|
LauncherSearch.results.slice(0, 10)
|
||||||
|
}
|
||||||
|
onValuesChanged: {
|
||||||
|
root.focusFirstItem();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
delegate: WSearchResultButton {
|
||||||
|
required property int index
|
||||||
|
required property var modelData
|
||||||
|
entry: modelData
|
||||||
|
firstEntry: index === 0
|
||||||
|
width: ListView.view?.width
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
component ResultPreview: Rectangle {
|
||||||
|
Layout.fillHeight: true
|
||||||
|
color: Looks.colors.bg1
|
||||||
|
radius: Looks.radius.large
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -14,26 +14,43 @@ WBarAttachedPanelContent {
|
|||||||
id: root
|
id: root
|
||||||
|
|
||||||
property bool searching: false
|
property bool searching: false
|
||||||
property string searchText: ""
|
property string searchText: LauncherSearch.query
|
||||||
|
|
||||||
contentItem: WPane {
|
contentItem: WPane {
|
||||||
contentItem: WPanelPageColumn {
|
contentItem: WPanelPageColumn {
|
||||||
SearchBar {
|
SearchBar {
|
||||||
focus: true
|
focus: true
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
|
implicitWidth: 832 // TODO: Make sizes naturally inferred
|
||||||
|
horizontalPadding: root.searching ? 24 : 32
|
||||||
|
// verticalPadding: root.searching ? 32 : 16 // TODO: make this not nuke the panel
|
||||||
Synchronizer on searching {
|
Synchronizer on searching {
|
||||||
property alias target: root.searching
|
property alias target: root.searching
|
||||||
}
|
}
|
||||||
Synchronizer on text {
|
text: root.searchText
|
||||||
property alias source: root.searchText
|
onTextChanged: {
|
||||||
|
LauncherSearch.query = text;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Loader {
|
Item {
|
||||||
id: pageContentLoader
|
implicitHeight: root.searching ? 736 : 736 // TODO: Make sizes naturally inferred
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
source: root.searching ? "SearchPageContent.qml" : "StartPageContent.qml"
|
Loader {
|
||||||
|
id: pageContentLoader
|
||||||
|
anchors.fill: parent
|
||||||
|
sourceComponent: root.searching ? searchPageComp : startPageComp
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Component {
|
||||||
|
id: searchPageComp
|
||||||
|
SearchPageContent {}
|
||||||
|
}
|
||||||
|
|
||||||
|
Component {
|
||||||
|
id: startPageComp
|
||||||
|
StartPageContent {}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ WPanelPageColumn {
|
|||||||
WPanelSeparator {}
|
WPanelSeparator {}
|
||||||
|
|
||||||
BodyRectangle {
|
BodyRectangle {
|
||||||
implicitHeight: 736 // TODO: Make sizes naturally inferred
|
Layout.fillHeight: true
|
||||||
}
|
}
|
||||||
|
|
||||||
WPanelSeparator {}
|
WPanelSeparator {}
|
||||||
|
|||||||
@@ -0,0 +1,92 @@
|
|||||||
|
pragma ComponentBehavior: Bound
|
||||||
|
import QtQuick
|
||||||
|
import QtQuick.Controls
|
||||||
|
import QtQuick.Layouts
|
||||||
|
import Quickshell
|
||||||
|
import qs
|
||||||
|
import qs.services
|
||||||
|
import qs.modules.common
|
||||||
|
import qs.modules.common.functions
|
||||||
|
import qs.modules.waffle.looks
|
||||||
|
|
||||||
|
RowLayout {
|
||||||
|
WPanelIconButton {
|
||||||
|
implicitWidth: 36
|
||||||
|
implicitHeight: 36
|
||||||
|
iconSize: 24
|
||||||
|
iconName: "arrow-left"
|
||||||
|
onClicked: LauncherSearch.query = ""
|
||||||
|
}
|
||||||
|
ListView {
|
||||||
|
id: tagListView
|
||||||
|
Layout.fillWidth: true
|
||||||
|
Layout.fillHeight: true
|
||||||
|
orientation: Qt.Horizontal
|
||||||
|
spacing: 4
|
||||||
|
model: [
|
||||||
|
{
|
||||||
|
name: Translation.tr("All"),
|
||||||
|
prefix: ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: Translation.tr("Apps"),
|
||||||
|
prefix: Config.options.search.prefix.app
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: Translation.tr("Actions"),
|
||||||
|
prefix: Config.options.search.prefix.action
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: Translation.tr("Clipboard"),
|
||||||
|
prefix: Config.options.search.prefix.clipboard
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: Translation.tr("Emojis"),
|
||||||
|
prefix: Config.options.search.prefix.emojis
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: Translation.tr("Math"),
|
||||||
|
prefix: Config.options.search.prefix.math
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: Translation.tr("Commands"),
|
||||||
|
prefix: Config.options.search.prefix.shellCommand
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: Translation.tr("Web"),
|
||||||
|
prefix: Config.options.search.prefix.webSearch
|
||||||
|
},
|
||||||
|
]
|
||||||
|
delegate: WBorderedButton {
|
||||||
|
id: tagButton
|
||||||
|
required property var modelData
|
||||||
|
border.width: 1
|
||||||
|
radius: height / 2
|
||||||
|
implicitWidth: tagButtonText.implicitWidth + 12 * 2
|
||||||
|
implicitHeight: 32
|
||||||
|
checked: {
|
||||||
|
if (modelData.prefix != "") {
|
||||||
|
return LauncherSearch.query.startsWith(modelData.prefix);
|
||||||
|
} else {
|
||||||
|
return !tagListView.model.some(i => (i.prefix != "" && LauncherSearch.query.startsWith(i.prefix)))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
contentItem: Item {
|
||||||
|
WText {
|
||||||
|
id: tagButtonText
|
||||||
|
anchors.centerIn: parent
|
||||||
|
color: tagButton.fgColor
|
||||||
|
text: tagButton.modelData.name
|
||||||
|
font.pixelSize: Looks.font.pixelSize.large
|
||||||
|
}
|
||||||
|
}
|
||||||
|
onClicked: LauncherSearch.ensurePrefix(tagButton.modelData.prefix)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
WPanelIconButton {
|
||||||
|
implicitWidth: 36
|
||||||
|
implicitHeight: 36
|
||||||
|
iconSize: 24
|
||||||
|
iconName: "more-horizontal"
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,81 @@
|
|||||||
|
import QtQuick
|
||||||
|
import QtQuick.Layouts
|
||||||
|
import Quickshell
|
||||||
|
import qs
|
||||||
|
import qs.services
|
||||||
|
import qs.modules.common
|
||||||
|
import qs.modules.common.models
|
||||||
|
import qs.modules.common.functions
|
||||||
|
import qs.modules.common.widgets
|
||||||
|
import qs.modules.waffle.looks
|
||||||
|
|
||||||
|
WChoiceButton {
|
||||||
|
id: root
|
||||||
|
|
||||||
|
required property LauncherSearchResult entry
|
||||||
|
property bool firstEntry: false
|
||||||
|
|
||||||
|
checked: focus
|
||||||
|
animateChoiceHighlight: false
|
||||||
|
implicitWidth: contentLayout.implicitWidth + leftPadding + rightPadding
|
||||||
|
implicitHeight: contentLayout.implicitHeight + topPadding + bottomPadding
|
||||||
|
|
||||||
|
onClicked: {
|
||||||
|
GlobalStates.searchOpen = false
|
||||||
|
root.entry.execute()
|
||||||
|
}
|
||||||
|
|
||||||
|
contentItem: RowLayout {
|
||||||
|
id: contentLayout
|
||||||
|
spacing: 8
|
||||||
|
|
||||||
|
EntryIcon {}
|
||||||
|
EntryNameColumn {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
Layout.alignment: Qt.AlignVCenter
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
component EntryIcon: Item {
|
||||||
|
implicitWidth: 24
|
||||||
|
implicitHeight: 24
|
||||||
|
Loader {
|
||||||
|
anchors.centerIn: parent
|
||||||
|
active: root.entry.iconType === LauncherSearchResult.IconType.System
|
||||||
|
sourceComponent: WAppIcon {
|
||||||
|
implicitSize: 24
|
||||||
|
tryCustomIcon: false
|
||||||
|
iconName: root.entry.iconName
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Loader {
|
||||||
|
anchors.centerIn: parent
|
||||||
|
active: root.entry.iconType === LauncherSearchResult.IconType.Text
|
||||||
|
sourceComponent: WText {
|
||||||
|
text: root.entry.iconName
|
||||||
|
font.pixelSize: 24
|
||||||
|
horizontalAlignment: Text.AlignHCenter
|
||||||
|
verticalAlignment: Text.AlignVCenter
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
component EntryNameColumn: ColumnLayout {
|
||||||
|
spacing: 4
|
||||||
|
|
||||||
|
WText {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
wrapMode: Text.Wrap
|
||||||
|
text: root.entry.name
|
||||||
|
font.pixelSize: Looks.font.pixelSize.large
|
||||||
|
maximumLineCount: 2
|
||||||
|
}
|
||||||
|
|
||||||
|
WText {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
visible: root.firstEntry
|
||||||
|
text: root.entry.type
|
||||||
|
color: Looks.colors.accentUnfocused
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -4,7 +4,6 @@ import qs.modules.common
|
|||||||
import qs.modules.common.models
|
import qs.modules.common.models
|
||||||
import qs.modules.common.functions
|
import qs.modules.common.functions
|
||||||
import QtQuick
|
import QtQuick
|
||||||
import QtQuick.Controls
|
|
||||||
import Quickshell
|
import Quickshell
|
||||||
import Quickshell.Io
|
import Quickshell.Io
|
||||||
|
|
||||||
@@ -12,6 +11,15 @@ Singleton {
|
|||||||
id: root
|
id: root
|
||||||
|
|
||||||
property string query: ""
|
property string query: ""
|
||||||
|
|
||||||
|
function ensurePrefix(prefix) {
|
||||||
|
if ([Config.options.search.prefix.action, Config.options.search.prefix.app, Config.options.search.prefix.clipboard, Config.options.search.prefix.emojis, Config.options.search.prefix.math, Config.options.search.prefix.shellCommand, Config.options.search.prefix.webSearch,].some(i => root.query.startsWith(i))) {
|
||||||
|
root.query = prefix + root.query.slice(1);
|
||||||
|
} else {
|
||||||
|
root.query = prefix + root.query;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
property var searchActions: [
|
property var searchActions: [
|
||||||
{
|
{
|
||||||
action: "accentcolor",
|
action: "accentcolor",
|
||||||
@@ -74,12 +82,13 @@ Singleton {
|
|||||||
property string mathResult: ""
|
property string mathResult: ""
|
||||||
property bool clipboardWorkSafetyActive: {
|
property bool clipboardWorkSafetyActive: {
|
||||||
const enabled = Config.options.workSafety.enable.clipboard;
|
const enabled = Config.options.workSafety.enable.clipboard;
|
||||||
const sensitiveNetwork = (StringUtils.stringListContainsSubstring(Network.networkName.toLowerCase(), Config.options.workSafety.triggerCondition.networkNameKeywords))
|
const sensitiveNetwork = (StringUtils.stringListContainsSubstring(Network.networkName.toLowerCase(), Config.options.workSafety.triggerCondition.networkNameKeywords));
|
||||||
return enabled && sensitiveNetwork;
|
return enabled && sensitiveNetwork;
|
||||||
}
|
}
|
||||||
|
|
||||||
function containsUnsafeLink(entry) {
|
function containsUnsafeLink(entry) {
|
||||||
if (entry == undefined) return false;
|
if (entry == undefined)
|
||||||
|
return false;
|
||||||
const unsafeKeywords = Config.options.workSafety.triggerCondition.linkKeywords;
|
const unsafeKeywords = Config.options.workSafety.triggerCondition.linkKeywords;
|
||||||
return StringUtils.stringListContainsSubstring(entry.toLowerCase(), unsafeKeywords);
|
return StringUtils.stringListContainsSubstring(entry.toLowerCase(), unsafeKeywords);
|
||||||
}
|
}
|
||||||
@@ -128,95 +137,121 @@ Singleton {
|
|||||||
shouldBlurImage = shouldBlurImage && (root.containsUnsafeLink(array[index - 1]) || root.containsUnsafeLink(array[index + 1]));
|
shouldBlurImage = shouldBlurImage && (root.containsUnsafeLink(array[index - 1]) || root.containsUnsafeLink(array[index + 1]));
|
||||||
}
|
}
|
||||||
const type = `#${entry.match(/^\s*(\S+)/)?.[1] || ""}`;
|
const type = `#${entry.match(/^\s*(\S+)/)?.[1] || ""}`;
|
||||||
return {
|
return resultComp.createObject(null, {
|
||||||
key: type,
|
rawValue: entry,
|
||||||
cliphistRawString: entry,
|
|
||||||
name: StringUtils.cleanCliphistEntry(entry),
|
name: StringUtils.cleanCliphistEntry(entry),
|
||||||
clickActionName: "",
|
verb: "",
|
||||||
type: type,
|
type: type,
|
||||||
execute: () => {
|
execute: () => {
|
||||||
Cliphist.copy(entry);
|
Cliphist.copy(entry);
|
||||||
},
|
},
|
||||||
actions: [
|
actions: [resultComp.createObject(null, {
|
||||||
{
|
name: Translation.tr("Copy"),
|
||||||
name: "Copy",
|
iconName: "content_copy",
|
||||||
materialIcon: "content_copy",
|
iconType: LauncherSearchResult.IconType.Material,
|
||||||
execute: () => {
|
execute: () => {
|
||||||
Cliphist.copy(entry);
|
Cliphist.copy(entry);
|
||||||
}
|
}
|
||||||
},
|
}), resultComp.createObject(null, {
|
||||||
{
|
name: Translation.tr("Delete"),
|
||||||
name: "Delete",
|
iconName: "delete",
|
||||||
materialIcon: "delete",
|
iconType: LauncherSearchResult.IconType.Material,
|
||||||
execute: () => {
|
execute: () => {
|
||||||
Cliphist.deleteEntry(entry);
|
Cliphist.deleteEntry(entry);
|
||||||
}
|
}
|
||||||
}
|
})],
|
||||||
],
|
blurImage: shouldBlurImage
|
||||||
blurImage: shouldBlurImage,
|
});
|
||||||
blurImageText: Translation.tr("Work safety")
|
|
||||||
};
|
|
||||||
}).filter(Boolean);
|
}).filter(Boolean);
|
||||||
} else if (root.query.startsWith(Config.options.search.prefix.emojis)) {
|
} else if (root.query.startsWith(Config.options.search.prefix.emojis)) {
|
||||||
// Clipboard
|
// Clipboard
|
||||||
const searchString = StringUtils.cleanPrefix(root.query, Config.options.search.prefix.emojis);
|
const searchString = StringUtils.cleanPrefix(root.query, Config.options.search.prefix.emojis);
|
||||||
return Emojis.fuzzyQuery(searchString).map(entry => {
|
return Emojis.fuzzyQuery(searchString).map(entry => {
|
||||||
const emoji = entry.match(/^\s*(\S+)/)?.[1] || "";
|
const emoji = entry.match(/^\s*(\S+)/)?.[1] || "";
|
||||||
return {
|
return resultComp.createObject(null, {
|
||||||
key: emoji,
|
rawValue: entry,
|
||||||
cliphistRawString: entry,
|
|
||||||
bigText: emoji,
|
|
||||||
name: entry.replace(/^\s*\S+\s+/, ""),
|
name: entry.replace(/^\s*\S+\s+/, ""),
|
||||||
clickActionName: "",
|
iconName: emoji,
|
||||||
type: "Emoji",
|
iconType: LauncherSearchResult.IconType.Text,
|
||||||
|
verb: Translation.tr("Copy"),
|
||||||
|
type: Translation.tr("Emoji"),
|
||||||
execute: () => {
|
execute: () => {
|
||||||
Quickshell.clipboardText = entry.match(/^\s*(\S+)/)?.[1];
|
Quickshell.clipboardText = entry.match(/^\s*(\S+)/)?.[1];
|
||||||
}
|
}
|
||||||
};
|
});
|
||||||
}).filter(Boolean);
|
}).filter(Boolean);
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////// Init ///////////////////
|
////////////////// Init ///////////////////
|
||||||
nonAppResultsTimer.restart();
|
nonAppResultsTimer.restart();
|
||||||
const mathResultObject = {
|
const mathResultObject = resultComp.createObject(null, {
|
||||||
key: `Math result: ${root.mathResult}`,
|
|
||||||
name: root.mathResult,
|
name: root.mathResult,
|
||||||
clickActionName: Translation.tr("Copy"),
|
verb: Translation.tr("Copy"),
|
||||||
type: Translation.tr("Math result"),
|
type: Translation.tr("Math result"),
|
||||||
fontType: "monospace",
|
fontType: LauncherSearchResult.FontType.Monospace,
|
||||||
materialSymbol: 'calculate',
|
iconName: 'calculate',
|
||||||
|
iconType: LauncherSearchResult.IconType.Material,
|
||||||
execute: () => {
|
execute: () => {
|
||||||
Quickshell.clipboardText = root.mathResult;
|
Quickshell.clipboardText = root.mathResult;
|
||||||
}
|
}
|
||||||
};
|
|
||||||
const appResultObjects = AppSearch.fuzzyQuery(StringUtils.cleanPrefix(root.query, Config.options.search.prefix.app)).map(entry => {
|
|
||||||
entry.clickActionName = Translation.tr("Launch");
|
|
||||||
entry.type = Translation.tr("App");
|
|
||||||
entry.key = entry.execute;
|
|
||||||
return entry;
|
|
||||||
});
|
});
|
||||||
const commandResultObject = {
|
const appResultObjects = AppSearch.fuzzyQuery(StringUtils.cleanPrefix(root.query, Config.options.search.prefix.app)).map(entry => {
|
||||||
key: `cmd ${root.query}`,
|
return resultComp.createObject(null, {
|
||||||
|
type: Translation.tr("App"),
|
||||||
|
name: entry.name,
|
||||||
|
iconName: entry.icon,
|
||||||
|
iconType: LauncherSearchResult.IconType.System,
|
||||||
|
verb: Translation.tr("Launch"),
|
||||||
|
execute: () => {
|
||||||
|
if (!entry.runInTerminal)
|
||||||
|
entry.execute();
|
||||||
|
else {
|
||||||
|
// Probably needs more proper escaping, but this will do for now
|
||||||
|
Quickshell.execDetached(["bash", '-c', `${Config.options.apps.terminal} -e '${StringUtils.shellSingleQuoteEscape(entry.command.join(' '))}'`]);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
comment: entry.comment,
|
||||||
|
runInTerminal: entry.runInTerminal,
|
||||||
|
genericName: entry.genericName,
|
||||||
|
keywords: entry.keywords,
|
||||||
|
actions: entry.actions.map(action => {
|
||||||
|
return resultComp.createObject(null, {
|
||||||
|
name: action.name,
|
||||||
|
iconName: action.icon,
|
||||||
|
iconType: LauncherSearchResult.IconType.System,
|
||||||
|
execute: () => {
|
||||||
|
if (!action.runInTerminal)
|
||||||
|
action.execute();
|
||||||
|
else {
|
||||||
|
Quickshell.execDetached(["bash", '-c', `${Config.options.apps.terminal} -e '${StringUtils.shellSingleQuoteEscape(action.command.join(' '))}'`]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
})
|
||||||
|
});
|
||||||
|
});
|
||||||
|
const commandResultObject = resultComp.createObject(null, {
|
||||||
name: StringUtils.cleanPrefix(root.query, Config.options.search.prefix.shellCommand).replace("file://", ""),
|
name: StringUtils.cleanPrefix(root.query, Config.options.search.prefix.shellCommand).replace("file://", ""),
|
||||||
clickActionName: Translation.tr("Run"),
|
verb: Translation.tr("Run"),
|
||||||
type: Translation.tr("Run command"),
|
type: Translation.tr("Run command"),
|
||||||
fontType: "monospace",
|
fontType: LauncherSearchResult.FontType.Monospace,
|
||||||
materialSymbol: 'terminal',
|
iconName: 'terminal',
|
||||||
|
iconType: LauncherSearchResult.IconType.Material,
|
||||||
execute: () => {
|
execute: () => {
|
||||||
let cleanedCommand = root.query.replace("file://", "");
|
let cleanedCommand = root.query.replace("file://", "");
|
||||||
cleanedCommand = StringUtils.cleanPrefix(cleanedCommand, Config.options.search.prefix.shellCommand);
|
cleanedCommand = StringUtils.cleanPrefix(cleanedCommand, Config.options.search.prefix.shellCommand);
|
||||||
if (cleanedCommand.startsWith(Config.options.search.prefix.shellCommand)) {
|
if (cleanedCommand.startsWith(Config.options.search.prefix.shellCommand)) {
|
||||||
cleanedCommand = cleanedCommand.slice(Config.options.search.prefix.shellCommand.length);
|
cleanedCommand = cleanedCommand.slice(Config.options.search.prefix.shellCommand.length);
|
||||||
}
|
}
|
||||||
Quickshell.execDetached(["bash", "-c", searchingText.startsWith('sudo') ? `${Config.options.apps.terminal} fish -C '${cleanedCommand}'` : cleanedCommand]);
|
Quickshell.execDetached(["bash", "-c", root.query.startsWith('sudo') ? `${Config.options.apps.terminal} fish -C '${cleanedCommand}'` : cleanedCommand]);
|
||||||
}
|
}
|
||||||
};
|
});
|
||||||
const webSearchResultObject = {
|
const webSearchResultObject = resultComp.createObject(null, {
|
||||||
key: `website ${root.query}`,
|
|
||||||
name: StringUtils.cleanPrefix(root.query, Config.options.search.prefix.webSearch),
|
name: StringUtils.cleanPrefix(root.query, Config.options.search.prefix.webSearch),
|
||||||
clickActionName: Translation.tr("Search"),
|
verb: Translation.tr("Search"),
|
||||||
type: Translation.tr("Search the web"),
|
type: Translation.tr("Search the web"),
|
||||||
materialSymbol: 'travel_explore',
|
iconName: 'travel_explore',
|
||||||
|
iconType: LauncherSearchResult.IconType.Material,
|
||||||
execute: () => {
|
execute: () => {
|
||||||
let query = StringUtils.cleanPrefix(root.query, Config.options.search.prefix.webSearch);
|
let query = StringUtils.cleanPrefix(root.query, Config.options.search.prefix.webSearch);
|
||||||
let url = Config.options.search.engineBaseUrl + query;
|
let url = Config.options.search.engineBaseUrl + query;
|
||||||
@@ -225,20 +260,20 @@ Singleton {
|
|||||||
}
|
}
|
||||||
Qt.openUrlExternally(url);
|
Qt.openUrlExternally(url);
|
||||||
}
|
}
|
||||||
};
|
});
|
||||||
const launcherActionObjects = root.searchActions.map(action => {
|
const launcherActionObjects = root.searchActions.map(action => {
|
||||||
const actionString = `${Config.options.search.prefix.action}${action.action}`;
|
const actionString = `${Config.options.search.prefix.action}${action.action}`;
|
||||||
if (actionString.startsWith(root.query) || root.query.startsWith(actionString)) {
|
if (actionString.startsWith(root.query) || root.query.startsWith(actionString)) {
|
||||||
return {
|
return resultComp.createObject(null, {
|
||||||
key: `Action ${actionString}`,
|
|
||||||
name: root.query.startsWith(actionString) ? root.query : actionString,
|
name: root.query.startsWith(actionString) ? root.query : actionString,
|
||||||
clickActionName: Translation.tr("Run"),
|
verb: Translation.tr("Run"),
|
||||||
type: Translation.tr("Action"),
|
type: Translation.tr("Action"),
|
||||||
materialSymbol: 'settings_suggest',
|
iconName: 'settings_suggest',
|
||||||
|
iconType: LauncherSearchResult.IconType.Material,
|
||||||
execute: () => {
|
execute: () => {
|
||||||
action.execute(root.query.split(" ").slice(1).join(" "));
|
action.execute(root.query.split(" ").slice(1).join(" "));
|
||||||
}
|
}
|
||||||
};
|
});
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}).filter(Boolean);
|
}).filter(Boolean);
|
||||||
@@ -275,4 +310,9 @@ Singleton {
|
|||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Component {
|
||||||
|
id: resultComp
|
||||||
|
LauncherSearchResult {}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -102,6 +102,10 @@ Singleton {
|
|||||||
|
|
||||||
Process {
|
Process {
|
||||||
id: findCpuMaxFreqProc
|
id: findCpuMaxFreqProc
|
||||||
|
environment: ({
|
||||||
|
LANG: "C",
|
||||||
|
LC_ALL: "C"
|
||||||
|
})
|
||||||
command: ["bash", "-c", "lscpu | grep 'CPU max MHz' | awk '{print $4}'"]
|
command: ["bash", "-c", "lscpu | grep 'CPU max MHz' | awk '{print $4}'"]
|
||||||
running: true
|
running: true
|
||||||
stdout: StdioCollector {
|
stdout: StdioCollector {
|
||||||
|
|||||||
@@ -43,6 +43,11 @@ if ! command -v pacman >/dev/null 2>&1; then
|
|||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
# Keep makepkg from resetting sudo credentials
|
||||||
|
if [[ -z "${PACMAN_AUTH:-}" ]]; then
|
||||||
|
export PACMAN_AUTH="sudo"
|
||||||
|
fi
|
||||||
|
|
||||||
showfun remove_deprecated_dependencies
|
showfun remove_deprecated_dependencies
|
||||||
v remove_deprecated_dependencies
|
v remove_deprecated_dependencies
|
||||||
|
|
||||||
|
|||||||
@@ -80,6 +80,50 @@ function prevent_sudo_or_root(){
|
|||||||
root) echo -e "${STY_RED}[$0]: This script is NOT to be executed with sudo or as root. Aborting...${STY_RST}";exit 1;;
|
root) echo -e "${STY_RED}[$0]: This script is NOT to be executed with sudo or as root. Aborting...${STY_RST}";exit 1;;
|
||||||
esac
|
esac
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Initialize sudo session and keep it alive in background
|
||||||
|
# Store PID in a global variable that can be accessed by trap
|
||||||
|
declare -g SUDO_KEEPALIVE_PID=""
|
||||||
|
|
||||||
|
function sudo_init_keepalive(){
|
||||||
|
# Check if sudo is available
|
||||||
|
if ! command -v sudo >/dev/null 2>&1; then
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Skip if already initialized
|
||||||
|
if [[ -n "$SUDO_KEEPALIVE_PID" ]] && kill -0 "$SUDO_KEEPALIVE_PID" 2>/dev/null; then
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Prompt for sudo password once at the beginning
|
||||||
|
echo -e "${STY_CYAN}[$0]: Requesting sudo privileges for installation...${STY_RST}"
|
||||||
|
if ! sudo -v; then
|
||||||
|
echo -e "${STY_RED}[$0]: Failed to obtain sudo privileges. Aborting...${STY_RST}"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Start background process to keep sudo session alive
|
||||||
|
# This updates the sudo timestamp every 60 seconds
|
||||||
|
(
|
||||||
|
while true; do
|
||||||
|
sleep 60
|
||||||
|
sudo -v 2>/dev/null || exit 0
|
||||||
|
done
|
||||||
|
) &
|
||||||
|
SUDO_KEEPALIVE_PID=$!
|
||||||
|
|
||||||
|
echo -e "${STY_GREEN}[$0]: Sudo session initialized and will be kept alive (PID: $SUDO_KEEPALIVE_PID)${STY_RST}"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Stop the sudo keepalive background process
|
||||||
|
function sudo_stop_keepalive(){
|
||||||
|
if [[ -n "$SUDO_KEEPALIVE_PID" ]] && kill -0 "$SUDO_KEEPALIVE_PID" 2>/dev/null; then
|
||||||
|
kill "$SUDO_KEEPALIVE_PID" 2>/dev/null
|
||||||
|
wait "$SUDO_KEEPALIVE_PID" 2>/dev/null
|
||||||
|
SUDO_KEEPALIVE_PID=""
|
||||||
|
fi
|
||||||
|
}
|
||||||
function git_auto_unshallow(){
|
function git_auto_unshallow(){
|
||||||
# We need this function for latest_commit_hash to work properly
|
# We need this function for latest_commit_hash to work properly
|
||||||
if [[ -f "$(git rev-parse --git-dir)/shallow" ]]; then
|
if [[ -f "$(git rev-parse --git-dir)/shallow" ]]; then
|
||||||
|
|||||||
@@ -71,6 +71,10 @@ case ${SUBCMD_NAME} in
|
|||||||
$function
|
$function
|
||||||
done
|
done
|
||||||
pause
|
pause
|
||||||
|
# Initialize sudo keepalive for the entire install process
|
||||||
|
sudo_init_keepalive
|
||||||
|
# Set trap to cleanup when this subcommand exits
|
||||||
|
trap sudo_stop_keepalive EXIT INT TERM
|
||||||
if [[ "${SKIP_ALLGREETING}" != true ]]; then
|
if [[ "${SKIP_ALLGREETING}" != true ]]; then
|
||||||
source ${SUBCMD_DIR}/0.greeting.sh
|
source ${SUBCMD_DIR}/0.greeting.sh
|
||||||
fi
|
fi
|
||||||
@@ -89,6 +93,10 @@ case ${SUBCMD_NAME} in
|
|||||||
$function
|
$function
|
||||||
done
|
done
|
||||||
pause
|
pause
|
||||||
|
# Initialize sudo keepalive for dependency installation
|
||||||
|
sudo_init_keepalive
|
||||||
|
# Set trap to cleanup when this subcommand exits
|
||||||
|
trap sudo_stop_keepalive EXIT INT TERM
|
||||||
if [[ "${SKIP_ALLDEPS}" != true ]]; then
|
if [[ "${SKIP_ALLDEPS}" != true ]]; then
|
||||||
source ${SUBCMD_DIR}/1.deps-router.sh
|
source ${SUBCMD_DIR}/1.deps-router.sh
|
||||||
fi
|
fi
|
||||||
@@ -98,6 +106,10 @@ case ${SUBCMD_NAME} in
|
|||||||
$function
|
$function
|
||||||
done
|
done
|
||||||
pause
|
pause
|
||||||
|
# Initialize sudo keepalive for setup steps
|
||||||
|
sudo_init_keepalive
|
||||||
|
# Set trap to cleanup when this subcommand exits
|
||||||
|
trap sudo_stop_keepalive EXIT INT TERM
|
||||||
if [[ "${SKIP_ALLSETUPS}" != true ]]; then
|
if [[ "${SKIP_ALLSETUPS}" != true ]]; then
|
||||||
source ${SUBCMD_DIR}/2.setups.sh
|
source ${SUBCMD_DIR}/2.setups.sh
|
||||||
fi
|
fi
|
||||||
|
|||||||
Reference in New Issue
Block a user