initial commit

This commit is contained in:
2025-05-04 23:56:04 +02:00
commit 4e10b4d2c2
354 changed files with 53348 additions and 0 deletions

View File

@@ -0,0 +1,35 @@
/*
* Copyright 2018 Michail Vourlakos <mvourlakos@gmail.com>
*
* This file is part of applet-window-title
*
* Latte-Dock 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.
*
* Latte-Dock 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, see <http://www.gnu.org/licenses/>.
*/
import QtQuick 2.0
import org.kde.plasma.configuration 2.0
ConfigModel {
ConfigCategory {
name: i18n("Appearance")
icon: "preferences-desktop-display-color"
source: "config/ConfigAppearance.qml"
}
ConfigCategory {
name: i18n("Behavior")
icon: "preferences-desktop"
source: "config/ConfigBehavior.qml"
}
}

View File

@@ -0,0 +1,118 @@
<?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="style" type="Enum">
<choices>
<choice name="Application"/>
<choice name="Title"/>
<choice name="ApplicationTitle"/>
<choice name="TitleApplication"/>
<choice name="NoText"/>
</choices>
<label>which style is going to be used for the application title/name</label>
<default>0</default>
</entry>
<entry name="showIcon" type="Bool">
<default>true</default>
<label>show available icon</label>
</entry>
<entry name="iconFillThickness" type="Bool">
<default>true</default>
<label>icon fills applet thickness in order to not look too small in some cases</label>
</entry>
<entry name="iconSize" type="Int">
<default>36</default>
<label>icon size when fill thickness is not enabled</label>
</entry>
<entry name="boldFont" type="Bool">
<default>true</default>
<label>bold text font</label>
</entry>
<entry name="italicFont" type="Bool">
<default>false</default>
<label>italic text font</label>
</entry>
<entry name="capitalFont" type="Bool">
<default>true</default>
<label>first letter is each word becomes capital</label>
</entry>
<entry name="lengthFirstMargin" type="Int">
<default>0</default>
<label>first margin used to increase or decrease the icons distance from surrounding applets</label>
</entry>
<entry name="lengthLastMargin" type="Int">
<default>0</default>
<label>last margin used to increase or decrease the icons distance from surrounding applets</label>
</entry>
<entry name="lengthMarginsLock" type="Bool">
<default>true</default>
<label>used only by the settings window in order to remember the user choice concerning the locker</label>
</entry>
<entry name="appMenuIsPresent" type="Bool">
<default>false</default>
<label>try to identify if appmenu exists in the same containment. This is set only with applets cooperation</label>
</entry>
<entry name="showAppMenuOnMouseEnter" type="Bool">
<default>false</default>
<label>will become hidden in favour of appmenu when the mouse enters the applet</label>
</entry>
<entry name="spacing" type="Int">
<default>4</default>
<label>spacing between icons</label>
</entry>
<entry name="inFillMode" type="Bool">
<default>false</default>
<label>applet fills all available space in the panel</label>
</entry>
<entry name="showTooltip" type="Bool">
<default>true</default>
<label>display tooltip on hover</label>
</entry>
<entry name="maximumLength" type="Int">
<default>1500</default>
<label>maximum length when the user shows window title</label>
</entry>
<entry name="filterByScreen" type="Bool">
<default>false</default>
<label>If true, it shows window information only from the current screen</label>
</entry>
<entry name="filterActivityInfo" type="Bool">
<default>true</default>
<label>If false, it shows only the placeHolder text</label>
</entry>
<entry name="placeHolder" type="string">
<default></default>
<label>The text shown if nothing else is available</label>
</entry>
<entry name="formFactor" type="Int">
<default>2</default>
<label>it is used in order to inform settings window about the plasmoid form factor. 2=Horizontal and 3=Vertical</label>
</entry>
<entry name="containmentType" type="Enum">
<choices>
<choice name="Loading"/>
<choice name="Plasma"/>
<choice name="Latte"/>
</choices>
<label>it helps to enable/disable options that are specific to plasma or Latte panels</label>
<default>0</default>
</entry>
<entry name="subsMatch" type="StringList">
<default>"Telegram Desktop","Gimp-.*"</default>
<label>substitutions criteria - match for application names</label>
</entry>
<entry name="subsReplace" type="StringList">
<default>"Telegram","Gimp"</default>
<label>substitutions replacements for application names</label>
</entry>
<entry name="actionScrollMinimize" type="Bool">
<default>true</default>
<label>If true, upward mouse scrolling cycles through tasks and downwards can be used to minimize them</label>
</entry>
</group>
</kcfg>

View File

@@ -0,0 +1,47 @@
/*
* Copyright 2018 Michail Vourlakos <mvourlakos@gmail.com>
*
* This file is part of applet-window-title
*
* Latte-Dock 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.
*
* Latte-Dock 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, see <http://www.gnu.org/licenses/>.
*/
function qBound(min,value,max)
{
return Math.max(Math.min(max, root.width - 150), min);
}
function cleanStringListItem(item)
{
//console.log(item + " * " + item.length + " * " + item.indexOf('"') + " * " + item.lastIndexOf('"'));
if (item.length>=2 && item.indexOf('"')===0 && item.lastIndexOf('"')===item.length-1) {
return item.substring(1, item.length-1);
} else {
return item;
}
}
function applySubstitutes(text)
{
var minSize = Math.min(plasmoid.configuration.subsMatch.length, plasmoid.configuration.subsReplace.length);
for (var i = 0; i<minSize; ++i){
var fromS = cleanStringListItem(plasmoid.configuration.subsMatch[i]);
var toS = cleanStringListItem(plasmoid.configuration.subsReplace[i]);
var regEx = new RegExp(fromS, "ig"); //case insensitive
text = text.replace(regEx,toS);
}
return text;
}

View File

@@ -0,0 +1,103 @@
/*
* Copyright 2020 Michail Vourlakos <mvourlakos@gmail.com>
*
* This file is part of applet-window-title
*
* Latte-Dock 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.
*
* Latte-Dock 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, see <http://www.gnu.org/licenses/>.
*/
import QtQuick 2.7
import org.kde.plasma.plasmoid 2.0
MouseArea {
id: actionsArea
acceptedButtons: Qt.LeftButton | Qt.MidButton
hoverEnabled: true
property bool wheelIsBlocked: false
onClicked: {
if (existsWindowActive && mouse.button === Qt.MidButton) {
windowInfoLoader.item.requestClose();
}
}
onDoubleClicked: {
if (existsWindowActive && mouse.button === Qt.LeftButton) {
windowInfoLoader.item.toggleMaximized();
}
}
onWheel: {
if (wheelIsBlocked || !plasmoid.configuration.actionScrollMinimize) {
return;
}
wheelIsBlocked = true;
scrollDelayer.start();
var delta = 0;
if (wheel.angleDelta.y>=0 && wheel.angleDelta.x>=0) {
delta = Math.max(wheel.angleDelta.y, wheel.angleDelta.x);
} else {
delta = Math.min(wheel.angleDelta.y, wheel.angleDelta.x);
}
var angle = delta / 8;
var ctrlPressed = (wheel.modifiers & Qt.ControlModifier);
if (angle>10) {
//! upwards
if (!ctrlPressed) {
windowInfoLoader.item.activateNextPrevTask(true);
} else if (windowInfoLoader.item.activeTaskItem
&& !windowInfoLoader.item.activeTaskItem.isMaximized){
windowInfoLoader.item.toggleMaximized();
}
} else if (angle<-10) {
//! downwards
if (!ctrlPressed) {
if (windowInfoLoader.item.activeTaskItem
&& !windowInfoLoader.item.activeTaskItem.isMinimized
&& windowInfoLoader.item.activeTaskItem.isMaximized){
//! maximized
windowInfoLoader.item.activeTaskItem.toggleMaximized();
} else if (windowInfoLoader.item.activeTaskItem
&& !windowInfoLoader.item.activeTaskItem.isMinimized
&& !windowInfoLoader.item.activeTaskItem.isMaximized) {
//! normal
windowInfoLoader.item.activeTaskItem.toggleMinimized();
}
} else if (windowInfoLoader.item.activeTaskItem
&& windowInfoLoader.item.activeTaskItem.isMaximized) {
windowInfoLoader.item.activeTaskItem.toggleMaximized();
}
}
}
//! A timer is needed in order to handle also touchpads that probably
//! send too many signals very fast. This way the signals per sec are limited.
//! The user needs to have a steady normal scroll in order to not
//! notice a annoying delay
Timer{
id: scrollDelayer
interval: 200
onTriggered: actionsArea.wheelIsBlocked = false;
}
}

View File

@@ -0,0 +1,147 @@
/*
* Copyright 2019 Michail Vourlakos <mvourlakos@gmail.com>
*
* This file is part of applet-window-title
*
* Latte-Dock 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.
*
* Latte-Dock 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, see <http://www.gnu.org/licenses/>.
*/
import QtQuick 2.7
import org.kde.plasma.plasmoid 2.0
import org.kde.plasma.core 2.0 as PlasmaCore
Item{
id: broadcaster
property bool hiddenFromBroadcast: false
readonly property bool showAppMenuEnabled: plasmoid.configuration.showAppMenuOnMouseEnter
property bool appMenuRequestsCooperation: false
property bool menuIsPresent: false
readonly property bool cooperationEstablished: appMenuRequestsCooperation && isActive
readonly property bool isActive: plasmoid.configuration.appMenuIsPresent && showAppMenuEnabled
function sendMessage() {
if (cooperationEstablished && menuIsPresent) {
broadcasterDelayer.start();
}
}
function cancelMessage() {
if (cooperationEstablished) {
broadcasterDelayer.stop();
}
}
Component.onDestruction: {
if (latteBridge) {
latteBridge.actions.broadcastToApplet("org.kde.windowappmenu", "setCooperation", false);
}
}
onCooperationEstablishedChanged: {
if (!cooperationEstablished) {
broadcaster.hiddenFromBroadcast = false;
}
}
onIsActiveChanged: {
if (latteBridge) {
latteBridge.actions.broadcastToApplet("org.kde.windowappmenu", "setCooperation", isActive);
}
}
Connections {
target: latteBridge
onBroadcasted: {
//console.log(" BROADCASTED FROM APPMENU ::: " + action + " : " + value);
if (action === "setVisible") {
if (value === true) {
broadcaster.hiddenFromBroadcast = false;
} else {
broadcaster.hiddenFromBroadcast = true;
}
} else if (action === "isPresent") {
plasmoid.configuration.appMenuIsPresent = value;
} else if (action === "menuIsPresent") {
broadcaster.menuIsPresent = value;
} else if (action === "setCooperation") {
broadcaster.appMenuRequestsCooperation = value;
}
}
}
Timer{
id: broadcasterDelayer
interval: 5
onTriggered: {
if (latteBridge) {
if (broadcasterMouseArea.realContainsMouse && existsWindowActive) {
broadcaster.hiddenFromBroadcast = true;
latteBridge.actions.broadcastToApplet("org.kde.windowappmenu", "setVisible", true);
} else {
broadcaster.hiddenFromBroadcast = false;
latteBridge.actions.broadcastToApplet("org.kde.windowappmenu", "setVisible", false);
}
}
}
}
//!!!! MouseArea for Broadcaster
MouseArea{
id: broadcasterMouseArea
anchors.fill: parent
visible: broadcaster.cooperationEstablished && broadcaster.menuIsPresent
hoverEnabled: true
propagateComposedEvents: true
property int mouseAX: -1
property int mouseAY: -1
//! HACK :: For some reason containsMouse breaks in some cases
//! this hack is used in order to be sure when the mouse is really
//! inside the MouseArea or not
readonly property bool realContainsMouse: mouseAX !== -1 || mouseAY !== -1
onContainsMouseChanged: {
mouseAX = -1;
mouseAY = -1;
}
onMouseXChanged: mouseAX = mouseX;
onMouseYChanged: mouseAY = mouseY;
onRealContainsMouseChanged: {
if (broadcaster.cooperationEstablished) {
if (realContainsMouse) {
broadcaster.sendMessage();
} else {
broadcaster.cancelMessage();
}
}
}
onPressed: {
mouse.accepted = false;
}
onReleased: {
mouse.accepted = false;
}
}
}

View File

@@ -0,0 +1,101 @@
/*
* Copyright 2019 Michail Vourlakos <mvourlakos@gmail.com>
*
* This file is part of applet-window-title
*
* Latte-Dock 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.
*
* Latte-Dock 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, see <http://www.gnu.org/licenses/>.
*/
import QtQuick 2.7
Item {
id: latteWindowsTracker
readonly property bool existsWindowActive: selectedTracker.lastActiveWindow.isValid && !activeTaskItem.isMinimized
readonly property QtObject selectedTracker: plasmoid.configuration.filterByScreen ? latteBridge.windowsTracker.currentScreen : latteBridge.windowsTracker.allScreens
readonly property Item activeTaskItem: Item {
id: taskInfoItem
readonly property string appName: modelAppName !== "" ? modelAppName : discoveredAppName
readonly property bool isMinimized: selectedTracker.lastActiveWindow.isMinimized
readonly property bool isMaximized: selectedTracker.lastActiveWindow.isMaximized
readonly property bool isActive: selectedTracker.lastActiveWindow.isActive
readonly property bool isOnAllDesktops: selectedTracker.lastActiveWindow.isOnAllDesktops
property var icon: selectedTracker.lastActiveWindow.icon
readonly property string modelAppName: selectedTracker.lastActiveWindow.appName
readonly property string modelDisplay: selectedTracker.lastActiveWindow.display
property string title: ""
property string discoveredAppName: ""
function cleanupTitle() {
var text = modelDisplay;
var t = text;
var sep = t.lastIndexOf(" —– ");
var spacer = 4;
if (sep === -1) {
sep = t.lastIndexOf(" -- ");
spacer = 4;
}
if (sep === -1) {
sep = t.lastIndexOf(" -- ");
spacer = 4;
}
if (sep === -1) {
sep = t.lastIndexOf(" — ");
spacer = 3;
}
if (sep === -1) {
sep = t.lastIndexOf(" - ");
spacer = 3;
}
var dTitle = "";
var dAppName = "";
if (sep>-1) {
dTitle = text.substring(0, sep);
discoveredAppName = text.substring(sep+spacer, text.length);
//if title starts with application name, swap the found records
if (dTitle.startsWith(modelAppName)) {
var firstPart = dTitle;
dTitle = discoveredAppName;
discoveredAppName = firstPart;
}
}
if (sep>-1) {
title = dTitle;
} else {
title = t;
}
}
onModelAppNameChanged: taskInfoItem.cleanupTitle()
onModelDisplayChanged: taskInfoItem.cleanupTitle()
Component.onCompleted: taskInfoItem.cleanupTitle()
}
function toggleMaximized() {
selectedTracker.lastActiveWindow.requestToggleMaximized();
}
}

View File

@@ -0,0 +1,237 @@
/*
* Copyright 2019 Michail Vourlakos <mvourlakos@gmail.com>
*
* This file is part of applet-window-title
*
* Latte-Dock 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.
*
* Latte-Dock 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, see <http://www.gnu.org/licenses/>.
*/
import QtQuick 2.7
import QtQml.Models 2.2
import org.kde.taskmanager 0.1 as TaskManager
Item {
id: plasmaTasksItem
readonly property bool existsWindowActive: root.activeTaskItem && tasksRepeater.count > 0 && activeTaskItem.isActive
property Item activeTaskItem: null
TaskManager.TasksModel {
id: tasksModel
sortMode: TaskManager.TasksModel.SortVirtualDesktop
groupMode: TaskManager.TasksModel.GroupDisabled
screenGeometry: plasmoid.screenGeometry
activity: activityInfo.currentActivity
virtualDesktop: virtualDesktopInfo.currentDesktop
filterByScreen: plasmoid.configuration.filterByScreen
filterByVirtualDesktop: true
filterByActivity: true
}
Item{
id: taskList
Repeater{
id: tasksRepeater
model: tasksModel
Item{
id: task
readonly property string appName: modelAppName !== "" ? modelAppName : discoveredAppName
readonly property bool isMinimized: IsMinimized === true ? true : false
readonly property bool isMaximized: IsMaximized === true ? true : false
readonly property bool isActive: IsActive === true ? true : false
readonly property bool isOnAllDesktops: IsOnAllVirtualDesktops === true ? true : false
property var icon: decoration
readonly property string modelAppName: AppName
readonly property string modelDisplay: display
property string title: ""
property string discoveredAppName: ""
readonly property var m: model
function cleanupTitle() {
var text = display;
var t = modelDisplay;
var sep = t.lastIndexOf(" —– ");
var spacer = 4;
if (sep === -1) {
sep = t.lastIndexOf(" -- ");
spacer = 4;
}
if (sep === -1) {
sep = t.lastIndexOf(" -- ");
spacer = 4;
}
if (sep === -1) {
sep = t.lastIndexOf(" — ");
spacer = 3;
}
if (sep === -1) {
sep = t.lastIndexOf(" - ");
spacer = 3;
}
var dTitle = "";
var dAppName = "";
if (sep>-1) {
dTitle = text.substring(0, sep);
discoveredAppName = text.substring(sep+spacer, text.length);
//if title starts with application name, swap the found records
if (dTitle.startsWith(modelAppName)) {
var firstPart = dTitle;
dTitle = discoveredAppName;
discoveredAppName = firstPart;
}
}
if (sep>-1) {
title = dTitle;
} else {
title = t;
}
}
onIsActiveChanged: {
if (isActive) {
plasmaTasksItem.activeTaskItem = task;
}
}
onModelAppNameChanged: task.cleanupTitle()
onModelDisplayChanged: task.cleanupTitle()
Component.onCompleted: task.cleanupTitle()
Component.onDestruction: {
if (plasmaTasksItem.lastActiveTaskItem === task) {
plasmaTasksItem.lastActiveTaskItem = null;
}
}
function modelIndex(){
return tasksModel.makeModelIndex(index);
}
function toggleMaximized() {
tasksModel.requestToggleMaximized(modelIndex());
}
function toggleMinimized() {
tasksModel.requestToggleMinimized(modelIndex());
}
function requestClose() {
tasksModel.requestClose(modelIndex());
}
function togglePinToAllDesktops() {
if (root.plasma515) {
tasksModel.requestVirtualDesktops(modelIndex(), 0);
} else {
tasksModel.requestVirtualDesktop(modelIndex(), 0);
}
}
function toggleKeepAbove(){
tasksModel.requestToggleKeepAbove(modelIndex());
}
}
}
}
//! Functionality
function toggleMaximized() {
if (activeTaskItem) {
activeTaskItem.toggleMaximized();
}
}
function toggleMinimized() {
if (activeTaskItem) {
activeTaskItem.toggleMinimized();
}
}
function requestClose() {
if (activeTaskItem) {
activeTaskItem.requestClose();
}
}
function togglePinToAllDesktops() {
if (activeTaskItem) {
activeTaskItem.togglePinToAllDesktops();
}
}
function toggleKeepAbove(){
if (activeTaskItem) {
activeTaskItem.toggleKeepAbove();
}
}
//! Cycle Through Tasks
function activateNextPrevTask(next) {
var taskIndexList = [];
var activeTaskIndex = tasksModel.activeTask;
for (var i = 0; i < taskList.children.length - 1; ++i) {
var task = taskList.children[i];
var modelIndex = task.modelIndex(i);
if (task.m.IsLauncher !== true && task.m.IsStartup !== true) {
if (task.m.IsGroupParent === true) {
for (var j = 0; j < tasksModel.rowCount(modelIndex); ++j) {
taskIndexList.push(tasksModel.makeModelIndex(i, j));
}
} else {
taskIndexList.push(modelIndex);
}
}
}
if (!taskIndexList.length) {
return;
}
var target = taskIndexList[0];
for (var i = 0; i < taskIndexList.length; ++i) {
if (taskIndexList[i] === activeTaskIndex)
{
if (next && i < (taskIndexList.length - 1)) {
target = taskIndexList[i + 1];
} else if (!next) {
if (i) {
target = taskIndexList[i - 1];
} else {
target = taskIndexList[taskIndexList.length - 1];
}
}
break;
}
}
tasksModel.requestActivate(target);
}
}

View File

@@ -0,0 +1,26 @@
/*
* Copyright 2018 Michail Vourlakos <mvourlakos@gmail.com>
*
* This file is part of applet-window-title
*
* Latte-Dock 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.
*
* Latte-Dock 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, see <http://www.gnu.org/licenses/>.
*/
import QtQuick 2.7
import org.kde.kquickcontrolsaddons 2.0 as QuickAddons
QuickAddons.QIconItem {
}

View File

@@ -0,0 +1,283 @@
/*
* Copyright 2018-2019 Michail Vourlakos <mvourlakos@gmail.com>
*
* This file is part of applet-window-title
*
* Latte-Dock 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.
*
* Latte-Dock 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, see <http://www.gnu.org/licenses/>.
*/
import QtQuick 2.7
import QtQml.Models 2.2
import QtQuick.Layouts 1.1
import QtQuick.Controls 1.4
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
GridLayout{
id: titleLayout
rows: plasmoid.formFactor === PlasmaCore.Types.Horizontal ? 1 : -1
columns: plasmoid.formFactor === PlasmaCore.Types.Horizontal ? -1 : 1
columnSpacing: 0
rowSpacing: 0
property bool isUsedForMetrics: false
property bool exceedsAvailableSpace: false
property bool exceedsApplicationText: false
property int applicationTextLength: {
var applicationLength = 0;
var midSpacerLength = midSpacer.visible ?
(plasmoid.formFactor === PlasmaCore.Types.Horizontal ? midSpacer.width : midSpacer.height) : 0;
if (plasmoid.configuration.style === 0 /*Application*/
|| plasmoid.configuration.style === 2) { /*ApplicationTitle*/
applicationLength = firstTxt.implicitWidth;
} else if (plasmoid.configuration.style === 3) { /*TitleApplication*/
applicationLength = lastTxt.implicitWidth + midSpacerLength;
}
var iconLength = mainIcon.visible ?
(plasmoid.formFactor === PlasmaCore.Types.Horizontal ? mainIcon.width : mainIcon.height) : 0;
var subElements = plasmoid.formFactor === PlasmaCore.Types.Horizontal ?
firstSpacer.width + iconLength + midSpacerLength + lastSpacer.width:
firstSpacer.height + iconLength + midSpacerLength + lastSpacer.height;
return subElements + applicationLength;
}
Item{
id: firstSpacer
Layout.minimumWidth: plasmoid.formFactor === PlasmaCore.Types.Horizontal ? plasmoid.configuration.lengthFirstMargin : -1
Layout.preferredWidth: Layout.minimumWidth
Layout.maximumWidth: Layout.minimumWidth
Layout.minimumHeight: plasmoid.formFactor === PlasmaCore.Types.Horizontal ? -1 : plasmoid.configuration.lengthFirstMargin
Layout.preferredHeight: Layout.minimumHeight
Layout.maximumHeight: Layout.minimumHeight
}
Item {
id: mainIcon
Layout.minimumWidth: plasmoid.formFactor === PlasmaCore.Types.Horizontal ?
iconItem.iconSize : root.thickness
Layout.maximumWidth: Layout.minimumWidth
Layout.minimumHeight: plasmoid.formFactor === PlasmaCore.Types.Horizontal ?
root.thickness : iconItem.iconSize
Layout.maximumHeight: Layout.minimumHeight
visible: plasmoid.configuration.showIcon
QIconItem{
id: iconItem
anchors.fill: parent
anchors.topMargin: plasmoid.formFactor === PlasmaCore.Types.Horizontal ? thickMargin : 0
anchors.bottomMargin: plasmoid.formFactor === PlasmaCore.Types.Horizontal ? thickMargin : 0
anchors.leftMargin: plasmoid.formFactor === PlasmaCore.Types.Vertical ? thickMargin : 0
anchors.rightMargin: plasmoid.formFactor === PlasmaCore.Types.Vertical ? thickMargin : 0
icon: existsWindowActive ? activeTaskItem.icon : fullActivityInfo.icon
readonly property int thickMargin: plasmoid.configuration.iconFillThickness ?
0 : (root.thickness - iconSize) / 2
readonly property int iconSize: plasmoid.configuration.iconFillThickness ?
root.thickness : Math.min(root.thickness, plasmoid.configuration.iconSize)
}
}
Item{
id: midSpacer
Layout.minimumWidth: plasmoid.formFactor === PlasmaCore.Types.Horizontal ? plasmoid.configuration.spacing : -1
Layout.preferredWidth: Layout.minimumWidth
Layout.maximumWidth: Layout.minimumWidth
Layout.minimumHeight: plasmoid.formFactor === PlasmaCore.Types.Horizontal ? -1 : plasmoid.configuration.spacing
Layout.preferredHeight: Layout.minimumHeight
Layout.maximumHeight: Layout.minimumHeight
visible: mainIcon.visible && plasmoid.configuration.style !== 4 /*NoText*/
}
Item{
id: textsContainer
Layout.minimumWidth: plasmoid.formFactor === PlasmaCore.Types.Horizontal ? -1 : root.thickness
Layout.preferredWidth: plasmoid.formFactor === PlasmaCore.Types.Horizontal ? textRow.availableSpace : root.thickness
Layout.maximumWidth: plasmoid.formFactor === PlasmaCore.Types.Horizontal ? textRow.availableSpace : root.thickness
Layout.minimumHeight: plasmoid.formFactor === PlasmaCore.Types.Horizontal ? root.thickness : -1
Layout.preferredHeight: plasmoid.formFactor === PlasmaCore.Types.Horizontal ? root.thickness : textRow.availableSpace
Layout.maximumHeight: plasmoid.formFactor === PlasmaCore.Types.Horizontal ? root.thickness : textRow.availableSpace
visible: plasmoid.configuration.style !== 4 /*NoText*/
RowLayout {
id: textRow
anchors.centerIn: parent
spacing: 0
width: plasmoid.formFactor === PlasmaCore.Types.Horizontal ? parent.width : parent.height
height: plasmoid.formFactor === PlasmaCore.Types.Horizontal ? parent.height : parent.width
readonly property int availableSpace: {
if (!titleLayout.isUsedForMetrics) {
if (plasmoid.formFactor === PlasmaCore.Types.Horizontal) {
var iconL = mainIcon.visible ? mainIcon.width : 0;
var midL = midSpacer.visible ? midSpacer.width : 0;
return titleLayout.width - firstSpacer.width - iconL - midL - lastSpacer.width;
} else {
var iconL = mainIcon.visible ? mainIcon.height : 0;
var midL = midSpacer.visible ? midSpacer.height : 0;
return titleLayout.height - firstSpacer.height - iconL - midL - lastSpacer.height;
}
}
return implicitWidths;
}
readonly property int implicitWidths: {
return Math.ceil(firstTxt.implicitWidth) + Math.ceil(midTxt.implicitWidth) + Math.ceil(lastTxt.implicitWidth);
}
transformOrigin: Item.Center
rotation: {
if (plasmoid.formFactor === PlasmaCore.Types.Horizontal) {
return 0;
} else if (plasmoid.location === PlasmaCore.Types.LeftEdge) {
return -90;
} else if (plasmoid.location === PlasmaCore.Types.RightEdge) {
return 90;
}
}
Label{
id: firstTxt
Layout.fillWidth: elide === Text.ElideNone ? false : true
width: Text.ElideNone ? implicitWidth : -1
verticalAlignment: Text.AlignVCenter
text: existsWindowActive ? root.firstTitleText : root.fallBackText
color: enforceLattePalette ? latteBridge.palette.textColor : theme.textColor
font.capitalization: plasmoid.configuration.capitalFont ? Font.Capitalize : Font.MixedCase
font.bold: plasmoid.configuration.boldFont
font.italic: plasmoid.configuration.italicFont
readonly property bool showsTitleText: plasmoid.configuration.style === 1 /*Title*/
|| plasmoid.configuration.style === 3 /*TitleApplication*/
readonly property bool showsApplicationText: plasmoid.configuration.style === 0 /*Application*/
|| plasmoid.configuration.style === 2 /*ApplicationTitle*/
elide: {
if (plasmoid.configuration.style === 1 && titleLayout.exceedsAvailableSpace){ /*Title*/
return Text.ElideRight;
} else if (plasmoid.configuration.style === 3
&& activeTaskItem
&& activeTaskItem.appName !== activeTaskItem.title
&& titleLayout.exceedsAvailableSpace){ /*TitleApplication*/
return Text.ElideRight;
} else if (showsApplicationText && !isUsedForMetrics && exceedsApplicationText) {
return Text.ElideRight;
}
return Text.ElideNone;
}
visible: {
if (!isUsedForMetrics && showsTitleText && exceedsApplicationText) {
return false;
}
return true;
}
}
Label{
id: midTxt
verticalAlignment: firstTxt.verticalAlignment
width: implicitWidth
visible: !exceedsApplicationText && text !== ""
text: {
if (!existsWindowActive) {
return "";
}
if (plasmoid.configuration.style === 2 || plasmoid.configuration.style === 3){ /*ApplicationTitle*/ /*OR*/ /*TitleApplication*/
if (activeTaskItem.appName !== activeTaskItem.title && activeTaskItem.appName !== "" && activeTaskItem.title !== "") {
return " - ";
}
}
return "";
}
color: firstTxt.color
font.capitalization: firstTxt.font.capitalization
font.bold: firstTxt.font.bold
font.italic: firstTxt.font.italic
}
Label{
id: lastTxt
Layout.fillWidth: elide === Text.ElideNone ? false : true
width: Text.ElideNone ? implicitWidth : -1
verticalAlignment: firstTxt.verticalAlignment
text: existsWindowActive ? root.lastTitleText : ""
color: firstTxt.color
font.capitalization: firstTxt.font.capitalization
font.bold: firstTxt.font.bold
font.italic: firstTxt.font.italic
visible: text !== "" && !(showsTitleText && exceedsApplicationText)
readonly property bool showsTitleText: plasmoid.configuration.style === 2 /*ApplicationTitle*/
elide: {
if (activeTaskItem
&& activeTaskItem.appName !== activeTaskItem.title
&& plasmoid.configuration.style === 2 /*ApplicationTitle*/
&& titleLayout.exceedsAvailableSpace){ /*AND is shown*/
return Text.ElideRight;
} else if(plasmoid.configuration.style === 3 /*TitleApplication*/
&& exceedsApplicationText) {
return Text.ElideRight;
}
return Text.ElideNone;
}
}
}
}
Item{
id: lastSpacer
Layout.minimumWidth: plasmoid.formFactor === PlasmaCore.Types.Horizontal ? plasmoid.configuration.lengthLastMargin : -1
Layout.preferredWidth: Layout.minimumWidth
Layout.maximumWidth: Layout.minimumWidth
Layout.minimumHeight: plasmoid.formFactor === PlasmaCore.Types.Horizontal ? -1 : plasmoid.configuration.lengthLastMargin
Layout.preferredHeight: Layout.minimumHeight
Layout.maximumHeight: Layout.minimumHeight
}
}

View File

@@ -0,0 +1,292 @@
/*
* Copyright 2018 Michail Vourlakos <mvourlakos@gmail.com>
*
* This file is part of applet-window-title
*
* Latte-Dock 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.
*
* Latte-Dock 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, see <http://www.gnu.org/licenses/>.
*/
import QtQuick 2.9
import QtQuick.Controls 1.0
import QtQuick.Controls 2.2 as Controls22
import QtGraphicalEffects 1.0
import QtQuick.Layouts 1.0
import org.kde.plasma.core 2.0 as PlasmaCore
import "../../tools/Tools.js" as Tools
Item {
id: root
property alias cfg_boldFont: boldChk.checked
property alias cfg_italicFont: italicChk.checked
property alias cfg_capitalFont: capitalChk.checked
property alias cfg_showIcon: showIconChk.checked
property alias cfg_iconFillThickness: iconFillChk.checked
property alias cfg_iconSize: iconSizeSpn.value
property alias cfg_spacing: spacingSpn.value
property alias cfg_style: root.selectedStyle
property alias cfg_lengthFirstMargin: lengthFirstSpn.value
property alias cfg_lengthLastMargin: lengthLastSpn.value
property alias cfg_lengthMarginsLock: lockItem.locked
property alias cfg_inFillMode: inFillChk.checked
property alias cfg_maximumLength: maxLengthSlider.value
property alias cfg_subsMatch: root.selectedMatches
property alias cfg_subsReplace: root.selectedReplacements
// used as bridge to communicate properly between configuration and ui
property int selectedStyle
property var selectedMatches: []
property var selectedReplacements: []
// used from the ui
readonly property real centerFactor: 0.3
readonly property int minimumWidth: 220
onSelectedStyleChanged: {
if (selectedStyle === 4) { /*NoText*/
showIconChk.checked = true;
}
}
SystemPalette {
id: palette
}
ColumnLayout {
id:mainColumn
spacing: units.largeSpacing
Layout.fillWidth: true
GridLayout{
columns: 2
Label{
Layout.minimumWidth: Math.max(centerFactor * root.width, minimumWidth)
text: i18n("Text style:")
horizontalAlignment: Text.AlignRight
}
StyleComboBox{
Layout.minimumWidth: 220
Layout.preferredWidth: 0.25 * root.width
Layout.maximumWidth: 320
}
}
GridLayout{
columns: 2
Label{
Layout.minimumWidth: Math.max(centerFactor * root.width, minimumWidth)
text: i18n("Icon:")
horizontalAlignment: Text.AlignRight
}
CheckBox{
id: showIconChk
text: i18n("Show when available")
enabled: root.selectedStyle !== 4 /*NoText*/
}
Label{
}
CheckBox{
id: iconFillChk
text: i18n("Fill thickness")
enabled: showIconChk.checked
}
Label{
}
RowLayout{
enabled: !iconFillChk.checked
SpinBox{
id: iconSizeSpn
minimumValue: 16
maximumValue: 128
suffix: " " + i18nc("pixels","px.")
enabled: !iconFillChk.checked
}
Label {
Layout.leftMargin: units.smallSpacing
text: "maximum"
}
}
}
GridLayout{
columns: 2
enabled : root.selectedStyle !== 4 /*NoText*/
Label{
Layout.minimumWidth: Math.max(centerFactor * root.width, minimumWidth)
text: i18n("Font:")
horizontalAlignment: Text.AlignRight
}
CheckBox{
id: boldChk
text: i18n("Bold")
}
Label{
id: italicLbl
font.italic: true
}
CheckBox{
id: italicChk
text: i18n("Italic")
}
Label{
}
CheckBox{
id: capitalChk
text: i18n("First letters capital")
}
}
GridLayout{
columns: 2
enabled : root.selectedStyle !== 4 /*NoText*/
Label{
id: lengthLbl
Layout.minimumWidth: Math.max(centerFactor * root.width, minimumWidth)
text: i18n("Length:")
horizontalAlignment: Text.AlignRight
}
CheckBox{
id: inFillChk
text: i18n("Fill available space")
}
Label{
}
RowLayout{
enabled: !inFillChk.checked
Slider {
id: maxLengthSlider
minimumValue: 24
maximumValue: 1500
stepSize: 2
}
Label {
text: maxLengthSlider.value + " " + i18n("px. at maximum")
}
}
}
ColumnLayout{
GridLayout{
id: visualSettingsGroup1
columns: 2
enabled: showIconChk.checked && root.selectedStyle !== 4 /*NoText*/
Label{
Layout.minimumWidth: Math.max(centerFactor * root.width, minimumWidth)
text: i18n("Spacing:")
horizontalAlignment: Text.AlignRight
}
SpinBox{
id: spacingSpn
minimumValue: 0
maximumValue: 36
suffix: " " + i18nc("pixels","px.")
}
}
GridLayout{
id: visualSettingsGroup2
columns: 3
rows: 2
flow: GridLayout.TopToBottom
columnSpacing: visualSettingsGroup1.columnSpacing
rowSpacing: visualSettingsGroup1.rowSpacing
property int lockerHeight: firstLengthLbl.height + rowSpacing/2
Label{
id: firstLengthLbl
Layout.minimumWidth: Math.max(centerFactor * root.width, minimumWidth)
text: plasmoid.configuration.formFactor===PlasmaCore.Types.Horizontal ?
i18n("Left margin:") : i18n("Top margin:")
horizontalAlignment: Text.AlignRight
}
Label{
Layout.minimumWidth: Math.max(centerFactor * root.width, minimumWidth)
text: plasmoid.configuration.formFactor===PlasmaCore.Types.Horizontal ?
i18n("Right margin:") : i18n("Bottom margin:")
horizontalAlignment: Text.AlignRight
enabled: !lockItem.locked
}
SpinBox{
id: lengthFirstSpn
minimumValue: 0
maximumValue: 24
suffix: " " + i18nc("pixels","px.")
property int lastValue: -1
onValueChanged: {
if (lockItem.locked) {
var step = value - lastValue > 0 ? 1 : -1;
lastValue = value;
lengthLastSpn.value = lengthLastSpn.value + step;
}
}
Component.onCompleted: {
lastValue = plasmoid.configuration.lengthFirstMargin;
}
}
SpinBox{
id: lengthLastSpn
minimumValue: 0
maximumValue: 24
suffix: " " + i18nc("pixels","px.")
enabled: !lockItem.locked
}
LockItem{
id: lockItem
Layout.minimumWidth: 40
Layout.maximumWidth: 40
Layout.alignment: Qt.AlignTop | Qt.AlignLeft
Layout.minimumHeight: visualSettingsGroup2.lockerHeight
Layout.maximumHeight: Layout.minimumHeight
Layout.topMargin: firstLengthLbl.height / 2
Layout.rowSpan: 2
}
}
} // ColumnLayout
} //mainColumn
}

View File

@@ -0,0 +1,160 @@
/*
* Copyright 2018 Michail Vourlakos <mvourlakos@gmail.com>
*
* This file is part of applet-window-title
*
* Latte-Dock 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.
*
* Latte-Dock 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, see <http://www.gnu.org/licenses/>.
*/
import QtQuick 2.9
import QtQuick.Controls 1.0
import QtQuick.Layouts 1.0
import org.kde.plasma.core 2.0 as PlasmaCore
Item {
id: behaviorPage
property alias cfg_filterByScreen: filterByScreenChk.checked
property alias cfg_filterActivityInfo: filterActivityChk.checked
property alias cfg_showAppMenuOnMouseEnter: showAppMenuChk.checked
property alias cfg_showTooltip: showTooltip.checked
property alias cfg_actionScrollMinimize: cycleMinimizeChk.checked
property alias cfg_subsMatch: behaviorPage.selectedMatches
property alias cfg_subsReplace: behaviorPage.selectedReplacements
property alias cfg_placeHolder: placeHolder.text
// used as bridge to communicate properly between configuration and ui
property var selectedMatches: []
property var selectedReplacements: []
// used from the ui
readonly property real centerFactor: 0.3
readonly property int minimumWidth: 220
ColumnLayout {
id:mainColumn
spacing: units.largeSpacing
Layout.fillWidth: true
GridLayout {
columns: 2
Label{
Layout.minimumWidth: Math.max(centerFactor * behaviorPage.width, minimumWidth)
text: i18n("Filters:")
horizontalAlignment: Text.AlignRight
}
CheckBox{
id: filterByScreenChk
text: i18n("Show only window information from current screen")
}
}
GridLayout {
columns: 2
Label{
Layout.minimumWidth: Math.max(centerFactor * behaviorPage.width, minimumWidth)
text: i18n("Mouse:")
horizontalAlignment: Text.AlignRight
}
CheckBox{
id: showTooltip
text: i18n("Show tooltip on hover")
}
Label{
visible: showAppMenuChk.visible
enabled: showAppMenuChk.enabled
}
CheckBox{
id: showAppMenuChk
text: i18n("Show Window AppMenu applet on enter")
visible: plasmoid.configuration.containmentType === 2 /*Latte Containment*/
enabled: plasmoid.configuration.appMenuIsPresent
}
Label{
visible: cycleMinimizeChk.visible
}
CheckBox {
id: cycleMinimizeChk
text: i18n("Scroll to cycle and minimize through your tasks")
visible: plasmoid.configuration.containmentType === 1 /*Plasma Containment*/
}
}
GridLayout {
columns: 2
Label{
Layout.minimumWidth: Math.max(centerFactor * behaviorPage.width, minimumWidth)
text: i18n("Placeholder:")
horizontalAlignment: Text.AlignRight
}
CheckBox{
id: filterActivityChk
text: i18n("Show activity information")
}
Label{}
TextField {
id: placeHolder
text: plasmoid.configuration.placeHolder
Layout.fillWidth: true
enabled: !filterActivityChk.checked
placeholderText: i18n("placeholder text...")
}
}
GridLayout{
columns: 2
Label{
Layout.minimumWidth: Math.max(centerFactor * behaviorPage.width, minimumWidth)
text: i18n("Application name:")
horizontalAlignment: Text.AlignRight
}
Button{
checkable: true
checked: subsSlidingBox.shown
text: " " + i18n("Manage substitutions...") + " "
onClicked: {
if (subsSlidingBox.shown) {
subsSlidingBox.slideOut();
} else {
subsSlidingBox.slideIn();
}
}
SubstitutionsPopup {
id: subsSlidingBox
page: behaviorPage
slideOutFrom: PlasmaCore.Types.BottomEdge
}
}
}
}
}

View File

@@ -0,0 +1,88 @@
/*
* Copyright 2018 Michail Vourlakos <mvourlakos@gmail.com>
*
* This file is part of applet-window-title
*
* Latte-Dock 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.
*
* Latte-Dock 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, see <http://www.gnu.org/licenses/>.
*/
import QtQuick 2.9
import QtQuick.Controls 1.3
import QtQuick.Layouts 1.0
import org.kde.plasma.core 2.0 as PlasmaCore
import org.kde.kquickcontrolsaddons 2.0 as KQuickAddons
Item{
id: main
property bool locked: true
readonly property int verticalSubHeight: height - (button.height/2)
ColumnLayout{
id: column
spacing: 0
opacity: locked ? 1 : 0.5
Rectangle{
id: subRectTop
Layout.minimumWidth: button.width/2 + Layout.minimumHeight/2
Layout.minimumHeight: 3
Layout.maximumWidth: Layout.minimumWidth
Layout.maximumHeight: Layout.minimumHeight
color: palette.text
}
Rectangle {
Layout.leftMargin: subRectTop.Layout.minimumWidth - subRectTop.Layout.minimumHeight
Layout.minimumWidth: subRectTop.Layout.minimumHeight
Layout.minimumHeight: verticalSubHeight
Layout.maximumWidth: Layout.minimumWidth
Layout.maximumHeight: Layout.minimumHeight
color: palette.text
}
KQuickAddons.QIconItem{
id: button
width: 24
height: 24
icon: locked ? "lock" : "unlock"
}
Rectangle {
Layout.leftMargin: subRectTop.Layout.minimumWidth - subRectTop.Layout.minimumHeight
Layout.minimumWidth: subRectTop.Layout.minimumHeight
Layout.minimumHeight: verticalSubHeight
Layout.maximumWidth: Layout.minimumWidth
Layout.maximumHeight: Layout.minimumHeight
color: palette.text
}
Rectangle{
Layout.minimumWidth: subRectTop.Layout.minimumWidth
Layout.minimumHeight: subRectTop.Layout.minimumHeight
Layout.maximumWidth: Layout.minimumWidth
Layout.maximumHeight: Layout.minimumHeight
color: palette.text
}
}
MouseArea{
anchors.fill: column
onClicked: locked = !locked;
}
}

View File

@@ -0,0 +1,127 @@
/*
* Copyright 2018 Michail Vourlakos <mvourlakos@gmail.com>
*
* This file is part of applet-window-title
*
* Latte-Dock 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.
*
* Latte-Dock 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, see <http://www.gnu.org/licenses/>.
*/
import QtQuick 2.9
import QtQuick.Controls 1.0
import QtGraphicalEffects 1.0
import QtQuick.Controls 2.2 as Controls22
import QtQuick.Layouts 1.0
import org.kde.plasma.core 2.0 as PlasmaCore
Item{
id: box
clip: true
x: parent.width/2 - width/2
/*y: slideOutFrom === PlasmaCore.Types.BottomEdge ? 0
height: 0*/
opacity: 0
property QtObject contentItem: null
property int slideOutFrom: PlasmaCore.Types.TopEdge
property bool shown: false
readonly property int availableWidth: width - 2*12 - 2*units.largeSpacing
readonly property int availableHeight: contentItem.childrenRect.height + 2*units.largeSpacing
readonly property int maximumHeight: availableHeight + 2*12
onContentItemChanged: {
if (contentItem){
contentItem.parent = centralItem
}
}
function slideIn() {
if (slideOutFrom === PlasmaCore.Types.TopEdge) {
height = maximumHeight;
y = -maximumHeight;
} else {
height = maximumHeight;
y = parent.height;
}
opacity = 1;
shown = true;
}
function slideOut() {
if (slideOutFrom === PlasmaCore.Types.TopEdge) {
height = 0;
y = 0;
} else {
height = 0;
y = parent.height;
}
opacity = 0;
shown = false;
}
Behavior on y{
NumberAnimation {
duration: 300
easing.type: Easing.OutCubic
}
}
Behavior on height{
NumberAnimation {
duration: 300
easing.type: Easing.OutCubic
}
}
Behavior on opacity{
NumberAnimation {
duration: 300
easing.type: Easing.OutCubic
}
}
SystemPalette {
id: palette
}
Item{
id: mainElement
width: parent.width
height: contentItem ? maximumHeight : 100
Rectangle{
id: centralItem
anchors.fill: parent
anchors.margins: 12
color: palette.alternateBase
border.width: 1
border.color: palette.mid
radius: 1
layer.enabled: true
layer.effect: DropShadow {
id: shadowElement
radius: 12
fast: true
samples: 2 * radius
color: palette.shadow
}
}
}
}

View File

@@ -0,0 +1,85 @@
/*
* Copyright 2018 Michail Vourlakos <mvourlakos@gmail.com>
*
* This file is part of applet-window-title
*
* Latte-Dock 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.
*
* Latte-Dock 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, see <http://www.gnu.org/licenses/>.
*/
import QtQuick 2.0
import QtQuick.Controls 1.0
import QtQuick.Controls 2.2 as Controls22
import QtQuick.Layouts 1.0
Controls22.ComboBox{
id: combobox
model: titleStyles
property var titleStyles: [
i18n("Application"),
i18n("Title"),
i18n("Application - Title"),
i18n("Title - Application"),
i18n("Do not show any text"),
];
Connections{
target: popup
onClosed: root.forceActiveFocus();
}
delegate: MouseArea{
width: combobox.width
height: combobox.height
hoverEnabled: true
onClicked: {
combobox.currentIndex = index;
root.selectedStyle = index;
combobox.popup.close();
}
Rectangle{
id:delegateBackground
anchors.fill: parent
color: {
if (containsMouse) {
return palette.highlight;
}
if (combobox.currentIndex === index) {
return selectedColor;
}
return "transparent";
}
readonly property color selectedColor: Qt.rgba(palette.highlight.r, palette.highlight.g, palette.highlight.b, 0.5);
Label{
id: label
anchors.left: parent.left
anchors.leftMargin: units.smallSpacing
anchors.verticalCenter: parent.verticalCenter
text: titleStyles[index];
color: containsMouse ? palette.highlightedText : palette.text
}
}
}
Component.onCompleted: {
currentIndex = plasmoid.configuration.style;
}
}

View File

@@ -0,0 +1,114 @@
/*
* Copyright 2018 Michail Vourlakos <mvourlakos@gmail.com>
*
* This file is part of applet-window-title
*
* Latte-Dock 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.
*
* Latte-Dock 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, see <http://www.gnu.org/licenses/>.
*/
import QtQuick 2.9
import QtQuick.Controls 1.0
import QtQuick.Controls 2.2 as Controls22
import QtQuick.Layouts 1.0
import org.kde.plasma.core 2.0 as PlasmaCore
import "../../tools/Tools.js" as Tools
SlidingBox {
id: popup
width: Tools.qBound(400, 0.6*page.width, 750)
property QtObject page: null
function textAreaToList(text) {
var res = text.split("\n");
return res;
}
function listToText(text) {
var res = text.join("\n");
return res;
}
contentItem: ColumnLayout{
id: mainColumn
width: popup.availableWidth
anchors.margins: units.largeSpacing
anchors.centerIn: parent
spacing: units.largeSpacing
Label{
Layout.fillWidth: true
horizontalAlignment: Qt.AlignHCenter
font.bold: true
text: i18n("Substitutions")
}
GridLayout {
columns: 2
Label{
Layout.fillWidth: true
horizontalAlignment: Qt.AlignHCenter
font.bold: true
text: "Match"
}
Label{
Layout.fillWidth: true
horizontalAlignment: Qt.AlignHCenter
font.bold: true
text: "Replace with"
}
TextArea{
id: textAreaMatch
Layout.fillWidth: true
Layout.fillHeight: true
text: listToText(page.selectedMatches)
onTextChanged: page.selectedMatches = popup.textAreaToList(text)
flickableItem.onContentYChanged: {
textAreaReplace.flickableItem.contentY = flickableItem.contentY
}
}
TextArea{
id: textAreaReplace
Layout.fillWidth: true
Layout.fillHeight: true
text: listToText(page.selectedReplacements)
onTextChanged: page.selectedReplacements = popup.textAreaToList(text)
flickableItem.onContentYChanged: {
textAreaMatch.flickableItem.contentY = flickableItem.contentY
}
}
}
Label{
Layout.fillWidth: true
horizontalAlignment: Qt.AlignHCenter
font.italic: true
color: "#ff0000"
text: {
if (page.selectedMatches.length !== page.selectedReplacements.length) {
return i18n("Warning: Matches and Replacements do not have the same size...");
}
return "";
}
}
}
}

View File

@@ -0,0 +1,326 @@
/*
* Copyright 2018-2019 Michail Vourlakos <mvourlakos@gmail.com>
*
* This file is part of applet-window-title
*
* Latte-Dock 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.
*
* Latte-Dock 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, see <http://www.gnu.org/licenses/>.
*/
import QtQuick 2.7
import QtQuick.Layouts 1.1
import QtQuick.Controls 1.4
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.taskmanager 0.1 as TaskManager
import org.kde.activities 0.1 as Activities
import "../tools/Tools.js" as Tools
Item {
id: root
clip: true
Layout.fillWidth: (inFillMode && plasmoid.formFactor === PlasmaCore.Types.Horizontal)
|| plasmoid.formFactor === PlasmaCore.Types.Vertical ? true : false
Layout.fillHeight: (inFillMode && plasmoid.formFactor === PlasmaCore.Types.Vertical)
|| plasmoid.formFactor === PlasmaCore.Types.Horizontal ? true : false
Layout.minimumWidth: plasmoid.formFactor === PlasmaCore.Types.Horizontal ? (inFillMode && latteInEditMode ? maximumTitleLength : 0) : 0
Layout.preferredWidth: plasmoid.formFactor === PlasmaCore.Types.Horizontal ? (inFillMode ? -1 : maximumTitleLength) : -1
Layout.maximumWidth: plasmoid.formFactor === PlasmaCore.Types.Horizontal ? (inFillMode ? Infinity : maximumTitleLength) : -1
Layout.minimumHeight: plasmoid.formFactor === PlasmaCore.Types.Vertical ? (inFillMode && latteInEditMode ? maximumTitleLength : 0) : 0
Layout.preferredHeight: plasmoid.formFactor === PlasmaCore.Types.Vertical ? (inFillMode ? -1 : maximumTitleLength) : -1
Layout.maximumHeight: plasmoid.formFactor === PlasmaCore.Types.Vertical ? (inFillMode ? Infinity : maximumTitleLength) : -1
Plasmoid.preferredRepresentation: Plasmoid.fullRepresentation
Plasmoid.onFormFactorChanged: plasmoid.configuration.formFactor = plasmoid.formFactor;
Plasmoid.status: {
if (broadcaster.hiddenFromBroadcast && !inEditMode) {
return PlasmaCore.Types.HiddenStatus;
}
return PlasmaCore.Types.PassiveStatus;
}
readonly property bool inFillMode: plasmoid.configuration.inFillMode
readonly property bool inEditMode: plasmoid.userConfiguring || latteInEditMode
readonly property int containmentType: plasmoid.configuration.containmentType
readonly property int thickness: plasmoid.formFactor === PlasmaCore.Types.Horizontal ? root.height : root.width
readonly property int maximumTitleLength: {
if (broadcaster.hiddenFromBroadcast) {
return 0;
}
if (plasmoid.formFactor === PlasmaCore.Types.Horizontal) {
return inFillMode ? metricsContents.width : Math.min(metricsContents.width, plasmoid.configuration.maximumLength);
} else {
return Math.min(metricsContents.height, plasmoid.configuration.maximumLength);
}
}
readonly property bool existsWindowActive: windowInfoLoader.item && windowInfoLoader.item.existsWindowActive
readonly property bool isActiveWindowPinned: existsWindowActive && activeTaskItem.isOnAllDesktops
readonly property bool isActiveWindowMaximized: existsWindowActive && activeTaskItem.isMaximized
readonly property Item activeTaskItem: windowInfoLoader.item.activeTaskItem
property string fallBackText: {
if (!plasmoid.configuration.filterActivityInfo) {
return plasmoid.configuration.placeHolder;
} else {
return fullActivityInfo.name;
}
}
readonly property string firstTitleText: {
if (!activeTaskItem) {
return "";
}
if (plasmoid.configuration.style === 0){ /*Application*/
return Tools.applySubstitutes(activeTaskItem.appName);
} else if (plasmoid.configuration.style === 1){ /*Title*/
return activeTaskItem.title;
} else if (plasmoid.configuration.style === 2){ /*ApplicationTitle*/
return Tools.applySubstitutes(activeTaskItem.appName);
} else if (plasmoid.configuration.style === 3){ /*TitleApplication*/
var finalText = activeTaskItem.appName === activeTaskItem.title ?
Tools.applySubstitutes(activeTaskItem.appName) : activeTaskItem.title;
return finalText;
} else if (plasmoid.configuration.style === 4){ /*NoText*/
return "";
}
return "";
}
readonly property string lastTitleText: {
if (!activeTaskItem) {
return "";
}
if (plasmoid.configuration.style === 2){ /*ApplicationTitle*/
var finalText = activeTaskItem.appName === activeTaskItem.title ? "" : activeTaskItem.title;
return finalText;
} else if (plasmoid.configuration.style === 3){ /*TitleApplication*/
var finalText = activeTaskItem.appName === activeTaskItem.title ? "" : Tools.applySubstitutes(activeTaskItem.appName);
return finalText;
}
return "";
}
//BEGIN Latte Dock Communicator
property bool isInLatte: false // deprecated Latte v0.8 API
property QtObject latteBridge: null // current Latte v0.9 API
onLatteBridgeChanged: {
if (latteBridge) {
plasmoid.configuration.containmentType = 2; /*Latte containment with new API*/
latteBridge.actions.setProperty(plasmoid.id, "latteSideColoringEnabled", false);
latteBridge.actions.setProperty(plasmoid.id, "windowsTrackingEnabled", true);
}
}
//END Latte Dock Communicator
//BEGIN Latte based properties
readonly property bool enforceLattePalette: latteBridge && latteBridge.applyPalette && latteBridge.palette
readonly property bool latteInEditMode: latteBridge && latteBridge.inEditMode
//END Latte based properties
Component.onCompleted: {
plasmoid.configuration.appMenuIsPresent = false;
containmentIdentifierTimer.start();
}
// START Tasks logic
// To get current activity name
TaskManager.ActivityInfo {
id: activityInfo
}
Activities.ActivityInfo {
id: fullActivityInfo
activityId: ":current"
}
// To get virtual desktop name
TaskManager.VirtualDesktopInfo {
id: virtualDesktopInfo
}
Loader {
id: windowInfoLoader
sourceComponent: latteBridge
&& latteBridge.windowsTracker
&& latteBridge.windowsTracker.currentScreen.lastActiveWindow
&& latteBridge.windowsTracker.allScreens.lastActiveWindow ? latteTrackerComponent : plasmaTasksModel
Component{
id: latteTrackerComponent
LatteWindowsTracker{}
}
Component{
id: plasmaTasksModel
PlasmaTasksModel{}
}
}
// END Tasks logic
// BEGIN Title Layout(s)
// This Layout is used to count if the title overceeds the available space
// in order for the Visible Layout to elide its contents
TitleLayout {
id: metricsContents
anchors.top: parent.top
anchors.left: parent.left
//anchors.topMargin: 8
//visible:false, does not return proper metrics, this is why opacity:0 is preferred
opacity: 0
isUsedForMetrics: true
}
// This is the reas Visible Layout that is shown to the user
TitleLayout {
id: visibleContents
anchors.top: parent.top
anchors.left: parent.left
width: plasmoid.formFactor === PlasmaCore.Types.Horizontal ?
(!exceedsAvailableSpace ? metricsContents.width : root.width) : thickness
height: plasmoid.formFactor === PlasmaCore.Types.Vertical ?
(!exceedsAvailableSpace ? metricsContents.height : root.height) : thickness
exceedsAvailableSpace: plasmoid.formFactor === PlasmaCore.Types.Horizontal ?
metricsContents.width > root.width :
metricsContents.height > root.height
exceedsApplicationText: plasmoid.formFactor === PlasmaCore.Types.Horizontal ?
metricsContents.applicationTextLength > root.width :
metricsContents.applicationTextLength > root.height
visible: !(!plasmoid.configuration.filterActivityInfo && !root.existsWindowActive && !plasmoid.configuration.placeHolder)
}
// END Title Layout(s)
//! Tooltip Area
PlasmaCore.ToolTipArea {
id: contentsTooltip
anchors.fill: visibleContents
active: text !== ""
interactive: true
location: plasmoid.location
readonly property string text: {
if (!existsWindowActive || !plasmoid.configuration.showTooltip) {
return "";
}
/* Try to show only information that are not already shown*/
if (plasmoid.configuration.style === 0){ /*Application*/
return activeTaskItem.appName === activeTaskItem.title ? "" : activeTaskItem.title;
} else if (plasmoid.configuration.style === 1
|| plasmoid.configuration.style === 2
|| plasmoid.configuration.style === 4 ){ /*Title OR ApplicationTitle OR NoText*/
var finalText = activeTaskItem.appName === activeTaskItem.title ?
Tools.applySubstitutes(activeTaskItem.appName) :
Tools.applySubstitutes(activeTaskItem.appName) + " - " + activeTaskItem.title;
return finalText;
} else if (plasmoid.configuration.style === 3){ /*TitleApplication*/
var finalText = activeTaskItem.appName === activeTaskItem.title ?
Tools.applySubstitutes(activeTaskItem.appName) :
activeTaskItem.title + " - " + Tools.applySubstitutes(activeTaskItem.appName);
return finalText;
}
return "";
}
mainItem: RowLayout {
spacing: units.largeSpacing
Layout.margins: units.smallSpacing
PlasmaCore.IconItem {
Layout.minimumWidth: units.iconSizes.medium
Layout.minimumHeight: units.iconSizes.medium
Layout.maximumWidth: Layout.minimumWidth
Layout.maximumHeight: Layout.minimumHeight
source: existsWindowActive ? activeTaskItem.icon : fullActivityInfo.icon
visible: !plasmoid.configuration.showIcon
}
PlasmaComponents.Label {
id: fullText
Layout.minimumWidth: 0
Layout.preferredWidth: implicitWidth
Layout.maximumWidth: 750
Layout.minimumHeight: implicitHeight
Layout.maximumHeight: Layout.minimumHeight
elide: Text.ElideRight
text: contentsTooltip.text
}
}
}
//! END of ToolTip area
Loader {
id: actionsLoader
anchors.fill: inFillMode ? parent : visibleContents
active: containmentType === 1 /*plasma or old latte containment*/
sourceComponent: ActionsMouseArea {
anchors.fill: parent
}
}
Broadcaster{
id: broadcaster
anchors.fill: parent
}
//! this timer is used in order to identify in which containment the applet is in
//! it should be called only the first time an applet is created and loaded because
//! afterwards the applet has no way to move between different processes such
//! as Plasma and Latte
Timer{
id: containmentIdentifierTimer
interval: 5000
onTriggered: {
if (latteBridge) {
plasmoid.configuration.containmentType = 2; /*Latte containment with new API*/
latteBridge.actions.broadcastToApplet("org.kde.windowappmenu", "isPresent", true);
} else {
plasmoid.configuration.containmentType = 1; /*Plasma containment or Latte with old API*/
}
}
}
}