launcher: add favorite apps (#946)
* launcher: add favorite apps Favorite apps always appear above non-favorite apps Accepts regex, same logic as #920 Added the same regex logic to hidden apps Added util file may need to be relocated * addressed requested changes * fix: Renamed newly added util singleton Also added a null check to favorite icon loader in AppItem.qml * controlCenter/launcherPane: added favorite apps added icons to the app list to indicate if they are favorited/hidden marking as favorite/hidden is desabled if the other is selected * favouriteApps: renamed from favorite to favourite Also disabled favorite/hidden switch for entries added as regex * appDb: added notify and emit to favoriteApps * controlCentre/Launcher: Fixed bug with favourite switch not enabling itself when no hiddenApps exist Added a comment to explain the enabled state of the switches icon loader is now a single loader rather than two, hidden icon has priority * spelling mistakes * fixed warning * formatting fixes
This commit is contained in:
parent
3a7309294c
commit
40a2552830
10 changed files with 180 additions and 32 deletions
|
|
@ -562,6 +562,7 @@ default, you must create it manually.
|
||||||
"wallpapers": false
|
"wallpapers": false
|
||||||
},
|
},
|
||||||
"showOnHover": false,
|
"showOnHover": false,
|
||||||
|
"favouriteApps": [],
|
||||||
"hiddenApps": []
|
"hiddenApps": []
|
||||||
},
|
},
|
||||||
"lock": {
|
"lock": {
|
||||||
|
|
|
||||||
|
|
@ -297,6 +297,7 @@ Singleton {
|
||||||
enableDangerousActions: launcher.enableDangerousActions,
|
enableDangerousActions: launcher.enableDangerousActions,
|
||||||
dragThreshold: launcher.dragThreshold,
|
dragThreshold: launcher.dragThreshold,
|
||||||
vimKeybinds: launcher.vimKeybinds,
|
vimKeybinds: launcher.vimKeybinds,
|
||||||
|
favouriteApps: launcher.favouriteApps,
|
||||||
hiddenApps: launcher.hiddenApps,
|
hiddenApps: launcher.hiddenApps,
|
||||||
useFuzzy: {
|
useFuzzy: {
|
||||||
apps: launcher.useFuzzy.apps,
|
apps: launcher.useFuzzy.apps,
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,7 @@ JsonObject {
|
||||||
property bool enableDangerousActions: false // Allow actions that can cause losing data, like shutdown, reboot and logout
|
property bool enableDangerousActions: false // Allow actions that can cause losing data, like shutdown, reboot and logout
|
||||||
property int dragThreshold: 50
|
property int dragThreshold: 50
|
||||||
property bool vimKeybinds: false
|
property bool vimKeybinds: false
|
||||||
|
property list<string> favouriteApps: []
|
||||||
property list<string> hiddenApps: []
|
property list<string> hiddenApps: []
|
||||||
property UseFuzzy useFuzzy: UseFuzzy {}
|
property UseFuzzy useFuzzy: UseFuzzy {}
|
||||||
property Sizes sizes: Sizes {}
|
property Sizes sizes: Sizes {}
|
||||||
|
|
|
||||||
|
|
@ -24,6 +24,7 @@ Item {
|
||||||
|
|
||||||
property var selectedApp: root.session.launcher.active
|
property var selectedApp: root.session.launcher.active
|
||||||
property bool hideFromLauncherChecked: false
|
property bool hideFromLauncherChecked: false
|
||||||
|
property bool favouriteChecked: false
|
||||||
|
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
|
|
||||||
|
|
@ -43,16 +44,14 @@ Item {
|
||||||
function updateToggleState() {
|
function updateToggleState() {
|
||||||
if (!root.selectedApp) {
|
if (!root.selectedApp) {
|
||||||
root.hideFromLauncherChecked = false;
|
root.hideFromLauncherChecked = false;
|
||||||
|
root.favouriteChecked = false;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const appId = root.selectedApp.id || root.selectedApp.entry?.id;
|
const appId = root.selectedApp.id || root.selectedApp.entry?.id;
|
||||||
|
|
||||||
if (Config.launcher.hiddenApps && Config.launcher.hiddenApps.length > 0) {
|
root.hideFromLauncherChecked = Config.launcher.hiddenApps && Config.launcher.hiddenApps.length > 0 && Strings.testRegexList(Config.launcher.hiddenApps, appId);
|
||||||
root.hideFromLauncherChecked = Config.launcher.hiddenApps.includes(appId);
|
root.favouriteChecked = Config.launcher.favouriteApps && Config.launcher.favouriteApps.length > 0 && Strings.testRegexList(Config.launcher.favouriteApps, appId);
|
||||||
} else {
|
|
||||||
root.hideFromLauncherChecked = false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function saveHiddenApps(isHidden) {
|
function saveHiddenApps(isHidden) {
|
||||||
|
|
@ -83,6 +82,7 @@ Item {
|
||||||
id: allAppsDb
|
id: allAppsDb
|
||||||
|
|
||||||
path: `${Paths.state}/apps.sqlite`
|
path: `${Paths.state}/apps.sqlite`
|
||||||
|
favouriteApps: Config.launcher.favouriteApps
|
||||||
entries: DesktopEntries.applications.values
|
entries: DesktopEntries.applications.values
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -286,6 +286,7 @@ Item {
|
||||||
id: appsListLoader
|
id: appsListLoader
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
Layout.fillHeight: true
|
Layout.fillHeight: true
|
||||||
|
asynchronous: true
|
||||||
active: true
|
active: true
|
||||||
|
|
||||||
sourceComponent: StyledListView {
|
sourceComponent: StyledListView {
|
||||||
|
|
@ -305,7 +306,8 @@ Item {
|
||||||
delegate: StyledRect {
|
delegate: StyledRect {
|
||||||
required property var modelData
|
required property var modelData
|
||||||
|
|
||||||
width: parent ? parent.width : 0
|
width: parent ? parent.width : 0
|
||||||
|
implicitHeight: 40
|
||||||
|
|
||||||
readonly property bool isSelected: root.selectedApp === modelData
|
readonly property bool isSelected: root.selectedApp === modelData
|
||||||
|
|
||||||
|
|
@ -353,9 +355,34 @@ Item {
|
||||||
text: modelData.name || modelData.entry?.name || qsTr("Unknown")
|
text: modelData.name || modelData.entry?.name || qsTr("Unknown")
|
||||||
font.pointSize: Appearance.font.size.normal
|
font.pointSize: Appearance.font.size.normal
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
implicitHeight: 40
|
Loader {
|
||||||
|
Layout.alignment: Qt.AlignVCenter
|
||||||
|
readonly property bool isHidden: modelData ? Strings.testRegexList(Config.launcher.hiddenApps, modelData.id) : false
|
||||||
|
readonly property bool isFav: modelData ? Strings.testRegexList(Config.launcher.favouriteApps, modelData.id) : false
|
||||||
|
active: isHidden || isFav
|
||||||
|
|
||||||
|
sourceComponent: isHidden ? hiddenIcon : (isFav ? favouriteIcon : null)
|
||||||
|
}
|
||||||
|
|
||||||
|
Component {
|
||||||
|
id: hiddenIcon
|
||||||
|
MaterialIcon {
|
||||||
|
text: "visibility_off"
|
||||||
|
fill: 1
|
||||||
|
color: Colours.palette.m3primary
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Component {
|
||||||
|
id: favouriteIcon
|
||||||
|
MaterialIcon {
|
||||||
|
text: "favorite"
|
||||||
|
fill: 1
|
||||||
|
color: Colours.palette.m3primary
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -440,13 +467,11 @@ Item {
|
||||||
onDisplayedAppChanged: {
|
onDisplayedAppChanged: {
|
||||||
if (displayedApp) {
|
if (displayedApp) {
|
||||||
const appId = displayedApp.id || displayedApp.entry?.id;
|
const appId = displayedApp.id || displayedApp.entry?.id;
|
||||||
if (Config.launcher.hiddenApps && Config.launcher.hiddenApps.length > 0) {
|
root.hideFromLauncherChecked = Config.launcher.hiddenApps && Config.launcher.hiddenApps.length > 0 && Strings.testRegexList(Config.launcher.hiddenApps, appId);
|
||||||
root.hideFromLauncherChecked = Config.launcher.hiddenApps.includes(appId);
|
root.favouriteChecked = Config.launcher.favouriteApps && Config.launcher.favouriteApps.length > 0 && Strings.testRegexList(Config.launcher.favouriteApps, appId);
|
||||||
} else {
|
|
||||||
root.hideFromLauncherChecked = false;
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
root.hideFromLauncherChecked = false;
|
root.hideFromLauncherChecked = false;
|
||||||
|
root.favouriteChecked = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -559,12 +584,51 @@ Item {
|
||||||
anchors.top: parent.top
|
anchors.top: parent.top
|
||||||
spacing: Appearance.spacing.normal
|
spacing: Appearance.spacing.normal
|
||||||
|
|
||||||
|
SwitchRow {
|
||||||
|
Layout.topMargin: Appearance.spacing.normal
|
||||||
|
visible: appDetailsLayout.displayedApp !== null
|
||||||
|
label: qsTr("Mark as favourite")
|
||||||
|
checked: root.favouriteChecked
|
||||||
|
// disabled if:
|
||||||
|
// * app is hidden
|
||||||
|
// * app isn't in favouriteApps array but marked as favourite anyway
|
||||||
|
// ^^^ This means that this app is favourited because of a regex check
|
||||||
|
// this button can not toggle regexed apps
|
||||||
|
enabled: appDetailsLayout.displayedApp !== null && !root.hideFromLauncherChecked && (Config.launcher.favouriteApps.indexOf(appDetailsLayout.displayedApp.id || appDetailsLayout.displayedApp.entry?.id) !== -1 || !root.favouriteChecked)
|
||||||
|
opacity: enabled ? 1 : 0.6
|
||||||
|
onToggled: checked => {
|
||||||
|
root.favouriteChecked = checked;
|
||||||
|
const app = appDetailsLayout.displayedApp;
|
||||||
|
if (app) {
|
||||||
|
const appId = app.id || app.entry?.id;
|
||||||
|
const favouriteApps = Config.launcher.favouriteApps ? [...Config.launcher.favouriteApps] : [];
|
||||||
|
if (checked) {
|
||||||
|
if (!favouriteApps.includes(appId)) {
|
||||||
|
favouriteApps.push(appId);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
const index = favouriteApps.indexOf(appId);
|
||||||
|
if (index !== -1) {
|
||||||
|
favouriteApps.splice(index, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Config.launcher.favouriteApps = favouriteApps;
|
||||||
|
Config.save();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
SwitchRow {
|
SwitchRow {
|
||||||
Layout.topMargin: Appearance.spacing.normal
|
Layout.topMargin: Appearance.spacing.normal
|
||||||
visible: appDetailsLayout.displayedApp !== null
|
visible: appDetailsLayout.displayedApp !== null
|
||||||
label: qsTr("Hide from launcher")
|
label: qsTr("Hide from launcher")
|
||||||
checked: root.hideFromLauncherChecked
|
checked: root.hideFromLauncherChecked
|
||||||
enabled: appDetailsLayout.displayedApp !== null
|
// disabled if:
|
||||||
|
// * app is favourited
|
||||||
|
// * app isn't in hiddenApps array but marked as hidden anyway
|
||||||
|
// ^^^ This means that this app is hidden because of a regex check
|
||||||
|
// this button can not toggle regexed apps
|
||||||
|
enabled: appDetailsLayout.displayedApp !== null && !root.favouriteChecked && (Config.launcher.hiddenApps.indexOf(appDetailsLayout.displayedApp.id || appDetailsLayout.displayedApp.entry?.id) !== -1 || !root.hideFromLauncherChecked)
|
||||||
|
opacity: enabled ? 1 : 0.6
|
||||||
onToggled: checked => {
|
onToggled: checked => {
|
||||||
root.hideFromLauncherChecked = checked;
|
root.hideFromLauncherChecked = checked;
|
||||||
const app = appDetailsLayout.displayedApp;
|
const app = appDetailsLayout.displayedApp;
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@ import qs.components
|
||||||
import qs.components.containers
|
import qs.components.containers
|
||||||
import qs.services
|
import qs.services
|
||||||
import qs.config
|
import qs.config
|
||||||
|
import qs.utils
|
||||||
import qs.modules.bar
|
import qs.modules.bar
|
||||||
import Quickshell
|
import Quickshell
|
||||||
import Quickshell.Wayland
|
import Quickshell.Wayland
|
||||||
|
|
@ -18,20 +19,7 @@ Variants {
|
||||||
id: scope
|
id: scope
|
||||||
|
|
||||||
required property ShellScreen modelData
|
required property ShellScreen modelData
|
||||||
readonly property bool barDisabled: {
|
readonly property bool barDisabled: Strings.testRegexList(Config.bar.excludedScreens, modelData.name)
|
||||||
const regexChecker = /^\^.*\$$/;
|
|
||||||
for (const filter of Config.bar.excludedScreens) {
|
|
||||||
// If filter is a regex
|
|
||||||
if (regexChecker.test(filter)) {
|
|
||||||
if ((new RegExp(filter)).test(modelData.name))
|
|
||||||
return true;
|
|
||||||
} else {
|
|
||||||
if (filter === modelData.name)
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
Exclusions {
|
Exclusions {
|
||||||
screen: scope.modelData
|
screen: scope.modelData
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@ import "../services"
|
||||||
import qs.components
|
import qs.components
|
||||||
import qs.services
|
import qs.services
|
||||||
import qs.config
|
import qs.config
|
||||||
|
import qs.utils
|
||||||
import Quickshell
|
import Quickshell
|
||||||
import Quickshell.Widgets
|
import Quickshell.Widgets
|
||||||
import QtQuick
|
import QtQuick
|
||||||
|
|
@ -46,7 +47,7 @@ Item {
|
||||||
anchors.leftMargin: Appearance.spacing.normal
|
anchors.leftMargin: Appearance.spacing.normal
|
||||||
anchors.verticalCenter: icon.verticalCenter
|
anchors.verticalCenter: icon.verticalCenter
|
||||||
|
|
||||||
implicitWidth: parent.width - icon.width
|
implicitWidth: parent.width - icon.width - favouriteIcon.width
|
||||||
implicitHeight: name.implicitHeight + comment.implicitHeight
|
implicitHeight: name.implicitHeight + comment.implicitHeight
|
||||||
|
|
||||||
StyledText {
|
StyledText {
|
||||||
|
|
@ -64,10 +65,24 @@ Item {
|
||||||
color: Colours.palette.m3outline
|
color: Colours.palette.m3outline
|
||||||
|
|
||||||
elide: Text.ElideRight
|
elide: Text.ElideRight
|
||||||
width: root.width - icon.width - Appearance.rounding.normal * 2
|
width: root.width - icon.width - favouriteIcon.width - Appearance.rounding.normal * 2
|
||||||
|
|
||||||
anchors.top: name.bottom
|
anchors.top: name.bottom
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loader {
|
||||||
|
id: favouriteIcon
|
||||||
|
|
||||||
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
anchors.right: parent.right
|
||||||
|
active: modelData && Strings.testRegexList(Config.launcher.favouriteApps, modelData.id)
|
||||||
|
|
||||||
|
sourceComponent: MaterialIcon {
|
||||||
|
text: "favorite"
|
||||||
|
fill: 1
|
||||||
|
color: Colours.palette.m3primary
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -72,6 +72,7 @@ Searcher {
|
||||||
id: appDb
|
id: appDb
|
||||||
|
|
||||||
path: `${Paths.state}/apps.sqlite`
|
path: `${Paths.state}/apps.sqlite`
|
||||||
entries: DesktopEntries.applications.values.filter(a => !Config.launcher.hiddenApps.includes(a.id))
|
favouriteApps: Config.launcher.favouriteApps
|
||||||
|
entries: DesktopEntries.applications.values.filter(a => !Strings.testRegexList(Config.launcher.hiddenApps, a.id))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -162,6 +162,39 @@ void AppDb::setEntries(const QObjectList& entries) {
|
||||||
m_timer->start();
|
m_timer->start();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QStringList AppDb::favouriteApps() const {
|
||||||
|
return m_favouriteApps;
|
||||||
|
}
|
||||||
|
|
||||||
|
void AppDb::setFavouriteApps(const QStringList& favApps) {
|
||||||
|
if (m_favouriteApps == favApps) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_favouriteApps = favApps;
|
||||||
|
emit favouriteAppsChanged();
|
||||||
|
m_favouriteAppsRegex.clear();
|
||||||
|
m_favouriteAppsRegex.reserve(m_favouriteApps.size());
|
||||||
|
for (const QString& item : std::as_const(m_favouriteApps)) {
|
||||||
|
const QRegularExpression re(regexifyString(item));
|
||||||
|
if (re.isValid()) {
|
||||||
|
m_favouriteAppsRegex << re;
|
||||||
|
} else {
|
||||||
|
qWarning() << "AppDb::setFavouriteApps: Regular expression is not valid: " << re.pattern();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
emit appsChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
QString AppDb::regexifyString(const QString& original) const {
|
||||||
|
if (original.startsWith('^') && original.endsWith('$'))
|
||||||
|
return original;
|
||||||
|
|
||||||
|
const QString escaped = QRegularExpression::escape(original);
|
||||||
|
return QStringLiteral("^%1$").arg(escaped);
|
||||||
|
}
|
||||||
|
|
||||||
QQmlListProperty<AppEntry> AppDb::apps() {
|
QQmlListProperty<AppEntry> AppDb::apps() {
|
||||||
return QQmlListProperty<AppEntry>(this, &getSortedApps());
|
return QQmlListProperty<AppEntry>(this, &getSortedApps());
|
||||||
}
|
}
|
||||||
|
|
@ -192,7 +225,12 @@ void AppDb::incrementFrequency(const QString& id) {
|
||||||
|
|
||||||
QList<AppEntry*>& AppDb::getSortedApps() const {
|
QList<AppEntry*>& AppDb::getSortedApps() const {
|
||||||
m_sortedApps = m_apps.values();
|
m_sortedApps = m_apps.values();
|
||||||
std::sort(m_sortedApps.begin(), m_sortedApps.end(), [](AppEntry* a, AppEntry* b) {
|
std::sort(m_sortedApps.begin(), m_sortedApps.end(), [this](AppEntry* a, AppEntry* b) {
|
||||||
|
bool aIsFav = isFavourite(a);
|
||||||
|
bool bIsFav = isFavourite(b);
|
||||||
|
if (aIsFav != bIsFav) {
|
||||||
|
return aIsFav;
|
||||||
|
}
|
||||||
if (a->frequency() != b->frequency()) {
|
if (a->frequency() != b->frequency()) {
|
||||||
return a->frequency() > b->frequency();
|
return a->frequency() > b->frequency();
|
||||||
}
|
}
|
||||||
|
|
@ -201,6 +239,15 @@ QList<AppEntry*>& AppDb::getSortedApps() const {
|
||||||
return m_sortedApps;
|
return m_sortedApps;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool AppDb::isFavourite(const AppEntry* app) const {
|
||||||
|
for (const QRegularExpression& re : m_favouriteAppsRegex) {
|
||||||
|
if (re.match(app->id()).hasMatch()) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
quint32 AppDb::getFrequency(const QString& id) const {
|
quint32 AppDb::getFrequency(const QString& id) const {
|
||||||
auto db = QSqlDatabase::database(m_uuid);
|
auto db = QSqlDatabase::database(m_uuid);
|
||||||
QSqlQuery query(db);
|
QSqlQuery query(db);
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@
|
||||||
#include <qobject.h>
|
#include <qobject.h>
|
||||||
#include <qqmlintegration.h>
|
#include <qqmlintegration.h>
|
||||||
#include <qqmllist.h>
|
#include <qqmllist.h>
|
||||||
|
#include <qregularexpression.h>
|
||||||
#include <qtimer.h>
|
#include <qtimer.h>
|
||||||
|
|
||||||
namespace caelestia {
|
namespace caelestia {
|
||||||
|
|
@ -66,6 +67,7 @@ class AppDb : public QObject {
|
||||||
Q_PROPERTY(QString uuid READ uuid CONSTANT)
|
Q_PROPERTY(QString uuid READ uuid CONSTANT)
|
||||||
Q_PROPERTY(QString path READ path WRITE setPath NOTIFY pathChanged REQUIRED)
|
Q_PROPERTY(QString path READ path WRITE setPath NOTIFY pathChanged REQUIRED)
|
||||||
Q_PROPERTY(QObjectList entries READ entries WRITE setEntries NOTIFY entriesChanged REQUIRED)
|
Q_PROPERTY(QObjectList entries READ entries WRITE setEntries NOTIFY entriesChanged REQUIRED)
|
||||||
|
Q_PROPERTY(QStringList favouriteApps READ favouriteApps WRITE setFavouriteApps NOTIFY favouriteAppsChanged REQUIRED)
|
||||||
Q_PROPERTY(QQmlListProperty<caelestia::AppEntry> apps READ apps NOTIFY appsChanged)
|
Q_PROPERTY(QQmlListProperty<caelestia::AppEntry> apps READ apps NOTIFY appsChanged)
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
@ -79,6 +81,9 @@ public:
|
||||||
[[nodiscard]] QObjectList entries() const;
|
[[nodiscard]] QObjectList entries() const;
|
||||||
void setEntries(const QObjectList& entries);
|
void setEntries(const QObjectList& entries);
|
||||||
|
|
||||||
|
[[nodiscard]] QStringList favouriteApps() const;
|
||||||
|
void setFavouriteApps(const QStringList& favApps);
|
||||||
|
|
||||||
[[nodiscard]] QQmlListProperty<AppEntry> apps();
|
[[nodiscard]] QQmlListProperty<AppEntry> apps();
|
||||||
|
|
||||||
Q_INVOKABLE void incrementFrequency(const QString& id);
|
Q_INVOKABLE void incrementFrequency(const QString& id);
|
||||||
|
|
@ -86,6 +91,7 @@ public:
|
||||||
signals:
|
signals:
|
||||||
void pathChanged();
|
void pathChanged();
|
||||||
void entriesChanged();
|
void entriesChanged();
|
||||||
|
void favouriteAppsChanged();
|
||||||
void appsChanged();
|
void appsChanged();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
@ -94,10 +100,14 @@ private:
|
||||||
const QString m_uuid;
|
const QString m_uuid;
|
||||||
QString m_path;
|
QString m_path;
|
||||||
QObjectList m_entries;
|
QObjectList m_entries;
|
||||||
|
QStringList m_favouriteApps; // unedited string list from qml
|
||||||
|
QList<QRegularExpression> m_favouriteAppsRegex; // pre-regexified m_favouriteApps list
|
||||||
QHash<QString, AppEntry*> m_apps;
|
QHash<QString, AppEntry*> m_apps;
|
||||||
mutable QList<AppEntry*> m_sortedApps;
|
mutable QList<AppEntry*> m_sortedApps;
|
||||||
|
|
||||||
|
QString regexifyString(const QString& original) const;
|
||||||
QList<AppEntry*>& getSortedApps() const;
|
QList<AppEntry*>& getSortedApps() const;
|
||||||
|
bool isFavourite(const AppEntry* app) const;
|
||||||
quint32 getFrequency(const QString& id) const;
|
quint32 getFrequency(const QString& id) const;
|
||||||
void updateAppFrequencies();
|
void updateAppFrequencies();
|
||||||
void updateApps();
|
void updateApps();
|
||||||
|
|
|
||||||
20
utils/Strings.qml
Normal file
20
utils/Strings.qml
Normal file
|
|
@ -0,0 +1,20 @@
|
||||||
|
pragma Singleton
|
||||||
|
|
||||||
|
import Quickshell
|
||||||
|
|
||||||
|
Singleton {
|
||||||
|
function testRegexList(filterList: list<string>, target: string): bool {
|
||||||
|
const regexChecker = /^\^.*\$$/;
|
||||||
|
for (const filter of filterList) {
|
||||||
|
// If filter is a regex
|
||||||
|
if (regexChecker.test(filter)) {
|
||||||
|
if ((new RegExp(filter)).test(target))
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
if (filter === target)
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Add table
Reference in a new issue