Skip to content

Commit

Permalink
#44: sortable replacements, replacements listeners decoupled to avoid…
Browse files Browse the repository at this point in the history
… dead-locking
  • Loading branch information
antroids committed Jul 10, 2024
1 parent 94d9353 commit 4684971
Show file tree
Hide file tree
Showing 3 changed files with 197 additions and 67 deletions.
177 changes: 140 additions & 37 deletions package/contents/ui/config/TitleReplacements.qml
Original file line number Diff line number Diff line change
Expand Up @@ -26,12 +26,85 @@ KCM.SimpleKCM {
Regex
}

ListModel {
id: replacementsModel

function updateModelFromConfig() {
clear();
for (let i = 0; i < cfg_titleReplacementsPatterns.length; i++) {
append({
"pattern": cfg_titleReplacementsPatterns[i],
"template": cfg_titleReplacementsTemplates[i],
"type": cfg_titleReplacementsTypes[i]
});
}
}

function updateConfigFromModel() {
Qt.callLater(_updateConfigFromModel);
}

function _updateConfigFromModel() {
const length = count;
cfg_titleReplacementsPatterns.length = length;
cfg_titleReplacementsTemplates.length = length;
cfg_titleReplacementsTypes.length = length;
for (let i = 0; i < length; i++) {
const rowValue = get(i);
cfg_titleReplacementsPatterns[i] = rowValue.pattern;
cfg_titleReplacementsTemplates[i] = rowValue.template;
cfg_titleReplacementsTypes[i] = rowValue.type;
}
}

function pushNewReplacement() {
append({
"pattern": "",
"template": "",
"type": TitleReplacements.Type.String
});
updateConfigFromModel();
}

function deleteReplacement(index) {
remove(index);
updateConfigFromModel();
}

function setType(index, type) {
set(index, {
"type": type
});
updateConfigFromModel();
}

function setPattern(index, pattern) {
set(index, {
"pattern": pattern
});
updateConfigFromModel();
}

function setTemplate(index, template) {
set(index, {
"template": template
});
updateConfigFromModel();
}

function moveReplacement(from, to) {
move(from, to, 1);
updateConfigFromModel();
}

Component.onCompleted: updateModelFromConfig()
}

ColumnLayout {
RowLayout {
visible: replacementsRepeater.count > 5
Button {
text: i18n("Add Title Replacement")
onClicked: pushNewReplacement()
onClicked: replacementsModel.pushNewReplacement()
}
Label {
text: i18n("<a href=\"https://www.w3schools.com/jsref/jsref_obj_regexp.asp\">JavaScript RegExp Reference</a>")
Expand All @@ -44,34 +117,72 @@ KCM.SimpleKCM {
Repeater {
id: replacementsRepeater

function updateModel() {
model = cfg_titleReplacementsPatterns.length;
}

Component.onCompleted: updateModel()

model: replacementsModel
delegate: RowLayout {
id: replacement
required property int index
required property var modelData

Drag.source: dragArea
Drag.active: dragArea.drag.active
Drag.hotSpot.y: height / 2

Kirigami.Icon {
Layout.maximumWidth: Kirigami.Units.gridUnit

source: "transform-move-vertical"
MouseArea {
id: dragArea
anchors.fill: parent
drag.axis: Drag.YAxis
drag.target: replacement
cursorShape: Qt.DragMoveCursor

drag {
onActiveChanged: function () {
if (!drag.active) {
replacementsModel.updateModelFromConfig();
}
}
}

states: State {
when: dragArea.drag.active

PropertyChanges {
target: replacement
z: 1
}
}

DropArea {
anchors.fill: parent
onEntered: drag => {
replacementsModel.moveReplacement(drag.source.DelegateModel.itemsIndex, dragArea.DelegateModel.itemsIndex);
}
}
}
}

ComboBox {
id: titleReplacementsType
Layout.maximumWidth: Kirigami.Units.gridUnit * 5

model: [i18n("String"), i18n("RegExp")]
onActivated: function () {
cfg_titleReplacementsTypes[replacement.index] = currentIndex;
replacementsModel.setType(index, currentIndex);
}
Component.onCompleted: currentIndex = cfg_titleReplacementsTypes[replacement.index]
currentIndex: modelData.type
}

TextField {
id: titleReplacementsPattern

onTextEdited: function () {
cfg_titleReplacementsPatterns[replacement.index] = text;
replacementsModel.setPattern(index, text);
}
Layout.alignment: Qt.AlignLeft
Component.onCompleted: text = cfg_titleReplacementsPatterns[replacement.index]
text: modelData.pattern
}

Label {
Expand All @@ -82,24 +193,25 @@ KCM.SimpleKCM {
id: titleReplacementsTemplate

onTextEdited: function () {
cfg_titleReplacementsTemplates[replacement.index] = text;
replacementsModel.setTemplate(index, text);
}
Layout.alignment: Qt.AlignLeft
Component.onCompleted: text = cfg_titleReplacementsTemplates[replacement.index]
text: modelData.template
}

Button {
icon.name: "delete"
onClicked: function () {
deleteReplacement(replacement.index);
replacementsModel.deleteReplacement(replacement.index);
}
}
}
}
RowLayout {
visible: replacementsRepeater.count > 5
Button {
text: i18n("Add Title Replacement")
onClicked: pushNewReplacement()
onClicked: replacementsModel.pushNewReplacement()
}
Label {
text: i18n("<a href=\"https://www.w3schools.com/jsref/jsref_obj_regexp.asp\">JavaScript RegExp Reference</a>")
Expand Down Expand Up @@ -143,41 +255,32 @@ KCM.SimpleKCM {
}

Connections {
target: page
target: replacementsModel

function onCfg_titleReplacementsTypesChanged() {
function onDataChanged() {
testOutput.updateTestOutput();
}

function onCfg_titleReplacementsPatternsChanged() {
function onRowsRemoved() {
testOutput.updateTestOutput();
}
}

function onCfg_titleReplacementsTemplatesChanged() {
testOutput.updateTestOutput();
function _updateTestOutput() {
let outputText = testInput.text;
for (let i = 0; i < replacementsModel.count; i++) {
const rowValue = replacementsModel.get(i);
const replacement = Utils.Replacement.createReplacement(rowValue.type, rowValue.pattern, rowValue.template);
outputText = replacement.replace(outputText);
}
testOutput.text = outputText;
}

function updateTestOutput() {
const replacements = Utils.Replacement.createReplacementList(cfg_titleReplacementsTypes, cfg_titleReplacementsPatterns, cfg_titleReplacementsTemplates);
testOutput.text = Utils.Replacement.applyReplacementList(testInput.text, replacements);
Qt.callLater(_updateTestOutput);
}

Component.onCompleted: updateTestOutput()
}
}

function pushNewReplacement() {
cfg_titleReplacementsTypes.push(TitleReplacements.Type.String);
cfg_titleReplacementsTemplates.push("");
cfg_titleReplacementsPatterns.push("");
replacementsRepeater.updateModel();
}

function deleteReplacement(index) {
cfg_titleReplacementsPatterns.splice(index, 1);
cfg_titleReplacementsTypes.splice(index, 1);
cfg_titleReplacementsTemplates.splice(index, 1);
replacementsRepeater.updateModel();
}
}
72 changes: 48 additions & 24 deletions package/contents/ui/main.qml
Original file line number Diff line number Diff line change
Expand Up @@ -183,32 +183,10 @@ PlasmoidItem {
property bool empty: text === undefined || text === ""
property bool hideEmpty: empty && plasmoid.configuration.windowTitleHideEmpty
property int windowTitleSource: plasmoid.configuration.overrideElementsMaximized && tasksModel.activeWindow.maximized ? plasmoid.configuration.windowTitleSourceMaximized : plasmoid.configuration.windowTitleSource
property var titleTextReplacements: Utils.Replacement.createReplacementList(plasmoid.configuration.titleReplacementsTypes, plasmoid.configuration.titleReplacementsPatterns, plasmoid.configuration.titleReplacementsTemplates)

function titleText(windowTitleSource) {
let titleTextResult = "";
switch (windowTitleSource) {
case 0:
titleTextResult = tasksModel.activeWindow.appName;
break;
case 1:
titleTextResult = tasksModel.activeWindow.decoration;
break;
case 2:
titleTextResult = tasksModel.activeWindow.genericAppName;
break;
case 3:
titleTextResult = plasmoid.configuration.windowTitleUndefined;
break;
}
if (titleTextResult) {
titleTextResult = Utils.Replacement.applyReplacementList(titleTextResult, titleTextReplacements);
}
return titleTextResult;
}
property var titleTextReplacements: []

Layout.leftMargin: !hideEmpty ? plasmoid.configuration.windowTitleMarginsLeft : 0
Layout.topMargin: !hideEmpty ? plasmoid.configuration.windowTitleMarginsTop : 0
Layout.topMargin: !hideEmpty ? plasmoid.configuration.windowTitleMarginsTotitleReplacementsTypesp : 0
Layout.bottomMargin: !hideEmpty ? plasmoid.configuration.windowTitleMarginsBottom : 0
Layout.rightMargin: !hideEmpty ? plasmoid.configuration.windowTitleMarginsRight : 0
Layout.minimumWidth: plasmoid.configuration.windowTitleMinimumWidth
Expand All @@ -224,6 +202,22 @@ PlasmoidItem {
wrapMode: Text.WrapAnywhere
enabled: tasksModel.hasActiveWindow

Connections {
target: plasmoid.configuration

function onTitleReplacementsTypesChanged() {
updateTitleTextReplacements();
}

function onTitleReplacementsPatternsChanged() {
updateTitleTextReplacements();
}

function onTitleReplacementsTemplatesChanged() {
updateTitleTextReplacements();
}
}

WidgetDragHandler {
Component.onCompleted: {
invokeKWinShortcut.connect(root.invokeKWinShortcut);
Expand All @@ -249,6 +243,36 @@ PlasmoidItem {
invokeKWinShortcut.connect(root.invokeKWinShortcut);
}
}

function titleText(windowTitleSource) {
let titleTextResult = "";
switch (windowTitleSource) {
case 0:
titleTextResult = tasksModel.activeWindow.appName;
break;
case 1:
titleTextResult = tasksModel.activeWindow.decoration;
break;
case 2:
titleTextResult = tasksModel.activeWindow.genericAppName;
break;
case 3:
titleTextResult = plasmoid.configuration.windowTitleUndefined;
break;
}
if (titleTextResult) {
titleTextResult = Utils.Replacement.applyReplacementList(titleTextResult, titleTextReplacements);
}
return titleTextResult;
}

function updateTitleTextReplacements() {
Qt.callLater(_updateTitleTextReplacements);
}

function _updateTitleTextReplacements() {
titleTextReplacements = Utils.Replacement.createReplacementList(plasmoid.configuration.titleReplacementsTypes, plasmoid.configuration.titleReplacementsPatterns, plasmoid.configuration.titleReplacementsTemplates);
}
}
}

Expand Down
15 changes: 9 additions & 6 deletions package/contents/ui/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -120,13 +120,16 @@ class Replacement {

static createReplacementList(types, patterns, templates) {
const length = types.length;
if (length !== patterns.length || length !== templates.length) {
return [];
}

let result = new Array(length);
let result = new Array();
for (let i = 0; i < length; i++) {
result[i] = Replacement.createReplacement(types[i], patterns[i], templates[i]);
const type = types[i];
const pattern = patterns[i];
const template = templates[i];
if (type === undefined || pattern === undefined || template === undefined) {
break; // Inconsistent state
} else {
result.push(Replacement.createReplacement(type, pattern, template));
}
}
return result;
}
Expand Down

0 comments on commit 4684971

Please sign in to comment.