Launcher: refactor, renaming plugins to providers to avoid confusion with the plugin system.

This commit is contained in:
Lemmy
2026-01-03 13:41:14 -05:00
parent 3c80d87bee
commit ffb1811782
20 changed files with 528 additions and 528 deletions
+122 -122
View File
@@ -6,7 +6,7 @@ import Quickshell.Widgets
import "../../../Helpers/AdvancedMath.js" as AdvancedMath
import "../../../Helpers/FuzzySort.js" as Fuzzysort
import "Plugins"
import "Providers"
import qs.Commons
import qs.Modules.MainScreen
import qs.Services.Keyboard
@@ -50,8 +50,8 @@ SmartPanel {
property string searchText: ""
property int selectedIndex: 0
property var results: []
property var plugins: []
property var activePlugin: null
property var providers: []
property var activeProvider: null
property bool resultsReady: false
property bool ignoreMouseHover: Settings.data.appLauncher.ignoreMouseInput
@@ -62,7 +62,7 @@ SmartPanel {
if (searchText.startsWith(">clip") || searchText.startsWith(">calc")) {
return false;
}
if (activePlugin === emojiPlugin && emojiPlugin.isBrowsingMode) {
if (activeProvider === emojiProvider && emojiProvider.isBrowsingMode) {
return true;
}
return Settings.data.appLauncher.viewMode === "grid";
@@ -84,31 +84,31 @@ SmartPanel {
// They are instead being forwared from the search field NTextInput below.
function onTabPressed() {
// In emoji browsing mode, Tab navigates between categories
if (activePlugin === emojiPlugin && emojiPlugin.isBrowsingMode) {
var currentIndex = emojiPlugin.categories.indexOf(emojiPlugin.selectedCategory);
var nextIndex = (currentIndex + 1) % emojiPlugin.categories.length;
emojiPlugin.selectCategory(emojiPlugin.categories[nextIndex]);
} else if ((activePlugin === null || activePlugin === appsPlugin) && appsPlugin.isBrowsingMode && !root.searchText.startsWith(">") && Settings.data.appLauncher.showCategories) {
if (activeProvider === emojiProvider && emojiProvider.isBrowsingMode) {
var currentIndex = emojiProvider.categories.indexOf(emojiProvider.selectedCategory);
var nextIndex = (currentIndex + 1) % emojiProvider.categories.length;
emojiProvider.selectCategory(emojiProvider.categories[nextIndex]);
} else if ((activeProvider === null || activeProvider === appsProvider) && appsProvider.isBrowsingMode && !root.searchText.startsWith(">") && Settings.data.appLauncher.showCategories) {
// In apps browsing mode (no search), Tab navigates between categories
var availableCategories = appsPlugin.availableCategories || ["all"];
var currentIndex = availableCategories.indexOf(appsPlugin.selectedCategory);
var availableCategories = appsProvider.availableCategories || ["all"];
var currentIndex = availableCategories.indexOf(appsProvider.selectedCategory);
var nextIndex = (currentIndex + 1) % availableCategories.length;
appsPlugin.selectCategory(availableCategories[nextIndex]);
appsProvider.selectCategory(availableCategories[nextIndex]);
} else {
selectNextWrapped();
}
}
function onBackTabPressed() {
if (activePlugin === emojiPlugin && emojiPlugin.isBrowsingMode) {
var currentIndex = emojiPlugin.categories.indexOf(emojiPlugin.selectedCategory);
var previousIndex = ((currentIndex - 1) % emojiPlugin.categories.length + emojiPlugin.categories.length) % emojiPlugin.categories.length;
emojiPlugin.selectCategory(emojiPlugin.categories[previousIndex]);
} else if ((activePlugin === null || activePlugin === appsPlugin) && appsPlugin.isBrowsingMode && !root.searchText.startsWith(">") && Settings.data.appLauncher.showCategories) {
var availableCategories = appsPlugin.availableCategories || ["all"];
var currentIndex = availableCategories.indexOf(appsPlugin.selectedCategory);
if (activeProvider === emojiProvider && emojiProvider.isBrowsingMode) {
var currentIndex = emojiProvider.categories.indexOf(emojiProvider.selectedCategory);
var previousIndex = ((currentIndex - 1) % emojiProvider.categories.length + emojiProvider.categories.length) % emojiProvider.categories.length;
emojiProvider.selectCategory(emojiProvider.categories[previousIndex]);
} else if ((activeProvider === null || activeProvider === appsProvider) && appsProvider.isBrowsingMode && !root.searchText.startsWith(">") && Settings.data.appLauncher.showCategories) {
var availableCategories = appsProvider.availableCategories || ["all"];
var currentIndex = availableCategories.indexOf(appsProvider.selectedCategory);
var previousIndex = ((currentIndex - 1) % availableCategories.length + availableCategories.length) % availableCategories.length;
appsPlugin.selectCategory(availableCategories[previousIndex]);
appsProvider.selectCategory(availableCategories[previousIndex]);
} else {
selectPreviousWrapped();
}
@@ -188,24 +188,24 @@ SmartPanel {
// Delete clipboard entry if one is selected
if (selectedIndex >= 0 && results && results[selectedIndex] && results[selectedIndex].clipboardId) {
const clipboardId = results[selectedIndex].clipboardId;
clipPlugin.gotResults = false;
clipPlugin.isWaitingForData = true;
clipPlugin.lastSearchText = root.searchText;
clipProvider.gotResults = false;
clipProvider.isWaitingForData = true;
clipProvider.lastSearchText = root.searchText;
ClipboardService.deleteById(String(clipboardId));
}
}
// Public API for plugins
// Public API for providers
function setSearchText(text) {
searchText = text;
}
// Plugin registration
function registerPlugin(plugin) {
plugins.push(plugin);
plugin.launcher = root;
if (plugin.init)
plugin.init();
// Provider registration
function registerProvider(provider) {
providers.push(provider);
provider.launcher = root;
if (provider.init)
provider.init();
}
// Caclualtor handling
@@ -261,26 +261,26 @@ SmartPanel {
// Search handling
function updateResults() {
results = [];
activePlugin = null;
activeProvider = null;
// Check for command mode
if (searchText.startsWith(">")) {
// Find plugin that handles this command
for (let plugin of plugins) {
if (plugin.handleCommand && plugin.handleCommand(searchText)) {
activePlugin = plugin;
results = plugin.getResults(searchText);
// Find provider that handles this command
for (let provider of providers) {
if (provider.handleCommand && provider.handleCommand(searchText)) {
activeProvider = provider;
results = provider.getResults(searchText);
break;
}
}
// Show available commands if just ">" or filter commands if partial match
if (!activePlugin) {
// Collect all commands from all plugins
if (!activeProvider) {
// Collect all commands from all providers
let allCommands = [];
for (let plugin of plugins) {
if (plugin.commands) {
allCommands = allCommands.concat(plugin.commands());
for (let provider of providers) {
if (provider.commands) {
allCommands = allCommands.concat(provider.commands());
}
}
@@ -312,11 +312,11 @@ SmartPanel {
}
}
} else {
// Regular search - let plugins contribute results
for (let plugin of plugins) {
if (plugin.handleSearch) {
const pluginResults = plugin.getResults(searchText);
results = results.concat(pluginResults);
// Regular search - let providers contribute results
for (let provider of providers) {
if (provider.handleSearch) {
const providerResults = provider.getResults(searchText);
results = results.concat(providerResults);
}
}
@@ -337,12 +337,12 @@ SmartPanel {
resultsReady = false;
ignoreMouseHover = true;
// Notify plugins and update results
// Use Qt.callLater to ensure plugins are registered (Component.onCompleted runs first)
// Notify providers and update results
// Use Qt.callLater to ensure providers are registered (Component.onCompleted runs first)
Qt.callLater(() => {
for (let plugin of plugins) {
if (plugin.onOpened)
plugin.onOpened();
for (let provider of providers) {
if (provider.onOpened)
provider.onOpened();
}
updateResults();
resultsReady = true;
@@ -354,53 +354,53 @@ SmartPanel {
searchText = "";
ignoreMouseHover = true;
// Notify plugins
for (let plugin of plugins) {
if (plugin.onClosed)
plugin.onClosed();
// Notify providers
for (let provider of providers) {
if (provider.onClosed)
provider.onClosed();
}
}
// Plugin components - declared inline so imports work correctly
ApplicationsPlugin {
id: appsPlugin
// Provider components - declared inline so imports work correctly
ApplicationsProvider {
id: appsProvider
Component.onCompleted: {
registerPlugin(this);
Logger.d("Launcher", "Registered: ApplicationsPlugin");
registerProvider(this);
Logger.d("Launcher", "Registered: ApplicationsProvider");
}
}
CalculatorPlugin {
id: calcPlugin
CalculatorProvider {
id: calcProvider
Component.onCompleted: {
registerPlugin(this);
Logger.d("Launcher", "Registered: CalculatorPlugin");
registerProvider(this);
Logger.d("Launcher", "Registered: CalculatorProvider");
}
}
ClipboardPlugin {
id: clipPlugin
ClipboardProvider {
id: clipProvider
Component.onCompleted: {
if (Settings.data.appLauncher.enableClipboardHistory) {
registerPlugin(this);
Logger.d("Launcher", "Registered: ClipboardPlugin");
registerProvider(this);
Logger.d("Launcher", "Registered: ClipboardProvider");
}
}
}
CommandPlugin {
id: cmdPlugin
CommandProvider {
id: cmdProvider
Component.onCompleted: {
registerPlugin(this);
Logger.d("Launcher", "Registered: CommandPlugin");
registerProvider(this);
Logger.d("Launcher", "Registered: CommandProvider");
}
}
EmojiPlugin {
id: emojiPlugin
EmojiProvider {
id: emojiProvider
Component.onCompleted: {
registerPlugin(this);
Logger.d("Launcher", "Registered: EmojiPlugin");
registerProvider(this);
Logger.d("Launcher", "Registered: EmojiProvider");
}
}
@@ -728,7 +728,7 @@ SmartPanel {
}
NIconButton {
visible: root.activePlugin === null || root.activePlugin === appsPlugin
visible: root.activeProvider === null || root.activeProvider === appsProvider
icon: Settings.data.appLauncher.viewMode === "grid" ? "layout-list" : "layout-grid"
tooltipText: Settings.data.appLauncher.viewMode === "grid" ? I18n.tr("tooltips.list-view") : I18n.tr("tooltips.grid-view")
Layout.preferredWidth: searchInput.height
@@ -742,41 +742,41 @@ SmartPanel {
// Emoji category tabs (shown when in browsing mode)
NTabBar {
id: emojiCategoryTabs
visible: root.activePlugin === emojiPlugin && emojiPlugin.isBrowsingMode
visible: root.activeProvider === emojiProvider && emojiProvider.isBrowsingMode
Layout.fillWidth: true
margins: Style.marginM
property int computedCurrentIndex: {
if (visible && emojiPlugin.categories) {
return emojiPlugin.categories.indexOf(emojiPlugin.selectedCategory);
if (visible && emojiProvider.categories) {
return emojiProvider.categories.indexOf(emojiProvider.selectedCategory);
}
return 0;
}
currentIndex: computedCurrentIndex
Repeater {
model: emojiPlugin.categories
model: emojiProvider.categories
NIconTabButton {
required property string modelData
required property int index
icon: emojiPlugin.categoryIcons[modelData] || "star"
tooltipText: emojiPlugin.getCategoryName ? emojiPlugin.getCategoryName(modelData) : modelData
icon: emojiProvider.categoryIcons[modelData] || "star"
tooltipText: emojiProvider.getCategoryName ? emojiProvider.getCategoryName(modelData) : modelData
tabIndex: index
checked: emojiCategoryTabs.currentIndex === index
onClicked: {
emojiPlugin.selectCategory(modelData);
emojiProvider.selectCategory(modelData);
}
}
}
}
Connections {
target: emojiPlugin
target: emojiProvider
enabled: emojiCategoryTabs.visible
function onSelectedCategoryChanged() {
// Force update of currentIndex when selectedCategory changes
Qt.callLater(() => {
if (emojiCategoryTabs.visible && emojiPlugin.categories) {
const newIndex = emojiPlugin.categories.indexOf(emojiPlugin.selectedCategory);
if (emojiCategoryTabs.visible && emojiProvider.categories) {
const newIndex = emojiProvider.categories.indexOf(emojiProvider.selectedCategory);
if (newIndex >= 0 && emojiCategoryTabs.currentIndex !== newIndex) {
emojiCategoryTabs.currentIndex = newIndex;
}
@@ -788,41 +788,41 @@ SmartPanel {
// App category tabs (shown when browsing apps without search)
NTabBar {
id: appCategoryTabs
visible: (root.activePlugin === null || root.activePlugin === appsPlugin) && appsPlugin.isBrowsingMode && !root.searchText.startsWith(">") && Settings.data.appLauncher.showCategories
visible: (root.activeProvider === null || root.activeProvider === appsProvider) && appsProvider.isBrowsingMode && !root.searchText.startsWith(">") && Settings.data.appLauncher.showCategories
Layout.fillWidth: true
margins: Style.marginM
property int computedCurrentIndex: {
if (visible && appsPlugin.availableCategories) {
return appsPlugin.availableCategories.indexOf(appsPlugin.selectedCategory);
if (visible && appsProvider.availableCategories) {
return appsProvider.availableCategories.indexOf(appsProvider.selectedCategory);
}
return 0;
}
currentIndex: computedCurrentIndex
Repeater {
model: appsPlugin.availableCategories || []
model: appsProvider.availableCategories || []
NIconTabButton {
required property string modelData
required property int index
icon: appsPlugin.categoryIcons[modelData] || "apps"
tooltipText: appsPlugin.getCategoryName ? appsPlugin.getCategoryName(modelData) : modelData
icon: appsProvider.categoryIcons[modelData] || "apps"
tooltipText: appsProvider.getCategoryName ? appsProvider.getCategoryName(modelData) : modelData
tabIndex: index
checked: appCategoryTabs.currentIndex === index
onClicked: {
appsPlugin.selectCategory(modelData);
appsProvider.selectCategory(modelData);
}
}
}
}
Connections {
target: appsPlugin
target: appsProvider
enabled: appCategoryTabs.visible
function onSelectedCategoryChanged() {
// Force update of currentIndex when selectedCategory changes
Qt.callLater(() => {
if (appCategoryTabs.visible && appsPlugin.availableCategories) {
const newIndex = appsPlugin.availableCategories.indexOf(appsPlugin.selectedCategory);
if (appCategoryTabs.visible && appsProvider.availableCategories) {
const newIndex = appsProvider.availableCategories.indexOf(appsProvider.selectedCategory);
if (newIndex >= 0 && appCategoryTabs.currentIndex !== newIndex) {
appCategoryTabs.currentIndex = newIndex;
}
@@ -1109,14 +1109,14 @@ SmartPanel {
NIconButton {
visible: !!modelData.clipboardId && entry.isSelected
icon: "trash"
tooltipText: I18n.tr("plugins.clipboard-delete")
tooltipText: I18n.tr("launcher.providers.clipboard-delete")
z: 1
onClicked: {
if (modelData.clipboardId) {
// Set plugin state before deletion so refresh works
clipPlugin.gotResults = false;
clipPlugin.isWaitingForData = true;
clipPlugin.lastSearchText = root.searchText;
// Set provider state before deletion so refresh works
clipProvider.gotResults = false;
clipProvider.isWaitingForData = true;
clipProvider.lastSearchText = root.searchText;
// Delete the item - deleteById now uses Process and will refresh automatically
ClipboardService.deleteById(String(modelData.clipboardId));
}
@@ -1162,7 +1162,7 @@ SmartPanel {
width: parent.width
height: parent.height
cellWidth: {
if (root.activePlugin === emojiPlugin && emojiPlugin.isBrowsingMode) {
if (root.activeProvider === emojiProvider && emojiProvider.isBrowsingMode) {
return parent.width / root.targetGridColumns;
}
// Make cells fit exactly like the tab bar
@@ -1170,7 +1170,7 @@ SmartPanel {
return parent.width / root.targetGridColumns;
}
cellHeight: {
if (root.activePlugin === emojiPlugin && emojiPlugin.isBrowsingMode) {
if (root.activeProvider === emojiProvider && emojiProvider.isBrowsingMode) {
return (parent.width / root.targetGridColumns) * 1.2;
}
// Cell height scales automatically as parent.width scales with uiScaleRatio
@@ -1195,7 +1195,7 @@ SmartPanel {
function updateGridColumns() {
// Update gridColumns based on actual GridView width
// This ensures navigation works correctly regardless of panel size
if (root.activePlugin === emojiPlugin && emojiPlugin.isBrowsingMode) {
if (root.activeProvider === emojiProvider && emojiProvider.isBrowsingMode) {
// Always 5 columns for emoji browsing mode
root.gridColumns = 5;
} else {
@@ -1220,9 +1220,9 @@ SmartPanel {
// Update gridColumns when entering/exiting emoji browsing mode
Connections {
target: emojiPlugin
target: emojiProvider
function onIsBrowsingModeChanged() {
if (emojiPlugin.isBrowsingMode) {
if (emojiProvider.isBrowsingMode) {
root.gridColumns = 5;
}
}
@@ -1302,14 +1302,14 @@ SmartPanel {
ColumnLayout {
anchors.fill: parent
anchors.margins: (root.activePlugin === emojiPlugin && emojiPlugin.isBrowsingMode) ? 4 : Style.marginM
anchors.bottomMargin: (root.activePlugin === emojiPlugin && emojiPlugin.isBrowsingMode) ? Style.marginL : Style.marginM
anchors.margins: (root.activeProvider === emojiProvider && emojiProvider.isBrowsingMode) ? 4 : Style.marginM
anchors.bottomMargin: (root.activeProvider === emojiProvider && emojiProvider.isBrowsingMode) ? Style.marginL : Style.marginM
spacing: Style.marginS
// Icon badge or Image preview or Emoji
Rectangle {
Layout.preferredWidth: {
if (root.activePlugin === emojiPlugin && emojiPlugin.isBrowsingMode && modelData.emojiChar) {
if (root.activeProvider === emojiProvider && emojiProvider.isBrowsingMode && modelData.emojiChar) {
return gridEntry.width - 8;
}
// Scale badge relative to cell size for proper scaling on all resolutions
@@ -1317,7 +1317,7 @@ SmartPanel {
return Math.round(gridEntry.width * 0.6);
}
Layout.preferredHeight: {
if (root.activePlugin === emojiPlugin && emojiPlugin.isBrowsingMode && modelData.emojiChar) {
if (root.activeProvider === emojiProvider && emojiProvider.isBrowsingMode && modelData.emojiChar) {
return gridEntry.width - 8;
}
// Scale badge relative to cell size for proper scaling on all resolutions
@@ -1406,7 +1406,7 @@ SmartPanel {
text: modelData.emojiChar ? modelData.emojiChar : modelData.name.charAt(0).toUpperCase()
pointSize: {
if (modelData.emojiChar) {
if (root.activePlugin === emojiPlugin && emojiPlugin.isBrowsingMode) {
if (root.activeProvider === emojiProvider && emojiProvider.isBrowsingMode) {
// Scale with cell width but cap at reasonable maximum
const cellBasedSize = gridEntry.width * 0.4;
const maxSize = Style.fontSizeXXXL * Style.uiScaleRatio;
@@ -1429,7 +1429,7 @@ SmartPanel {
NText {
text: modelData.name || "Unknown"
pointSize: {
if (root.activePlugin === emojiPlugin && emojiPlugin.isBrowsingMode && modelData.emojiChar) {
if (root.activeProvider === emojiProvider && emojiProvider.isBrowsingMode && modelData.emojiChar) {
return Style.fontSizeS * Style.uiScaleRatio;
}
// Scale font size relative to cell width for low res, but cap at maximum
@@ -1443,8 +1443,8 @@ SmartPanel {
elide: Text.ElideRight
Layout.fillWidth: true
Layout.maximumWidth: gridEntry.width - 8
Layout.leftMargin: (root.activePlugin === emojiPlugin && emojiPlugin.isBrowsingMode && modelData.emojiChar) ? Style.marginS : 0
Layout.rightMargin: (root.activePlugin === emojiPlugin && emojiPlugin.isBrowsingMode && modelData.emojiChar) ? Style.marginS : 0
Layout.leftMargin: (root.activeProvider === emojiProvider && emojiProvider.isBrowsingMode && modelData.emojiChar) ? Style.marginS : 0
Layout.rightMargin: (root.activeProvider === emojiProvider && emojiProvider.isBrowsingMode && modelData.emojiChar) ? Style.marginS : 0
horizontalAlignment: Text.AlignHCenter
wrapMode: Text.NoWrap
maximumLineCount: 1
@@ -1472,14 +1472,14 @@ SmartPanel {
NIconButton {
visible: !!modelData.clipboardId && gridEntry.isSelected
icon: "trash"
tooltipText: I18n.tr("plugins.clipboard-delete")
tooltipText: I18n.tr("launcher.providers.clipboard-delete")
z: 11
onClicked: {
if (modelData.clipboardId) {
// Set plugin state before deletion so refresh works
clipPlugin.gotResults = false;
clipPlugin.isWaitingForData = true;
clipPlugin.lastSearchText = root.searchText;
// Set provider state before deletion so refresh works
clipProvider.gotResults = false;
clipProvider.isWaitingForData = true;
clipProvider.lastSearchText = root.searchText;
// Delete the item - deleteById now uses Process and will refresh automatically
ClipboardService.deleteById(String(modelData.clipboardId));
}
@@ -1521,12 +1521,12 @@ SmartPanel {
if (results.length === 0) {
if (searchText) {
return "No results";
} else if (activePlugin === emojiPlugin && emojiPlugin.isBrowsingMode && emojiPlugin.selectedCategory === "recent") {
} else if (activeProvider === emojiProvider && emojiProvider.isBrowsingMode && emojiProvider.selectedCategory === "recent") {
return "No recently used emoji";
}
return "";
}
var prefix = activePlugin && activePlugin.name ? activePlugin.name + ": " : "";
var prefix = activeProvider && activeProvider.name ? activeProvider.name + ": " : "";
return prefix + results.length + " result" + (results.length !== 1 ? 's' : '');
}
pointSize: Style.fontSizeXS
@@ -8,7 +8,7 @@ Item {
id: root
property var launcher: null
property string name: I18n.tr("plugins.applications")
property string name: I18n.tr("launcher.providers.applications")
property bool handleSearch: true
property var entries: []
@@ -332,7 +332,7 @@ Item {
function loadApplications() {
if (typeof DesktopEntries === 'undefined') {
Logger.w("ApplicationsPlugin", "DesktopEntries service not available");
Logger.w("ApplicationsProvider", "DesktopEntries service not available");
return;
}
@@ -352,7 +352,7 @@ Item {
// If exec is different, it's a legitimate different entry - keep it
if (previousExec !== execCmd) {
Logger.d("ApplicationsPlugin", `Keeping variant of ${appId}: ${execCmd} (differs from ${previousExec})`);
Logger.d("ApplicationsProvider", `Keeping variant of ${appId}: ${execCmd} (differs from ${previousExec})`);
// Add with modified ID to make it unique
app.id = `${appId}_${execCmd}`;
seen.set(app.id, execCmd);
@@ -360,7 +360,7 @@ Item {
}
// Same appId AND same exec = true duplicate, skip it
Logger.d("ApplicationsPlugin", `Skipping duplicate: ${appId}`);
Logger.d("ApplicationsProvider", `Skipping duplicate: ${appId}`);
return false;
}
@@ -371,7 +371,7 @@ Item {
return app;
});
Logger.d("ApplicationsPlugin", `Loaded ${entries.length} applications`);
Logger.d("ApplicationsProvider", `Loaded ${entries.length} applications`);
updateAvailableCategories();
}
@@ -542,7 +542,7 @@ Item {
// Defer execution to next event loop iteration to ensure panel is fully closed
Qt.callLater(() => {
Logger.d("ApplicationsPlugin", `Launching: ${app.name}`);
Logger.d("ApplicationsProvider", `Launching: ${app.name}`);
// Record usage and persist asynchronously
if (Settings.data.appLauncher.sortByMostUsed) {
recordUsage(app);
@@ -561,7 +561,7 @@ Item {
Quickshell.execDetached(command);
}
} else if (Settings.data.appLauncher.useApp2Unit && app.id) {
Logger.d("ApplicationsPlugin", `Using app2unit for: ${app.id}`);
Logger.d("ApplicationsProvider", `Using app2unit for: ${app.id}`);
if (app.runInTerminal)
Quickshell.execDetached(["app2unit", "--", app.id + ".desktop"]);
else
@@ -570,7 +570,7 @@ Item {
// Fallback logic when app2unit is not used
if (app.runInTerminal) {
// If app.execute() fails for terminal apps, we handle it manually.
Logger.d("ApplicationsPlugin", "Executing terminal app manually: " + app.name);
Logger.d("ApplicationsProvider", "Executing terminal app manually: " + app.name);
const terminal = Settings.data.appLauncher.terminalCommand.split(" ");
const command = terminal.concat(app.command);
Quickshell.execDetached(command);
@@ -579,7 +579,7 @@ Item {
} else if (app.execute) {
app.execute();
} else {
Logger.w("ApplicationsPlugin", `Could not launch: ${app.name}. No valid launch method.`);
Logger.w("ApplicationsProvider", `Could not launch: ${app.name}. No valid launch method.`);
}
}
});
@@ -6,7 +6,7 @@ import qs.Commons
// TODO: Remove this plugin in 2-3 bussiness days
Item {
property var launcher: null
property string name: I18n.tr("plugins.calculator")
property string name: I18n.tr("launcher.providers.calculator")
property string iconMode: Settings.data.appLauncher.iconMode
function handleCommand(query) {
@@ -18,7 +18,7 @@ Item {
return [
{
"name": ">calc",
"description": I18n.tr("plugins.calculator-deprecated"),
"description": I18n.tr("launcher.providers.calculator-deprecated"),
"icon": "alert-triangle",
"isTablerIcon": true,
"isImage": false,
@@ -43,8 +43,8 @@ Item {
if (!expression) {
return [
{
"name": I18n.tr("plugins.calculator-name"),
"description": I18n.tr("plugins.calculator-deprecated"),
"name": I18n.tr("launcher.providers.calculator-name"),
"description": I18n.tr("launcher.providers.calculator-deprecated"),
"icon": "alert-triangle",
"isTablerIcon": true,
"isImage": false,
@@ -72,7 +72,7 @@ Item {
} catch (error) {
return [
{
"name": I18n.tr("plugins.calculator-error"),
"name": I18n.tr("launcher.providers.calculator-error"),
"description": error.message || "Invalid expression",
"icon": iconMode === "tabler" ? "circle-x" : "dialog-error",
"isTablerIcon": true,
@@ -6,12 +6,12 @@ import qs.Services.Keyboard
Item {
id: root
// Plugin metadata
property string name: I18n.tr("plugins.clipboard")
// Provider metadata
property string name: I18n.tr("launcher.providers.clipboard")
property var launcher: null
property string iconMode: Settings.data.appLauncher.iconMode
// Plugin capabilities
// Provider capabilities
property bool handleSearch: false // Don't handle regular search
// Internal state
@@ -39,9 +39,9 @@ Item {
}
}
// Initialize plugin
// Initialize provider
function init() {
Logger.i("ClipboardPlugin", "Initialized");
Logger.i("ClipboardProvider", "Initialized");
// Pre-load clipboard data if service is active
if (ClipboardService.active) {
ClipboardService.list(100);
@@ -60,7 +60,7 @@ Item {
}
}
// Check if this plugin handles the command
// Check if this provider handles the command
function handleCommand(searchText) {
return searchText.startsWith(">clip");
}
@@ -70,7 +70,7 @@ Item {
return [
{
"name": ">clip",
"description": I18n.tr("plugins.clipboard-search-description"),
"description": I18n.tr("launcher.providers.clipboard-search-description"),
"icon": iconMode === "tabler" ? "clipboard" : "text-x-generic",
"isTablerIcon": true,
"isImage": false,
@@ -80,7 +80,7 @@ Item {
},
{
"name": ">clip clear",
"description": I18n.tr("plugins.clipboard-clear-description"),
"description": I18n.tr("launcher.providers.clipboard-clear-description"),
"icon": iconMode === "tabler" ? "trash" : "user-trash",
"isTablerIcon": true,
"isImage": false,
@@ -106,8 +106,8 @@ Item {
if (!ClipboardService.active) {
return [
{
"name": I18n.tr("plugins.clipboard-history-disabled"),
"description": I18n.tr("plugins.clipboard-history-disabled-description"),
"name": I18n.tr("launcher.providers.clipboard-history-disabled"),
"description": I18n.tr("launcher.providers.clipboard-history-disabled-description"),
"icon": iconMode === "tabler" ? "refresh" : "view-refresh",
"isTablerIcon": true,
"isImage": false,
@@ -120,8 +120,8 @@ Item {
if (query === "clear") {
return [
{
"name": I18n.tr("plugins.clipboard-clear-history"),
"description": I18n.tr("plugins.clipboard-clear-description-full"),
"name": I18n.tr("launcher.providers.clipboard-clear-history"),
"description": I18n.tr("launcher.providers.clipboard-clear-description-full"),
"icon": iconMode === "tabler" ? "trash" : "delete_sweep",
"isTablerIcon": true,
"isImage": false,
@@ -137,8 +137,8 @@ Item {
if (ClipboardService.loading || isWaitingForData) {
return [
{
"name": I18n.tr("plugins.clipboard-loading"),
"description": I18n.tr("plugins.clipboard-loading-description"),
"name": I18n.tr("launcher.providers.clipboard-loading"),
"description": I18n.tr("launcher.providers.clipboard-loading-description"),
"icon": iconMode === "tabler" ? "refresh" : "view-refresh",
"isTablerIcon": true,
"isImage": false,
@@ -156,8 +156,8 @@ Item {
ClipboardService.list(100);
return [
{
"name": I18n.tr("plugins.clipboard-loading"),
"description": I18n.tr("plugins.clipboard-loading-description"),
"name": I18n.tr("launcher.providers.clipboard-loading"),
"description": I18n.tr("launcher.providers.clipboard-loading-description"),
"icon": iconMode === "tabler" ? "refresh" : "view-refresh",
"isTablerIcon": true,
"isImage": false,
@@ -4,7 +4,7 @@ import qs.Commons
Item {
property var launcher: null
property string name: I18n.tr("plugins.command")
property string name: I18n.tr("launcher.providers.command")
property string iconMode: Settings.data.appLauncher.iconMode
function handleCommand(query) {
@@ -15,7 +15,7 @@ Item {
return [
{
"name": ">cmd",
"description": I18n.tr("plugins.command-description"),
"description": I18n.tr("launcher.providers.command-description"),
"icon": iconMode === "tabler" ? "terminal" : "utilities-terminal",
"isTablerIcon": true,
"isImage": false,
@@ -33,8 +33,8 @@ Item {
let expression = query.substring(4).trim();
return [
{
"name": I18n.tr("plugins.command-name"),
"description": I18n.tr("plugins.command-description"),
"name": I18n.tr("launcher.providers.command-name"),
"description": I18n.tr("launcher.providers.command-description"),
"icon": iconMode === "tabler" ? "terminal" : "utilities-terminal",
"isTablerIcon": true,
"isImage": false,
@@ -6,8 +6,8 @@ import qs.Services.Keyboard
Item {
id: root
// Plugin metadata
property string name: I18n.tr("plugins.emoji")
// Provider metadata
property string name: I18n.tr("launcher.providers.emoji")
property var launcher: null
property string iconMode: Settings.data.appLauncher.iconMode
property bool handleSearch: false
@@ -56,9 +56,9 @@ Item {
}
}
// Initialize plugin
// Initialize provider
function init() {
Logger.i("EmojiPlugin", "Initialized");
Logger.d("EmojiProvider", "Initialized");
}
function selectCategory(category) {
@@ -73,7 +73,7 @@ Item {
selectedCategory = "recent";
}
// Check if this plugin handles the command
// Check if this provider handles the command
function handleCommand(searchText) {
return searchText.startsWith(">emoji");
}
@@ -83,7 +83,7 @@ Item {
return [
{
"name": ">emoji",
"description": I18n.tr("plugins.emoji-search-description"),
"description": I18n.tr("launcher.providers.emoji-search-description"),
"icon": iconMode === "tabler" ? "mood-smile" : "face-smile",
"isTablerIcon": true,
"isImage": false,
@@ -103,8 +103,8 @@ Item {
if (!EmojiService.loaded) {
return [
{
"name": I18n.tr("plugins.emoji-loading"),
"description": I18n.tr("plugins.emoji-loading-description"),
"name": I18n.tr("launcher.providers.emoji-loading"),
"description": I18n.tr("launcher.providers.emoji-loading-description"),
"icon": iconMode === "tabler" ? "refresh" : "view-refresh",
"isTablerIcon": true,
"isImage": false,