Initial import

This is an import of Kickoff launcher before the redesign in 5.21
Note that this launcher won't be supported, so there won't be any bugfixes
Outside of potential backports (Not guaranteed)
This commit is contained in:
Mikel Johnson
2021-01-03 13:18:29 +03:00
commit 451f3f177e
28 changed files with 3841 additions and 0 deletions

View File

@ -0,0 +1,29 @@
/*
* Copyright 2013 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 2.010-1301, USA.
*/
import QtQuick 2.0
import org.kde.plasma.configuration 2.0
ConfigModel {
ConfigCategory {
name: i18n("General")
icon: "preferences-desktop-plasma"
source: "ConfigGeneral.qml"
}
}

View File

@ -0,0 +1,43 @@
<?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="switchTabsOnHover" type="Bool">
<label>Whether to switch between menu tabs by hovering them.</label>
<default>true</default>
</entry>
<entry name="showAppsByName" type="Bool">
<label>Whether to display specific application names instead of their generic names (e.g. Dolphin instead of File Manager).</label>
<default>true</default>
</entry>
<entry name="icon" type="String">
<label>The name of the icon used in the compact representation (e.g. on a small panel).</label>
<default>start-here-kde</default>
</entry>
<entry name="favorites" type="StringList">
<label>List of general favorites. Supported values are menu id's (usually .desktop file names), special URLs that expand into default applications (e.g. preferred://browser), document URLs and KPeople contact URIs.</label>
<default>preferred://browser,kontact.desktop,systemsettings.desktop,org.kde.dolphin.desktop,ktp-contactlist.desktop,org.kde.kate.desktop,org.kde.discover.desktop</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="systemApplications" type="StringList">
<label>List of applications at the top of the "Computer" tab.</label>
<default>systemsettings.desktop,org.kde.kinfocenter.desktop,org.kde.discover.desktop</default>
</entry>
<entry name="menuItems" type="StringList">
<label>The menu tabs to show.</label>
<default>bookmark:t,application:t,computer:t,used:t,oftenUsed:f,leave:t</default>
</entry>
<entry name="alphaSort" type="Bool">
<label>Whether to sort menu contents alphabetically or use manual/system sort order.</label>
<default>false</default>
</entry>
</group>
</kcfg>

View File

@ -0,0 +1,144 @@
/***************************************************************************
* Copyright (C) 2013 by Aurélien Gâteau <agateau@kde.org> *
* 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 org.kde.plasma.components 2.0 as PlasmaComponents
Item {
id: root
property QtObject menu
property Item visualParent
property variant actionList
property bool opened: menu ? (menu.status !== PlasmaComponents.DialogStatus.Closed) : false
signal actionClicked(string actionId, variant actionArgument)
signal closed
onActionListChanged: refreshMenu();
onOpenedChanged: {
if (!opened) {
closed();
}
}
function open(x, y) {
if (!actionList || !actionList.length) {
return;
}
if (x && y) {
menu.open(x, y);
} else {
menu.open();
}
}
function refreshMenu() {
if (menu) {
menu.destroy();
}
if (!actionList) {
return;
}
menu = contextMenuComponent.createObject(root);
// actionList.forEach(function(actionItem) {
// var item = contextMenuItemComponent.createObject(menu, {
// "actionItem": actionItem,
// });
// });
fillMenu(menu, actionList);
}
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,
}
);
}
});
}
Component {
id: contextMenuComponent
PlasmaComponents.ContextMenu {
visualParent: root.visualParent
}
}
Component {
id: contextSubmenuItemComponent
PlasmaComponents.MenuItem {
id: submenuItem
property variant actionItem
text: actionItem.text ? actionItem.text : ""
icon: actionItem.icon ? actionItem.icon : null
property variant submenu : submenu_
PlasmaComponents.ContextMenu {
id: submenu_
visualParent: submenuItem.action
}
}
}
Component {
id: contextMenuItemComponent
PlasmaComponents.MenuItem {
property variant actionItem
text : actionItem.text ? actionItem.text : ""
enabled : actionItem.type !== "title" && ("enabled" in actionItem ? actionItem.enabled : true)
separator : actionItem.type === "separator"
section : actionItem.type === "title"
icon : actionItem.icon ? actionItem.icon : null
checkable : actionItem.checkable ? actionItem.checkable : false
checked : actionItem.checked ? actionItem.checked : false
onClicked: {
actionClicked(actionItem.actionId, actionItem.actionArgument);
}
}
}
}

View File

@ -0,0 +1,285 @@
/*
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 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 2.0 as PlasmaComponents
Item {
id: appViewContainer
anchors.fill: parent
objectName: "ApplicationsView"
property ListView listView: applicationsView.listView
function decrementCurrentIndex() {
applicationsView.decrementCurrentIndex();
}
function incrementCurrentIndex() {
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;
}
function reset() {
applicationsView.model = rootModel;
applicationsView.clearBreadcrumbs();
}
function refreshed() {
reset();
updatedLabelTimer.running = true;
}
Connections {
target: plasmoid
function onExpandedChanged() {
if (!plasmoid.expanded) {
reset();
}
}
}
Item {
id: crumbContainer
anchors {
top: parent.top
left: parent.left
right: parent.right
}
height: childrenRect.height
Behavior on opacity { NumberAnimation { duration: PlasmaCore.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
PlasmaComponents.ButtonRow {
id: breadcrumbsElement
exclusive: false
Breadcrumb {
id: rootBreadcrumb
root: true
text: i18n("All Applications")
depth: 0
}
Repeater {
model: ListModel {
id: crumbModel
// Array of the models
property var models: []
}
Breadcrumb {
root: false
text: model.text
}
}
onWidthChanged: {
if (LayoutMirroring.enabled) {
breadcrumbFlickable.contentX = -Math.max(0, breadcrumbsElement.width - breadcrumbFlickable.width)
} else {
breadcrumbFlickable.contentX = Math.max(0, breadcrumbsElement.width - breadcrumbFlickable.width)
}
}
}
} // Flickable
} // crumbContainer
KickoffListView {
id: applicationsView
anchors {
top: crumbContainer.bottom
bottom: parent.bottom
rightMargin: -PlasmaCore.Units.largeSpacing
leftMargin: -PlasmaCore.Units.largeSpacing
}
width: parent.width
property Item activatedItem: null
property var newModel: null
Behavior on opacity { NumberAnimation { duration: PlasmaCore.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);
}
function moveRight() {
state = "";
activatedItem.activate()
applicationsView.listView.positionViewAtBeginning()
}
function clearBreadcrumbs() {
crumbModel.clear();
crumbModel.models = [];
}
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: "x,opacity"; easing.type: Easing.InQuad; duration: PlasmaCore.Units.longDuration }
ScriptAction { script: applicationsView.moveRight() }
}
},
Transition {
to: "OutgoingRight"
SequentialAnimation {
NumberAnimation { properties: "x,opacity"; easing.type: Easing.InQuad; duration: PlasmaCore.Units.longDuration }
ScriptAction { script: applicationsView.moveLeft() }
}
}
]
}
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: PlasmaCore.Units.shortDuration } }
}
Component.onCompleted: {
rootModel.cleared.connect(refreshed);
}
} // appViewContainer

View File

@ -0,0 +1,67 @@
/*
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 2.0 as PlasmaComponents
import org.kde.draganddrop 2.0
Item {
property alias model: baseView.model
property alias delegate: baseView.delegate
property ListView listView: baseView.listView
function decrementCurrentIndex() {
baseView.decrementCurrentIndex();
}
function incrementCurrentIndex() {
baseView.incrementCurrentIndex();
}
function activateCurrentIndex() {
baseView.currentItem.activate();
}
function openContextMenu() {
baseView.currentItem.openActionMenu();
}
Connections {
target: plasmoid
function onExpandedChanged() {
if (!plasmoid.expanded) {
baseView.currentIndex = -1;
}
}
}
KickoffListView {
id: baseView
anchors.fill: parent
currentIndex: -1
interactive: contentHeight > height
}
}

View File

@ -0,0 +1,74 @@
/*
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 2.0 as PlasmaComponents
Item {
id: crumbRoot
height: crumb.implicitHeight
width: crumb.implicitWidth + arrowSvg.width
property string text
property bool root: false
property int depth: model.depth
function clickCrumb() {
crumb.clicked();
}
PlasmaComponents.ToolButton {
id: crumb
anchors.left: arrowSvg.right
text: crumbRoot.text
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";
}
}
PlasmaCore.SvgItem {
id: arrowSvg
anchors.left: parent.left
anchors.verticalCenter: parent.verticalCenter
height: crumbRoot.height / 2
width: visible ? height : 0
svg: PlasmaCore.Svg {
imagePath: "icons/go"
}
elementId: LayoutMirroring.enabled ? "go-previous" : "go-next"
visible: !crumbRoot.root
}
} // crumbRoot

View File

@ -0,0 +1,55 @@
/*
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>
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.private.kicker 0.1 as Kicker
BaseView {
objectName: "ComputerView"
model: Kicker.ComputerModel {
id: computerModel
appNameFormat: rootModel.appNameFormat
appletInterface: plasmoid
favoritesModel: globalFavorites
Component.onCompleted: {
systemApplications = plasmoid.configuration.systemApplications;
}
}
Connections {
target: computerModel
function onSystemApplicationsChanged() {
plasmoid.configuration.systemApplications = target.systemApplications;
}
}
Connections {
target: plasmoid.configuration
function onSystemApplicationsChanged() {
computerModel.systemApplications = plasmoid.configuration.systemApplications;
}
}
}

View File

@ -0,0 +1,227 @@
/*
* Copyright 2016 John Salatas <jsalatas@gmail.com>
*
* 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.5
import QtQml.Models 2.1
import org.kde.plasma.core 2.0 as PlasmaCore
import org.kde.kirigami 2.5 as Kirigami
GridView {
id: configButtons
cellHeight: PlasmaCore.Units.gridUnit * 5 + PlasmaCore.Units.smallSpacing
cellWidth: PlasmaCore.Units.gridUnit * 5
implicitWidth: cellWidth * 5
implicitHeight: cellHeight * 2
property var items: {
"bookmark": { icon: "bookmarks", text: i18n("Favorites")},
"application": { icon: "applications-other", text: i18n("Applications")},
"computer": { icon: "pm", text: i18n("Computer")},
"used": { icon: "view-history", text: i18n("History")},
"oftenUsed": { icon: "office-chart-pie", text: i18n("Often Used")},
"leave": { icon: "system-log-out", text: i18n("Leave")}
}
property var menuItems
property var previousCell: [-1, -1]
property alias listModel: visualModel.model
property int sourceIndex: -1
Component.onCompleted: {
menuItems = plasmoid.configuration.menuItems;
resetModel();
}
function updateModel() {
var enabledItems = [];
var disabledItems = [];
for(var i = 0; i < menuItems.length; i++) {
var confItemName = menuItems[i].substring(0, menuItems[i].indexOf(":"));
var confItemEnabled = menuItems[i].substring(menuItems[i].length-1) === "t";
var listItem = items[confItemName];
listItem['name'] = confItemName;
listItem['enabled'] = confItemEnabled;
if(confItemEnabled) {
enabledItems.push(listItem);
} else {
disabledItems.push(listItem);
}
}
fillEmpty(enabledItems);
fillEmpty(disabledItems);
return enabledItems.concat(disabledItems);
}
function fillEmpty(list) {
var emptyItem = { icon: undefined, text: undefined, name: 'empty', enabled: undefined};
var itemsToAdd = 5 - list.length;
for(var j = 0; j < itemsToAdd; j++) {
list.push(emptyItem);
}
}
function updateConfiguration() {
menuItems = [];
for(var i = 0; i < visualModel.items.count; i++) {
var itemName = visualModel.items.get(i).model['name'];
if(itemName !== 'empty') {
var configItem = itemName +":" +(i<5?"t":"f");
menuItems.push(configItem);
}
}
resetModel();
}
function resetModel() {
listModel.clear();
var items = updateModel();
for(var i = 0; i< items.length; i++) {
listModel.append(items[i]);
}
}
displaced: Transition {
NumberAnimation { properties: "x,y"; easing.type: Easing.OutQuad }
}
PlasmaCore.DataSource {
id: pmSource
engine: "powermanagement"
connectedSources: ["PowerDevil"]
}
model: DelegateModel {
id: visualModel
model: ListModel {
id: listModel
}
delegate: MouseArea {
id: delegateRoot
width: PlasmaCore.Units.gridUnit * 5
height: PlasmaCore.Units.gridUnit * 4
property int visualIndex: DelegateModel.itemsIndex
drag.target: button
onReleased: {
button.Drag.drop()
}
KickoffConfigurationButton {
id: button
icon: model.icon === "pm" ? (pmSource.data["PowerDevil"] && pmSource.data["PowerDevil"]["Is Lid Present"] ? "computer-laptop" : "computer") : model.icon
text: model.text || ""
name: model.name
anchors {
horizontalCenter: parent.horizontalCenter;
verticalCenter: parent.verticalCenter
}
Drag.active: delegateRoot.drag.active && name != 'empty'
Drag.source: delegateRoot
Drag.hotSpot.x: 36
Drag.hotSpot.y: 36
onStateChanged: {
if(!Drag.active && sourceIndex != -1) {
sourceIndex = -1;
updateConfiguration();
}
}
states: [
State {
when: button.Drag.active
ParentChange {
target: button;
parent: root;
}
AnchorChanges {
target: button;
anchors.horizontalCenter: undefined;
anchors.verticalCenter: undefined;
}
}
]
}
DropArea {
anchors { fill: parent; margins: 15 }
onEntered: {
var source = drag.source.visualIndex;
var target = delegateRoot.visualIndex;
sourceIndex = drag.source.visualIndex;
if(!(previousCell[0] === source && previousCell[1] === target)) {
previousCell = [source, target];
if(source < 5 && target >= 5) {
visualModel.items.move(source, target);
visualModel.items.move(target === 9 ? 8 : 9, 4);
} else if (source >= 5 && target < 5) {
visualModel.items.move(source, target);
visualModel.items.move(5, 9);
} else {
visualModel.items.move(source, target);
}
}
}
onDropped: {
var targetIndex = drag.source.visualIndex;
updateConfiguration();
sourceIndex = -1;
previousCell = [-1, -1];
}
}
}
}
header: Kirigami.Heading {
level: 2
text: i18n("Active Tabs")
width: parent.width
horizontalAlignment: Text.AlignHCenter
}
// the middle label is placed right the middle of the grid view, which is a single grid with a gap in the middle
Kirigami.Heading {
level: 2
text: i18n("Inactive Tabs")
anchors.top: configButtons.verticalCenter
width: parent.width
horizontalAlignment: Text.AlignHCenter
}
}

View File

@ -0,0 +1,129 @@
/*
* Copyright 2013 David Edmundson <davidedmundson@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 2.010-1301, USA.
*/
import QtQuick 2.5
import QtQuick.Layouts 1.1
import QtQuick.Controls 2.5
import org.kde.plasma.core 2.0 as PlasmaCore
import org.kde.kquickcontrolsaddons 2.0 as KQuickAddons
import org.kde.kirigami 2.5 as Kirigami
ColumnLayout {
property string cfg_icon: plasmoid.configuration.icon
property alias cfg_switchTabsOnHover: switchTabsOnHoverCheckbox.checked
property alias cfg_showAppsByName: showApplicationsByNameCheckbox.checked
property alias cfg_alphaSort: alphaSort.checked
property alias cfg_menuItems: configButtons.menuItems
Kirigami.FormLayout {
Button {
id: iconButton
Kirigami.FormData.label: i18n("Icon:")
implicitWidth: previewFrame.width + PlasmaCore.Units.smallSpacing * 2
implicitHeight: previewFrame.height + PlasmaCore.Units.smallSpacing * 2
KQuickAddons.IconDialog {
id: iconDialog
onIconNameChanged: cfg_icon = iconName || "start-here-kde"
}
onPressed: iconMenu.opened ? iconMenu.close() : iconMenu.open()
PlasmaCore.FrameSvgItem {
id: previewFrame
anchors.centerIn: parent
imagePath: plasmoid.location === PlasmaCore.Types.Vertical || plasmoid.location === PlasmaCore.Types.Horizontal
? "widgets/panel-background" : "widgets/background"
width: PlasmaCore.Units.iconSizes.large + fixedMargins.left + fixedMargins.right
height: PlasmaCore.Units.iconSizes.large + fixedMargins.top + fixedMargins.bottom
PlasmaCore.IconItem {
anchors.centerIn: parent
width: PlasmaCore.Units.iconSizes.large
height: width
source: cfg_icon
}
}
Menu {
id: iconMenu
// Appear below the button
y: +parent.height
MenuItem {
text: i18nc("@item:inmenu Open icon chooser dialog", "Choose...")
icon.name: "document-open-folder"
onClicked: iconDialog.open()
}
MenuItem {
text: i18nc("@item:inmenu Reset icon to default", "Clear Icon")
icon.name: "edit-clear"
onClicked: cfg_icon = "start-here-kde"
}
}
}
Item {
Kirigami.FormData.isSection: true
}
CheckBox {
id: switchTabsOnHoverCheckbox
Kirigami.FormData.label: i18n("General:")
text: i18n("Switch tabs on hover")
}
CheckBox {
id: showApplicationsByNameCheckbox
text: i18n("Show applications by name")
}
Button {
icon.name: "settings-configure"
text: i18n("Configure enabled search plugins")
onPressed: KQuickAddons.KCMShell.open(["kcm_plasmasearch"])
}
CheckBox {
id: alphaSort
text: i18n("Sort alphabetically")
}
}
ConfigButtons {
id: configButtons
Layout.alignment: Qt.AlignHCenter
}
Label {
Layout.fillWidth: true
text: i18n("Drag tabs between the boxes to show/hide them, or reorder the visible tabs by dragging.")
wrapMode: Text.WordWrap
horizontalAlignment: Text.AlignHCenter
}
Item {
Layout.fillHeight: true
}
}

View File

@ -0,0 +1,155 @@
/*
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.core 2.0 as PlasmaCore
import org.kde.plasma.extras 2.0 as PlasmaExtras
import org.kde.plasma.components 2.0 as PlasmaComponents
import org.kde.draganddrop 2.0
import org.kde.plasma.private.kicker 0.1 as Kicker
Item {
anchors.fill: parent
anchors.topMargin: PlasmaCore.Units.largeSpacing
objectName: "FavoritesView"
property ListView listView: favoritesView.listView
function decrementCurrentIndex() {
favoritesView.decrementCurrentIndex();
}
function incrementCurrentIndex() {
favoritesView.incrementCurrentIndex();
}
function activateCurrentIndex() {
favoritesView.currentItem.activate();
}
function openContextMenu() {
favoritesView.currentItem.openActionMenu();
}
// 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);
}
DropArea {
property int startRow: -1
anchors.fill: parent
enabled: plasmoid.immutability !== PlasmaCore.Types.SystemImmutable
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;
}
}
onDragEnter: {
syncTarget(event);
startRow = favoritesView.currentIndex;
}
onDragMove: syncTarget(event)
}
Transition {
id: moveTransition
SequentialAnimation {
PropertyAction { target: favoritesView; property: "animating"; value: true }
NumberAnimation {
duration: favoritesView.animationDuration
properties: "x, y"
easing.type: Easing.OutQuad
}
PropertyAction { target: favoritesView; property: "animating"; value: false }
}
}
Connections {
target: plasmoid
function onExpandedChanged() {
if (!plasmoid.expanded) {
favoritesView.currentIndex = -1;
}
}
}
KickoffListView {
id: favoritesView
anchors.fill: parent
property bool animating: false
property int animationDuration: resetAnimationDurationTimer.interval
interactive: contentHeight > height
move: moveTransition
moveDisplaced: moveTransition
model: globalFavorites
onCountChanged: {
animationDuration = 0;
resetAnimationDurationTimer.start();
}
}
Timer {
id: resetAnimationDurationTimer
interval: 150
onTriggered: favoritesView.animationDuration = interval - 20
}
}

View File

@ -0,0 +1,778 @@
/*
Copyright (C) 2011 Martin Gräßlin <mgraesslin@kde.org>
Copyright (C) 2012 Gregor Taetzner <gregor@freenet.de>
Copyright (C) 2012 Marco Martin <mart@kde.org>
Copyright (C) 2013 2014 David Edmundson <davidedmundson@kde.org>
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.3
import org.kde.plasma.plasmoid 2.0
import QtQuick.Layouts 1.1
import org.kde.plasma.core 2.0 as PlasmaCore
import org.kde.plasma.components 2.0 as PlasmaComponents
import org.kde.plasma.extras 2.0 as PlasmaExtras
import org.kde.kquickcontrolsaddons 2.0
import org.kde.plasma.private.kicker 0.1 as Kicker
Item {
id: root
Layout.minimumWidth: PlasmaCore.Units.gridUnit * 26
Layout.maximumWidth: Layout.minimumWidth
Layout.minimumHeight: PlasmaCore.Units.gridUnit * 34
Layout.maximumHeight: Layout.minimumHeight
property string previousState
property bool switchTabsOnHover: plasmoid.configuration.switchTabsOnHover
property Item currentView: mainTabGroup.currentTab.decrementCurrentIndex ? mainTabGroup.currentTab : mainTabGroup.currentTab.item
property KickoffButton firstButton: null
property var configMenuItems
property QtObject globalFavorites: rootModelFavorites
state: "Normal"
onFocusChanged: {
header.input.forceActiveFocus();
}
function switchToInitial() {
if (firstButton != null) {
root.state = "Normal";
mainTabGroup.currentTab = firstButton.tab;
tabBar.currentTab = firstButton;
header.query = ""
}
}
Kicker.DragHelper {
id: dragHelper
dragIconSize: PlasmaCore.Units.iconSizes.medium
onDropped: kickoff.dragSource = null
}
Kicker.AppsModel {
id: rootModel
autoPopulate: false
appletInterface: plasmoid
appNameFormat: plasmoid.configuration.showAppsByName ? 0 : 1
flat: false
sorted: plasmoid.configuration.alphaSort
showSeparators: false
showTopLevelItems: true
favoritesModel: Kicker.KAStatsFavoritesModel {
id: rootModelFavorites
favorites: plasmoid.configuration.favorites
onFavoritesChanged: {
plasmoid.configuration.favorites = favorites;
}
}
Component.onCompleted: {
favoritesModel.initForClient("org.kde.plasma.kickoff.favorites.instance-" + plasmoid.id)
if (!plasmoid.configuration.favoritesPortedToKAstats) {
favoritesModel.portOldFavorites(plasmoid.configuration.favorites);
plasmoid.configuration.favoritesPortedToKAstats = true;
}
rootModel.refresh();
}
}
PlasmaCore.DataSource {
id: pmSource
engine: "powermanagement"
connectedSources: ["PowerDevil"]
}
PlasmaCore.Svg {
id: arrowsSvg
imagePath: "widgets/arrows"
size: "16x16"
}
Header {
id: header
}
Item {
id: mainArea
anchors.topMargin: mainTabGroup.state == "top" ? PlasmaCore.Units.smallSpacing : 0
PlasmaComponents.TabGroup {
id: mainTabGroup
currentTab: favoritesPage
anchors {
fill: parent
}
//pages
FavoritesView {
id: favoritesPage
}
PlasmaExtras.ConditionalLoader {
id: applicationsPage
when: mainTabGroup.currentTab == applicationsPage
source: Qt.resolvedUrl("ApplicationsView.qml")
}
PlasmaExtras.ConditionalLoader {
id: systemPage
when: mainTabGroup.currentTab == systemPage
source: Qt.resolvedUrl("ComputerView.qml")
}
PlasmaExtras.ConditionalLoader {
id: recentlyUsedPage
when: mainTabGroup.currentTab == recentlyUsedPage
source: Qt.resolvedUrl("RecentlyUsedView.qml")
}
PlasmaExtras.ConditionalLoader {
id: oftenUsedPage
when: mainTabGroup.currentTab == oftenUsedPage
source: Qt.resolvedUrl("OftenUsedView.qml")
}
PlasmaExtras.ConditionalLoader {
id: leavePage
when: mainTabGroup.currentTab == leavePage
source: Qt.resolvedUrl("LeaveView.qml")
}
PlasmaExtras.ConditionalLoader {
id: searchPage
when: root.state == "Search"
//when: mainTabGroup.currentTab == searchPage || root.state == "Search"
source: Qt.resolvedUrl("SearchView.qml")
}
state: {
switch (plasmoid.location) {
case PlasmaCore.Types.LeftEdge:
return LayoutMirroring.enabled ? "right" : "left";
case PlasmaCore.Types.TopEdge:
return "top";
case PlasmaCore.Types.RightEdge:
return LayoutMirroring.enabled ? "left" : "right";
case PlasmaCore.Types.BottomEdge:
default:
return "bottom";
}
}
states: [
State {
name: "left"
AnchorChanges {
target: header
anchors {
left: root.left
top: undefined
right: root.right
bottom: root.bottom
}
}
PropertyChanges {
target: header
width: header.implicitWidth
location: PlasmaExtras.PlasmoidHeading.Location.Footer
}
AnchorChanges {
target: mainArea
anchors {
left: tabBar.right
top: root.top
right: root.right
bottom: header.top
}
}
PropertyChanges {
target: tabBar
width: (tabBar.opacity == 0) ? 0 : PlasmaCore.Units.gridUnit * 5
}
AnchorChanges {
target: tabBar
anchors {
left: root.left
top: root.top
right: undefined
bottom: header.top
}
}
PropertyChanges {
target:tabBarSeparator
width: tabBarSeparatorLine.elementSize("vertical-line").width
elementId: "vertical-line"
}
AnchorChanges {
target: tabBarSeparator
anchors {
left: tabBar.right
top: tabBar.top
bottom:tabBar.bottom
}
}
},
State {
name: "top"
AnchorChanges {
target: header
anchors {
left: root.left
top: undefined
right: root.right
bottom: root.bottom
}
}
PropertyChanges {
target: header
height: header.implicitHeight
location: PlasmaExtras.PlasmoidHeading.Location.Footer
}
AnchorChanges {
target: mainArea
anchors {
left: root.left
top: tabBar.bottom
right: root.right
bottom: header.top
}
}
PropertyChanges {
target: tabBar
height: (tabBar.opacity == 0) ? 0 : PlasmaCore.Units.gridUnit * 5
}
AnchorChanges {
target: tabBar
anchors {
left: root.left
top: root.top
right: root.right
bottom: undefined
}
}
PropertyChanges {
target:tabBarSeparator
height: tabBarSeparatorLine.elementSize("horizontal-line").height
elementId: "horizontal-line"
}
AnchorChanges {
target: tabBarSeparator
anchors {
left: tabBar.left
right: tabBar.right
top: tabBar.bottom
}
}
},
State {
name: "right"
AnchorChanges {
target: header
anchors {
left: root.left
top: undefined
right: root.right
bottom: root.bottom
}
}
PropertyChanges {
target: header
width: header.implicitWidth
location: PlasmaExtras.PlasmoidHeading.Location.Footer
}
AnchorChanges {
target: mainArea
anchors {
left: root.left
top: root.top
right: tabBar.left
bottom: header.top
}
}
PropertyChanges {
target: tabBar
width: (tabBar.opacity == 0) ? 0 : PlasmaCore.Units.gridUnit * 5
}
AnchorChanges {
target: tabBar
anchors {
left: undefined
top: root.top
right: root.right
bottom: header.top
}
}
PropertyChanges {
target:tabBarSeparator
width: tabBarSeparatorLine.elementSize("vertical-line").width
elementId: "vertical-line"
}
AnchorChanges {
target: tabBarSeparator
anchors {
right: tabBar.left
top: tabBar.top
bottom: tabBar.bottom
}
}
},
State {
name: "bottom"
AnchorChanges {
target: header
anchors {
left: root.left
top: root.top
right: root.right
bottom: undefined
}
}
PropertyChanges {
target: header
height: header.implicitHeight
location: PlasmaExtras.PlasmoidHeading.Location.Header
}
AnchorChanges {
target: mainArea
anchors {
left: root.left
top: header.bottom
right: root.right
bottom: tabBar.top
}
}
PropertyChanges {
target: tabBar
height: (tabBar.opacity == 0) ? 0 : PlasmaCore.Units.gridUnit * 5
}
AnchorChanges {
target: tabBar
anchors {
left: root.left
top: undefined
right: root.right
bottom: root.bottom
}
}
PropertyChanges {
target:tabBarSeparator
height: tabBarSeparatorLine.elementSize("horizontal-line").height
elementId: "horizontal-line"
}
AnchorChanges {
target: tabBarSeparator
anchors {
bottom: tabBar.top
left: tabBar.left
right: tabBar.right
}
}
}
]
} // mainTabGroup
}
PlasmaComponents.TabBar {
id: tabBar
property int count: 5 // updated in createButtons()
Behavior on width {
NumberAnimation { duration: PlasmaCore.Units.longDuration; easing.type: Easing.InQuad; }
enabled: plasmoid.expanded
}
Behavior on height {
NumberAnimation { duration: PlasmaCore.Units.longDuration; easing.type: Easing.InQuad; }
enabled: plasmoid.expanded
}
tabPosition: {
switch (plasmoid.location) {
case PlasmaCore.Types.TopEdge:
return Qt.TopEdge;
case PlasmaCore.Types.LeftEdge:
return Qt.LeftEdge;
case PlasmaCore.Types.RightEdge:
return Qt.RightEdge;
default:
return Qt.BottomEdge;
}
}
onCurrentTabChanged: header.input.forceActiveFocus();
Connections {
target: plasmoid
function onExpandedChanged() {
if(menuItemsChanged()) {
createButtons();
}
if (!plasmoid.expanded) {
switchToInitial();
}
}
}
} // tabBar
PlasmaCore.SvgItem {
id: tabBarSeparator
svg: PlasmaCore.Svg {
id: tabBarSeparatorLine
imagePath: "widgets/line"
}
}
MouseArea {
anchors.fill: tabBar
property var oldPos: null
enabled: root.state !== "Search"
hoverEnabled: root.switchTabsOnHover
onExited: {
// Reset so we switch immediately when MouseArea is entered
// freshly, e.g. from the panel.
oldPos = null;
clickTimer.stop();
}
onPositionChanged: {
// Reject multiple events with the same coordinates that QQuickWindow
// synthesizes.
if (oldPos === Qt.point(mouse.x, mouse.y)) {
return;
}
var button = tabBar.layout.childAt(mouse.x, mouse.y);
if (!button || button.objectName !== "KickoffButton") {
clickTimer.stop();
return;
}
// Switch immediately when MouseArea was freshly entered, e.g.
// from the panel.
if (oldPos === null) {
oldPos = Qt.point(mouse.x, mouse.y);
clickTimer.stop();
button.clicked();
return;
}
var dx = (mouse.x - oldPos.x);
var dy = (mouse.y - oldPos.y);
// Check Manhattan length against drag distance to get a decent
// pointer motion vector.
if ((Math.abs(dx) + Math.abs(dy)) > Qt.styleHints.startDragDistance) {
if (tabBar.currentTab !== button) {
var tabBarPos = mapToItem(tabBar, oldPos.x, oldPos.y);
oldPos = Qt.point(mouse.x, mouse.y);
var angleMouseMove = Math.atan2(dy, dx) * 180 / Math.PI;
var angleToCornerA = 0;
var angleToCornerB = 0;
switch (plasmoid.location) {
case PlasmaCore.Types.TopEdge: {
angleToCornerA = Math.atan2(tabBar.height - tabBarPos.y, 0 - tabBarPos.x);
angleToCornerB = Math.atan2(tabBar.height - tabBarPos.y, tabBar.width - tabBarPos.x);
break;
}
case PlasmaCore.Types.LeftEdge: {
angleToCornerA = Math.atan2(0 - tabBarPos.y, tabBar.width - tabBarPos.x);
angleToCornerB = Math.atan2(tabBar.height - tabBarPos.y, tabBar.width - tabBarPos.x);
break;
}
case PlasmaCore.Types.RightEdge: {
angleToCornerA = Math.atan2(0 - tabBarPos.y, 0 - tabBarPos.x);
angleToCornerB = Math.atan2(tabBar.height - tabBarPos.y, 0 - tabBarPos.x);
break;
}
// PlasmaCore.Types.BottomEdge
default: {
angleToCornerA = Math.atan2(0 - tabBarPos.y, 0 - tabBarPos.x);
angleToCornerB = Math.atan2(0 - tabBarPos.y, tabBar.width - tabBarPos.x);
}
}
// Degrees are nicer to debug than radians.
angleToCornerA = angleToCornerA * 180 / Math.PI;
angleToCornerB = angleToCornerB * 180 / Math.PI;
var lower = Math.min(angleToCornerA, angleToCornerB);
var upper = Math.max(angleToCornerA, angleToCornerB);
// If the motion vector is outside the angle range from oldPos to the
// relevant tab bar corners, switch immediately. Otherwise start the
// timer, which gets aborted should the pointer exit the tab bar
// early.
var inRange = (lower < angleMouseMove == angleMouseMove < upper);
// Mirror-flip.
if (plasmoid.location === PlasmaCore.Types.RightEdge ? inRange : !inRange) {
clickTimer.stop();
button.clicked();
return;
} else {
clickTimer.pendingButton = button;
clickTimer.start();
}
} else {
oldPos = Qt.point(mouse.x, mouse.y);
}
}
}
onClicked: {
clickTimer.stop();
var button = tabBar.layout.childAt(mouse.x, mouse.y);
if (!button || button.objectName !== "KickoffButton") {
return;
}
button.clicked();
}
Timer {
id: clickTimer
property Item pendingButton: null
interval: 250
onTriggered: {
if (pendingButton) {
pendingButton.clicked();
}
}
}
}
Keys.forwardTo: [tabBar.layout]
Keys.onPressed: {
if (mainTabGroup.currentTab == applicationsPage) {
if (event.key !== Qt.Key_Tab) {
root.state = "Applications";
}
}
switch(event.key) {
case Qt.Key_Up: {
currentView.decrementCurrentIndex();
event.accepted = true;
break;
}
case Qt.Key_Down: {
currentView.incrementCurrentIndex();
event.accepted = true;
break;
}
case Qt.Key_Left: {
if (header.input.focus && header.state == "query") {
break;
}
if (!currentView.deactivateCurrentIndex()) {
if (root.state == "Applications") {
mainTabGroup.currentTab = firstButton.tab;
tabBar.currentTab = firstButton;
}
root.state = "Normal"
}
event.accepted = true;
break;
}
case Qt.Key_Right: {
if (header.input.focus && header.state == "query") {
break;
}
currentView.activateCurrentIndex();
event.accepted = true;
break;
}
case Qt.Key_Tab: {
root.state == "Applications" ? root.state = "Normal" : root.state = "Applications";
event.accepted = true;
break;
}
case Qt.Key_Enter:
case Qt.Key_Return: {
currentView.activateCurrentIndex(1);
event.accepted = true;
break;
}
case Qt.Key_Escape: {
if (header.state != "query") {
plasmoid.expanded = false;
} else {
header.query = "";
}
event.accepted = true;
break;
}
case Qt.Key_Menu: {
currentView.openContextMenu();
event.accepted = true;
break;
}
default:
if (!header.input.focus) {
header.input.forceActiveFocus();
}
}
}
states: [
State {
name: "Normal"
PropertyChanges {
target: root
Keys.forwardTo: [tabBar.layout]
}
PropertyChanges {
target: tabBar
//Set the opacity and NOT the visibility, as visibility is recursive
//and this binding would be executed also on popup show/hide
//as recommended by the docs: https://doc.qt.io/qt-5/qml-qtquick-item.html#visible-prop
//plus, it triggers https://bugreports.qt.io/browse/QTBUG-66907
//in which a mousearea may think it's under the mouse while it isn't
opacity: tabBar.count > 1 ? 1 : 0
}
},
State {
name: "Applications"
PropertyChanges {
target: root
Keys.forwardTo: [root]
}
PropertyChanges {
target: tabBar
opacity: tabBar.count > 1 ? 1 : 0
}
},
State {
name: "Search"
PropertyChanges {
target: tabBar
opacity: 0
}
PropertyChanges {
target: mainTabGroup
currentTab: searchPage
}
PropertyChanges {
target: root
Keys.forwardTo: [root]
}
}
] // states
function getButtonDefinition(name) {
switch(name) {
case "bookmark":
return {id: "bookmarkButton", tab: favoritesPage, iconSource: "bookmarks", text: i18n("Favorites")};
case "application":
return {id: "applicationButton", tab: applicationsPage, iconSource: "applications-other", text: i18n("Applications")};
case "computer":
return {id: "computerButton", tab: systemPage, iconSource: pmSource.data["PowerDevil"] && pmSource.data["PowerDevil"]["Is Lid Present"] ? "computer-laptop" : "computer", text: i18n("Computer")};
case "used":
return {id: "usedButton", tab: recentlyUsedPage, iconSource: "view-history", text: i18n("History")};
case "oftenUsed":
return {id: "usedButton", tab: oftenUsedPage, iconSource: "office-chart-pie", text: i18n("Often Used")};
case "leave":
return {id: "leaveButton", tab: leavePage, iconSource: "system-log-out", text: i18n("Leave")};
}
}
Component {
id: kickoffButton
KickoffButton {}
}
Component.onCompleted: {
createButtons();
}
function getEnabled(configuration) {
var res = [];
for(var i = 0; i < configuration.length; i++) {
var confItemName = configuration[i].substring(0, configuration[i].indexOf(":"));
var confItemEnabled = configuration[i].substring(configuration[i].length-1) === "t";
if(confItemEnabled) {
res.push(confItemName);
}
}
return res;
}
function createButtons() {
configMenuItems = plasmoid.configuration.menuItems;
var menuItems = getEnabled(plasmoid.configuration.menuItems);
tabBar.count = menuItems.length
// remove old menu items
for(var i = tabBar.layout.children.length -1; i >= 0; i--) {
if(tabBar.layout.children[i].objectName === "KickoffButton") {
tabBar.layout.children[i].destroy();
}
}
for (var i = 0; i < menuItems.length; i++) {
var props = getButtonDefinition(menuItems[i]);
var button = kickoffButton.createObject(tabBar.layout, props);
if(i === 0) {
firstButton = button;
switchToInitial();
}
}
}
function menuItemsChanged() {
if(configMenuItems.length !== plasmoid.configuration.menuItems.length) {
return true;
}
for(var i = 0; i < configMenuItems.length; i++) {
if(configMenuItems[i] !== plasmoid.configuration.menuItems[i]) {
return true;
}
}
return false;
}
}

View File

@ -0,0 +1,163 @@
/*
* Copyright 2014 Sebastian Kügler <sebas@kde.org>
* SPDX-FileCopyrightText: (C) 2020 Carl Schwan <carl@carlschwan.eu>
*
* 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 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.kcoreaddons 1.0 as KCoreAddons
// While using Kirigami in applets is normally a no, we
// use Avatar, which doesn't need to read the colour scheme
// at all to function, so there won't be any oddities with colours.
import org.kde.kirigami 2.13 as Kirigami
import org.kde.kquickcontrolsaddons 2.0
import QtGraphicalEffects 1.0
PlasmaExtras.PlasmoidHeading {
id: header
implicitHeight: PlasmaCore.Units.gridUnit * 5
property alias query: queryField.text
property Item input: queryField
KCoreAddons.KUser {
id: kuser
}
state: "name"
states: [
State {
name: "name"
PropertyChanges {
target: nameLabel
opacity: 1
}
PropertyChanges {
target: infoLabel
opacity: 0
}
},
State {
name: "info"
PropertyChanges {
target: nameLabel
opacity: 0
}
PropertyChanges {
target: infoLabel
opacity: 1
}
}
] // states
RowLayout {
anchors.fill: parent
PlasmaComponents.RoundButton {
visible: KCMShell.authorize("kcm_users.desktop").length > 0
flat: true
Layout.preferredWidth: PlasmaCore.Units.gridUnit * 3
Layout.preferredHeight: PlasmaCore.Units.gridUnit * 3
Kirigami.Avatar {
source: kuser.faceIconUrl
name: nameLabel
anchors {
fill: parent
margins: PlasmaCore.Units.smallSpacing
}
}
onClicked: {
KCMShell.openSystemSettings("kcm_users")
}
}
ColumnLayout {
Layout.fillWidth: true
Layout.rightMargin: PlasmaCore.Units.gridUnit
Item {
Layout.fillWidth: true
Layout.preferredHeight: PlasmaCore.Units.gridUnit
PlasmaExtras.Heading {
id: nameLabel
anchors.fill: parent
level: 2
text: kuser.fullName
elide: Text.ElideRight
horizontalAlignment: Text.AlignLeft
verticalAlignment: Text.AlignBottom
Behavior on opacity { NumberAnimation { duration: PlasmaCore.Units.longDuration; easing.type: Easing.InOutQuad; } }
// Show the info instead of the user's name when hovering over it
MouseArea {
anchors.fill: nameLabel
hoverEnabled: true
onEntered: {
header.state = "info"
}
onExited: {
header.state = "name"
}
}
}
PlasmaExtras.Heading {
id: infoLabel
anchors.fill: parent
level: 5
opacity: 0
text: kuser.os !== "" ? i18n("%2@%3 (%1)", kuser.os, kuser.loginName, kuser.host) : i18n("%1@%2", kuser.loginName, kuser.host)
elide: Text.ElideRight
horizontalAlignment: Text.AlignLeft
verticalAlignment: Text.AlignBottom
Behavior on opacity { NumberAnimation { duration: PlasmaCore.Units.longDuration; easing.type: Easing.InOutQuad; } }
}
}
PlasmaComponents.TextField {
id: queryField
Layout.fillWidth: true
placeholderText: i18n("Search...")
clearButtonShown: true
onTextChanged: {
if (root.state != "Search") {
root.previousState = root.state;
root.state = "Search";
}
if (text == "") {
root.state = root.previousState;
}
}
}
}
}
}

View File

@ -0,0 +1,148 @@
/*
Copyright (C) 2011 Martin Gräßlin <mgraesslin@kde.org>
Copyright (C) 2012 Gregor Taetzner <gregor@freenet.de>
Copyright (C) 2012 Marco Martin <mart@kde.org>
Copyright (C) 2013 David Edmundson <davidedmundson@kde.org>
Copyright (C) 2015 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.plasma.components 2.0 as PlasmaComponents
import org.kde.plasma.extras 2.0 as PlasmaExtras
import org.kde.kquickcontrolsaddons 2.0
import org.kde.plasma.private.kicker 0.1 as Kicker
Item {
id: kickoff
readonly property bool inPanel: (plasmoid.location === PlasmaCore.Types.TopEdge
|| plasmoid.location === PlasmaCore.Types.RightEdge
|| plasmoid.location === PlasmaCore.Types.BottomEdge
|| plasmoid.location === PlasmaCore.Types.LeftEdge)
readonly property bool vertical: (plasmoid.formFactor === PlasmaCore.Types.Vertical)
Plasmoid.switchWidth: PlasmaCore.Units.gridUnit * 20
Plasmoid.switchHeight: PlasmaCore.Units.gridUnit * 30
Plasmoid.fullRepresentation: FullRepresentation {}
Plasmoid.icon: plasmoid.configuration.icon
Plasmoid.compactRepresentation: MouseArea {
id: compactRoot
Layout.minimumWidth: {
if (!inPanel) {
return PlasmaCore.Units.iconSizeHints.panel;
}
if (vertical) {
return -1;
} else {
return Math.min(PlasmaCore.Units.iconSizeHints.panel, parent.height) * buttonIcon.aspectRatio;
}
}
Layout.minimumHeight: {
if (!inPanel) {
return PlasmaCore.Units.iconSizeHints.panel;
}
if (vertical) {
return Math.min(PlasmaCore.Units.iconSizeHints.panel, parent.width) * buttonIcon.aspectRatio;
} else {
return -1;
}
}
Layout.maximumWidth: {
if (!inPanel) {
return -1;
}
if (vertical) {
return PlasmaCore.Units.iconSizeHints.panel;
} else {
return Math.min(PlasmaCore.Units.iconSizeHints.panel, parent.height) * buttonIcon.aspectRatio;
}
}
Layout.maximumHeight: {
if (!inPanel) {
return -1;
}
if (vertical) {
return Math.min(PlasmaCore.Units.iconSizeHints.panel, parent.width) * buttonIcon.aspectRatio;
} else {
return PlasmaCore.Units.iconSizeHints.panel;
}
}
hoverEnabled: true
onClicked: plasmoid.expanded = !plasmoid.expanded
DropArea {
id: compactDragArea
anchors.fill: parent
}
Timer {
id: expandOnDragTimer
interval: 250
running: compactDragArea.containsDrag
onTriggered: plasmoid.expanded = true
}
PlasmaCore.IconItem {
id: buttonIcon
readonly property double aspectRatio: (vertical ? implicitHeight / implicitWidth
: implicitWidth / implicitHeight)
anchors.fill: parent
source: plasmoid.icon
active: parent.containsMouse || compactDragArea.containsDrag
smooth: true
roundToIconSize: aspectRatio === 1
}
}
property Item dragSource: null
Kicker.ProcessRunner {
id: processRunner;
}
function action_menuedit() {
processRunner.runMenuEditor();
}
Component.onCompleted: {
if (plasmoid.hasOwnProperty("activationTogglesExpanded")) {
plasmoid.activationTogglesExpanded = true
}
if (plasmoid.immutability !== PlasmaCore.Types.SystemImmutable) {
plasmoid.setAction("menuedit", i18n("Edit Applications..."), "kmenuedit");
}
}
} // root

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 2.0
import org.kde.plasma.core 2.0 as PlasmaCore
import org.kde.plasma.components 2.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: PlasmaCore.Units.smallSpacing
left: parent.left
right: parent.right
verticalCenter: parent.verticalCenter
}
height: childrenRect.height
PlasmaCore.IconItem {
id: iconElement
anchors.horizontalCenter: parent.horizontalCenter
width: PlasmaCore.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,60 @@
/*
* Copyright 2016 John Salatas <jsalatas@gmail.com>
*
* 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.0
import org.kde.plasma.core 2.0 as PlasmaCore
import QtQuick.Controls 1.0 as QtControls
import QtQuick.Layouts 1.1
import org.kde.kquickcontrolsaddons 2.0
PlasmaCore.FrameSvgItem {
id: button
property alias icon: iconElement.source
property alias text: textElement.text
property string name
width: PlasmaCore.Units.gridUnit * 5
height: PlasmaCore.Units.gridUnit * 4
visible: name != "empty"
imagePath: "widgets/background"
ColumnLayout {
anchors.centerIn: parent
PlasmaCore.IconItem {
id: iconElement
Layout.alignment: Qt.AlignHCenter
Layout.preferredWidth: PlasmaCore.Units.iconSizes.medium
Layout.preferredHeight: width
source: icon
}
QtControls.Label {
id: textElement
Layout.alignment: Qt.AlignHCenter
horizontalAlignment: Text.AlignHCenter
elide: Text.ElideRight
color: PlasmaCore.ColorScope.textColor
font: theme.smallestFont
}
}
}

View File

@ -0,0 +1,31 @@
/*
* 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 2.0 as PlasmaComponents
Item {
PlasmaComponents.Highlight {
anchors {
fill: parent
leftMargin: PlasmaCore.Units.smallSpacing * 4
rightMargin: PlasmaCore.Units.smallSpacing * 4
}
}
}

View File

@ -0,0 +1,182 @@
/*
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 QtQuick 2.0
import org.kde.plasma.core 2.0 as PlasmaCore
import org.kde.plasma.components 2.0 as PlasmaComponents
import org.kde.draganddrop 2.0
import "code/tools.js" as Tools
Item {
id: listItem
enabled: !model.disabled
width: ListView.view.width
height: (PlasmaCore.Units.smallSpacing * 2) + 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)
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: {
var actionList = hasActionList ? model.actionList : [];
Tools.fillActionMenu(i18n, actionMenu, actionList, ListView.view.model.favoritesModel, model.favoriteId);
}
onActionTriggered: {
if (Tools.triggerAction(ListView.view.model, model.index, actionId, actionArgument) === true) {
plasmoid.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, display);
view.model = childModel;
} else {
view.model.trigger(index, "", null);
plasmoid.expanded = false;
listItem.reset();
}
}
function openActionMenu(x, y) {
aboutToShowActionMenu(actionMenu);
actionMenu.visualParent = listItem;
actionMenu.open(x, y);
}
ActionMenu {
id: actionMenu
onActionClicked: {
actionTriggered(actionId, actionArgument);
}
}
PlasmaCore.IconItem {
id: elementIcon
anchors {
left: parent.left
leftMargin: PlasmaCore.Units.smallSpacing * 6
verticalCenter: parent.verticalCenter
}
width: PlasmaCore.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 {
//bottom: elementIcon.verticalCenter
left: elementIcon.right
right: arrow.left
leftMargin: PlasmaCore.Units.smallSpacing * 4
rightMargin: PlasmaCore.Units.smallSpacing * 6
}
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
}
PlasmaComponents.Label {
id: subTitleElement
anchors {
left: titleElement.left
right: arrow.right
top: titleElement.bottom
}
height: implicitHeight
text: model.description || ""
opacity: isCurrent ? 0.8 : 0.6
font: theme.smallestFont
elide: Text.ElideMiddle
horizontalAlignment: Text.AlignLeft
}
PlasmaCore.SvgItem {
id: arrow
anchors {
right: parent.right
rightMargin: PlasmaCore.Units.smallSpacing * 6
verticalCenter: parent.verticalCenter
}
width: visible ? PlasmaCore.Units.iconSizes.small : 0
height: width
visible: (model.hasChildren === true)
opacity: (listItem.ListView.view.currentIndex === index) ? 1.0 : 0.4
svg: arrowsSvg
elementId: (Qt.application.layoutDirection == Qt.RightToLeft) ? "left-arrow" : "right-arrow"
}
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();
}
}
}
} // listItem

View File

@ -0,0 +1,210 @@
/*
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 2.0 as PlasmaComponents
FocusScope {
id: view
signal reset
signal addBreadcrumb(var model, string title)
readonly property Item listView: listView
readonly property Item scrollArea: scrollArea
property bool showAppsByName: true
property bool appView: false
property alias model: listView.model
property alias delegate: listView.delegate
property alias currentIndex: listView.currentIndex
property alias currentItem: listView.currentItem
property alias count: listView.count
property alias interactive: listView.interactive
property alias contentHeight: listView.contentHeight
property alias move: listView.move
property alias moveDisplaced: listView.moveDisplaced
function incrementCurrentIndex() {
listView.incrementCurrentIndex();
}
function decrementCurrentIndex() {
listView.decrementCurrentIndex();
}
Connections {
target: plasmoid
function onExpandedChanged() {
if (!plasmoid.expanded) {
listView.positionViewAtBeginning();
}
}
}
PlasmaExtras.ScrollArea {
id: scrollArea
frameVisible: false
anchors.fill: parent
ListView {
id: listView
focus: true
keyNavigationWraps: true
boundsBehavior: Flickable.StopAtBounds
highlight: KickoffHighlight {}
highlightMoveDuration : 0
highlightResizeDuration: 0
delegate: KickoffItem {
id: delegateItem
appView: view.appView
showAppsByName: view.showAppsByName
onReset: view.reset()
onAddBreadcrumb: view.addBreadcrumb(model, title)
}
section {
property: "group"
criteria: ViewSection.FullString
delegate: SectionDelegate {}
}
MouseArea {
anchors.left: parent.left
width: scrollArea.viewport.width
height: parent.height
id: mouseArea
property Item pressed: null
property int pressX: -1
property int pressY: -1
property bool tapAndHold: false
hoverEnabled: true
acceptedButtons: Qt.LeftButton | Qt.RightButton
onPressed: {
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;
pressX = mouse.x;
pressY = mouse.y;
}
}
onReleased: {
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();
}
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;
}
onPositionChanged: {
var mapped = listView.mapToItem(listView.contentItem, mouse.x, mouse.y);
var item = listView.itemAt(mapped.x, mapped.y);
if (item) {
listView.currentIndex = item.itemIndex;
} 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 = PlasmaCore.Units.iconSizes.huge
dragHelper.startDrag(kickoff, pressed.url, pressed.decoration);
} else {
dragHelper.dragIconSize = PlasmaCore.Units.iconSizes.medium
dragHelper.startDrag(kickoff, pressed.url, pressed.decoration);
}
pressed = null;
pressX = -1;
pressY = -1;
tapAndHold = false;
}
}
}
onContainsMouseChanged: {
if (!containsMouse) {
pressed = null;
pressX = -1;
pressY = -1;
tapAndHold = false;
}
}
onPressAndHold: {
if (mouse.source == Qt.MouseEventSynthesizedByQt) {
tapAndHold = true;
positionChanged(mouse);
}
}
}
}
}
}

View File

@ -0,0 +1,32 @@
/*
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>
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.private.kicker 0.1 as Kicker
BaseView {
objectName: "LeaveView"
model: Kicker.SystemModel {
favoritesModel: globalFavorites
}
delegate: KickoffItem {
usePlasmaIcon: true
}
}

View File

@ -0,0 +1,33 @@
/*
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 2.0 as PlasmaComponents
import org.kde.plasma.private.kicker 0.1 as Kicker
BaseView {
objectName: "OftenUsedView"
model: Kicker.RecentUsageModel {
favoritesModel: globalFavorites
ordering: 1 // Popular / Often Used
}
}

View File

@ -0,0 +1,31 @@
/*
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>
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 2.0 as PlasmaComponents
import org.kde.plasma.private.kicker 0.1 as Kicker
BaseView {
objectName: "RecentlyUsedView"
model: Kicker.RecentUsageModel {
favoritesModel: globalFavorites
}
}

View File

@ -0,0 +1,87 @@
/*
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 2.0 as PlasmaComponents
import org.kde.plasma.private.kicker 0.1 as Kicker
Item {
id: searchViewContainer
anchors.fill: parent
objectName: "SearchView"
function decrementCurrentIndex() {
searchView.decrementCurrentIndex();
}
function incrementCurrentIndex() {
searchView.incrementCurrentIndex();
}
function activateCurrentIndex() {
searchView.currentItem.activate();
}
function openContextMenu() {
searchView.currentItem.openActionMenu();
}
Kicker.RunnerModel {
id: runnerModel
appletInterface: plasmoid
mergeResults: true
favoritesModel: globalFavorites
}
Connections {
target: header
function onQueryChanged() {
runnerModel.query = header.query;
searchView.currentIndex = 0;
if (!header.query) {
searchView.model = null;
}
}
}
Connections {
target: runnerModel
function onCountChanged() {
if (runnerModel.count && !searchView.model) {
searchView.model = runnerModel.modelForRow(0);
}
}
}
KickoffListView {
id: searchView
anchors.fill: parent
showAppsByName: false //krunner results have the most relevant field in the "display" column, which is showAppsByName = false
}
}

View File

@ -0,0 +1,49 @@
/*
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 2.0 as PlasmaComponents
import org.kde.plasma.extras 2.0 as PlasmaExtras
Item {
id: sectionDelegate
width: parent.width
height: childrenRect.height
PlasmaExtras.Heading {
id: sectionHeading
anchors {
left: parent.left
right: parent.right
leftMargin: PlasmaCore.Units.gridUnit
}
y: Math.round(PlasmaCore.Units.gridUnit / 4)
level: 4
text: section
}
Item {
width: parent.width
height: Math.round(PlasmaCore.Units.gridUnit / 4)
anchors.left: parent.left
anchors.top: sectionHeading.bottom
}
} // sectionDelegate

View File

@ -0,0 +1,202 @@
/***************************************************************************
* Copyright (C) 2013 by Aurélien Gâteau <agateau@kde.org> *
* Copyright (C) 2013-2015 by Eike Hein <hein@kde.org> *
* Copyright (C) 2017 by 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 . *
***************************************************************************/
.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.push(separator);
// actionList = actions.concat(actionList); // this crashes Qt O.o
actionList.push.apply(actionList, actions);
} else {
actionList = actions;
}
}
actionMenu.actionList = actionList;
}
function createFavoriteActions(i18n, favoriteModel, favoriteId) {
if (favoriteModel === null || !favoriteModel.enabled || favoriteId == null) {
return null;
}
if (favoriteModel.activities === undefined ||
favoriteModel.activities.runningActivities.length <= 1) {
var action = {};
if (favoriteModel.isFavorite(favoriteId)) {
action.text = i18n("Remove from Favorites");
action.icon = "bookmark-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);
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;
console.log(actionId);
if (favoriteModel === null || favoriteId == null) {
return null;
}
if (actionId == "_kicker_favorite_remove") {
console.log("Removing from all activities");
favoriteModel.removeFavorite(favoriteId);
} else if (actionId == "_kicker_favorite_add") {
console.log("Adding to global activity");
favoriteModel.addFavorite(favoriteId);
} 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);
}
}