diff --git a/package/contents/config/main.xml b/package/contents/config/main.xml
index 4fbc298..8b38b91 100644
--- a/package/contents/config/main.xml
+++ b/package/contents/config/main.xml
@@ -1,231 +1,234 @@
buttons|icon|title|menu
5.0
-
+
0
true
true
-
+
0
-
+
0
true
true
-
+
0
-
+
0
true
true
-
+
0
-
+
0
true
true
+
+ 0
+
0
false
false
0.2
0.0
true
0
0
0
false
^(.*)\s*[—–\-:]\s*(Mozilla )?([^—–\-:]+)$
$3 — $1
Plasma Desktop :: %activity%
false
1000
0
1
false
false
false
false
close|maximize|minimize|pin
false
10
0.5
0
true
false
false
1
true
0.1
1.0
true
0
0
false
0
diff --git a/package/contents/ui/AppMenu.qml b/package/contents/ui/AppMenu.qml
index 6f672b4..5a64640 100644
--- a/package/contents/ui/AppMenu.qml
+++ b/package/contents/ui/AppMenu.qml
@@ -1,159 +1,159 @@
import QtQuick 2.2
import QtQuick.Layouts 1.1
import org.kde.plasma.plasmoid 2.0
import org.kde.plasma.components 2.0 as PlasmaComponents
MouseArea {
id: appmenu
property bool mouseInWidget: appmenuOpened || appmenu.containsMouse
property bool appmenuEnabled: plasmoid.configuration.controlPartMenuShowOnMouseIn || plasmoid.configuration.controlPartMenuShowOnMouseOut
property bool appmenuFillHeight: plasmoid.configuration.appmenuFillHeight
property bool appmenuFontBold: plasmoid.configuration.appmenuFontBold
property bool appmenuEnabledAndNonEmpty: appmenuEnabled && appMenuModel !== null && appMenuModel.menuAvailable
property bool appmenuOpened: appmenuEnabled && plasmoid.nativeInterface.currentIndex > -1
property var appMenuModel: null
visible: appmenuEnabledAndNonEmpty && !main.noWindowActive
property bool showItem
- property double recommendedWidth
+ property double recommendedMaxWidth
opacity: showItem ? 1 : 0
- width: recommendedWidth
+ width: recommendedMaxWidth
hoverEnabled: true
GridLayout {
id: buttonGrid
Layout.minimumWidth: implicitWidth
Layout.minimumHeight: implicitHeight
flow: GridLayout.LeftToRight
rowSpacing: 0
columnSpacing: 0
anchors.top: parent.top
anchors.left: parent.left
Component.onCompleted: {
plasmoid.nativeInterface.buttonGrid = buttonGrid
plasmoid.nativeInterface.enabled = appmenuEnabled
}
Connections {
target: plasmoid.nativeInterface
onRequestActivateIndex: {
var idx = Math.max(0, Math.min(buttonRepeater.count - 1, index))
var button = buttonRepeater.itemAt(index)
if (button) {
button.clicked(null)
}
}
}
Repeater {
id: buttonRepeater
model: null
MouseArea {
id: appmenuButton
hoverEnabled: true
readonly property int buttonIndex: index
property bool menuOpened: plasmoid.nativeInterface.currentIndex === index
Layout.preferredWidth: appmenuButtonBackground.width
Layout.preferredHeight: appmenuButtonBackground.height
Rectangle {
id: appmenuButtonBackground
border.color: 'transparent'
width: appmenuButtonTitle.implicitWidth + units.smallSpacing * 3
height: appmenuFillHeight ? appmenu.height : appmenuButtonTitle.implicitHeight + units.smallSpacing
color: menuOpened ? theme.highlightColor : 'transparent'
radius: units.smallSpacing / 2
}
PlasmaComponents.Label {
id: appmenuButtonTitle
anchors.top: appmenuButtonBackground.top
anchors.bottom: appmenuButtonBackground.bottom
verticalAlignment: Text.AlignVCenter
anchors.horizontalCenter: appmenuButtonBackground.horizontalCenter
font.pixelSize: main.fontPixelSize * plasmoid.configuration.appmenuButtonTextSizeScale
text: activeMenu.replace('&', '')
font.weight: appmenuFontBold ? Font.Bold : theme.defaultFont.weight
}
onClicked: {
plasmoid.nativeInterface.trigger(this, index)
}
onEntered: {
appmenuButtonBackground.border.color = theme.highlightColor
}
onExited: {
appmenuButtonBackground.border.color = 'transparent'
}
}
}
}
function initializeAppModel() {
if (appMenuModel !== null) {
return
}
print('initializing appMenuModel...')
try {
appMenuModel = Qt.createQmlObject(
'import QtQuick 2.2;\
import org.kde.plasma.plasmoid 2.0;\
import org.kde.private.activeWindowControl 1.0 as ActiveWindowControlPrivate;\
ActiveWindowControlPrivate.AppMenuModel {\
id: appMenuModel;\
Component.onCompleted: {\
plasmoid.nativeInterface.model = appMenuModel\
}\
}', main)
} catch (e) {
print('appMenuModel failed to initialize: ' + e)
}
print('initializing appmenu...DONE ' + appMenuModel)
if (appMenuModel !== null) {
resetAppmenuModel()
}
}
function resetAppmenuModel() {
if (appmenuEnabled) {
initializeAppModel()
if (appMenuModel === null) {
return
}
print('setting model in QML: ' + appMenuModel)
for (var key in appMenuModel) {
print(' ' + key + ' -> ' + appMenuModel[key])
}
plasmoid.nativeInterface.model = appMenuModel
buttonRepeater.model = appMenuModel
} else {
plasmoid.nativeInterface.model = null
buttonRepeater.model = null
}
}
onAppmenuEnabledChanged: {
appmenu.resetAppmenuModel()
if (appMenuModel !== null) {
plasmoid.nativeInterface.enabled = appmenuEnabled
}
}
}
\ No newline at end of file
diff --git a/package/contents/ui/WindowTitle.qml b/package/contents/ui/WindowTitle.qml
index d5db510..9a051ac 100644
--- a/package/contents/ui/WindowTitle.qml
+++ b/package/contents/ui/WindowTitle.qml
@@ -1,67 +1,75 @@
import QtQuick 2.2
import QtGraphicalEffects 1.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
PlasmaComponents.Label {
id: titleItem
property double properHeight: parent.height
property int fontBold: plasmoid.configuration.textFontBold
property string fontFamily: plasmoid.configuration.fontFamily
property int fitText: plasmoid.configuration.fitText
property bool noElide: fitText === 2 || (fitText === 1 && mainMouseArea.containsMouse)
property int allowFontSizeChange: 3
property int minimumPixelSize: 8
property bool limitTextWidth: plasmoid.configuration.limitTextWidth
property int textWidthLimit: plasmoid.configuration.textWidthLimit
- property double recommendedWidth
+ property double recommendedMaxWidth
+ property bool useUpPossibleWidth: main.useUpWidthItem === 0
+ property bool doNotRestrictWidth: useUpPossibleWidth && autoFillWidth
- onRecommendedWidthChanged: {
- if (limitTextWidth) {
+ onRecommendedMaxWidthChanged: {
+ var maxWidth = limitTextWidth ? Math.min(textWidthLimit, recommendedMaxWidth) : recommendedMaxWidth
+ width = undefined
+ if (useUpPossibleWidth || (limitTextWidth && implicitWidth > maxWidth)) {
+ width = maxWidth
+ }
+ }
+
+ onUseUpPossibleWidthChanged: recommendedMaxWidthChanged()
+
+ onDoNotRestrictWidthChanged: {
+ if (doNotRestrictWidth) {
width = undefined
- if (implicitWidth > textWidthLimit) {
- width = textWidthLimit
- } else {
- width = recommendedWidth
- }
} else {
- width = recommendedWidth
+ recommendedMaxWidthChanged()
}
}
verticalAlignment: Text.AlignVCenter
+ horizontalAlignment: plasmoid.configuration.controlPartTitleHorizontalAlignment === 0 ? Text.AlignLeft : Text.AlignRight
text: plasmoid.configuration.noWindowText
wrapMode: Text.Wrap
- width: recommendedWidth
+ //width: recommendedMaxWidth
height: properHeight
elide: noElide ? Text.ElideNone : Text.ElideRight
font.pixelSize: fontPixelSize
font.pointSize: -1
font.weight: fontBold === 1 || (fontBold === 2 && menuItem.showItem) ? Font.Bold : theme.defaultFont.weight
font.family: fontFamily || theme.defaultFont.family
opacity: menuItem.showItem ? plasmoid.configuration.appmenuIconAndTextOpacity : 1
onTextChanged: {
font.pixelSize = fontPixelSize
allowFontSizeChange = 3
- recommendedWidthChanged()
+ recommendedMaxWidthChanged()
}
onNoElideChanged: {
font.pixelSize = fontPixelSize
allowFontSizeChange = 3
}
onPaintedHeightChanged: {
if (allowFontSizeChange > 0 && noElide && paintedHeight > properHeight) {
var newPixelSize = (properHeight / paintedHeight) * fontPixelSize
font.pixelSize = newPixelSize < minimumPixelSize ? minimumPixelSize : newPixelSize
}
allowFontSizeChange--
}
}
\ No newline at end of file
diff --git a/package/contents/ui/config/ConfigLayout.qml b/package/contents/ui/config/ConfigLayout.qml
index 1e6903c..a0fddee 100644
--- a/package/contents/ui/config/ConfigLayout.qml
+++ b/package/contents/ui/config/ConfigLayout.qml
@@ -1,395 +1,421 @@
import QtQuick 2.2
import QtQuick.Controls 1.3
import QtQuick.Layouts 1.1
import QtQml.Models 2.1
Item {
id: configLayout
property string cfg_controlPartOrder
property alias cfg_controlPartSpacing: controlPartSpacing.value
+ property alias cfg_useUpWidthItem: useUpWidthItem.currentIndex
// GENERATED config (start)
- property alias cfg_controlPartIconPosition: controlPartIconPosition.currentIndex
property alias cfg_controlPartIconShowOnMouseIn: controlPartIconShowOnMouseIn.checked
property alias cfg_controlPartIconShowOnMouseOut: controlPartIconShowOnMouseOut.checked
+ property alias cfg_controlPartIconPosition: controlPartIconPosition.currentIndex
property alias cfg_controlPartIconHorizontalAlignment: controlPartIconHorizontalAlignment.currentIndex
- property alias cfg_controlPartTitlePosition: controlPartTitlePosition.currentIndex
property alias cfg_controlPartTitleShowOnMouseIn: controlPartTitleShowOnMouseIn.checked
property alias cfg_controlPartTitleShowOnMouseOut: controlPartTitleShowOnMouseOut.checked
+ property alias cfg_controlPartTitlePosition: controlPartTitlePosition.currentIndex
property alias cfg_controlPartTitleHorizontalAlignment: controlPartTitleHorizontalAlignment.currentIndex
- property alias cfg_controlPartButtonsPosition: controlPartButtonsPosition.currentIndex
property alias cfg_controlPartButtonsShowOnMouseIn: controlPartButtonsShowOnMouseIn.checked
property alias cfg_controlPartButtonsShowOnMouseOut: controlPartButtonsShowOnMouseOut.checked
+ property alias cfg_controlPartButtonsPosition: controlPartButtonsPosition.currentIndex
property alias cfg_controlPartButtonsHorizontalAlignment: controlPartButtonsHorizontalAlignment.currentIndex
- property alias cfg_controlPartMenuPosition: controlPartMenuPosition.currentIndex
property alias cfg_controlPartMenuShowOnMouseIn: controlPartMenuShowOnMouseIn.checked
property alias cfg_controlPartMenuShowOnMouseOut: controlPartMenuShowOnMouseOut.checked
+ property alias cfg_controlPartMenuPosition: controlPartMenuPosition.currentIndex
property alias cfg_controlPartMenuHorizontalAlignment: controlPartMenuHorizontalAlignment.currentIndex
// GENERATED config (end)
property alias cfg_controlPartMouseAreaRestrictedToWidget: controlPartMouseAreaRestrictedToWidget.checked
property alias cfg_autoFillWidth: autoFillWidth.checked
property alias cfg_horizontalScreenWidthPercent: horizontalScreenWidthPercent.value
property alias cfg_widthFineTuning: widthFineTuning.value
ListModel {
id: partsToSpend
ListElement {
name: 'icon'
text: 'Icon'
}
ListElement {
name: 'title'
text: 'Title'
}
ListElement {
name: 'buttons'
text: 'Buttons'
}
ListElement {
name: 'menu'
text: 'Menu'
}
}
function sortPartOrder() {
buttonOrder.model.clear()
cfg_controlPartOrder.split('|').forEach(function (itemId, index) {
var partIndex = -1
print('adding ' + itemId);
if (itemId === 'icon') {
partIndex = 0
} else if (itemId === 'title') {
partIndex = 1
} else if (itemId === 'buttons') {
partIndex = 2
} else if (itemId === 'menu') {
partIndex = 3
}
if (partIndex >= 0) {
buttonOrder.model.append(partsToSpend.get(partIndex));
}
});
print('model count: ' + buttonOrder.model.count)
}
GridLayout {
columns: 3
Label {
text: i18n('Plasmoid version: ') + '1.8.0-git'
Layout.alignment: Qt.AlignRight
Layout.columnSpan: 3
}
Item {
width: 2
height: units.largeSpacing
Layout.columnSpan: 3
}
Label {
text: i18n("Item order:")
}
OrderableListView {
id: buttonOrder
Layout.columnSpan: 2
itemHeight: units.gridUnit * 2
itemWidth: units.gridUnit * 4
height: itemHeight
width: itemWidth * 4
model: ListModel {
// will be filled initially by sortButtonOrder() method
}
orientation: ListView.Horizontal
onModelOrderChanged: {
var orderStr = '';
for (var i = 0; i < model.count; i++) {
var item = model.get(i)
if (orderStr.length > 0) {
orderStr += '|';
}
orderStr += item.name;
}
cfg_controlPartOrder = orderStr;
print('written: ' + cfg_controlPartOrder);
}
}
Label {
text: i18n("Item spacing:")
}
SpinBox {
id: controlPartSpacing
decimals: 1
stepSize: 0.5
minimumValue: 0.5
maximumValue: 300
Layout.columnSpan: 2
}
+ Label {
+ text: i18n('Item to use up all possible width:')
+ }
+ ComboBox {
+ id: useUpWidthItem
+ model: [i18n('Title'), i18n('Menu'), i18n('None')]
+ Layout.columnSpan: 2
+ }
+
// GENERATED controls (start)
GridLayout {
columns: 2
Item {
width: 2
height: units.largeSpacing
Layout.columnSpan: 2
}
Label {
text: i18n('Icon')
font.bold: true
Layout.columnSpan: 2
}
- Label {
- text: i18n('Position:')
- Layout.alignment: Qt.AlignVCenter | Qt.AlignRight
- }
-
- ComboBox {
- id: controlPartIconPosition
- model: [i18n('Occupy'), i18n('Floating layer'), i18n('Absolute')]
- }
-
CheckBox {
id: controlPartIconShowOnMouseIn
text: i18n('Show on mouse in')
Layout.columnSpan: 2
}
CheckBox {
id: controlPartIconShowOnMouseOut
text: i18n('Show on mouse out')
Layout.columnSpan: 2
}
- Label {
- text: i18n('Horizontal alignment:')
- Layout.alignment: Qt.AlignVCenter | Qt.AlignRight
- }
+ GridLayout {
+ columns: 2
+ Layout.columnSpan: 2
+ enabled: controlPartIconShowOnMouseIn.checked || controlPartIconShowOnMouseOut.checked
- ComboBox {
- id: controlPartIconHorizontalAlignment
- model: [i18n('Left'), i18n('Right')]
+ Label {
+ text: i18n('Position:')
+ Layout.alignment: Qt.AlignVCenter | Qt.AlignRight
+ }
+ ComboBox {
+ id: controlPartIconPosition
+ model: [i18n('Occupy'), i18n('Floating layer'), i18n('Absolute')]
+ }
+
+ Label {
+ text: i18n('Align:')
+ Layout.alignment: Qt.AlignVCenter | Qt.AlignRight
+ }
+ ComboBox {
+ id: controlPartIconHorizontalAlignment
+ model: [i18n('Left'), i18n('Right')]
+ }
}
Item {
width: 2
height: units.largeSpacing
Layout.columnSpan: 2
}
Label {
text: i18n('Buttons')
font.bold: true
Layout.columnSpan: 2
}
- Label {
- text: i18n('Position:')
- Layout.alignment: Qt.AlignVCenter | Qt.AlignRight
- }
-
- ComboBox {
- id: controlPartButtonsPosition
- model: [i18n('Occupy'), i18n('Floating layer'), i18n('Absolute')]
- }
-
CheckBox {
id: controlPartButtonsShowOnMouseIn
text: i18n('Show on mouse in')
Layout.columnSpan: 2
}
CheckBox {
id: controlPartButtonsShowOnMouseOut
text: i18n('Show on mouse out')
Layout.columnSpan: 2
}
- Label {
- text: i18n('Horizontal alignment:')
- Layout.alignment: Qt.AlignVCenter | Qt.AlignRight
- }
+ GridLayout {
+ columns: 2
+ Layout.columnSpan: 2
+ enabled: controlPartButtonsShowOnMouseIn.checked || controlPartButtonsShowOnMouseOut.checked
+
+ Label {
+ text: i18n('Position:')
+ Layout.alignment: Qt.AlignVCenter | Qt.AlignRight
+ }
+ ComboBox {
+ id: controlPartButtonsPosition
+ model: [i18n('Occupy'), i18n('Floating layer'), i18n('Absolute')]
+ }
- ComboBox {
- id: controlPartButtonsHorizontalAlignment
- model: [i18n('Left'), i18n('Right')]
+ Label {
+ text: i18n('Align:')
+ Layout.alignment: Qt.AlignVCenter | Qt.AlignRight
+ }
+ ComboBox {
+ id: controlPartButtonsHorizontalAlignment
+ model: [i18n('Left'), i18n('Right')]
+ }
}
}
Item {
width: units.largeSpacing
height: units.largeSpacing
}
GridLayout {
columns: 2
Item {
width: 2
height: units.largeSpacing
Layout.columnSpan: 2
}
Label {
text: i18n('Title')
font.bold: true
Layout.columnSpan: 2
}
- Label {
- text: i18n('Position:')
- Layout.alignment: Qt.AlignVCenter | Qt.AlignRight
- }
-
- ComboBox {
- id: controlPartTitlePosition
- model: [i18n('Occupy'), i18n('Floating layer'), i18n('Absolute')]
- }
-
CheckBox {
id: controlPartTitleShowOnMouseIn
text: i18n('Show on mouse in')
Layout.columnSpan: 2
}
CheckBox {
id: controlPartTitleShowOnMouseOut
text: i18n('Show on mouse out')
Layout.columnSpan: 2
}
- Label {
- text: i18n('Horizontal alignment:')
- Layout.alignment: Qt.AlignVCenter | Qt.AlignRight
- }
+ GridLayout {
+ columns: 2
+ Layout.columnSpan: 2
+ enabled: controlPartTitleShowOnMouseIn.checked || controlPartTitleShowOnMouseOut.checked
+
+ Label {
+ text: i18n('Position:')
+ Layout.alignment: Qt.AlignVCenter | Qt.AlignRight
+ }
+ ComboBox {
+ id: controlPartTitlePosition
+ model: [i18n('Occupy'), i18n('Floating layer'), i18n('Absolute')]
+ }
- ComboBox {
- id: controlPartTitleHorizontalAlignment
- model: [i18n('Left'), i18n('Right')]
+ Label {
+ text: i18n('Align:')
+ Layout.alignment: Qt.AlignVCenter | Qt.AlignRight
+ }
+ ComboBox {
+ id: controlPartTitleHorizontalAlignment
+ model: [i18n('Left'), i18n('Right')]
+ }
}
Item {
width: 2
height: units.largeSpacing
Layout.columnSpan: 2
}
Label {
text: i18n('Menu')
font.bold: true
Layout.columnSpan: 2
}
- Label {
- text: i18n('Position:')
- Layout.alignment: Qt.AlignVCenter | Qt.AlignRight
- }
-
- ComboBox {
- id: controlPartMenuPosition
- model: [i18n('Occupy'), i18n('Floating layer'), i18n('Absolute')]
- }
-
CheckBox {
id: controlPartMenuShowOnMouseIn
text: i18n('Show on mouse in')
Layout.columnSpan: 2
}
CheckBox {
id: controlPartMenuShowOnMouseOut
text: i18n('Show on mouse out')
Layout.columnSpan: 2
}
- Label {
- text: i18n('Horizontal alignment:')
- Layout.alignment: Qt.AlignVCenter | Qt.AlignRight
- }
+ GridLayout {
+ columns: 2
+ Layout.columnSpan: 2
+ enabled: controlPartMenuShowOnMouseIn.checked || controlPartMenuShowOnMouseOut.checked
+
+ Label {
+ text: i18n('Position:')
+ Layout.alignment: Qt.AlignVCenter | Qt.AlignRight
+ }
+ ComboBox {
+ id: controlPartMenuPosition
+ model: [i18n('Occupy'), i18n('Floating layer'), i18n('Absolute')]
+ }
- ComboBox {
- id: controlPartMenuHorizontalAlignment
- model: [i18n('Left'), i18n('Right')]
+ Label {
+ text: i18n('Align:')
+ Layout.alignment: Qt.AlignVCenter | Qt.AlignRight
+ }
+ ComboBox {
+ id: controlPartMenuHorizontalAlignment
+ model: [i18n('Left'), i18n('Right')]
+ }
}
}
// GENERATED controls (end)
Item {
width: units.largeSpacing
height: units.largeSpacing
Layout.columnSpan: 3
}
CheckBox {
id: controlPartMouseAreaRestrictedToWidget
text: i18n('Restrict mouse area to widget')
Layout.columnSpan: 3
}
Item {
width: units.largeSpacing
height: units.largeSpacing
Layout.columnSpan: 3
}
Label {
text: i18n("Width in horizontal panel:")
font.bold: true
Layout.alignment: Qt.AlignLeft
Layout.columnSpan: 3
}
CheckBox {
id: autoFillWidth
text: i18n("Fill width")
Layout.columnSpan: 3
}
GridLayout {
columns: 2
Layout.columnSpan: 3
enabled: !autoFillWidth.checked
Slider {
id: horizontalScreenWidthPercent
stepSize: 0.001
minimumValue: 0.001
maximumValue: 1
Layout.preferredWidth: configLayout.width
Layout.columnSpan: 2
}
Label {
text: i18n("Fine tuning:")
Layout.alignment: Qt.AlignRight
}
SpinBox {
id: widthFineTuning
decimals: 1
stepSize: 0.5
minimumValue: -100
maximumValue: 100
}
}
}
Component.onCompleted: {
sortPartOrder()
}
}
diff --git a/package/contents/ui/config/ConfigTitleAndIcon.qml b/package/contents/ui/config/ConfigTitleAndIcon.qml
index 0cb9dc0..a932631 100644
--- a/package/contents/ui/config/ConfigTitleAndIcon.qml
+++ b/package/contents/ui/config/ConfigTitleAndIcon.qml
@@ -1,233 +1,233 @@
import QtQuick 2.2
import QtQuick.Controls 1.3
import QtQuick.Layouts 1.1
import org.kde.plasma.core 2.0 as PlasmaCore
Item {
property alias cfg_textType: textTypeCombo.currentIndex
property alias cfg_fitText: fitTextCombo.currentIndex
property alias cfg_tooltipTextType: tooltipTextTypeCombo.currentIndex
property alias cfg_useWindowTitleReplace: useWindowTitleReplace.checked
property alias cfg_replaceTextRegex: replaceTextRegex.text
property alias cfg_replaceTextReplacement: replaceTextReplacement.text
property alias cfg_noWindowText: noWindowText.text
property string cfg_noWindowIcon: plasmoid.configuration.noWindowIcon
property alias cfg_limitTextWidth: limitTextWidth.checked
property alias cfg_textWidthLimit: textWidthLimit.value
property alias cfg_textFontBold: textFontBoldCombo.currentIndex
property string cfg_fontFamily
property alias cfg_fontSizeScale: fontSizeScale.value
/* copied from /usr/share/plasma/plasmoids/org.kde.plasma.digitalclock/contents/ui/configAppearance.qml */
onCfg_fontFamilyChanged: {
// HACK by the time we populate our model and/or the ComboBox is finished the value is still undefined
if (cfg_fontFamily) {
for (var i = 0, j = fontsModel.count; i < j; ++i) {
if (fontsModel.get(i).value == cfg_fontFamily) {
fontFamilyComboBox.currentIndex = i
break
}
}
}
}
ListModel {
id: fontsModel
Component.onCompleted: {
var arr = [ {text: i18nc("Use default font", "Default"), value: ""} ]
Qt.fontFamilies().forEach(function (font) {
arr.push({text: font, value: font})
})
append(arr)
cfg_fontFamilyChanged();
}
}
GridLayout {
columns: 2
Label {
text: i18n('Text')
Layout.alignment: Qt.AlignLeft
font.bold: true
Layout.columnSpan: 2
}
Label {
text: i18n('Text type:')
Layout.alignment: Qt.AlignRight
}
ComboBox {
id: textTypeCombo
model: [i18n('Window title'), i18n('Application name')]
}
Label {
text: i18n('Fit text:')
Layout.alignment: Qt.AlignRight
}
ComboBox {
id: fitTextCombo
model: [i18n('Just elide'), i18n('Fit on hover'), i18n('Always fit')]
}
Label {
text: i18n('Tooltip text:')
Layout.alignment: Qt.AlignRight
}
ComboBox {
id: tooltipTextTypeCombo
model: [i18n('No tooltip'), i18n('Window title'), i18n('Application name')]
}
Item {
width: 2
height: units.largeSpacing
Layout.columnSpan: 2
}
Label {
text: i18n('Bold text:')
Layout.alignment: Qt.AlignRight
}
ComboBox {
id: textFontBoldCombo
// ComboBox's sizing is just utterly broken
Layout.minimumWidth: units.gridUnit * 10
model: [i18n('Never'), i18n('Always'), i18n('When appmenu is displayed')]
}
Label {
text: i18n('Text font:')
Layout.alignment: Qt.AlignRight
}
ComboBox {
id: fontFamilyComboBox
// ComboBox's sizing is just utterly broken
Layout.minimumWidth: units.gridUnit * 10
model: fontsModel
// doesn't autodeduce from model because we manually populate it
textRole: "text"
onCurrentIndexChanged: {
var current = model.get(currentIndex)
if (current) {
cfg_fontFamily = current.value
//appearancePage.configurationChanged()
console.log('change: ' + cfg_fontFamily)
}
}
}
Label {
text: i18n("Font size scale:")
Layout.alignment: Qt.AlignVCenter|Qt.AlignRight
}
SpinBox {
id: fontSizeScale
decimals: 2
stepSize: 0.05
minimumValue: 0
maximumValue: 3
}
CheckBox {
id: limitTextWidth
text: i18n('Limit text width')
Layout.alignment: Qt.AlignRight
}
SpinBox {
id: textWidthLimit
decimals: 0
stepSize: 10
minimumValue: 0
maximumValue: 10000
enabled: limitTextWidth.checked
suffix: i18nc('Abbreviation for pixels', 'px')
}
Item {
width: 2
height: units.largeSpacing
Layout.columnSpan: 2
}
CheckBox {
id: useWindowTitleReplace
text: '"' + i18n('Window title') + '".replace(/'
Layout.alignment: Qt.AlignRight
}
GridLayout {
columns: 4
TextField {
id: replaceTextRegex
placeholderText: '^(.*)\\s+[—–\\-:]\\s+([^—–\\-:]+)$'
- Layout.preferredWidth: 300
+ Layout.preferredWidth: 270
onTextChanged: cfg_replaceTextRegex = text
enabled: useWindowTitleReplace.checked
}
Label {
text: '/, "'
}
TextField {
id: replaceTextReplacement
placeholderText: '$2 — $1'
Layout.preferredWidth: 100
onTextChanged: cfg_replaceTextReplacement = text
enabled: useWindowTitleReplace.checked
}
Label {
text: '");'
}
}
Label {
text: i18n('No window text:')
Layout.alignment: Qt.AlignRight
}
GridLayout {
columns: 2
TextField {
id: noWindowText
placeholderText: 'Plasma Desktop :: %activity%'
onTextChanged: cfg_noWindowText = text
- Layout.preferredWidth: 300
+ Layout.preferredWidth: 270
}
Label {
text: i18n('Use %activity% placeholder to show current activity name.')
- Layout.preferredWidth: 200
+ Layout.preferredWidth: 150
wrapMode: Text.Wrap
}
}
Item {
width: 2
height: units.largeSpacing
Layout.columnSpan: 2
}
Label {
text: i18n('Icon')
Layout.alignment: Qt.AlignLeft
font.bold: true
Layout.columnSpan: 2
}
Label {
text: i18n("No window icon:")
Layout.alignment: Qt.AlignRight
}
IconPicker {
currentIcon: cfg_noWindowIcon
defaultIcon: ''
onIconChanged: cfg_noWindowIcon = iconName
}
}
}
diff --git a/package/contents/ui/main.qml b/package/contents/ui/main.qml
index 42b228c..700a99e 100644
--- a/package/contents/ui/main.qml
+++ b/package/contents/ui/main.qml
@@ -1,561 +1,600 @@
/*
* Copyright 2015 Martin Kotelnik
*
* 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, see .
*/
import QtQuick 2.2
import QtGraphicalEffects 1.0
import QtQuick.Layouts 1.1
import QtQuick.Window 2.2
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
Item {
id: main
property bool vertical: (plasmoid.formFactor == PlasmaCore.Types.Vertical)
property double horizontalScreenWidthPercent: plasmoid.configuration.horizontalScreenWidthPercent
property bool autoFillWidth: plasmoid.configuration.autoFillWidth
property double widthForHorizontalPanel: (Screen.width * horizontalScreenWidthPercent + plasmoid.configuration.widthFineTuning)
+ property int useUpWidthItem: plasmoid.configuration.useUpWidthItem
+
property int textType: plasmoid.configuration.textType
property int tooltipTextType: plasmoid.configuration.tooltipTextType
property string tooltipText: ''
property double fontPixelSize: theme.defaultFont.pixelSize * plasmoid.configuration.fontSizeScale
property bool noWindowActive: true
property bool currentWindowMaximized: false
property bool doubleClickMaximizes: plasmoid.configuration.doubleClickMaximizes
property int leftClickAction: plasmoid.configuration.leftClickAction
property string chosenLeftClickSource: leftClickAction === 1 ? shortcutDS.presentWindows : leftClickAction === 2 ? shortcutDS.presentWindowsAll : leftClickAction === 3 ? shortcutDS.presentWindowsClass : ''
property bool middleClickClose: plasmoid.configuration.middleClickAction === 1
property bool middleClickFullscreen: plasmoid.configuration.middleClickAction === 2
property bool wheelUpMaximizes: plasmoid.configuration.wheelUpMaximizes
property bool wheelDownMinimizes: plasmoid.configuration.wheelDownAction === 1
property bool wheelDownUnmaximizes: plasmoid.configuration.wheelDownAction === 2
property bool textColorLight: ((theme.textColor.r + theme.textColor.g + theme.textColor.b) / 3) > 0.5
property bool isActiveWindowPinned: false
property bool isActiveWindowMaximized: false
property bool controlPartMouseAreaRestrictedToWidget: plasmoid.configuration.controlPartMouseAreaRestrictedToWidget
property var activeTaskLocal: null
property int activityActionCount: 0
property var itemPartOrder: []
property bool mouseInWidget: mainMouseArea.containsMouse || buttonsItem.mouseInWidget || menuItem.mouseInWidget
anchors.fill: parent
- Layout.fillWidth: plasmoid.configuration.autoFillWidth
+ Layout.fillWidth: autoFillWidth
Layout.preferredWidth: autoFillWidth ? -1 : (vertical ? parent.width : (widthForHorizontalPanel > 0 ? widthForHorizontalPanel : 0.0001))
Layout.minimumWidth: Layout.preferredWidth
Layout.maximumWidth: Layout.preferredWidth
Layout.preferredHeight: parent === null ? 0 : vertical ? Math.min(theme.defaultFont.pointSize * 4, parent.width) : parent.height
Layout.minimumHeight: Layout.preferredHeight
Layout.maximumHeight: Layout.preferredHeight
Plasmoid.preferredRepresentation: Plasmoid.fullRepresentation
Plasmoid.status: {
if (menuItem.appmenuOpened) {
return PlasmaCore.Types.NeedsAttentionStatus;
} else if (!menuItem.appmenuOpened && menuItem.appmenuEnabledAndNonEmpty){
return PlasmaCore.Types.ActiveStatus;
} else {
return PlasmaCore.Types.PassiveStatus;
}
}
//
// MODEL
//
TaskManager.TasksModel {
id: tasksModel
sortMode: TaskManager.TasksModel.SortVirtualDesktop
groupMode: TaskManager.TasksModel.GroupDisabled
screenGeometry: plasmoid.screenGeometry
filterByScreen: plasmoid.configuration.showForCurrentScreenOnly
onActiveTaskChanged: {
updateActiveWindowInfo()
}
onDataChanged: {
updateActiveWindowInfo()
}
onCountChanged: {
updateActiveWindowInfo()
}
}
TaskManager.ActivityInfo {
id: activityInfo
onCurrentActivityChanged: {
if (noWindowActive) {
updateActiveWindowInfo();
}
reAddActivityActions()
}
onNumberOfRunningActivitiesChanged: {
reAddActivityActions()
}
}
Activities.ActivityModel {
id: activityModel
}
function activeTask() {
return activeTaskLocal
}
function activeTaskExists() {
return activeTaskLocal.display !== undefined
}
function updateTooltip() {
if (tooltipTextType === 1) {
tooltipText = replaceTitle(activeTask().display || '')
} else if (tooltipTextType === 2) {
tooltipText = activeTask().AppName || ''
} else {
tooltipText = ''
}
}
onTooltipTextTypeChanged: updateTooltip()
function composeNoWindowText() {
return plasmoid.configuration.noWindowText.replace('%activity%', activityInfo.activityName(activityInfo.currentActivity))
}
function updateActiveWindowInfo() {
var activeTaskIndex = tasksModel.activeTask
// fallback for Plasma 5.8
var abstractTasksModel = TaskManager.AbstractTasksModel || {}
var isActive = abstractTasksModel.IsActive || 271
var appName = abstractTasksModel.AppName || 258
var isMaximized = abstractTasksModel.IsMaximized || 276
var virtualDesktop = abstractTasksModel.VirtualDesktop || 286
activeTaskLocal = {}
if (tasksModel.data(activeTaskIndex, isActive)) {
activeTaskLocal = {
display: tasksModel.data(activeTaskIndex, Qt.DisplayRole),
decoration: tasksModel.data(activeTaskIndex, Qt.DecorationRole),
AppName: tasksModel.data(activeTaskIndex, appName),
IsMaximized: tasksModel.data(activeTaskIndex, isMaximized),
VirtualDesktop: tasksModel.data(activeTaskIndex, virtualDesktop)
}
}
var actTask = activeTask()
noWindowActive = !activeTaskExists()
currentWindowMaximized = !noWindowActive && actTask.IsMaximized === true
isActiveWindowPinned = actTask.VirtualDesktop === -1;
if (noWindowActive) {
titleItem.text = composeNoWindowText()
iconItem.source = plasmoid.configuration.noWindowIcon
} else {
titleItem.text = (textType === 1 ? actTask.AppName : null) || replaceTitle(actTask.display)
iconItem.source = actTask.decoration
}
updateTooltip()
}
function toggleMaximized() {
tasksModel.requestToggleMaximized(tasksModel.activeTask);
}
function toggleMinimized() {
tasksModel.requestToggleMinimized(tasksModel.activeTask);
}
function toggleClose() {
tasksModel.requestClose(tasksModel.activeTask);
}
function toggleFullscreen() {
tasksModel.requestToggleFullScreen(tasksModel.activeTask);
}
function togglePinToAllDesktops() {
tasksModel.requestVirtualDesktop(tasksModel.activeTask, 0);
}
function setMaximized(maximized) {
if ((maximized && !activeTask().IsMaximized)
|| (!maximized && activeTask().IsMaximized)) {
print('toggle maximized')
toggleMaximized()
}
}
function setMinimized() {
if (!activeTask().IsMinimized) {
toggleMinimized()
}
}
function getConfigName(itemName) {
return itemName.substring(0, 1).toUpperCase() + itemName.substring(1)
}
/*
* Position can be:
* 0 ... occupy
* 1 ... floating layer (second occupy)
* 2 ... absolute
*/
function getPosition(itemName) {
var configName = getConfigName(itemName)
print('getPosition: ' + configName)
print('POS: ' + plasmoid.configuration['controlPart' + configName + 'Position'])
return plasmoid.configuration['controlPart' + configName + 'Position']
}
+ /*
+ * Alignment can be:
+ * 0 ... left
+ * 1 ... right
+ */
+ function getAlignment(itemName) {
+ var configName = getConfigName(itemName)
+ print('getAlignment: ' + configName)
+ print('ALI: ' + plasmoid.configuration['controlPart' + configName + 'HorizontalAlignment'])
+ return plasmoid.configuration['controlPart' + configName + 'HorizontalAlignment']
+ }
+
function isRelevant(itemName) {
var configName = getConfigName(itemName)
- print('isRelevant: ' + configName)
- print('1IR: ' + plasmoid.configuration['controlPart' + configName + 'ShowOnMouseIn'])
- print('2IR: ' + plasmoid.configuration['controlPart' + configName + 'ShowOnMouseOut'])
- var result = plasmoid.configuration['controlPart' + configName + 'ShowOnMouseIn'] || plasmoid.configuration['controlPart' + configName + 'ShowOnMouseOut']
- print('res: ' + result)
- return result
+ var mouseInConfigName = 'controlPart' + configName + 'ShowOnMouseIn'
+ var mouseOutConfigName = 'controlPart' + configName + 'ShowOnMouseOut'
+ return plasmoid.configuration[mouseInConfigName] || plasmoid.configuration[mouseOutConfigName]
}
function getItem(itemName) {
if (itemName === 'icon') {
return iconItem
}
if (itemName === 'title') {
return titleItem
}
if (itemName === 'menu') {
return menuItem
}
if (itemName === 'buttons') {
return buttonsItem
}
return null
}
function getItemWidth(itemName) {
+ if (itemName === 'title' && !titleItem.useUpPossibleWidth) {
+ return getItem(itemName).implicitWidth
+ }
return getItem(itemName).width
}
function getLeftMargin(itemName) {
var itemPosition = getPosition(itemName)
+ var itemAlignment = getAlignment(itemName)
print('position of ' + itemName + ' is ' + itemPosition)
if (itemPosition === 2) {
return 0
}
var anchorSize = 0
- itemPartOrder.some(function (iName, index) {
+ var itemPartOrderArray = itemAlignment === 0 ? itemPartOrder : itemPartOrder.slice().reverse()
+ itemPartOrderArray.some(function (iName, index) {
print('iterating: ' + iName)
if (iName === itemName) {
return true
}
- if (getPosition(iName) === itemPosition && isRelevant(iName)) {
+ if (getPosition(iName) === itemPosition && getAlignment(iName) === itemAlignment && isRelevant(iName)) {
var currentItemWidth = getItemWidth(iName)
print('width of ' + iName + ' is ' + currentItemWidth)
anchorSize += currentItemWidth
anchorSize += plasmoid.configuration.controlPartSpacing
}
});
+ if (itemAlignment === 1) {
+ var computedWidth = autoFillWidth ? main.width : widthForHorizontalPanel
+ anchorSize = computedWidth - anchorSize - getItemWidth(itemName)
+ }
print('leftMargin of ' + itemName + ' is ' + anchorSize)
return anchorSize
}
- function getWidth(itemName) {
+ function getMaxWidth(itemName) {
var itemPosition = getPosition(itemName)
- print('getWidth(): position of ' + itemName + ' is ' + itemPosition)
+ print('getMaxWidth(): position of ' + itemName + ' is ' + itemPosition)
if (itemPosition === 2) {
return 0
}
- var computedWidth = widthForHorizontalPanel
+ var computedWidth = autoFillWidth ? main.width : widthForHorizontalPanel
itemPartOrder.forEach(function (iName, index) {
print('iterating: ' + iName)
if (iName === itemName) {
return;
}
if (getPosition(iName) === itemPosition && isRelevant(iName)) {
var currentItemWidth = getItemWidth(iName)
print('width of ' + iName + ' is ' + currentItemWidth)
computedWidth -= currentItemWidth
computedWidth -= plasmoid.configuration.controlPartSpacing
}
});
print('computedWidth of ' + itemName + ' is ' + computedWidth)
return computedWidth
}
function refreshItemPosition() {
- titleItem.recommendedWidth = getWidth('title')
- menuItem.recommendedWidth = getWidth('menu')
+ if (titleItem.useUpPossibleWidth) {
+ titleItem.recommendedMaxWidth = getMaxWidth('title')
+ menuItem.recommendedMaxWidth = getMaxWidth('menu')
+ } else {
+ titleItem.recommendedMaxWidth = getMaxWidth('title')
+ menuItem.recommendedMaxWidth = getMaxWidth('menu')
+ }
iconItem.x = getLeftMargin('icon')
titleItem.x = getLeftMargin('title')
menuItem.x = getLeftMargin('menu')
buttonsItem.x = getLeftMargin('buttons')
textSeparator.x = getLeftMargin('menu') - (plasmoid.configuration.controlPartSpacing / 2)
}
function replaceTitle(title) {
if (!plasmoid.configuration.useWindowTitleReplace) {
return title
}
return title.replace(new RegExp(plasmoid.configuration.replaceTextRegex), plasmoid.configuration.replaceTextReplacement);
}
+ onWidthChanged: {
+ if (autoFillWidth) {
+ refreshItemPosition();
+ }
+ }
onWidthForHorizontalPanelChanged: refreshItemPosition()
MouseArea {
id: mainMouseArea
anchors.fill: parent
hoverEnabled: true
acceptedButtons: Qt.LeftButton | Qt.MiddleButton
onWheel: {
if (wheel.angleDelta.y > 0) {
if (wheelUpMaximizes) {
setMaximized(true)
}
} else {
if (wheelDownMinimizes) {
setMinimized()
} else if (wheelDownUnmaximizes) {
setMaximized(false)
}
}
}
onDoubleClicked: {
if (doubleClickMaximizes && mouse.button == Qt.LeftButton) {
toggleMaximized()
}
}
onClicked: {
if (chosenLeftClickSource !== '' && !doubleClickMaximizes && mouse.button == Qt.LeftButton) {
shortcutDS.connectedSources.push(chosenLeftClickSource)
buttonsItem.mouseInWidget = false
return
}
if (mouse.button == Qt.MiddleButton) {
if (middleClickFullscreen) {
toggleFullscreen()
} else if (middleClickClose) {
toggleClose()
}
}
}
PlasmaCore.ToolTipArea {
anchors.fill: parent
active: tooltipTextType > 0 && tooltipText !== ''
interactive: true
location: plasmoid.location
mainItem: Row {
spacing: 0
Layout.minimumWidth: fullText.width + units.largeSpacing
Layout.minimumHeight: childrenRect.height
Layout.maximumWidth: Layout.minimumWidth
Layout.maximumHeight: Layout.minimumHeight
Item {
width: units.largeSpacing / 2
height: 2
}
PlasmaComponents.Label {
id: fullText
text: tooltipText
}
}
}
}
ListModel {
id: controlButtonsModel
}
WindowIcon {
id: iconItem
visible: ((mouseInWidget && plasmoid.configuration.controlPartIconShowOnMouseIn)
|| (!mouseInWidget && plasmoid.configuration.controlPartIconShowOnMouseOut))
onWidthChanged: refreshItemPosition()
}
WindowTitle {
id: titleItem
visible: ((mouseInWidget && plasmoid.configuration.controlPartTitleShowOnMouseIn)
|| (!mouseInWidget && plasmoid.configuration.controlPartTitleShowOnMouseOut))
+
+ onImplicitWidthChanged: {
+ if (!titleItem.useUpPossibleWidth) {
+ refreshItemPosition()
+ }
+ }
+
+ onUseUpPossibleWidthChanged: refreshItemPosition()
}
AppMenu {
id: menuItem
property bool mouseIn: controlPartMouseAreaRestrictedToWidget ? menuItem.mouseInWidget : main.mouseInWidget
height: main.height
showItem: !noWindowActive && ((mouseIn && plasmoid.configuration.controlPartMenuShowOnMouseIn)
|| (!mouseIn && plasmoid.configuration.controlPartMenuShowOnMouseOut))
}
ControlButtons {
id: buttonsItem
property bool mouseIn: controlPartMouseAreaRestrictedToWidget ? buttonsItem.mouseInWidget : main.mouseInWidget
showItem: !noWindowActive && ((mouseIn && plasmoid.configuration.controlPartButtonsShowOnMouseIn)
|| (!mouseIn && plasmoid.configuration.controlPartButtonsShowOnMouseOut))
onWidthChanged: refreshItemPosition()
}
Rectangle {
id: textSeparator
x: 0
anchors.verticalCenter: main.verticalCenter
height: 0.8 * parent.height
width: 1
visible: plasmoid.configuration.appmenuSeparatorEnabled && menuItem.showItem
color: theme.textColor
opacity: 0.4
}
function action_close() {
toggleClose()
}
function action_maximise() {
toggleMaximized()
}
function action_minimise() {
toggleMinimized()
}
function action_pinToAllDesktops() {
togglePinToAllDesktops()
}
function action_reloadTheme() {
plasmoid.nativeInterface.refreshAuroraeTheme();
}
function actionTriggered(actionName) {
if (actionName.indexOf("switchToActivity_") == 0) {
var activityIndex = actionName.replace("switchToActivity_", "")
var activityId = activityInfo.runningActivities()[activityIndex]
activityModel.setCurrentActivity(activityId, function() {});
}
}
function reAddActivityActions() {
plasmoid.removeAction("separator1")
for (var i = 0; i < activityActionCount; i++) {
plasmoid.removeAction('switchToActivity_' + i)
}
plasmoid.removeAction("separator2")
var runningActivities = activityInfo.runningActivities()
activityActionCount = runningActivities.length
if (activityActionCount === 0) {
return
}
plasmoid.setActionSeparator("separator1")
activityInfo.runningActivities().forEach(function (activityId, index) {
if (activityId === activityInfo.currentActivity) {
return;
}
var activityName = activityInfo.activityName(activityId)
plasmoid.setAction('switchToActivity_' + index, i18n('Switch to activity: %1', activityName), 'preferences-activities')
})
plasmoid.setActionSeparator("separator2")
}
property string controlPartOrder: plasmoid.configuration.controlPartOrder
onControlPartOrderChanged: refreshControlPartOrder()
+ onUseUpWidthItemChanged: refreshControlPartOrder()
function refreshControlPartOrder() {
itemPartOrder.length = 0
plasmoid.configuration.controlPartOrder.split('|').forEach(function (itemName, index) {
print('itemOrder: ' + itemName)
itemPartOrder.push(itemName)
print('itemZ: ' + index)
getItem(itemName).z = index
});
print('itemPartOrder initialized: ' + itemPartOrder)
refreshItemPosition()
}
Component.onCompleted: {
refreshControlPartOrder()
refreshItemPosition()
updateActiveWindowInfo()
// actions
plasmoid.setAction('close', i18n('Close'), 'window-close');
plasmoid.setAction('maximise', i18n('Toggle Maximise'), 'arrow-up-double');
plasmoid.setAction('minimise', i18n('Minimise'), 'draw-arrow-down');
plasmoid.setAction('pinToAllDesktops', i18n('Toggle Pin To All Desktops'), 'window-pin');
plasmoid.setActionSeparator("separator0")
plasmoid.setAction('reloadTheme', i18n('Reload Theme'), 'system-reboot');
reAddActivityActions()
}
PlasmaCore.DataSource {
id: shortcutDS
engine: 'executable'
property string presentWindows: 'qdbus org.kde.kglobalaccel /component/kwin invokeShortcut "Expose"'
property string presentWindowsAll: 'qdbus org.kde.kglobalaccel /component/kwin invokeShortcut "ExposeAll"'
property string presentWindowsClass: 'qdbus org.kde.kglobalaccel /component/kwin invokeShortcut "ExposeClass"'
connectedSources: []
onNewData: {
connectedSources.length = 0
}
}
}