Very early KDE 6 release.

This commit is contained in:
wackyideas 2024-08-09 03:20:25 +02:00
parent 7cc4ccabbc
commit 686046d4f7
6272 changed files with 140920 additions and 529657 deletions

View file

@ -0,0 +1,231 @@
/***************************************************************************
* Copyright (C) 2013 by Aurélien Gâteau <agateau@kde.org> *
* Copyright (C) 2013-2015 by Eike Hein <hein@kde.org> *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA . *
***************************************************************************/
.pragma library
function fillActionMenu(i18n, actionMenu, actionList, favoriteModel, favoriteId) {
// Accessing actionList can be a costly operation, so we don't
// access it until we need the menu.
var actions = createFavoriteActions(i18n, favoriteModel, favoriteId);
if (actions) {
if (actionList && actionList.length > 0) {
var separator = { "type": "separator" };
actionList.unshift(separator);
// actionList = actions.concat(actionList); // this crashes Qt O.o
actionList.unshift.apply(actionList, actions);
} else {
actionList = actions;
}
}
actionMenu.actionList = actionList;
}
function createFavoriteActions(i18n, favoriteModel, favoriteId) {
if (favoriteModel === null || !favoriteModel.enabled || favoriteId == null) {
return null;
}
if ("initForClient" in favoriteModel) {
var activities = favoriteModel.activities.runningActivities;
if (activities.length <= 1) {
var action = {};
if (favoriteModel.isFavorite(favoriteId)) {
action.text = i18n("Remove from Favorites");
action.icon = "list-remove";
action.actionId = "_kicker_favorite_remove";
} else if (favoriteModel.maxFavorites == -1 || favoriteModel.count < favoriteModel.maxFavorites) {
action.text = i18n("Add to Favorites");
action.icon = "bookmark-new";
action.actionId = "_kicker_favorite_add";
} else {
return null;
}
action.actionArgument = { favoriteModel: favoriteModel, favoriteId: favoriteId };
return [action];
} else {
var actions = [];
var linkedActivities = favoriteModel.linkedActivitiesFor(favoriteId);
// Adding the item to link/unlink to all activities
var linkedToAllActivities =
!(linkedActivities.indexOf(":global") === -1);
actions.push({
text : i18n("On All Activities"),
checkable : true,
actionId : linkedToAllActivities ?
"_kicker_favorite_remove_from_activity" :
"_kicker_favorite_set_to_activity",
checked : linkedToAllActivities,
actionArgument : {
favoriteModel: favoriteModel,
favoriteId: favoriteId,
favoriteActivity: ""
}
});
// Adding items for each activity separately
var addActivityItem = function(activityId, activityName) {
var linkedToThisActivity =
!(linkedActivities.indexOf(activityId) === -1);
actions.push({
text : activityName,
checkable : true,
checked : linkedToThisActivity && !linkedToAllActivities,
actionId :
// If we are on all activities, and the user clicks just one
// specific activity, unlink from everything else
linkedToAllActivities ? "_kicker_favorite_set_to_activity" :
// If we are linked to the current activity, just unlink from
// that single one
linkedToThisActivity ? "_kicker_favorite_remove_from_activity" :
// Otherwise, link to this activity, but do not unlink from
// other ones
"_kicker_favorite_add_to_activity",
actionArgument : {
favoriteModel : favoriteModel,
favoriteId : favoriteId,
favoriteActivity : activityId
}
});
};
// Adding the item to link/unlink to the current activity
addActivityItem(favoriteModel.activities.currentActivity, i18n("On The Current Activity"));
actions.push({
type: "separator",
actionId: "_kicker_favorite_separator"
});
// Adding the items for each activity
activities.forEach(function(activityId) {
addActivityItem(activityId, favoriteModel.activityNameForId(activityId));
});
return [{
text : i18n("Show In Favorites"),
icon : "favorite",
subActions : actions
}];
}
} else {
var action = {};
if (favoriteModel.isFavorite(favoriteId)) {
action.text = i18n("Remove from Favorites");
action.icon = "list-remove";
action.actionId = "_kicker_favorite_remove";
} else if (favoriteModel.maxFavorites == -1 || favoriteModel.count < favoriteModel.maxFavorites) {
action.text = i18n("Add to Favorites");
action.icon = "bookmark-new";
action.actionId = "_kicker_favorite_add";
} else {
return null;
}
action.actionArgument = { favoriteModel: favoriteModel, favoriteId: favoriteId };
return [action];
}
}
function triggerAction(plasmoid, model, index, actionId, actionArgument) {
function startsWith(txt, needle) {
return txt.substr(0, needle.length) === needle;
}
if (startsWith(actionId, "_kicker_favorite_")) {
handleFavoriteAction(actionId, actionArgument);
return;
}
var closeRequested = model.trigger(index, actionId, actionArgument);
if (closeRequested) {
plasmoid.expanded = false;
return true;
}
return false;
}
function handleFavoriteAction(actionId, actionArgument) {
var favoriteId = actionArgument.favoriteId;
var favoriteModel = actionArgument.favoriteModel;
console.log(actionId);
if (favoriteModel === null || favoriteId == null) {
return null;
}
if ("initForClient" in favoriteModel) {
if (actionId == "_kicker_favorite_remove") {
console.log("Removing from all activities");
favoriteModel.removeFavoriteFrom(favoriteId, ":any");
} else if (actionId == "_kicker_favorite_add") {
console.log("Adding to global activity");
favoriteModel.addFavoriteTo(favoriteId, ":global");
} else if (actionId == "_kicker_favorite_remove_from_activity") {
console.log("Removing from a specific activity");
favoriteModel.removeFavoriteFrom(favoriteId, actionArgument.favoriteActivity);
} else if (actionId == "_kicker_favorite_add_to_activity") {
console.log("Adding to another activity");
favoriteModel.addFavoriteTo(favoriteId, actionArgument.favoriteActivity);
} else if (actionId == "_kicker_favorite_set_to_activity") {
console.log("Removing the item from the favourites, and re-adding it just to be on a specific activity");
favoriteModel.setFavoriteOn(favoriteId, actionArgument.favoriteActivity);
}
} else {
if (actionId == "_kicker_favorite_remove") {
favoriteModel.removeFavorite(favoriteId);
} else if (actionId == "_kicker_favorite_add") {
favoriteModel.addFavorite(favoriteId);
}
}
}

View file

@ -0,0 +1,35 @@
/***************************************************************************
* Copyright (C) 2014 by Eike Hein <hein@kde.org> *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA . *
***************************************************************************/
import QtQuick 2.0
import org.kde.plasma.configuration 2.0
ConfigModel {
ConfigCategory {
name: i18n("General")
icon: "preferences-desktop-plasma-theme"
source: "ConfigGeneral.qml"
}
ConfigCategory {
name: i18n("Side panel")
icon: "menu_new"
source: "ConfigSidepanel.qml"
}
}

View file

@ -0,0 +1,128 @@
<?xml version="1.0" encoding="UTF-8"?>
<kcfg xmlns="http://www.kde.org/standards/kcfg/1.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.kde.org/standards/kcfg/1.0
http://www.kde.org/standards/kcfg/1.0/kcfg.xsd" >
<kcfgfile name=""/>
<group name="General">
<entry name="icon" type="String">
<default>start-here-kde</default>
</entry>
<entry name="useCustomButtonImage" type="Bool">
<default>true</default>
</entry>
<entry name="stickOutOrb" type="Bool">
<default>false</default>
</entry>
<entry name="customButtonImage" type="Url">
<default></default>
</entry>
<entry name="customButtonImageHover" type="Url">
<default></default>
</entry>
<entry name="customButtonImageActive" type="Url">
<default></default>
</entry>
<entry name="showFilterList" type="Bool">
<default>true</default>
</entry>
<entry name="appNameFormat" type="Int">
<default>0</default>
</entry>
<entry name="limitDepth" type="Bool">
<default>false</default>
</entry>
<entry name="numberColumns" type="Int">
<default>1</default>
</entry>
<entry name="numberRows" type="Int">
<default>12</default>
</entry>
<entry name="favoriteApps" type="StringList">
<default></default>
</entry>
<entry name="favoriteSystemActions" type="StringList">
<default>logout,lock-screen,reboot,shutdown</default>
</entry>
<entry name="hiddenApplications" type="StringList">
<default></default>
</entry>
<entry name="useExtraRunners" type="Bool">
<default>true</default>
</entry>
<entry name="extraRunners" type="StringList">
<label>The plugin id's of additional KRunner plugins to use. Only used if useExtraRunners is true.</label>
<default>shell,bookmarks,baloosearch,locations</default>
</entry>
<entry name="alignResultsToBottom" type="Bool">
<default>true</default>
</entry>
<entry name="switchCategoriesOnHover" type="Bool">
<label>Whether to switch between menu categories by hovering them.</label>
<default>true</default>
</entry>
<entry name="removeApplicationCommand" type="String">
<default>muon-discover --application</default>
</entry>
<entry name="favoritesPortedToKAstats" type="Bool">
<label>Are the favorites ported to use KActivitiesStats to allow per-activity favorites</label>
<default>false</default>
</entry>
<entry name="showRecentsView" type="Bool">
<default>true</default>
</entry>
<entry name="showHomeSidepanel" type="Bool">
<default>true</default>
</entry>
<entry name="showDocumentsSidepanel" type="Bool">
<default>true</default>
</entry>
<entry name="showPicturesSidepanel" type="Bool">
<default>true</default>
</entry>
<entry name="showMusicSidepanel" type="Bool">
<default>true</default>
</entry>
<entry name="showVideosSidepanel" type="Bool">
<default>true</default>
</entry>
<entry name="showDownloadsSidepanel" type="Bool">
<default>true</default>
</entry>
<entry name="showRootSidepanel" type="Bool">
<default>true</default>
</entry>
<entry name="showGamesSidepanel" type="Bool">
<default>false</default>
</entry>
<entry name="showRecentItemsSidepanel" type="Bool">
<default>false</default>
</entry>
<entry name="showNetworkSidepanel" type="Bool">
<default>false</default>
</entry>
<entry name="showSettingsSidepanel" type="Bool">
<default>true</default>
</entry>
<entry name="showDevicesSidepanel" type="Bool">
<default>false</default>
</entry>
<entry name="showDefaultsSidepanel" type="Bool">
<default>false</default>
</entry>
<entry name="showHelpSidepanel" type="Bool">
<default>false</default>
</entry>
</group>
</kcfg>

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 37 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

File diff suppressed because it is too large Load diff

After

Width:  |  Height:  |  Size: 115 KiB

View file

@ -0,0 +1,46 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
version="1.1"
viewBox="0 0 32 32"
id="svg7"
sodipodi:docname="system-lock-screen.svg"
inkscape:version="1.1 (c4e8f9ed74, 2021-05-24)"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg">
<sodipodi:namedview
id="namedview9"
pagecolor="#505050"
bordercolor="#ffffff"
borderopacity="1"
inkscape:pageshadow="0"
inkscape:pageopacity="0"
inkscape:pagecheckerboard="1"
showgrid="false"
inkscape:zoom="20.125"
inkscape:cx="15.975155"
inkscape:cy="15.975155"
inkscape:window-width="1600"
inkscape:window-height="832"
inkscape:window-x="0"
inkscape:window-y="0"
inkscape:window-maximized="1"
inkscape:current-layer="svg7" />
<defs
id="defs3">
<style
type="text/css"
id="current-color-scheme">
.ColorScheme-Text {
color:#eff0f1;
}
</style>
</defs>
<path
class="ColorScheme-Text"
d="m 16,8 c -2.216,0 -4,1.784 -4,4 v 4 h -2 v 8 H 22 V 16 H 20 V 12 C 20,9.784 18.216,8 16,8 Z m 0,1 c 1.662,0 3,1.561 3,3.5 V 16 H 13 V 12.5 C 13,10.561 14.338,9 16,9 Z"
fill="currentColor"
id="path5"
sodipodi:nodetypes="ssccccccssssccss" />
</svg>

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

View file

@ -0,0 +1,107 @@
/*
SPDX-FileCopyrightText: 2013 Aurélien Gâteau <agateau@kde.org>
SPDX-FileCopyrightText: 2014-2015 Eike Hein <hein@kde.org>
SPDX-License-Identifier: GPL-2.0-or-later
*/
import QtQuick 2.15
import org.kde.plasma.extras 2.0 as PlasmaExtras
Item {
id: root
property variant actionList
property QtObject menu
property bool opened: menu ? (menu.status !== PlasmaExtras.Menu.Closed) : false
property Item visualParent
signal actionClicked(string actionId, variant actionArgument)
signal closed
function fillMenu(menu, items) {
items.forEach(function (actionItem) {
if (actionItem.subActions) {
// This is a menu
var submenuItem = contextSubmenuItemComponent.createObject(menu, {
"actionItem": actionItem
});
fillMenu(submenuItem.submenu, actionItem.subActions);
} else {
var item = contextMenuItemComponent.createObject(menu, {
"actionItem": actionItem
});
}
});
}
function open(x, y) {
if (!actionList) {
return;
}
if (x && y) {
menu.open(x, y);
} else {
menu.open();
}
}
function refreshMenu() {
if (menu) {
menu.destroy();
}
if (!actionList) {
return;
}
menu = contextMenuComponent.createObject(root);
fillMenu(menu, actionList);
}
onActionListChanged: refreshMenu()
onOpenedChanged: {
if (!opened) {
closed();
}
}
Component {
id: contextMenuComponent
PlasmaExtras.Menu {
visualParent: root.visualParent
}
}
Component {
id: contextSubmenuItemComponent
PlasmaExtras.MenuItem {
id: submenuItem
property variant actionItem
property PlasmaExtras.Menu submenu: PlasmaExtras.Menu {
visualParent: submenuItem.action
}
icon: actionItem.icon ? actionItem.icon : null
text: actionItem.text ? actionItem.text : ""
}
}
Component {
id: contextMenuItemComponent
PlasmaExtras.MenuItem {
property variant actionItem
checkable: actionItem.checkable ? actionItem.checkable : false
checked: actionItem.checked ? actionItem.checked : false
enabled: actionItem.type !== "title" && ("enabled" in actionItem ? actionItem.enabled : true)
icon: actionItem.icon ? actionItem.icon : null
section: actionItem.type === "title"
separator: actionItem.type === "separator"
text: actionItem.text ? actionItem.text : ""
onClicked: {
root.actionClicked(actionItem.actionId, actionItem.actionArgument);
}
}
}
}

View file

@ -0,0 +1,350 @@
/*
Copyright (C) 2011 Martin Gräßlin <mgraesslin@kde.org>
Copyright (C) 2012 Gregor Taetzner <gregor@freenet.de>
Copyright 2014 Sebastian Kügler <sebas@kde.org>
Copyright (C) 2015-2018 Eike Hein <hein@kde.org>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
import org.kde.plasma.plasmoid
import QtQuick 2.0
import org.kde.plasma.core 2.0 as PlasmaCore
import org.kde.plasma.extras 2.0 as PlasmaExtras
import org.kde.plasma.components as PlasmaComponents
import org.kde.kirigami as Kirigami
Item {
id: appViewContainer
objectName: "ApplicationsView"
property ListView listView: applicationsView.listView
property alias currentIndex: applicationsView.currentIndex
property alias count: applicationsView.count
function decrementCurrentIndex() {
var tempIndex = applicationsView.currentIndex-1;
if(tempIndex < (crumbModel.count == 0 ? 1 : 0)) {
//applicationsView.currentIndex = applicationsView.count-1;
return;
}
applicationsView.decrementCurrentIndex();
}
function incrementCurrentIndex() {
var tempIndex = applicationsView.currentIndex+1;
if(tempIndex >= applicationsView.count) {
applicationsView.currentIndex = -1;
root.m_showAllButton.focus = true;
return;
}
applicationsView.incrementCurrentIndex();
}
function activateCurrentIndex(start) {
if (!applicationsView.currentItem.modelChildren) {
if (!start) {
return;
}
}
applicationsView.state = "OutgoingLeft";
}
function openContextMenu() {
applicationsView.currentItem.openActionMenu();
}
function deactivateCurrentIndex() {
if (crumbModel.count > 0) { // this is not the case when switching from the "Applications" to the "Favorites" tab using the "Left" key
breadcrumbsElement.children[crumbModel.count-1].clickCrumb();
applicationsView.state = "OutgoingRight";
return true;
}
return false;
}
onFocusChanged: {
if(focus)
applicationsView.currentIndex = crumbModel.count == 0 ? 1 : 0;
else applicationsView.currentIndex = -1;
}
Keys.onPressed: {
if(event.key == Qt.Key_Up) {
decrementCurrentIndex();
} else if(event.key == Qt.Key_Down) {
incrementCurrentIndex();
} else if(event.key == Qt.Key_Return || event.key == Qt.Key_Right) {
activateCurrentIndex(applicationsView.currentIndex);
} else if(event.key == Qt.Key_Menu) {
openContextMenu();
} else if(event.key == Qt.Key_Left || event.key == Qt.Key_Backspace) {
deactivateCurrentIndex();
}
}
KeyNavigation.tab: root.m_showAllButton
function reset() {
applicationsView.model = rootModel;
applicationsView.clearBreadcrumbs();
//root.resetRecents();
}
function refreshed() {
reset();
updatedLabelTimer.running = true;
}
Connections {
target: kicker
function onExpandedChanged() {
if (!plasmoid.expanded) {
reset();
}
}
}
Item {
id: crumbContainer
anchors {
top: parent.top
left: parent.left
right: parent.right
}
height: childrenRect.height
visible: false
opacity: crumbModel.count > 0
Behavior on opacity { NumberAnimation { duration: Kirigami.Units.longDuration } }
Flickable {
id: breadcrumbFlickable
anchors {
top: parent.top
left: parent.left
right: parent.right
}
height: breadcrumbsElement.height
boundsBehavior: Flickable.StopAtBounds
contentWidth: breadcrumbsElement.width
pixelAligned: true
//contentX: contentWidth - width
// HACK: Align the content to right for RTL locales
leftMargin: LayoutMirroring.enabled ? Math.max(0, width - contentWidth) : 0
ButtonRow {
id: breadcrumbsElement
exclusive: false
Breadcrumb {
id: rootBreadcrumb
root: true
text: i18n("Back")
depth: 0
}
Repeater {
model: ListModel {
id: crumbModel
// Array of the models
property var models: []
}
Breadcrumb {
root: false
text: model.text
visible: false
}
}
onWidthChanged: {
if (LayoutMirroring.enabled) {
breadcrumbFlickable.contentX = -Math.max(0, breadcrumbsElement.width - breadcrumbFlickable.width)
} else {
breadcrumbFlickable.contentX = Math.max(0, breadcrumbsElement.width - breadcrumbFlickable.width)
}
}
}
}
Rectangle {
id: sepLine
anchors {
top: breadcrumbFlickable.bottom
topMargin: -1
left: breadcrumbFlickable.left
leftMargin: Kirigami.Units.smallSpacing*2
right: breadcrumbFlickable.right
rightMargin: Kirigami.Units.smallSpacing*2
}
height: 1
color: "#d6e5f5"
opacity: 1
z: 6
}
} // crumbContainer
KickoffListView {
id: applicationsView
anchors {
top: (crumbContainer.visible && crumbContainer.opacity) ? crumbContainer.bottom : parent.top
topMargin: Kirigami.Units.smallSpacing/ (crumbContainer.visible ? 2 : 1) + 1
bottom: parent.bottom
rightMargin: -Kirigami.Units.gridUnit
leftMargin: -Kirigami.Units.gridUnit
}
width: parent.width
small: true
property Item activatedItem: null
property var newModel: null
Behavior on opacity { NumberAnimation { duration: Kirigami.Units.longDuration } }
focus: true
appView: true
model: rootModel
function moveLeft() {
state = "";
// newModelIndex set by clicked breadcrumb
var oldModel = applicationsView.model;
applicationsView.model = applicationsView.newModel;
var oldModelIndex = model.rowForModel(oldModel);
listView.currentIndex = oldModelIndex;
listView.positionViewAtIndex(oldModelIndex, ListView.Center);
crumbContainer.visible = false;
}
function moveRight() {
state = "";
activatedItem.activate();
applicationsView.listView.positionViewAtBeginning();
crumbContainer.visible = true;
//root.visible = false;
}
function clearBreadcrumbs() {
crumbModel.clear();
crumbModel.models = [];
applicationsView.listView.currentIndex = -1;
}
onReset: appViewContainer.reset()
onAddBreadcrumb: {
crumbModel.append({"text": title, "depth": crumbModel.count+1})
crumbModel.models.push(model);
}
states: [
State {
name: "OutgoingLeft"
PropertyChanges {
target: applicationsView
x: -parent.width
opacity: 0.0
}
},
State {
name: "OutgoingRight"
PropertyChanges {
target: applicationsView
x: parent.width
opacity: 0.0
}
}
]
transitions: [
Transition {
to: "OutgoingLeft"
SequentialAnimation {
// We need to cache the currentItem since the selection can move during animation,
// and we want the item that has been clicked on, not the one that is under the
// mouse once the animation is done
ScriptAction { script: applicationsView.activatedItem = applicationsView.currentItem }
NumberAnimation { properties: "opacity"; easing.type: Easing.InQuad; duration: 100 }
ScriptAction { script: { applicationsView.moveRight(); } }
}
},
Transition {
to: "OutgoingRight"
SequentialAnimation {
NumberAnimation { properties: "opacity"; easing.type: Easing.InQuad; duration: 100 }
ScriptAction { script: applicationsView.moveLeft() }
}
}
]
Component.onCompleted: {
applicationsView.listView.currentIndex = -1;
}
}
MouseArea {
anchors.fill: parent
acceptedButtons: Qt.BackButton
onClicked: {
deactivateCurrentIndex()
}
}
Timer {
id: updatedLabelTimer
interval: 1500
running: false
repeat: true
onRunningChanged: {
if (running) {
updatedLabel.opacity = 1;
crumbContainer.opacity = 0.3;
applicationsView.scrollArea.opacity = 0.3;
}
}
onTriggered: {
updatedLabel.opacity = 0;
crumbContainer.opacity = 1;
applicationsView.scrollArea.opacity = 1;
running = false;
}
}
PlasmaComponents.Label {
id: updatedLabel
text: i18n("Applications updated.")
opacity: 0
visible: opacity != 0
anchors.centerIn: parent
Behavior on opacity { NumberAnimation { duration: Kirigami.Units.shortDuration } }
}
Component.onCompleted: {
rootModel.cleared.connect(refreshed);
}
} // appViewContainer

View file

@ -0,0 +1,96 @@
/*
Copyright (C) 2011 Martin Gräßlin <mgraesslin@kde.org>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
import QtQuick 2.0
import org.kde.plasma.core 2.0 as PlasmaCore
import org.kde.plasma.components 3.0 as PlasmaComponents
import org.kde.plasma.extras 2.0 as PlasmaExtras
import org.kde.ksvg as KSvg
import org.kde.kirigami as Kirigami
//import QtQuick.Controls.Styles.Plasma as Styles
Item {
id: crumbRoot
height: crumb.implicitHeight + Kirigami.Units.smallSpacing * 2
width: crumb.implicitWidth + arrowSvg.width
property string text
property bool root: false
property int depth: model.depth
function clickCrumb() {
heading_ma.clicked(null);
}
PlasmaExtras.Heading {
id: crumb
anchors {
left: arrowSvg.right
top: parent.top
bottom: parent.bottom
topMargin: Kirigami.Units.smallSpacing
leftMargin: Kirigami.Units.smallSpacing
bottomMargin: Kirigami.Units.smallSpacing
}
horizontalAlignment: Text.AlignHCenter
text: crumbRoot.text + ""
color: "#404040"
font.underline: heading_ma.enabled && heading_ma.containsMouse
level: 5
MouseArea {
id: heading_ma
anchors.fill: parent
hoverEnabled: crumbRoot.depth < crumbModel.count
enabled: crumbRoot.depth < crumbModel.count
onClicked: {
// Remove all the breadcrumbs in front of the clicked one
while (crumbModel.count > 0 && crumbRoot.depth < crumbModel.get(crumbModel.count-1).depth) {
crumbModel.remove(crumbModel.count-1)
crumbModel.models.pop()
}
if (crumbRoot.root) {
applicationsView.newModel = rootModel;
} else {
applicationsView.newModel = crumbModel.models[index];
}
applicationsView.state = "OutgoingRight";
}
cursorShape: Qt.PointingHandCursor
z: 99
}
}
KSvg.SvgItem{
id: arrowSvg
anchors.left: parent.left
anchors.leftMargin: Kirigami.Units.smallSpacing*2
anchors.verticalCenter: parent.verticalCenter
height: crumbRoot.height / 2
width: visible ? height : 0
svg: arrowsSvg
elementId: LayoutMirroring.enabled ? "right-arrow" : "left-arrow"
}
} // crumbRoot

View file

@ -0,0 +1,149 @@
/*
SPDX-FileCopyrightText: 2011 Nokia Corporation and /or its subsidiary(-ies) <qt-info@nokia.com>
This file is part of the Qt Components project.
SPDX-License-Identifier: LGPL-2.1-only WITH Qt-LGPL-exception-1.1 OR GPL-3.0-only OR LicenseRef-Qt-Commercial
*/
var self;
var checkHandlers = [];
var visibleButtons = [];
var nonVisibleButtons = [];
var direction;
function create(that, options) {
self = that;
direction = options.direction || Qt.Horizontal;
self.childrenChanged.connect(rebuild);
self.exclusiveChanged.connect(rebuild);
// self.widthChanged.connect(resizeChildren);
build();
}
function isButton(item) {
if (item && item.hasOwnProperty("__position"))
return true;
return false;
}
function hasChecked(item) {
return (item && item.hasOwnProperty("checked"));
}
function destroy() {
self.childrenChanged.disconnect(rebuild);
// self.widthChanged.disconnect(resizeChildren);
cleanup();
}
function build() {
visibleButtons = [];
nonVisibleButtons = [];
for (var i = 0, item; (item = self.children[i]); i++) {
if (!hasChecked(item))
continue;
item.visibleChanged.connect(rebuild); // Not optimal, but hardly a bottleneck in your app
if (!item.visible) {
nonVisibleButtons.push(item);
continue;
}
visibleButtons.push(item);
if (self.exclusive && item.hasOwnProperty("checkable"))
item.checkable = true;
if (self.exclusive) {
checkHandlers.push(checkExclusive(item));
item.checkedChanged.connect(checkHandlers[checkHandlers.length - 1]);
}
if (item.checked) {
checkExclusive(item)()
if (item.checked) self.checkedButton = item
}
}
var nrButtons = visibleButtons.length;
if (nrButtons == 0)
return;
if (self.checkedButton)
self.checkedButton.checked = true;
else if (self.exclusive) {
self.checkedButton = visibleButtons[0];
self.checkedButton.checked = true;
}
if (nrButtons == 1) {
finishButton(visibleButtons[0], "only");
} else {
finishButton(visibleButtons[0], direction == Qt.Horizontal ? "leftmost" : "top");
for (var i = 1; i < nrButtons - 1; i++)
finishButton(visibleButtons[i], direction == Qt.Horizontal ? "h_middle": "v_middle");
finishButton(visibleButtons[nrButtons - 1], direction == Qt.Horizontal ? "rightmost" : "bottom");
}
}
function finishButton(button, position) {
if (isButton(button)) {
button.__position = position;
if (direction == Qt.Vertical) {
button.anchors.left = self.left //mm How to make this not cause binding loops? see QTBUG-17162
button.anchors.right = self.right
}
}
}
function cleanup() {
visibleButtons.forEach(function(item, i) {
if (checkHandlers[i])
item.checkedChanged.disconnect(checkHandlers[i]);
item.visibleChanged.disconnect(rebuild);
});
checkHandlers = [];
nonVisibleButtons.forEach(function(item, i) {
item.visibleChanged.disconnect(rebuild);
});
}
function rebuild() {
if (self == undefined)
return;
cleanup();
build();
}
function resizeChildren() {
if (direction != Qt.Horizontal)
return;
var extraPixels = self.width % visibleButtons;
var buttonSize = (self.width - extraPixels) / visibleButtons;
visibleButtons.forEach(function(item, i) {
if (!item || !item.visible)
return;
item.width = buttonSize + (extraPixels > 0 ? 1 : 0);
if (extraPixels > 0)
extraPixels--;
});
}
function checkExclusive(item) {
var button = item;
return function() {
for (var i = 0, ref; (ref = visibleButtons[i]); i++) {
if (ref.checked == (button === ref))
continue;
// Disconnect the signal to avoid recursive calls
ref.checkedChanged.disconnect(checkHandlers[i]);
ref.checked = !ref.checked;
ref.checkedChanged.connect(checkHandlers[i]);
}
self.checkedButton = button;
}
}

View file

@ -0,0 +1,57 @@
/*
SPDX-FileCopyrightText: 2011 Nokia Corporation and /or its subsidiary(-ies) <qt-info@nokia.com>
This file is part of the Qt Components project.
SPDX-License-Identifier: LGPL-2.1-only WITH Qt-LGPL-exception-1.1 OR GPL-3.0-only OR LicenseRef-Qt-Commercial
*/
import QtQuick 2.1
import org.kde.plasma.core 2.0 as PlasmaCore
import "ButtonGroup.js" as Behavior
/**
* A ButtonRow allows you to group Buttons in a row. It provides a
* selection-behavior as well.
*
* Note: This component does not support the enabled property. If you need to
* disable it you should disable all the buttons inside it.
*
* Example code:
*
* @code
* ButtonRow {
* Button { text: "Left" }
* Button { text: "Right" }
* }
* @endcode
*
* @inherit QtQuick.Row
*/
Row {
id: root
/**
* Specifies the grouping behavior. If enabled, the checked property on
* buttons contained in the group will be exclusive.The default value is true.
*
* Note that a button in an exclusive group will always be checkable
*/
property bool exclusive: true
/**
* Returns the last checked button
*/
property Item checkedButton;
spacing: PlasmaCore.Theme.defaultFont.pointSize
Component.onCompleted: {
Behavior.create(root, {direction: Qt.Horizontal});
}
Component.onDestruction: {
Behavior.destroy();
}
}

View file

@ -0,0 +1,284 @@
/***************************************************************************
* Copyright (C) 2013-2014 by Eike Hein <hein@kde.org> *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA . *
***************************************************************************/
import QtQuick 2.0
import QtQuick.Layouts 1.1
import org.kde.plasma.plasmoid 2.0
import org.kde.plasma.core 2.0 as PlasmaCore
import org.kde.kwindowsystem 1.0
import org.kde.kirigami as Kirigami
Item {
id: root
Layout.minimumHeight: floatingOrbPanel.buttonIconSizes.height;
Layout.maximumHeight: floatingOrbPanel.buttonIconSizes.height;
Layout.minimumWidth: floatingOrbPanel.buttonIconSizes.width;
Layout.maximumWidth: floatingOrbPanel.buttonIconSizes.width;
property bool compositing: false
/*
* The following code gets the ContainmentInterface instance which is used for keeping track of edit mode's state.
* This allows us to hide the StartOrb object so the user can actually highlight and select this plasmoid during edit mode.
*/
//property var containmentInterface: null
property QtObject contextMenu: null
property QtObject dashWindow: null
readonly property bool editMode: Plasmoid.containment.corona.editMode //containmentInterface ? containmentInterface.editMode : false
readonly property bool inPanel: (Plasmoid.location == PlasmaCore.Types.TopEdge || Plasmoid.location == PlasmaCore.Types.RightEdge || Plasmoid.location == PlasmaCore.Types.BottomEdge || Plasmoid.location == PlasmaCore.Types.LeftEdge)
property bool menuShown: dashWindow.visible
property QtObject orb: null
property alias orbTimer: orbTimer
readonly property var screenGeometry: Plasmoid.screenGeometry
// Should the orb be rendered in its own dialog window so that it can stick out of the panel?
readonly property bool stickOutOrb: Plasmoid.configuration.stickOutOrb && inPanel && !editMode
readonly property bool useCustomButtonImage: (Plasmoid.configuration.useCustomButtonImage)
readonly property bool vertical: (Plasmoid.formFactor == PlasmaCore.Types.Vertical)
//property int opacityDuration: 350
/*function createContextMenu(pos) {
contextMenu = Qt.createQmlObject("ContextMenu {}", root);
contextMenu.fillActions();
contextMenu.show();
}*/
// If the url is empty (default value), then use the fallback url. Otherwise, return the url path relative to
// the location of the source code.
function getResolvedUrl(url, fallback) {
if (url.toString() === "") {
return Qt.resolvedUrl(fallback);
}
return url;
}
function positionOrb() {
var pos = kicker.mapToGlobal(floatingOrbPanel.x, floatingOrbPanel.y);
pos.y -= 5;
//if(floatingOrbPanel.buttonIcon.implicitHeight === 54) // Using an orb with extra height around it
//var pos = kicker.mapToGlobal(kicker.x, kicker.y); // Gets the global position of this plasmoid, in screen coordinates.
orb.width = floatingOrbPanel.buttonIcon.implicitWidth// + panelSvg.margins.left;
orb.height = floatingOrbPanel.buttonIcon.implicitHeight;
orb.x = pos.x;
orb.y = pos.y;// + panelSvg.margins.bottom;
// Keep the orb positioned exactly on the bottom if it is rendered out of bounds (beyond the screen geometry)
/*if (orb.y + orb.height > kicker.screenGeometry.height) {
orb.y = kicker.screenGeometry.height - orb.height; //orb.y + orb.height - kicker.screenGeometry.height;
}*/
}
function showMenu() {
dashWindow.visible = !dashWindow.visible;
dashWindow.showingAllPrograms = false;
Plasmoid.setActiveWin(dashWindow);
console.log(floatingOrbPanel.buttonIcon.implicitHeight);
dashWindow.m_searchField.focus = true;
orb.raise();
}
function updateSizeHints() {
return;
if (useCustomButtonImage) {
if (vertical) {
var scaledHeight = Math.floor(parent.width * (floatingOrbPanel.buttonIcon.height / floatingOrbPanel.buttonIcon.width));
root.Layout.minimumHeight = scaledHeight;
root.Layout.maximumHeight = scaledHeight;
root.Layout.minimumWidth = Kirigami.Units.iconSizes.small;
root.Layout.maximumWidth = inPanel ? Kirigami.Units.iconSizes.medium : -1;
} else {
var scaledWidth = Math.floor(parent.height * (floatingOrbPanel.buttonIcon.width / floatingOrbPanel.buttonIcon.height));
root.Layout.minimumWidth = scaledWidth;
root.Layout.maximumWidth = scaledWidth;
root.Layout.minimumHeight = Kirigami.Units.iconSizes.small;
root.Layout.maximumHeight = inPanel ? Kirigami.Units.iconSizes.medium : -1;
}
} else {
root.Layout.minimumWidth = Kirigami.Units.iconSizes.small;
root.Layout.maximumWidth = inPanel ? Kirigami.Units.iconSizes.medium : -1;
root.Layout.minimumHeight = Kirigami.Units.iconSizes.small;
root.Layout.maximumHeight = inPanel ? Kirigami.Units.iconSizes.medium : -1;
}
if (stickOutOrb && orb) {
root.Layout.minimumWidth = orb.width + panelSvg.margins.right * (compositing ? 0 : 1);
root.Layout.maximumWidth = orb.width + panelSvg.margins.right * (compositing ? 0 : 1);
root.Layout.minimumHeight = orb.height;
root.Layout.maximumHeight = orb.height;
}
// This has to be done, or else the orb won't be positioned correctly. ??????????
/*orb.y += 5;
orb.y -= 5; // ??????????????????????????????????????*/
}
//kicker.status: PlasmaCore.Types.PassiveStatus
Plasmoid.status: dashWindow && dashWindow.visible ? PlasmaCore.Types.RequiresAttentionStatus : PlasmaCore.Types.PassiveStatus
//clip: true
Component.onCompleted: {
dashWindow = Qt.createQmlObject("MenuRepresentation {}", kicker);
orb = Qt.createQmlObject("StartOrb {}", kicker);
//Plasmoid.fullRepresentation = dashWindow
Plasmoid.activated.connect(function () {
showMenu();
});
}
onCompositingChanged: {
updateSizeHints();
positionOrb();
/*if (compositing) {
orb.x += panelSvg.margins.left;
}*/
compositingFix.start();
}
onHeightChanged: updateSizeHints()
onParentChanged: {
/*if (parent) {
for (var obj = root, depth = 0; !!obj; obj = obj.parent, depth++) {
if (obj.toString().startsWith('ContainmentInterface')) {
// desktop containment / plasmoidviewer
// Note: This doesn't always work. FolderViewDropArea may not yet have
// ContainmentInterface as a parent when this loop runs.
if (typeof obj['editMode'] === 'boolean') {
root.containmentInterface = obj;
break;
}
} else if (obj.toString().startsWith('DeclarativeDropArea')) {
// panel containment
if (typeof obj['Plasmoid'] !== 'undefined' && obj['Plasmoid'].toString().startsWith('ContainmentInterface')) {
if (typeof obj['Plasmoid']['editMode'] === 'boolean') {
root.containmentInterface = obj.Plasmoid;
break;
}
}
}
}
}*/
}
onStickOutOrbChanged: {
updateSizeHints();
positionOrb();
}
onWidthChanged: updateSizeHints()
/*Connections {
target: Kirigami.Units.iconSizeHints
function onPanelChanged() { updateSizeHints(); }
}*/
Connections {
target: Plasmoid.configuration
function onCustomButtonImageChanged() {
positionOrb();
console.log("AAAA")
}
}
Connections {
function onScreenChanged() {
positionOrb();
}
function onScreenGeometryChanged() {
positionOrb();
}
target: kicker
}
/*
* Three IconItems are used in order to achieve the same look and feel as Windows 7's
* orbs. When the menu is closed, hovering over the orb results in the hovered icon
* gradually appearing into view, and clicking on the orb causes an instant change in
* visibility, where the normal and hovered icons are invisible, and the pressed icon
* is visible.
*
* When they're bounded by the panel, these icons will by default try to fill up as
* much space as they can in the compact representation while preserving their aspect
* ratio.
*/
FloatingOrb {
id: floatingOrbPanel
anchors.left: parent.left
//anchors.leftMargin: -Kirigami.Units.mediumSpacing
anchors.verticalCenter: parent.verticalCenter
//anchors.verticalCenterOffset: Kirigami.Units.smallSpacing-1
//anchors.fill: parent
objectName: "innerorb"
opacity: (!stickOutOrb)
}
// Handles all mouse events for the popup orb
MouseArea {
id: mouseAreaCompositingOff
acceptedButtons: Qt.LeftButton | Qt.RightButton
anchors.fill: parent
hoverEnabled: true
//visible: !stickOutOrb
propagateComposedEvents: true
onPressed: mouse => {
if(mouse.button === Qt.LeftButton)
showMenu();
else
mouse.accepted = false;
}
}
// I hate this
// So the only way I could reasonably think of to make this work is running the function
// with a delay.
Timer {
id: compositingFix
interval: 150
onTriggered: {
if (!compositing) {
Plasmoid.setTransparentWindow();
}
}
}
// Even worse, this just makes things even more unsophisticated. If someone has a better
// way of solving this, I would love to know.
Timer {
id: orbTimer
interval: 15
onTriggered: {
Plasmoid.setOrb(orb);
// Currently hardcoded, will make it configurable soon, when it's been properly tested and hopefully slightly refactored.
Plasmoid.setMask(Qt.resolvedUrl("./orbs/mask.png"), false);
Plasmoid.setWinState(orb);
Plasmoid.setWinType(orb);
Plasmoid.setDashWindow(dashWindow);
updateSizeHints();
positionOrb();
}
}
}

View file

@ -0,0 +1,180 @@
/***************************************************************************
* Copyright (C) 2014 by Eike Hein <hein@kde.org> *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA . *
***************************************************************************/
import QtQuick 2.15
import QtQuick.Controls 2.15
import QtQuick.Dialogs
import QtQuick.Layouts
import org.kde.plasma.core 2.0 as PlasmaCore
import org.kde.plasma.components 3.0 as PlasmaComponents
import org.kde.kcmutils as KCM
import org.kde.draganddrop 2.0 as DragDrop
import org.kde.kirigami 2.3 as Kirigami
import org.kde.plasma.plasmoid 2.0
import org.kde.iconthemes as KIconThemes
import org.kde.plasma.private.kicker 0.1 as Kicker
KCM.SimpleKCM {
id: configGeneral
width: childrenRect.width
height: childrenRect.height
property string cfg_icon: Plasmoid.configuration.icon
property bool cfg_useCustomButtonImage: Plasmoid.configuration.useCustomButtonImage
property string cfg_customButtonImage: Plasmoid.configuration.customButtonImage
property string cfg_customButtonImageHover: Plasmoid.configuration.customButtonImageHover
property string cfg_customButtonImageActive: Plasmoid.configuration.customButtonImageActive
property alias cfg_showRecentsView: showRecentsView.checked
property alias cfg_appNameFormat: appNameFormat.currentIndex
property alias cfg_switchCategoriesOnHover: switchCategoriesOnHover.checked
property alias cfg_stickOutOrb: stickOutOrb.checked
property alias cfg_useExtraRunners: useExtraRunners.checked
property alias cfg_numberRows: numberRows.value
component CustomGroupBox: GroupBox {
id: gbox
label: Label {
id: lbl
x: gbox.leftPadding + 2
y: lbl.implicitHeight/2-gbox.bottomPadding-1
width: lbl.implicitWidth
text: gbox.title
elide: Text.ElideRight
Rectangle {
anchors.fill: parent
anchors.leftMargin: -2
anchors.rightMargin: -2
color: Kirigami.Theme.backgroundColor
z: -1
}
}
background: Rectangle {
y: gbox.topPadding - gbox.bottomPadding*2
width: parent.width
height: parent.height - gbox.topPadding + gbox.bottomPadding*2
color: "transparent"
border.color: "#d5dfe5"
radius: 3
}
}
ColumnLayout {
anchors.left: parent.left
anchors.right: parent.right
anchors.leftMargin: Kirigami.Units.gridUnit*4
anchors.rightMargin: Kirigami.Units.gridUnit*4
CustomGroupBox {
id: orbGroup
title: i18n("Orb texture")
Layout.fillWidth: true
IconPicker {
id: iconPickerNormal
currentIcon: cfg_customButtonImage
defaultIcon: ""
onIconChanged: iconName => { cfg_customButtonImage = iconName; }
anchors.right: parent.right
anchors.left: parent.left
}
}
CustomGroupBox {
Layout.fillWidth: true
title: i18n("Behavior")
//flat: false
ColumnLayout {
RowLayout {
visible: false
Label {
text: i18n("Show applications as:")
}
ComboBox {
id: appNameFormat
Layout.fillWidth: true
model: [i18n("Name only"), i18n("Description only"), i18n("Name (Description)"), i18n("Description (Name)")]
}
}
CheckBox {
id: switchCategoriesOnHover
visible: false
text: i18n("Switch categories on hover")
}
CheckBox {
id: useExtraRunners
visible: false
text: i18n("Expand search to bookmarks, files and emails")
}
CheckBox {
id: stickOutOrb
text: i18n("Force constant orb size")
}
CheckBox {
id: showRecentsView
text: i18n("Show recent programs")
}
RowLayout{
Layout.fillWidth: true
Label {
Layout.leftMargin: Kirigami.Units.smallSpacing
text: i18n("Number of rows:")
}
SpinBox{
id: numberRows
from: 10
to: 15
}
}
}
}
}
Component.onCompleted: {
if(Plasmoid.configuration.stickOutOrb) Plasmoid.setTransparentWindow();
}
Component.onDestruction: {
if(Plasmoid.configuration.stickOutOrb) Plasmoid.setTransparentWindow();
}
}

View file

@ -0,0 +1,141 @@
/***************************************************************************
* Copyright (C) 2014 by Eike Hein <hein@kde.org> *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA . *
***************************************************************************/
import QtQuick 2.15
import QtQuick.Controls 2.15
import QtQuick.Layouts
import org.kde.kcmutils as KCM
import org.kde.plasma.plasmoid 2.0
import org.kde.kirigami 2.3 as Kirigami
KCM.SimpleKCM {
id: configSidepanel
width: childrenRect.width
height: childrenRect.height
property alias cfg_showHomeSidepanel: showHomeSidepanel.checked
property alias cfg_showDocumentsSidepanel: showDocumentsSidepanel.checked
property alias cfg_showPicturesSidepanel: showPicturesSidepanel.checked
property alias cfg_showMusicSidepanel: showMusicSidepanel.checked
property alias cfg_showVideosSidepanel: showVideosSidepanel.checked
property alias cfg_showDownloadsSidepanel: showDownloadsSidepanel.checked
property alias cfg_showGamesSidepanel: showGamesSidepanel.checked
property alias cfg_showRecentItemsSidepanel: showRecentItemsSidepanel.checked
property alias cfg_showRootSidepanel: showRootSidepanel.checked
property alias cfg_showNetworkSidepanel: showNetworkSidepanel.checked
property alias cfg_showSettingsSidepanel: showSettingsSidepanel.checked
property alias cfg_showDevicesSidepanel: showDevicesSidepanel.checked
property alias cfg_showDefaultsSidepanel: showDefaultsSidepanel.checked
property alias cfg_showHelpSidepanel: showHelpSidepanel.checked
ColumnLayout {
anchors.left: parent.left
anchors.right: parent.right
anchors.leftMargin: Kirigami.Units.gridUnit*4
anchors.rightMargin: Kirigami.Units.gridUnit*4
GroupBox {
id: gbox
Layout.fillWidth: true
background: Rectangle {
color: "white"
border.color: "#bababe"
y: gbox.topPadding - gbox.bottomPadding
height: parent.height - gbox.topPadding + gbox.bottomPadding
}
label: Label {
x: gbox.leftPadding
width: gbox.availableWidth
text: gbox.title
elide: Text.ElideRight
}
title: i18n("Show sidebar items")
ColumnLayout {
CheckBox {
id: showHomeSidepanel
text: i18n("Home directory")
}
CheckBox {
id: showDocumentsSidepanel
text: i18n("Documents")
}
CheckBox {
id: showPicturesSidepanel
text: i18n("Pictures")
}
CheckBox {
id: showMusicSidepanel
text: i18n("Music")
}
CheckBox {
id: showVideosSidepanel
text: i18n("Videos")
}
CheckBox {
id: showDownloadsSidepanel
text: i18n("Downloads")
}
CheckBox {
id: showGamesSidepanel
text: i18n("Games")
}
CheckBox {
id: showRecentItemsSidepanel
text: i18n("Recent Items")
}
CheckBox {
id: showRootSidepanel
text: i18n("Computer")
}
CheckBox {
id: showNetworkSidepanel
text: i18n("Network")
}
CheckBox {
id: showSettingsSidepanel
text: i18n("Control Panel")
}
CheckBox {
id: showDevicesSidepanel
text: i18n("Devices and Printers")
}
CheckBox {
id: showDefaultsSidepanel
text: i18n("Default Programs")
}
CheckBox {
id: showHelpSidepanel
text: i18n("Help and Support")
}
}
}
}
Component.onCompleted: {
if(Plasmoid.configuration.stickOutOrb) Plasmoid.setTransparentWindow();
}
Component.onDestruction: {
if(Plasmoid.configuration.stickOutOrb) Plasmoid.setTransparentWindow();
}
}

View file

@ -0,0 +1,131 @@
/*
MIT License
Copyright (c) 2020 Pierre-Yves Siret
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
import QtQuick 2.15
import QtQml 2.15
Behavior {
id: root
property QtObject fadeTarget: targetProperty.object
property string fadeProperty: "opacity"
property var fadeProperties: [fadeProperty]
property var exitValue: 0
property var enterValue: exitValue
property int fadeDuration: 300
property string easingType: "Quad"
property bool delayWhile: false
property bool sequential: false
onDelayWhileChanged: {
if (!delayWhile)
sequentialAnimation.startExitAnimation();
}
readonly property Component shaderEffectSourceWrapperComponent: Item {
property alias shaderEffectSource: shaderEffectSource
property alias sourceItem: shaderEffectSource.sourceItem
parent: sourceItem.parent
x: sourceItem.x
y: sourceItem.y
ShaderEffectSource {
id: shaderEffectSource
transformOrigin: sourceItem.transformOrigin
hideSource: true
live: false
width: sourceItem.width
height: sourceItem.height
}
}
readonly property Component defaultExitAnimation: NumberAnimation {
properties: root.fadeProperties.join(',')
duration: root.fadeDuration
to: root.exitValue
easing.type: root.easingType === "Linear" ? Easing.Linear : Easing["In"+root.easingType]
}
property Component exitAnimation: defaultExitAnimation
// bind SES properties tu function provided by user: {rotation: (t) => () => t.progress * 180, opacity: (p) => 1 - p)}
readonly property Component defaultEnterAnimation: NumberAnimation {
properties: root.fadeProperties.join(',')
duration: root.fadeDuration
from: root.enterValue
to: root.fadeTarget[root.fadeProperties[0]]
easing.type: root.easingType === "Linear" ? Easing.Linear : Easing["Out"+root.easingType]
}
property Component enterAnimation: defaultEnterAnimation
SequentialAnimation {
id: sequentialAnimation
signal startEnterAnimation()
signal startExitAnimation()
ScriptAction {
script: {
const exitItem = shaderEffectSourceWrapperComponent.createObject(null, { sourceItem: root.fadeTarget });
const exitShaderEffectSource = exitItem.shaderEffectSource;
if (exitAnimation === root.defaultExitAnimation)
root.fadeProperties.forEach(p => exitShaderEffectSource[p] = root.fadeTarget[p]);
exitShaderEffectSource.width = root.fadeTarget.width;
exitShaderEffectSource.height = root.fadeTarget.height;
const exitAnimationInstance = exitAnimation.createObject(root, { target: exitItem.shaderEffectSource });
sequentialAnimation.startExitAnimation.connect(exitAnimationInstance.start);
if (root.sequential)
exitAnimationInstance.finished.connect(sequentialAnimation.startEnterAnimation);
else
exitAnimationInstance.started.connect(sequentialAnimation.startEnterAnimation);
exitAnimationInstance.finished.connect(() => {
exitItem.destroy();
exitAnimationInstance.destroy();
});
}
}
PauseAnimation {
duration: 5 // figure out how to wait on a signal in an animation (for ShaderEffectSource update or Image loading when Behaviour on source)
}
PropertyAction {}
ScriptAction {
script: {
const enterItem = shaderEffectSourceWrapperComponent.createObject(null, { sourceItem: root.fadeTarget });
const enterShaderEffectSource = enterItem.shaderEffectSource;
if (enterAnimation === root.defaultEnterAnimation)
root.fadeProperties.forEach(p => enterShaderEffectSource[p] = root.enterValue);
enterShaderEffectSource.live = true;
const enterAnimationInstance = enterAnimation.createObject(root, { target: enterItem.shaderEffectSource });
sequentialAnimation.startEnterAnimation.connect(enterAnimationInstance.start);
enterAnimationInstance.finished.connect(() => {
enterItem.destroy();
enterAnimationInstance.destroy();
});
if (!root.delayWhile)
sequentialAnimation.startExitAnimation();
}
}
}
}

View file

@ -0,0 +1,187 @@
/*
Copyright (C) 2011 Martin Gräßlin <mgraesslin@kde.org>
Copyright (C) 2012 Marco Martin <mart@kde.org>
Copyright 2014 Sebastian Kügler <sebas@kde.org>
Copyright (C) 2015-2018 Eike Hein <hein@kde.org>
Copyright (C) 2016 Jonathan Liu <net147@gmail.com>
Copyright (C) 2016 Kai Uwe Broulik <kde@privat.broulik.de>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
import QtQuick 2.0
import org.kde.kquickcontrolsaddons 2.0 as KQuickControlsAddons
import org.kde.plasma.plasmoid
import org.kde.plasma.core 2.0 as PlasmaCore
import org.kde.plasma.extras 2.0 as PlasmaExtras
import org.kde.plasma.components as PlasmaComponents
import org.kde.draganddrop 2.0
import org.kde.plasma.private.kicker 0.1 as Kicker
Item {
property ListView listView: favoritesView.listView
function activateCurrentIndex() {
favoritesView.currentItem.activate();
}
function decrementCurrentIndex() {
if (favoritesView.currentIndex == 0)
return;
favoritesView.decrementCurrentIndex();
}
function getFavoritesCount() {
return favoritesView.count;
}
function incrementCurrentIndex() {
var tempIndex = favoritesView.currentIndex + 1;
if (tempIndex >= favoritesView.count) {
favoritesView.currentIndex = -1;
if (Plasmoid.configuration.showRecentsView) {
root.m_recents.focus = true;
root.m_recents.currentIndex = 0;
} else {
root.m_showAllButton.focus = true;
}
return;
}
favoritesView.incrementCurrentIndex();
}
// QQuickItem::isAncestorOf is not invokable...
function isChildOf(item, parent) {
if (!item || !parent) {
return false;
}
if (item.parent === parent) {
return true;
}
return isChildOf(item, item.parent);
}
function openContextMenu() {
favoritesView.currentItem.openActionMenu();
}
function resetCurrentIndex() {
favoritesView.currentIndex = -1;
}
function setCurrentIndex() {
favoritesView.currentIndex = 0;
}
KeyNavigation.tab: Plasmoid.configuration.showRecentsView ? root.m_recents : root.m_showAllButton
//anchors.fill: parent
anchors.topMargin: Kirigami.Units.smallSpacing
objectName: "FavoritesView"
Keys.onPressed: event => {
if (event.key == Qt.Key_Up) {
decrementCurrentIndex();
} else if (event.key == Qt.Key_Down) {
incrementCurrentIndex();
} else if (event.key == Qt.Key_Return) {
activateCurrentIndex();
} else if (event.key == Qt.Key_Menu) {
openContextMenu();
}
}
onFocusChanged: {
if (focus)
setCurrentIndex();
else
resetCurrentIndex();
}
DropArea {
property int startRow: -1
function syncTarget(event) {
if (favoritesView.animating) {
return;
}
var pos = mapToItem(listView.contentItem, event.x, event.y);
var above = listView.itemAt(pos.x, pos.y);
var source = kickoff.dragSource;
if (above && above !== source && isChildOf(source, favoritesView)) {
favoritesView.model.moveRow(source.itemIndex, above.itemIndex);
// itemIndex changes directly after moving,
// we can just set the currentIndex to it then.
favoritesView.currentIndex = source.itemIndex;
}
}
anchors.fill: parent
enabled: plasmoid.immutability !== PlasmaCore.Types.SystemImmutable
onDragEnter: {
syncTarget(event);
startRow = favoritesView.currentIndex;
}
onDragMove: syncTarget(event)
}
Transition {
id: moveTransition
SequentialAnimation {
PropertyAction {
property: "animating"
target: favoritesView
value: true
}
NumberAnimation {
duration: favoritesView.animationDuration
easing.type: Easing.OutQuad
properties: "x, y"
}
PropertyAction {
property: "animating"
target: favoritesView
value: false
}
}
}
Connections {
function onExpandedChanged() {
if (!plasmoid.expanded) {
favoritesView.currentIndex = -1;
}
}
target: kicker
}
KickoffListView {
id: favoritesView
property bool animating: false
property int animationDuration: resetAnimationDurationTimer.interval
anchors.fill: parent
interactive: contentHeight > height
model: globalFavorites
move: moveTransition
moveDisplaced: moveTransition
onCountChanged: {
animationDuration = 0;
resetAnimationDurationTimer.start();
}
}
Timer {
id: resetAnimationDurationTimer
interval: 150
onTriggered: favoritesView.animationDuration = interval - 20
}
}

View file

@ -0,0 +1,104 @@
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
import QtQuick.Dialogs
import QtQuick.Window
import org.kde.plasma.plasmoid
import org.kde.plasma.core as PlasmaCore
import org.kde.plasma.components as PlasmaComponents
import org.kde.plasma.extras as PlasmaExtras
import org.kde.plasma.private.kicker as Kicker
import org.kde.coreaddons as KCoreAddons // kuser
import org.kde.plasma.private.shell 2.0
import org.kde.kwindowsystem 1.0
import org.kde.kquickcontrolsaddons 2.0
import org.kde.plasma.private.quicklaunch 1.0
import org.kde.kirigami 2.13 as Kirigami
import org.kde.kquickcontrolsaddons 2.0 as KQuickAddons
import org.kde.kcmutils as KCM
import org.kde.kwindowsystem 1.0
Item {
id: iconContainer
//The frame displayed on top of the user icon
height: Kirigami.Units.iconSizes.huge
//Kirigami.Units.iconSizes.huge
width: height
anchors.horizontalCenter: parent.horizontalCenter
property alias iconSource: imgAuthorIcon.source
Image {
source: "../pics/user.png"
smooth: true
z: 1
opacity: imgAuthorIcon.source === ""
Behavior on opacity {
NumberAnimation { duration: 350 }
}
anchors {
left: parent.left
right: parent.right
bottom: parent.bottom
top: parent.top
}
}
Kirigami.Icon {
id: imgAuthorIcon
source: ""
height: parent.height
width: height
smooth: true
visible: true
//usesPlasmaTheme: false
z: 99
CrossFadeBehavior on source {
fadeDuration: 350
}
}
Image {
id: imgAuthor
anchors {
top: parent.top
left: parent.left
right: parent.right
bottom: parent.bottom
topMargin: Kirigami.Units.smallSpacing*2
leftMargin: Kirigami.Units.smallSpacing*2
rightMargin: Kirigami.Units.smallSpacing*2
bottomMargin: Kirigami.Units.smallSpacing*2
}
opacity: imgAuthorIcon.source === ""
Behavior on opacity {
NumberAnimation { duration: 350 }
}
source: kuser.faceIconUrl.toString()
smooth: true
mipmap: true
visible: true
}
/*OpacityMask {
anchors.fill: imgAuthor
source: (kuser.faceIconUrl.toString() === "") ? imgAuthorIcon : imgAuthor;
maskSource: Rectangle {
width: imgAuthorIcon.source === "" ? imgAuthor.width : 0
height: imgAuthor.height
visible: false
}
}*/
MouseArea{
anchors.fill: parent
acceptedButtons: Qt.LeftButton
onPressed: {
root.visible = false;
KCM.KCMLauncher.openSystemSettings("kcm_users")
}
cursorShape: Qt.PointingHandCursor
}
}

View file

@ -0,0 +1,90 @@
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
import QtQuick.Dialogs
import QtQuick.Window
import org.kde.plasma.plasmoid
import org.kde.plasma.core as PlasmaCore
import org.kde.plasma.components as PlasmaComponents
import org.kde.plasma.extras as PlasmaExtras
import org.kde.plasma.private.kicker as Kicker
import org.kde.coreaddons as KCoreAddons // kuser
import org.kde.plasma.private.shell 2.0
import org.kde.kwindowsystem 1.0
import org.kde.kquickcontrolsaddons 2.0
import org.kde.plasma.private.quicklaunch 1.0
import org.kde.kirigami 2.13 as Kirigami
import org.kde.kquickcontrolsaddons 2.0 as KQuickAddons
import org.kde.kwindowsystem 1.0
import org.kde.kquickcontrolsaddons 2.0 as KQuickControlsAddons
import org.kde.kirigami as Kirigami
Item {
id: floatingOrb
width: buttonIconSizes.width
height: buttonIconSizes.height / 3
property alias buttonIconSizes: buttonIconSizes
property alias buttonIcon: buttonIcon
property alias buttonIconPressed: buttonIconPressed
property alias buttonIconHovered: buttonIconHovered
property alias mouseArea: mouseArea
property string orbTexture: getResolvedUrl(Plasmoid.configuration.customButtonImage, "orbs/orb.png")
property int opacityDuration: 300
Image {
id: buttonIconSizes
smooth: true
source: orbTexture
opacity: 0;
}
clip: false
Image {
id: buttonIcon
smooth: true
source: orbTexture
sourceClipRect: Qt.rect(0, 0, buttonIconSizes.width, buttonIconSizes.height / 3);
}
Image {
id: buttonIconPressed
visible: dashWindow.visible
smooth: true
source: orbTexture
verticalAlignment: Image.AlignBottom
sourceClipRect: Qt.rect(0, 2*buttonIconSizes.height / 3, buttonIconSizes.width, buttonIconSizes.height / 3);
}
Image {
id: buttonIconHovered
source: orbTexture
opacity: mouseArea.containsMouse || mouseAreaCompositingOff.containsMouse
visible: !dashWindow.visible
Behavior on opacity {
NumberAnimation { properties: "opacity"; easing.type: Easing.Linear; duration: opacityDuration }
}
verticalAlignment: Image.AlignVCenter
sourceClipRect: Qt.rect(0, buttonIconSizes.height / 3, buttonIconSizes.width, buttonIconSizes.height / 3);
}
MouseArea
{
id: mouseArea
anchors.fill: parent
hoverEnabled: true
acceptedButtons: Qt.LeftButton | Qt.RightButton
propagateComposedEvents: true
onPressed: mouse => {
if(mouse.button === Qt.LeftButton)
root.showMenu();
else
mouse.accepted = false;
}
}
}

View file

@ -0,0 +1,199 @@
/*****************************************************************************
* Copyright (C) 2022 by Friedrich Schriewer <friedrich.schriewer@gmx.net> *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA . *
****************************************************************************/
import QtQuick 2.12
import QtQuick.Layouts 1.12
import Qt5Compat.GraphicalEffects
import QtQuick.Window 2.2
import org.kde.plasma.components 3.0 as PlasmaComponents
import org.kde.plasma.plasmoid 2.0
import org.kde.plasma.core 2.0 as PlasmaCore
import org.kde.coreaddons 1.0 as KCoreAddons
import org.kde.kirigami 2.13 as Kirigami
import QtQuick.Controls 2.15
import "../code/tools.js" as Tools
Item {
id: allItem
width: scrollView.availableWidth - Kirigami.Units.mediumSpacing
height: Kirigami.Units.iconSizes.smallMedium
property var itemSection: model.group
property bool highlighted: false
property bool isDraging: false
property bool canDrag: true
property bool canNavigate: false
signal highlightChanged
signal aboutToShowActionMenu(variant actionMenu)
property bool hasActionList: ((model.favoriteId !== null)
|| (("hasActionList" in model) && (model.hasActionList !== null)))
property var triggerModel
onAboutToShowActionMenu: actionMenu => {
var actionList = allItem.hasActionList ? model.actionList : [];
Tools.fillActionMenu(i18n, actionMenu, actionList, globalFavorites, model.favoriteId);
}
function openActionMenu(x, y) {
aboutToShowActionMenu(actionMenu);
if(actionMenu.actionList.length === 0) return;
actionMenu.visualParent = allItem;
actionMenu.open(x, y);
}
function actionTriggered(actionId, actionArgument) {
var close = (Tools.triggerAction(triggerModel, index, actionId, actionArgument) === true);
if (close) {
//root.toggle();
root.visible = false;
}
}
function trigger() {
triggerModel.trigger(index, "", null);
root.visible = false;
}
function updateHighlight() {
if (navGrid.currentIndex == index){
highlighted = true
} else {
highlighted = false
}
}
function deselect(){
highlighted = false
listView.currentIndex = -1
}
Kirigami.Icon {
id: appicon
anchors.left: parent.left
anchors.verticalCenter: parent.verticalCenter
anchors.leftMargin: Kirigami.Units.smallSpacing*2 + Kirigami.Units.iconSizes.small
width: Kirigami.Units.iconSizes.small
height: width
source: model.decoration
}
PlasmaComponents.Label {
id: appname
anchors.left: appicon.right
anchors.right: parent.right
anchors.rightMargin: Kirigami.Units.smallSpacing
anchors.leftMargin: Kirigami.Units.smallSpacing
anchors.verticalCenter: appicon.verticalCenter
text: ("name" in model ? model.name : model.display)
font.underline: ma.containsMouse
elide: Text.ElideRight
}
KickoffHighlight {
id: rectFill
anchors.fill: parent
anchors.leftMargin: Kirigami.Units.iconSizes.small
opacity: (listView.currentIndex === index) * 0.7 + ma.containsMouse * 0.3
}
Timer {
id: toolTipTimer
interval: Kirigami.Units.longDuration*4
onTriggered: {
toolTip.showToolTip();
}
}
PlasmaCore.ToolTipArea {
id: toolTip
anchors {
fill: parent
}
active: appname.truncated
interactive: false
/*location: (((Plasmoid.location === PlasmaCore.Types.RightEdge)
* || (Qt.application.layoutDirection === Qt.RightToLeft))
* ? PlasmaCore.Types.RightEdge : PlasmaCore.Types.LeftEdge)*/
mainText: appname.text
}
MouseArea {
id: ma
anchors.fill: parent
anchors.leftMargin: Kirigami.Units.iconSizes.small
z: parent.z + 1
acceptedButtons: Qt.LeftButton | Qt.RightButton
cursorShape: Qt.PointingHandCursor
hoverEnabled: true
onClicked: mouse => {
if (mouse.button == Qt.RightButton) {
if (allItem.hasActionList) {
var mapped = mapToItem(allItem, mouse.x, mouse.y);
allItem.openActionMenu(mapped.x, mapped.y);
}
} else {
trigger()
}
}
onReleased: {
isDraging: false
}
// to prevent crashing
onEntered: {
if(parent.parent) {
listView.currentIndex = index;
}
toolTipTimer.start();
}
onExited: {
if(parent.parent) {
listView.currentIndex = -1;
toolTipTimer.stop();
toolTip.hideToolTip();
}
}
onPositionChanged: {
isDraging = pressed
if (pressed && canDrag){
if ("pluginName" in model) {
dragHelper.startDrag(kicker, model.url, model.decoration,
"text/x-plasmoidservicename", model.pluginName);
} else {
dragHelper.startDrag(kicker, model.url, model.decoration);
}
}
listView.currentIndex = containsMouse ? index : -1
/*if (containsMouse) {
if (canNavigate) {
listView.currentIndex = index
//listView.focus = true
}
}*/
}
}
ActionMenu {
id: actionMenu
onActionClicked: {
visualParent.actionTriggered(actionId, actionArgument);
//root.toggle()
}
}
}

View file

@ -0,0 +1,94 @@
import QtQuick 2.15
import QtQuick.Controls 2.15
import QtQuick.Layouts
import org.kde.plasma.core 2.0 as PlasmaCore
import org.kde.plasma.components 3.0 as PlasmaComponents
import org.kde.iconthemes as KIconThemes
import org.kde.ksvg as KSvg
import org.kde.plasma.plasmoid 2.0
import org.kde.plasma.extras as PlasmaExtras
import org.kde.kirigami 2.3 as Kirigami
// basically taken from kickoff
RowLayout {
id: iconButton
property string currentIcon
property string defaultIcon
signal iconChanged(string iconName)
//Layout.minimumWidth: previewFrame.width + Kirigami.Units.smallSpacing * 2
//Layout.maximumWidth: Layout.minimumWidth
//Layout.minimumHeight: previewFrame.height + Kirigami.Units.smallSpacing * 2
//Layout.maximumHeight: Layout.minimumWidth
KIconThemes.IconDialog {
id: iconDialog
onIconNameChanged: iconName => {
iconPreview.source = iconName
iconChanged(iconName)
}
}
Layout.fillWidth: true
ColumnLayout {
Text {
Layout.fillWidth: true
Layout.fillHeight: true
wrapMode: Text.WordWrap
text: "Customize the way the menu orb looks like using ClassicShell/OpenShell-compatible PNG resources.\nOnly orb textures with three frames are supported."
}
RowLayout {
Button {
text: i18nc("@item:inmenu Open icon chooser dialog", "Choose...")
onClicked: iconDialog.open()
}
Button {
text: i18nc("@item:inmenu Reset icon to default", "Reset")
onClicked: setDefaultIcon()
}
}
}
KSvg.FrameSvgItem {
id: previewFrame
//anchors.centerIn: parent
imagePath: Plasmoid.location === PlasmaCore.Types.Vertical || Plasmoid.location === PlasmaCore.Types.Horizontal
? "widgets/panel-background" : "widgets/background"
Layout.preferredWidth: Kirigami.Units.iconSizes.large + fixedMargins.left + fixedMargins.right
Layout.preferredHeight: Kirigami.Units.iconSizes.large + fixedMargins.top + fixedMargins.bottom
Layout.bottomMargin: Kirigami.Units.smallSpacing
Kirigami.Icon {
id: iconPreview
anchors.centerIn: parent
width: Kirigami.Units.iconSizes.large
height: width
source: currentIcon
}
}
function setDefaultIcon() {
iconPreview.source = defaultIcon
iconChanged(defaultIcon)
}
// QQC Menu can only be opened at cursor position, not a random one
/*PlasmaExtras.Menu {
id: iconMenu
PlasmaExtras.MenuItem {
text: i18nc("@item:inmenu Open icon chooser dialog", "Choose...")
icon: "document-open-folder"
onClicked: iconDialog.open()
}
PlasmaExtras.MenuItem {
text: i18nc("@item:inmenu Reset icon to default", "Clear Icon")
icon: "edit-clear"
onClicked: setDefaultIcon()
}
}*/
}

View file

@ -0,0 +1,67 @@
/*
Copyright (C) 2011 Martin Gräßlin <mgraesslin@kde.org>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
import QtQuick
import org.kde.plasma.core 2.0 as PlasmaCore
import org.kde.plasma.components 3.0 as PlasmaComponents
import org.kde.kquickcontrolsaddons 2.0
PlasmaComponents.TabButton {
id: button
objectName: "KickoffButton"
property string iconSource
property alias text: labelElement.text
implicitHeight: iconElement.height + labelElement.implicitHeight + iconElement.anchors.topMargin + labelElement.anchors.topMargin + labelElement.anchors.bottomMargin
Item {
anchors {
margins: Kirigami.Units.smallSpacing
left: parent.left
right: parent.right
verticalCenter: parent.verticalCenter
}
height: childrenRect.height
PlasmaCore.IconItem {
id: iconElement
anchors.horizontalCenter: parent.horizontalCenter
width: Kirigami.Units.iconSizes.medium
height: width
source: iconSource
}
PlasmaComponents.Label {
id: labelElement
anchors {
top: iconElement.bottom
left: parent.left
right: parent.right
}
horizontalAlignment: Text.AlignHCenter
elide: Text.ElideRight
wrapMode: Text.WordWrap
font: theme.smallestFont
}
}
} // button

View file

@ -0,0 +1,88 @@
/*
* Copyright 2014 Sebastian Kügler <sebas@kde.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
import QtQuick 2.0
import org.kde.plasma.core 2.0 as PlasmaCore
import org.kde.plasma.components as PlasmaComponents
import org.kde.ksvg as KSvg
import org.kde.kirigami as Kirigami
Item {
id: highlight
/** true if the user is hovering over the component */
//in the case we are the highlight of a listview, it follows the mouse, so hover = true
property bool hover: ListView ? true : false
/** true if the mouse button is pressed over the component. */
property bool pressed: false
width: ListView.view ? ListView.view.width : undefined
property alias marginHints: background.margins;
Connections {
target: highlight.ListView.view
function onCurrentIndexChanged() {
if (highlight.ListView.view.currentIndex >= 0) {
background.opacity = 1
} else {
background.opacity = 0
}
}
}
Behavior on opacity {
NumberAnimation {
duration: Kirigami.Units.veryShortDuration
easing.type: Easing.OutQuad
}
}
KSvg.FrameSvgItem {
id: background
imagePath: Qt.resolvedUrl("svgs/menuitem.svg")
prefix: {
if (pressed)
return hover ? "selected+hover" : "selected";
if (hover)
return "hover";
return "normal";
}
Behavior on opacity {
NumberAnimation {
duration: Kirigami.Units.veryShortDuration
easing.type: Easing.OutQuad
}
}
anchors {
fill: parent
leftMargin: Kirigami.Units.smallSpacing
rightMargin: Kirigami.Units.smallSpacing
//FIXME: breaks listviews and highlight item
// topMargin: -background.margins.top
// leftMargin: -background.margins.left
// bottomMargin: -background.margins.bottom
// rightMargin: -background.margins.right
}
}
}

View file

@ -0,0 +1,210 @@
/*
Copyright (C) 2011 Martin Gräßlin <mgraesslin@kde.org>
Copyright (C) 2012 Gregor Taetzner <gregor@freenet.de>
Copyright 2014 Sebastian Kügler <sebas@kde.org>
Copyright (C) 2015-2018 Eike Hein <hein@kde.org>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
//This is the generic item delegate used by FavoritesView, RecentlyUsedView and SearchView.
import QtQuick 2.0
import org.kde.plasma.plasmoid
import org.kde.plasma.core 2.0 as PlasmaCore
import org.kde.plasma.components as PlasmaComponents
import org.kde.draganddrop 2.0
import org.kde.kirigami as Kirigami
import org.kde.ksvg as KSvg
import "code/tools.js" as Tools
Item {
id: listItem
enabled: !model.disabled && !(model.display === "" || model.display === "Recent Applications")
visible: !(model.display === "" || model.display === "Recent Applications")
width: ListView.view.width
height: model.display === "" || model.display === "Recent Applications" ? 0 : (Kirigami.Units.smallSpacing / (small ? 2 : 1)) + Math.max(elementIcon.height, titleElement.implicitHeight /*+ subTitleElement.implicitHeight*/)
signal reset
signal actionTriggered(string actionId, variant actionArgument)
signal aboutToShowActionMenu(variant actionMenu)
signal addBreadcrumb(var model, string title)
property alias toolTip: toolTip
property bool smallIcon: false
readonly property int itemIndex: model.index
readonly property string url: model.url || ""
readonly property var decoration: model.decoration || ""
property bool dropEnabled: false
property bool appView: false
property bool modelChildren: model.hasChildren || false
property bool isCurrent: listItem.ListView.view.currentIndex === index;
property bool showAppsByName: Plasmoid.configuration.showAppsByName
property bool hasActionList: ((model.favoriteId !== null)
|| (("hasActionList" in model) && (model.hasActionList === true)))
property Item menu: actionMenu
//property alias usePlasmaIcon: elementIcon.usesPlasmaTheme
onAboutToShowActionMenu: (actionMenu) => {
var actionList = hasActionList ? model.actionList : [];
Tools.fillActionMenu(i18n, actionMenu, actionList, ListView.view.model.favoritesModel, model.favoriteId);
}
onActionTriggered: (actionId, actionArgument) => {
kicker.expanded = false;
if (Tools.triggerAction(ListView.view.model, model.index, actionId, actionArgument) === true) {
kicker.expanded = false;
}
/*if (actionId.indexOf("_kicker_favorite_") === 0) {
switchToInitial();
}*/
}
function activate() {
var view = listItem.ListView.view;
if (model.hasChildren) {
var childModel = view.model.modelForRow(index);
listItem.addBreadcrumb(childModel, model.display);
view.model = childModel;
} else {
view.model.trigger(model.index, "", null);
kicker.expanded = false;
listItem.reset();
}
}
function openActionMenu(x, y) {
aboutToShowActionMenu(actionMenu);
actionMenu.visualParent = listItem;
actionMenu.open(x, y);
}
ActionMenu {
id: actionMenu
onActionClicked: (actionId, actionArgument) => {
actionTriggered(actionId, actionArgument);
}
}
Kirigami.Icon {
id: elementIcon
anchors {
left: parent.left
leftMargin: Kirigami.Units.smallSpacing*2-1
verticalCenter: parent.verticalCenter
}
width: smallIcon ? Kirigami.Units.iconSizes.small : Kirigami.Units.iconSizes.medium
height: width
animated: false
//usesPlasmaTheme: false
source: model.decoration
}
PlasmaComponents.Label {
id: titleElement
y: Math.round((parent.height - titleElement.height - ( (subTitleElement.text != "") ? subTitleElement.implicitHeight : 0) ) / 2)
anchors {
left: elementIcon.right
right: arrow.left
leftMargin: Kirigami.Units.smallSpacing * 2 - 2
rightMargin: Kirigami.Units.smallSpacing * 2
}
height: implicitHeight //undo PC2 height override, remove when porting to PC3
// TODO: games should always show the by name!
text: model.display
elide: Text.ElideRight
horizontalAlignment: Text.AlignLeft
color: "#000000"
}
PlasmaComponents.Label {
id: subTitleElement
anchors {
left: titleElement.left
right: arrow.right
top: titleElement.bottom
}
height: implicitHeight
color: "#000000"
text: ""//model.description || ""
opacity: isCurrent ? 0.8 : 0.6
font: Kirigami.Theme.smallFont
elide: Text.ElideMiddle
horizontalAlignment: Text.AlignLeft
}
KSvg.SvgItem {
id: arrow
anchors {
right: parent.right
rightMargin: Kirigami.Units.smallSpacing
verticalCenter: parent.verticalCenter
}
width: visible ? Kirigami.Units.iconSizes.small : 0
height: width
visible: (model.hasChildren === true)
opacity: (listItem.ListView.view.currentIndex === index) ? 1.0 : 0.8
svg: arrowsSvg
elementId: (Qt.application.layoutDirection == Qt.RightToLeft) ? "left-arrow-black" : "right-arrow-black"
}
Keys.onPressed: {
if (event.key === Qt.Key_Menu && hasActionList) {
event.accepted = true;
openActionMenu();
} else if ((event.key === Qt.Key_Enter || event.key === Qt.Key_Return) && !modelChildren) {
if (!modelChildren) {
event.accepted = true;
listItem.activate();
}
}
}
PlasmaCore.ToolTipArea {
id: toolTip
anchors {
fill: parent
}
active: titleElement.truncated
interactive: false
/*location: (((Plasmoid.location === PlasmaCore.Types.RightEdge)
|| (Qt.application.layoutDirection === Qt.RightToLeft))
? PlasmaCore.Types.RightEdge : PlasmaCore.Types.LeftEdge)*/
mainText: model.display
}
}

View file

@ -0,0 +1,218 @@
/*
Copyright (C) 2011 Martin Gräßlin <mgraesslin@kde.org>
Copyright (C) 2012 Gregor Taetzner <gregor@freenet.de>
Copyright (C) 2015-2018 Eike Hein <hein@kde.org>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
import QtQuick 2.0
import org.kde.plasma.core 2.0 as PlasmaCore
import org.kde.plasma.extras 2.0 as PlasmaExtras
import org.kde.plasma.components as PlasmaComponents
import org.kde.kirigami as Kirigami
FocusScope {
id: view
property bool appView: false
property alias contentHeight: listView.contentHeight
property alias count: listView.count
property alias currentIndex: listView.currentIndex
property alias currentItem: listView.currentItem
property alias delegate: listView.delegate
property alias interactive: listView.interactive
readonly property Item listView: listView
property alias model: listView.model
property alias move: listView.move
property alias moveDisplaced: listView.moveDisplaced
readonly property Item scrollView: scrollView
property bool showAppsByName: true
property bool small: false
signal addBreadcrumb(var model, string title)
signal reset
function decrementCurrentIndex() {
listView.decrementCurrentIndex();
}
function incrementCurrentIndex() {
listView.incrementCurrentIndex();
}
Connections {
function onExpandedChanged() {
if (!kicker.expanded) {
listView.positionViewAtBeginning();
}
}
target: kicker
}
Timer {
id: toolTipTimer
interval: Kirigami.Units.longDuration*4
onTriggered: {
if(listView.currentItem) listView.currentItem.toolTip.showToolTip();
}
}
PlasmaComponents.ScrollView {
id: scrollView
//frameVisible: false
anchors.fill: parent
ListView {
id: listView
boundsBehavior: Flickable.StopAtBounds
focus: true
highlightMoveDuration: 0
highlightResizeDuration: 0
keyNavigationWraps: true
spacing: small ? 0 : Kirigami.Units.smallSpacing / 2
delegate: KickoffItem {
id: delegateItem
required property var model
required property int index
appView: view.appView
showAppsByName: view.showAppsByName
smallIcon: small
onAddBreadcrumb: view.addBreadcrumb(model, title)
onReset: view.reset()
}
highlight: KickoffHighlight {
}
section.property: "group"
/*section {
criteria: ViewSection.FullString
property: "group"
delegate: SectionDelegate {
}
}*/
MouseArea {
id: mouseArea
// property Item pressed: null
property int pressX: -1
property int pressY: -1
property bool tapAndHold: false
acceptedButtons: Qt.LeftButton | Qt.RightButton
anchors.left: parent.left
height: parent.height
hoverEnabled: true
width: scrollView.width
onContainsMouseChanged: {
if (!containsMouse) {
//pressed = null;
toolTipTimer.stop();
if(listView.currentItem) listView.currentItem.toolTip.hideToolTip();
pressX = -1;
pressY = -1;
tapAndHold = false;
listView.currentIndex = -1;
}
}
onPositionChanged: function(mouse) {
var mapped = listView.mapToItem(listView.contentItem, mouse.x, mouse.y);
var item = listView.itemAt(mapped.x, mapped.y);
if (item) {
toolTipTimer.stop();
if(listView.currentItem) listView.currentItem.toolTip.hideToolTip();
listView.currentIndex = item.itemIndex;
toolTipTimer.start();
//item.toolTip.showToolTip();
} else {
listView.currentIndex = -1;
}
if (mouse.source != Qt.MouseEventSynthesizedByQt || tapAndHold) {
if (pressed && pressX != -1 && pressed.url && dragHelper.isDrag(pressX, pressY, mouse.x, mouse.y)) {
kickoff.dragSource = item;
if (mouse.source == Qt.MouseEventSynthesizedByQt) {
dragHelper.dragIconSize = Kirigami.Units.iconSizes.huge;
dragHelper.startDrag(kickoff, pressed.url, pressed.decoration);
} else {
dragHelper.dragIconSize = Kirigami.Units.iconSizes.medium;
dragHelper.startDrag(kickoff, pressed.url, pressed.decoration);
}
//pressed = null;
pressX = -1;
pressY = -1;
tapAndHold = false;
}
}
}
onPressAndHold: function(mouse) {
if (mouse.source == Qt.MouseEventSynthesizedByQt) {
tapAndHold = true;
positionChanged(mouse);
}
}
onPressed: function(mouse) {
var mapped = listView.mapToItem(listView.contentItem, mouse.x, mouse.y);
var item = listView.itemAt(mapped.x, mapped.y);
if (!item) {
return;
}
if (mouse.buttons & Qt.RightButton) {
if (item.hasActionList) {
mapped = listView.contentItem.mapToItem(item, mapped.x, mapped.y);
listView.currentItem.openActionMenu(mapped.x, mapped.y);
}
} else {
//pressed = item;
//item.activate();
pressX = mouse.x;
pressY = mouse.y;
}
}
onReleased: function(mouse) {
var mapped = listView.mapToItem(listView.contentItem, mouse.x, mouse.y);
var item = listView.itemAt(mapped.x, mapped.y);
if (item && /*pressed === item && */!tapAndHold) {
if (item.appView) {
if (mouse.source == Qt.MouseEventSynthesizedByQt) {
positionChanged(mouse);
}
view.state = "OutgoingLeft";
} else {
item.activate();
root.visible = false;
}
listView.currentIndex = -1;
}
if (tapAndHold && mouse.source == Qt.MouseEventSynthesizedByQt) {
if (item.hasActionList) {
mapped = listView.contentItem.mapToItem(item, mapped.x, mapped.y);
listView.currentItem.openActionMenu(mapped.x, mapped.y);
}
}
//pressed = null;
pressX = -1;
pressY = -1;
tapAndHold = false;
}
}
}
}
}

View file

@ -0,0 +1,105 @@
/*
* Copyright 2015 Kai Uwe Broulik <kde@privat.broulik.de>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 2.010-1301, USA.
*/
import QtQuick 2.2
import QtQuick.Layouts 1.1
import org.kde.plasma.core 2.0 as PlasmaCore
import org.kde.plasma.components 3.0 as PlasmaComponents
import org.kde.kirigami as Kirigami
Item {
id: item
signal clicked
signal iconClicked
property alias text: label.text
// property alias subText: sublabel.text
property alias icon: icon.source
// "enabled" also affects all children
property bool interactive: true
property bool interactiveIcon: false
property bool showIcon: false
//property alias usesPlasmaTheme: icon.usesPlasmaTheme
property alias containsMouse: area.containsMouse
property alias size: icon.height
property Item highlight
Layout.fillWidth: true
height: size + 2 * Kirigami.Units.smallSpacing
width: height
MouseArea {
id: area
anchors.fill: parent
enabled: item.interactive
hoverEnabled: true
onClicked: item.clicked()
onContainsMouseChanged: {
if (!highlight) {
return
}
if (containsMouse) {
highlight.parent = item
highlight.width = item.width
highlight.height = item.height
}
highlight.visible = containsMouse
}
}
Kirigami.Icon {
id: icon
width: icon.height
anchors.verticalCenter: parent.verticalCenter
anchors.left: parent.left
anchors.leftMargin: Kirigami.Units.smallSpacing * 2
//usesPlasmaTheme: true
visible: showIcon
MouseArea {
anchors.fill: parent
visible: item.interactiveIcon
cursorShape: Qt.PointingHandCursor
onClicked: item.iconClicked()
}
}
PlasmaComponents.Label {
id: label
wrapMode: Text.NoWrap
elide: Text.ElideRight
anchors.left: showIcon ? icon.right : parent.left
anchors.leftMargin: Kirigami.Units.smallSpacing * 2
anchors.verticalCenter: icon.verticalCenter
style: Text.Sunken
styleColor: "transparent"
}
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,138 @@
/*****************************************************************************
* Copyright (C) 2022 by Friedrich Schriewer <friedrich.schriewer@gmx.net> *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA . *
****************************************************************************/
import QtQuick 2.12
import org.kde.plasma.core as PlasmaCore
import org.kde.plasma.components 3.0 as PlasmaComponents
import org.kde.plasma.extras 2.0 as PlasmaExtras
import org.kde.kquickcontrolsaddons 2.0
import QtQuick.Controls 2.15
import org.kde.draganddrop 2.0
FocusScope {
id: navGrid
signal keyNavUp
signal keyNavDown
property alias triggerModel: listView.model
property alias count: listView.count
property alias currentIndex: listView.currentIndex
property alias currentItem: listView.currentItem
property alias contentItem: listView.contentItem
property Item flickableItem: listView
onFocusChanged: {
if (!focus) {
currentIndex = -1;
}
}
function tryActivate() {
if(currentIndex === -1 && listView.count > 0) {
listView.itemAtIndex(0).trigger();
return;
}
if (currentItem){
currentItem.trigger()
}
}
function setFocus() {
currentIndex = 0
focus = true
}
function setFocusLast() {
if (count > 0) {
currentIndex = count - 1
focus = true
} else {
setFocus()
}
}
Text {
id: noResults
opacity: 0.6
text: "No items match your search."
anchors.fill: parent
anchors.topMargin: 13
horizontalAlignment: Text.AlignHCenter
visible: listView.count === 0 && searching
}
ScrollView {
id: scrollView
anchors.fill: parent
anchors.rightMargin: 4
ListView {
anchors.fill: parent
id: listView
currentIndex: -1
focus: true
property alias scrollBar: scrollView
highlightMoveDuration: 0
highlightResizeDuration: 0
snapMode: ListView.SnapToItem
interactive: false
boundsBehavior: Flickable.StopAtBounds
section {
criteria: ViewSection.FullString
property: "group"
delegate: SectionDelegate {
sectionCount: {
var x = 0;
if(!listView) return 0;
for(var i = 0; i < listView.count; i++) {
//console.log(listView.itemAtIndex(i));
if(listView.itemAtIndex(i)) {
if(listView.itemAtIndex(i).itemSection === section) x++;
}
}
return x;
}
}
}
delegate: GenericItem {
canNavigate: true
canDrag: true
triggerModel: listView.model
//Layout.leftMargin: Kirigami.Units.iconSizes.small
//x: Kirigami.Units.iconSizes.small
}
onCurrentIndexChanged: {
if (currentIndex != -1) {
focus = true;
}
}
onModelChanged: {
currentIndex = -1;
}
onFocusChanged: {
if (!focus) {
currentIndex = -1
}
}
}
}
}

View file

@ -0,0 +1,172 @@
/*
Copyright (C) 2011 Martin Gräßlin <mgraesslin@kde.org>
Copyright (C) 2012 Marco Martin <mart@kde.org>
Copyright (C) 2015 Eike Hein <hein@kde.org>
Copyright (C) 2017 Ivan Cukic <ivan.cukic@kde.org>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
import QtQuick 2.0
import org.kde.plasma.components as PlasmaComponents
import org.kde.kitemmodels as KItemModels
import org.kde.plasma.plasmoid
import org.kde.plasma.private.kicker 0.1 as Kicker
/*
* Copyright (C) 2011 Martin Gräßlin <mgraesslin@kde.org>
* Copyright (C) 2012 Marco Martin <mart@kde.org>
* Copyright (C) 2015-2018 Eike Hein <hein@kde.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
import QtQuick 2.0
import org.kde.plasma.core 2.0 as PlasmaCore
import org.kde.plasma.extras 2.0 as PlasmaExtras
import org.kde.plasma.components 3.0 as PlasmaComponents
import org.kde.draganddrop 2.0
Item {
property alias model: baseView.model
property alias delegate: baseView.delegate
property alias currentIndex: baseView.currentIndex;
property alias count: baseView.count;
objectName: "OftenUsedView"
property ListView listView: baseView.listView
function decrementCurrentIndex() {
var tempIndex = baseView.currentIndex-1;
if(tempIndex < 0) {
baseView.currentIndex = -1;
root.m_faves.focus = true;
root.m_faves.listView.currentIndex = root.m_faves.listView.count-1;
return;
}
baseView.decrementCurrentIndex();
}
KeyNavigation.tab: root.m_showAllButton
function incrementCurrentIndex() {
var tempIndex = baseView.currentIndex+1;
if(tempIndex >= baseView.count) {
baseView.currentIndex = -1;
root.m_showAllButton.focus = true;
return;
}
baseView.incrementCurrentIndex();
}
function activateCurrentIndex() {
baseView.currentItem.activate();
}
function openContextMenu() {
baseView.currentItem.openActionMenu();
}
function setCurrentIndex() {
baseView.currentIndex = 0;
}
function resetCurrentIndex() {
baseView.currentIndex = -1;
}
Connections {
target: kicker
function onExpandedChanged() {
if (!kicker.expanded) {
baseView.currentIndex = -1;
}
}
}
KickoffListView {
id: baseView
anchors.fill: parent
currentIndex: -1
interactive: contentHeight > height
model: KItemModels.KSortFilterProxyModel {
sourceModel: rootModel.modelForRow(0)
property var favoritesModel: globalFavorites
property int favoritesCount: sourceModel.favoritesModel.count
onFavoritesCountChanged: {
sourceModel.refresh();
}
function trigger(index, str, ptr) {
sourceModel.trigger(index, str, ptr);
}
filterRowCallback: function(source_row, source_parent) {
//return sourceModel.data(sourceModel.index(source_row, 0, source_parent), Qt.DisplayRole) == "...";
return source_row < Plasmoid.configuration.numberRows - sourceModel.favoritesModel.count;
};
}
}
onFocusChanged: {
if(focus) setCurrentIndex();
else resetCurrentIndex();
}
Keys.onPressed: event => {
if(event.key == Qt.Key_Up) {
decrementCurrentIndex();
} else if(event.key == Qt.Key_Down) {
incrementCurrentIndex();
} else if(event.key == Qt.Key_Return) {
activateCurrentIndex();
} else if(event.key == Qt.Key_Menu) {
openContextMenu();
}
}
}
/*
BaseView {
id: recentsModel
objectName: "OftenUsedView"
KeyNavigation.tab: root.m_showAllButton
model: KItemModels.KSortFilterProxyModel {
sourceModel: rootModel.modelForRow(0)
property var favoritesModel: globalFavorites
function trigger(index, str, ptr) {
sourceModel.trigger(index, str, ptr);
}
filterRowCallback: function(source_row, source_parent) {
//return sourceModel.data(sourceModel.index(source_row, 0, source_parent), Qt.DisplayRole) == "...";
return source_row < Plasmoid.configuration.numberRows - sourceModel.favoritesModel.count ;
};
}
}
*/

View file

@ -0,0 +1,104 @@
/*
Copyright (C) 2011 Martin Gräßlin <mgraesslin@kde.org>
Copyright (C) 2012 Gregor Taetzner <gregor@freenet.de>
Copyright (C) 2015-2018 Eike Hein <hein@kde.org>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
import QtQuick 2.0
import org.kde.plasma.core 2.0 as PlasmaCore
import org.kde.plasma.extras 2.0 as PlasmaExtras
import org.kde.plasma.components 3.0 as PlasmaComponents
import org.kde.plasma.plasmoid 2.0
import org.kde.plasma.private.kicker as Kicker
import org.kde.kirigami as Kirigami
Item {
id: searchViewContainer
property Item itemGrid: runnerGrid
property bool queryFinished: false
property int repeaterModelIndex: 0
function activateCurrentIndex() {
runnerGrid.tryActivate();
}
function decrementCurrentIndex() {
var listView = runnerGrid.flickableItem;
if(listView.currentIndex-1 < 0) {
listView.currentIndex = listView.count - 1;
} else {
listView.currentIndex--;
}
}
function incrementCurrentIndex() {
var listView = runnerGrid.flickableItem;
if(listView.currentIndex+1 >= listView.count) {
listView.currentIndex = 0;
} else {
listView.currentIndex++;
}
}
function onQueryChanged() {
queryFinished = false;
runnerModel.query = searchField.text;
if (!searchField.text) {
if (runnerModel.model)
runnerModel.model = null;
}
}
function openContextMenu() {
runnerModel.currentItem.openActionMenu();
}
function resetCurrentIndex() {
runnerModel.currentIndex = -1;
}
/*function setCurrentIndex() {
runnerGrid.modelIndex = 0;
}*/
objectName: "SearchView"
Connections {
function onCountChanged() {
if (runnerModel.count && !runnerGrid.model) {
runnerGrid.model = runnerModel.modelForRow(0);
}
}
function onQueryFinished() {
if (runnerModel.count) {
runnerGrid.model = null;
runnerGrid.model = runnerModel.modelForRow(0);
queryFinished = true;
var listView = runnerGrid.flickableItem;
if(listView.count > 0) listView.currentIndex = 0;
//console.log(runnerModel.modelForRow(0).modelForRow(0))
}
}
target: runnerModel
}
NavGrid {
id: runnerGrid
anchors.fill: parent
property alias model: runnerGrid.triggerModel
triggerModel: kicker.runnerModel.count ? kicker.runnerModel.modelForRow(0) : null
}
}

View file

@ -0,0 +1,61 @@
/*
Copyright (C) 2011 Martin Gräßlin <mgraesslin@kde.org>
Copyright (C) 2012 Marco Martin <mart@kde.org>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
import QtQuick 2.0
import org.kde.plasma.core 2.0 as PlasmaCore
import org.kde.plasma.components 3.0 as PlasmaComponents
import org.kde.plasma.extras 2.0 as PlasmaExtras
import QtQuick.Controls 2.15
import org.kde.kirigami as Kirigami
Item {
id: sectionDelegate
width: parent.width
height: Kirigami.Units.iconSizes.medium-1 //childrenRect.height
objectName: "SectionDelegate"
function getName() {
return sectionHeading.text;
}
property int sectionCount: 0
PlasmaExtras.Heading {
id: sectionHeading
anchors {
left: parent.left
leftMargin: Kirigami.Units.smallSpacing*2
verticalCenter: parent.verticalCenter
//verticalCenterOffset: Kirigami.Units.smallSpacing/2
}
color: "#1d3287"
//y: Math.round(Kirigami.Units.gridUnit / 4)
level: 3
text: section + (sectionCount > 0 ? " (" + sectionCount + ")" : "")
}
Rectangle {
id: line
anchors.left: sectionHeading.right
anchors.leftMargin: Kirigami.Units.largeSpacing-1
anchors.rightMargin: Kirigami.Units.largeSpacing+1 + (scrollView.ScrollBar.vertical.visible ? scrollView.ScrollBar.vertical.width : 0)
anchors.right: parent.right
anchors.verticalCenter: parent.verticalCenter
anchors.verticalCenterOffset: 1
height: 1
color: "#e5e5e5"
}
} // sectionDelegate

View file

@ -0,0 +1,136 @@
import QtQuick 2.4
import QtQuick.Controls
import QtQuick.Layouts 1.1
import QtQuick.Dialogs
import QtQuick.Window 2.1
import org.kde.plasma.plasmoid 2.0
import org.kde.plasma.core 2.0 as PlasmaCore
import org.kde.plasma.components as PlasmaComponents
import org.kde.plasma.extras 2.0 as PlasmaExtras
import org.kde.ksvg as KSvg
import org.kde.kirigami as Kirigami
Item {
id: sidePanelDelegate
objectName: "SidePanelItemDelegate"
property int iconSizeSide: Kirigami.Units.iconSizes.smallMedium
property string itemText: ""
property string itemIcon: ""
property string executableString: ""
property bool executeProgram: false
property alias textLabel: label
//text: itemText
//icon: itemIcon
width: label.implicitWidth + Kirigami.Units.largeSpacing*2
//Layout.preferredWidth: label.implicitWidth
height: 33
KeyNavigation.backtab: findPrevious();
KeyNavigation.tab: findNext();
function findItem() {
for(var i = 1; i < parent.visibleChildren.length-1; i++) {
if(sidePanelDelegate == parent.visibleChildren[i])
return i;
}
return -1;
}
function findPrevious() {
var i = findItem()-1;
if(i < 1) {
return root.m_searchField;
}
if(parent.visibleChildren[i].objectName == "SidePanelItemSeparator") {
i--;
}
return parent.visibleChildren[i];
}
function findNext() {
var i = findItem()+1;
if(i >= parent.visibleChildren.length-1) {
return root.m_shutDownButton;
}
if(parent.visibleChildren[i].objectName == "SidePanelItemSeparator") {
i++;
}
return parent.visibleChildren[i];
}
Keys.onPressed: event => {
if(event.key == Qt.Key_Return) {
sidePanelMouseArea.clicked(null);
} else if(event.key == Qt.Key_Up) {
//console.log(findPrevious());
findPrevious().focus = true;
} else if(event.key == Qt.Key_Down) {
//console.log(findNext());
findNext().focus = true;
} else if(event.key == Qt.Key_Left) {
var pos = parent.mapToItem(mainFocusScope, sidePanelDelegate.x, sidePanelDelegate.y);
var obj = mainFocusScope.childAt(Kirigami.Units.smallSpacing*10, pos.y);
if(obj.objectName == "") {
obj = root.m_recents;
}
obj.focus = true;
}
}
//For some reason this is the only thing that prevents a width reduction bug, despite it being UB in QML
/*anchors.left: parent.left;
anchors.right: parent.right;*/
KSvg.FrameSvgItem {
id: itemFrame
z: -1
opacity: sidePanelMouseArea.containsMouse || parent.focus
anchors.fill: parent
imagePath: Qt.resolvedUrl("svgs/sidebaritem.svg")
prefix: "menuitem"
}
PlasmaComponents.Label {
id: label
wrapMode: Text.NoWrap
//elide: Text.ElideRight
anchors.left: parent.left
anchors.leftMargin: Kirigami.Units.smallSpacing * 2
anchors.verticalCenter: sidePanelDelegate.verticalCenter
anchors.verticalCenterOffset: -1
style: Text.Sunken
styleColor: "transparent"
text: itemText
}
onFocusChanged: {
/*if(focus) {
root.m_sidebarIcon.source = itemIcon;
} else {
root.m_sidebarIcon.source = "";
}*/
if(root.m_delayTimer.running) root.m_delayTimer.restart();
else root.m_delayTimer.start();
}
MouseArea {
id: sidePanelMouseArea
enabled: !root.hoverDisabled
acceptedButtons: Qt.LeftButton
onEntered: {
sidePanelDelegate.focus = true;
}
onExited: {
sidePanelDelegate.focus = false;
}
onClicked: {
root.visible = false;
if(executeProgram)
executable.exec(executableString);
else {
Qt.openUrlExternally(executableString);
}
}
hoverEnabled: true
anchors.fill: parent
}
}

View file

@ -0,0 +1,55 @@
import QtQuick 2.4
import QtQuick.Controls
import QtQuick.Layouts 1.1
import QtQuick.Dialogs
import QtQuick.Window 2.1
import org.kde.plasma.plasmoid 2.0
import org.kde.plasma.core 2.0 as PlasmaCore
import org.kde.plasma.components as PlasmaComponents
import org.kde.plasma.extras 2.0 as PlasmaExtras
import org.kde.ksvg as KSvg
import org.kde.kirigami as Kirigami
Item {
id: sidePanelDelegate
objectName: "SidePanelItemSeparator"
//icon: itemIcon
function findItem() {
for(var i = 0; i < parent.visibleChildren.length; i++) {
if(sidePanelDelegate == parent.visibleChildren[i])
return i;
}
return -1;
}
function updateVisibility() {
if(!visible) visible = true;
var i = findItem();
var pred = i-1;
var succ = i+1;
if(pred <= 0 || succ >= parent.visibleChildren.length) {
sidePanelDelegate.visible = false;
return;
}
if(parent.visibleChildren[pred].objectName !== "SidePanelItemDelegate" || parent.visibleChildren[succ].objectName !== "SidePanelItemDelegate") {
sidePanelDelegate.visible = false;
return;
}
sidePanelDelegate.visible = true;
}
//For some reason this is the only thing that prevents a width reduction bug, despite it being UB in QML
/*anchors.left: parent.left;
anchors.right: parent.right;*/
height: 2;
KSvg.SvgItem {
id: itemFrame
anchors.fill: parent
anchors.leftMargin: Kirigami.Units.smallSpacing*2;
anchors.rightMargin: Kirigami.Units.smallSpacing*2;
svg: separatorSvg
elementId: "separator-line"
}
}

View file

@ -0,0 +1,75 @@
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts 1.1
import QtQuick.Dialogs
import QtQuick.Window 2.1
import org.kde.plasma.plasmoid 2.0
import org.kde.plasma.core 2.0 as PlasmaCore
import org.kde.plasma.components 3.0 as PlasmaComponents
import org.kde.plasma.extras 2.0 as PlasmaExtras
import org.kde.plasma.private.kicker 0.1 as Kicker
import org.kde.coreaddons as KCoreAddons // kuser
import org.kde.plasma.private.shell 2.0
import org.kde.kwindowsystem 1.0
import org.kde.kquickcontrolsaddons 2.0
import org.kde.plasma.private.quicklaunch 1.0
import org.kde.kirigami 2.13 as Kirigami
import org.kde.kquickcontrolsaddons 2.0 as KQuickAddons
import org.kde.kwindowsystem 1.0
import org.kde.kquickcontrolsaddons 2.0 as KQuickControlsAddons
/*
* This is the Dialog that displays the Start menu orb when it sticks out
* of the panel. In principle, it works in almost the same way as the
* Start menu user icon, in fact most of the code is directly copied from
* there.
*
* Compared to the popup avatar, this dialog window should NOT have any
* visualParent set, as it causes inexplicable behavior where the orb
* moves away during certain interactions. I have no idea why it does that.
*
* This has been developed only for the bottom/south oriented panel, and
* other orientations should receive support when I begin giving pretty
* much *everything* else support for other orientations.
*
*/
PlasmaCore.Dialog {
id: iconUser
flags: Qt.WindowStaysOnTopHint | Qt.Popup | Qt.WindowTransparentForInput
location: "Floating"
//outputOnly: true // Simplifies things, prevents accidental misclicks when clicking close to the orb.
// Positions are defined later when the plasmoid has been fully loaded, to prevent undefined behavior.
x: 0
y: 0
// Input masks won't be applied correctly when compositing is disabled unless I do this. WHY?
onYChanged: {
Plasmoid.setTransparentWindow();
}
onXChanged: {
Plasmoid.setTransparentWindow();
}
onVisibleChanged: {
if(visible) {
orbTimer.start(); // Delayed initialization, again, for what reason?
}
}
backgroundHints: PlasmaCore.Types.NoBackground // Prevents a dialog SVG background from being drawn.
visible: root.visible && stickOutOrb
opacity: iconUser.visible // To prevent even more NP-hard unpredictable behavior and visual glitches.
// The actual orb button, this dialog window is just a container for it.
mainItem: FloatingOrb {
id: floatingOrbIcon
}
}

View file

@ -0,0 +1,181 @@
/*
* SPDX-FileCopyrightText: 2013 Aurélien Gâteau <agateau@kde.org>
* SPDX-FileCopyrightText: 2013-2015 Eike Hein <hein@kde.org>
* SPDX-FileCopyrightText: 2017 Ivan Cukic <ivan.cukic@kde.org>
*
* SPDX-License-Identifier: GPL-2.0-or-later
*/
.pragma library
function fillActionMenu(i18n, actionMenu, actionList, favoriteModel, favoriteId) {
// Accessing actionList can be a costly operation, so we don't
// access it until we need the menu.
var actions = createFavoriteActions(i18n, favoriteModel, favoriteId);
if (actions) {
if (actionList && actionList.length > 0) {
var actionListCopy = Array.from(actionList);
var separator = { "type": "separator" };
actionListCopy.push(separator);
// actionList = actions.concat(actionList); // this crashes Qt O.o
actionListCopy.push.apply(actionListCopy, actions);
actionList = actionListCopy;
} else {
actionList = actions;
}
}
actionMenu.actionList = actionList;
}
function createFavoriteActions(i18n, favoriteModel, favoriteId) {
if (!favoriteModel || !favoriteModel.enabled || !favoriteId) {
return null;
}
if (favoriteModel.activities === undefined ||
favoriteModel.activities.runningActivities.length <= 1) {
var action = {};
if (favoriteModel.isFavorite(favoriteId)) {
action.text = i18n("Unpin from Start Menu");
//action.icon = "pin";
action.actionId = "_kicker_favorite_remove";
} else if (favoriteModel.maxFavorites === -1 || favoriteModel.count < favoriteModel.maxFavorites) {
action.text = i18n("Pin to Start Menu");
//action.icon = "bookmark-new";
action.actionId = "_kicker_favorite_add";
} else {
return null;
}
action.actionArgument = { favoriteModel: favoriteModel, favoriteId: favoriteId };
return [action];
} else {
var actions = [];
var linkedActivities = favoriteModel.linkedActivitiesFor(favoriteId);
var activities = favoriteModel.activities.runningActivities;
// Adding the item to link/unlink to all activities
var linkedToAllActivities =
!(linkedActivities.indexOf(":global") === -1);
actions.push({
text : i18n("On All Activities"),
checkable : true,
actionId : linkedToAllActivities ?
"_kicker_favorite_remove_from_activity" :
"_kicker_favorite_set_to_activity",
checked : linkedToAllActivities,
actionArgument : {
favoriteModel: favoriteModel,
favoriteId: favoriteId,
favoriteActivity: ""
}
});
// Adding items for each activity separately
var addActivityItem = function(activityId, activityName) {
var linkedToThisActivity =
!(linkedActivities.indexOf(activityId) === -1);
actions.push({
text : activityName,
checkable : true,
checked : linkedToThisActivity && !linkedToAllActivities,
actionId :
// If we are on all activities, and the user clicks just one
// specific activity, unlink from everything else
linkedToAllActivities ? "_kicker_favorite_set_to_activity" :
// If we are linked to the current activity, just unlink from
// that single one
linkedToThisActivity ? "_kicker_favorite_remove_from_activity" :
// Otherwise, link to this activity, but do not unlink from
// other ones
"_kicker_favorite_add_to_activity",
actionArgument : {
favoriteModel : favoriteModel,
favoriteId : favoriteId,
favoriteActivity : activityId
}
});
};
// Adding the item to link/unlink to the current activity
addActivityItem(favoriteModel.activities.currentActivity, i18n("On the Current Activity"));
actions.push({
type: "separator",
actionId: "_kicker_favorite_separator"
});
// Adding the items for each activity
activities.forEach(function(activityId) {
addActivityItem(activityId, favoriteModel.activityNameForId(activityId));
});
return [{
text : i18n("Show in Favorites"),
icon : "favorite",
subActions : actions
}];
}
}
function triggerAction(model, index, actionId, actionArgument) {
function startsWith(txt, needle) {
return txt.substr(0, needle.length) === needle;
}
if (startsWith(actionId, "_kicker_favorite_")) {
handleFavoriteAction(actionId, actionArgument);
return;
}
var closeRequested = model.trigger(index, actionId, actionArgument);
if (closeRequested) {
return true;
}
return false;
}
function handleFavoriteAction(actionId, actionArgument) {
var favoriteId = actionArgument.favoriteId;
var favoriteModel = actionArgument.favoriteModel;
if (favoriteModel === null || favoriteId === null) {
return null;
}
if (actionId === "_kicker_favorite_remove") {
favoriteModel.removeFavorite(favoriteId);
} else if (actionId === "_kicker_favorite_add") {
favoriteModel.addFavorite(favoriteId);
} else if (actionId === "_kicker_favorite_remove_from_activity") {
favoriteModel.removeFavoriteFrom(favoriteId, actionArgument.favoriteActivity);
} else if (actionId === "_kicker_favorite_add_to_activity") {
favoriteModel.addFavoriteTo(favoriteId, actionArgument.favoriteActivity);
} else if (actionId === "_kicker_favorite_set_to_activity") {
favoriteModel.setFavoriteOn(favoriteId, actionArgument.favoriteActivity);
}
}

View file

@ -0,0 +1,291 @@
/***************************************************************************
* Copyright (C) 2014-2015 by Eike Hein <hein@kde.org> *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA . *
***************************************************************************/
import QtQuick 2.0
import QtQuick.Layouts 1.1
import org.kde.plasma.plasmoid 2.0
import org.kde.plasma.core as PlasmaCore
import org.kde.plasma.components as PlasmaComponents
import org.kde.plasma.private.kicker 0.1 as Kicker
import org.kde.kquickcontrolsaddons as KQuickControlsAddons
import org.kde.kwindowsystem
import org.kde.ksvg as KSvg
import org.kde.kirigami as Kirigami
import org.kde.plasma.plasma5support as Plasma5Support
PlasmoidItem {
id: kicker
signal reset
anchors.fill: parent
property bool isDash: false
property Item dragSource: null
switchWidth: isDash || !fullRepresentationItem ? 0 :fullRepresentationItem.Layout.minimumWidth
switchHeight: isDash || !fullRepresentationItem ? 0 :fullRepresentationItem.Layout.minimumHeight
property QtObject globalFavorites: rootModel.favoritesModel
property QtObject systemFavorites: rootModel.systemFavoritesModel
// I see what you did here
//property bool compositingEnabled: kwindowsystem.compositingActive
property bool compositingEnabled: KWindowSystem.isPlatformX11 ? KX11Extras.compositingActive : true
preferredRepresentation: isDash ? menuRepresentation : null
compactRepresentation: isDash ? null : compactRepresentation
fullRepresentation: isDash ? compactRepresentation : menuRepresentation
Plasmoid.constraintHints: Plasmoid.CanFillArea
// Runs KMenuEdit.
function action_menuedit() {
processRunner.runMenuEditor();
}
function action_taskman() {
menu_executable.exec("ksysguard");
}
Component {
id: compactRepresentation
CompactRepresentation {}
}
Component {
id: menuRepresentation
MenuRepresentation { }
}
// Used to run separate programs through this plasmoid.
Plasma5Support.DataSource {
id: menu_executable
engine: "executable"
connectedSources: []
onNewData: {
var exitCode = data["exit code"]
var exitStatus = data["exit status"]
var stdout = data["stdout"]
var stderr = data["stderr"]
exited(sourceName, exitCode, exitStatus, stdout, stderr)
disconnectSource(sourceName)
}
function exec(cmd) {
if (cmd) {
connectSource(cmd)
}
}
signal exited(string cmd, int exitCode, int exitStatus, string stdout, string stderr)
}
Kicker.WindowSystem {
id: windowSystem
}
Kicker.RecentUsageModel {
id: recentUsageModel
favoritesModel: globalFavorites
ordering: 0
shownItems: Kicker.RecentUsageModel.OnlyApps
}
Kicker.RunnerModel {
id: runnerModel
appletInterface: kicker
//query: kickoff.searchField ? kickoff.searchField.text : ""
//deleteWhenEmpty: false
favoritesModel: rootModel.favoritesModel
//runners: ["Dictionary","services","calculator","shell","org.kde.windowedwidgets","org.kde.datetime","baloosearch","locations","unitconverter","bookmarks", "krunner_services", "krunner_systemsettings", "krunner_sessions", "krunner_powerdevil"]
/*runners: {
const results = ["Dictionary","services","calculator","shell","org.kde.windowedwidgets","org.kde.datetime","baloosearch","locations","unitconverter","bookmarks", "krunner_services", "krunner_systemsettings", "krunner_sessions", "krunner_powerdevil"];
if (Plasmoid.configuration.useExtraRunners) {
results.push(...Plasmoid.configuration.extraRunners);
}
return results;
}*/
mergeResults: true
}
//KWindowSystem { id: kwindowsystem } // Used for detecting compositing changes.
Kicker.RootModel {
id: rootModel
autoPopulate: false
appNameFormat: Plasmoid.configuration.appNameFormat
flat: true
sorted: true
showSeparators: false
appletInterface: kicker
paginate: false
pageSize: Plasmoid.configuration.numberColumns * Plasmoid.configuration.numberRows
showAllApps: false
showAllAppsCategorized: false
showRecentApps: true
showRecentDocs: false
//showRecentContacts: false
showPowerSession: false
onFavoritesModelChanged: {
if ("initForClient" in favoritesModel) {
favoritesModel.initForClient("org.kde.plasma.kicker.favorites.instance-" + plasmoid.id)
if (!Plasmoid.configuration.favoritesPortedToKAstats) {
favoritesModel.portOldFavorites(Plasmoid.configuration.favoriteApps);
Plasmoid.configuration.favoritesPortedToKAstats = true;
}
} else {
favoritesModel.favorites = Plasmoid.configuration.favoriteApps;
}
favoritesModel.maxFavorites = pageSize;
}
onSystemFavoritesModelChanged: {
systemFavoritesModel.enabled = false;
systemFavoritesModel.favorites = Plasmoid.configuration.favoriteSystemActions;
systemFavoritesModel.maxFavorites = 8;
}
Component.onCompleted: {
if ("initForClient" in favoritesModel) {
favoritesModel.initForClient("org.kde.plasma.kicker.favorites.instance-" + plasmoid.id)
if (!Plasmoid.configuration.favoritesPortedToKAstats) {
favoritesModel.portOldFavorites(Plasmoid.configuration.favoriteApps);
Plasmoid.configuration.favoritesPortedToKAstats = true;
}
} else {
favoritesModel.favorites = Plasmoid.configuration.favoriteApps;
}
favoritesModel.maxFavorites = pageSize;
rootModel.refresh();
}
}
Connections {
target: globalFavorites
function onFavoritesChanged() {
Plasmoid.configuration.favoriteApps = target.favorites;
}
}
Connections {
target: systemFavorites
function onFavoritesChanged() {
Plasmoid.configuration.favoriteSystemActions = target.favorites;
}
}
Connections {
target: Plasmoid.configuration
function onFavoriteAppsChanged() {
globalFavorites.favorites = Plasmoid.configuration.favoriteApps;
}
function onFavoriteSystemActionsChanged() {
systemFavorites.favorites = Plasmoid.configuration.favoriteSystemActions;
}
}
Kicker.DragHelper {
id: dragHelper
}
Kicker.ProcessRunner {
id: processRunner
}
// SVGs
KSvg.FrameSvgItem {
id : highlightItemSvg
visible: false
imagePath: Qt.resolvedUrl("svgs/menuitem.svg")
prefix: "hover"
}
KSvg.FrameSvgItem {
id : panelSvg
visible: false
imagePath: "widgets/panel-background"
}
KSvg.Svg {
id: arrowsSvg
imagePath: Qt.resolvedUrl("svgs/arrows.svgz")
size: "16x16"
}
KSvg.Svg {
id: separatorSvg
imagePath: Qt.resolvedUrl("svgs/sidebarseparator.svg")
}
KSvg.Svg {
id: lockScreenSvg
imagePath: Qt.resolvedUrl("svgs/system-lock-screen.svg")
}
PlasmaComponents.Label {
id: toolTipDelegate
width: contentWidth
height: contentHeight
property Item toolTip
text: (toolTip != null) ? toolTip.text : ""
}
function resetDragSource() {
dragSource = null;
}
function enableHideOnWindowDeactivate() {
kicker.hideOnWindowDeactivate = true;
}
Plasmoid.contextualActions: [
PlasmaCore.Action {
text: i18n("Edit Applications...")
icon.name: "application-menu"
onTriggered: menu_executable.exec("kmenuedit");
},
PlasmaCore.Action {
text: i18n("Task Manager")
icon.name: "ksysguardd"
onTriggered: menu_executable.exec("ksysguard");
}
]
Component.onCompleted: {
if (Plasmoid.hasOwnProperty("activationTogglesExpanded")) {
Plasmoid.activationTogglesExpanded = !kicker.isDash
}
windowSystem.focusIn.connect(enableHideOnWindowDeactivate);
kicker.hideOnWindowDeactivate = true;
rootModel.refreshed.connect(reset);
dragHelper.dropped.connect(resetDragSource);
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

File diff suppressed because it is too large Load diff

After

Width:  |  Height:  |  Size: 141 KiB

File diff suppressed because it is too large Load diff

After

Width:  |  Height:  |  Size: 41 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 115 KiB

File diff suppressed because it is too large Load diff

After

Width:  |  Height:  |  Size: 64 KiB

File diff suppressed because it is too large Load diff

After

Width:  |  Height:  |  Size: 38 KiB

File diff suppressed because it is too large Load diff

After

Width:  |  Height:  |  Size: 115 KiB

View file

@ -0,0 +1,54 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
version="1.1"
viewBox="0 0 32 32"
id="svg7"
sodipodi:docname="system-lock-screen.svg"
inkscape:version="1.2.1 (9c6d41e410, 2022-07-14, custom)"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg">
<sodipodi:namedview
id="namedview9"
pagecolor="#505050"
bordercolor="#ffffff"
borderopacity="1"
inkscape:pageshadow="0"
inkscape:pageopacity="0"
inkscape:pagecheckerboard="1"
showgrid="false"
inkscape:zoom="10.0625"
inkscape:cx="9.689441"
inkscape:cy="15.204969"
inkscape:window-width="1440"
inkscape:window-height="874"
inkscape:window-x="1600"
inkscape:window-y="150"
inkscape:window-maximized="1"
inkscape:current-layer="svg7"
inkscape:showpageshadow="2"
inkscape:deskcolor="#505050" />
<defs
id="defs3">
<style
type="text/css"
id="current-color-scheme">
.ColorScheme-Text {
color:#eff0f1;
}
</style>
</defs>
<path
class="ColorScheme-Text"
d="m 16,8 c -2.216,0 -4,1.784 -4,4 v 4 h -2 v 8 H 22 V 16 H 20 V 12 C 20,9.784 18.216,8 16,8 Z m 0,1 c 1.662,0 3,1.561 3,3.5 V 16 H 13 V 12.5 C 13,10.561 14.338,9 16,9 Z"
fill="currentColor"
id="light-lock"
sodipodi:nodetypes="ssccccccssssccss" />
<path
d="m 16,8 c -2.216,0 -4,1.784 -4,4 v 4 h -2 v 8 H 22 V 16 H 20 V 12 C 20,9.784 18.216,8 16,8 Z m 0,1 c 1.662,0 3,1.561 3,3.5 V 16 H 13 V 12.5 C 13,10.561 14.338,9 16,9 Z"
fill="currentColor"
id="dark-lock"
sodipodi:nodetypes="ssccccccssssccss"
style="fill:#202020;fill-opacity:1" />
</svg>

After

Width:  |  Height:  |  Size: 1.8 KiB