From 8a390dab2a77918f7ca196daea55cf463b98a32b Mon Sep 17 00:00:00 2001 From: James Turner Date: Mon, 16 Apr 2018 15:04:21 +0100 Subject: [PATCH] Add-ons page UI improvements based on feedback --- src/GUI/qml/AddOns.qml | 766 +++++++++--------- src/GUI/qml/DeleteButton.qml | 2 +- src/GUI/qml/DragToReorderButton.qml | 18 +- src/GUI/qml/PathListDelegate.qml | 6 +- src/GUI/qml/icons8-cancel-25.png | Bin 0 -> 1717 bytes src/GUI/qml/icons8-drag-reorder-filled-25.png | Bin 0 -> 1039 bytes src/GUI/resources.qrc | 2 + 7 files changed, 415 insertions(+), 379 deletions(-) create mode 100644 src/GUI/qml/icons8-cancel-25.png create mode 100644 src/GUI/qml/icons8-drag-reorder-filled-25.png diff --git a/src/GUI/qml/AddOns.qml b/src/GUI/qml/AddOns.qml index 21b1319eb..c02150b9e 100644 --- a/src/GUI/qml/AddOns.qml +++ b/src/GUI/qml/AddOns.qml @@ -2,412 +2,426 @@ import QtQuick 2.4 import FlightGear.Launcher 1.0 import "." -Flickable { - flickableDirection: Flickable.VerticalFlick - contentHeight: contents.childrenRect.height +Item { + Flickable { + id: flick + height: parent.height + width: parent.width - scrollbar.width + flickableDirection: Flickable.VerticalFlick + contentHeight: contents.childrenRect.height - interactive: false + Component { + id: catalogDelegate - Component { - id: catalogDelegate + Rectangle { + id: delegateRoot - Rectangle { - id: delegateRoot + // don't show the delegate for newly added catalogs, until the + // adding process is complete + visible: !model.isNewlyAdded - // don't show the delegate for newly added catalogs, until the - // adding process is complete - visible: !model.isNewlyAdded - - height: catalogTextColumn.childrenRect.height + Style.margin * 2 - border.width: 1 - border.color: Style.themeColor - width: catalogsColumn.width + height: catalogTextColumn.childrenRect.height + Style.margin * 2 + border.width: 1 + border.color: Style.themeColor + width: catalogsColumn.width - Column { - id: catalogTextColumn + Column { + id: catalogTextColumn - y: Style.margin - anchors.left: parent.left - anchors.leftMargin: Style.margin - anchors.right: catalogDeleteButton.left - anchors.rightMargin: Style.margin - spacing: Style.margin + y: Style.margin + anchors.left: parent.left + anchors.leftMargin: Style.margin + anchors.right: catalogDeleteButton.left + anchors.rightMargin: Style.margin + spacing: Style.margin + + Text { + font.pixelSize: Style.subHeadingFontPixelSize + font.bold: true + width: parent.width + text: model.name + } + + Text { + visible: model.status === CatalogListModel.Ok + width: parent.width + text: model.description + wrapMode: Text.WordWrap + } + + ClickableText { + visible: model.status !== CatalogListModel.Ok + width: parent.width + wrapMode: Text.WordWrap + text: qsTr("This hangar is currently disabled due to a problem. " + + "Click here to try updating the hangar information from the server. " + + "(An Internet connection is required for this)"); + onClicked: { + _addOns.catalogs.refreshCatalog(model.index) + } + } + + Text { + width: parent.width + text: model.url + } - Text { - font.pixelSize: Style.subHeadingFontPixelSize - font.bold: true - width: parent.width - text: model.name } - Text { - visible: model.status === CatalogListModel.Ok - width: parent.width - text: model.description - wrapMode: Text.WordWrap - } + DeleteButton { + id: catalogDeleteButton + anchors.right: parent.right + anchors.rightMargin: Style.margin + anchors.verticalCenter: parent.verticalCenter + visible: delegateHover.containsMouse - ClickableText { - visible: model.status !== CatalogListModel.Ok - width: parent.width - wrapMode: Text.WordWrap - text: qsTr("This hangar is currently disabled due to a problem. " + - "Click here to try updating the hangar information from the server. " - + "(An Internet connection is required for this)"); onClicked: { - _addOns.catalogs.refreshCatalog(model.index) + confirmDeleteHangar.visible = true; + } + } + + MouseArea { + id: delegateHover + anchors.fill: parent + hoverEnabled: true + acceptedButtons: Qt.NoButton + } + + YesNoPanel { + id: confirmDeleteHangar + visible: false + anchors.fill: parent + + yesText: qsTr("Remove") + noText: qsTr("Cancel") + yesIsDestructive: true + promptText: qsTr("Remove this hangar? (Downloaded aircraft will be deleted from your computer)"); + onAccepted: { + _addOns.catalogs.removeCatalog(model.index); + } + + onRejected: { + confirmDeleteHangar.visible = false + } + } + + + } + } + + Column { + id: contents + width: parent.width - (Style.margin * 2) + x: Style.margin + spacing: Style.margin + + ////////////////////////////////////////////////////////////////// + // catalogs ////////////////////////////////////////////////////// + + Item { + id: catalogHeaderItem + width: parent.width + height: catalogHeadingText.height + catalogDescriptionText.height + Style.margin + + Text { + id: catalogHeadingText + text: qsTr("Aircraft hangars") + font.pixelSize: Style.headingFontPixelSize + width: parent.width + } + + Text { + id: catalogDescriptionText + text: qsTr("Aircraft hangars are managed collections of aircraft, which can be " + + "downloaded, installed and updated inside FlightGear.") + anchors { + top: catalogHeadingText.bottom + topMargin: Style.margin + } + + width: parent.width + wrapMode: Text.WordWrap + } + + + } // of catalogs header item + + Rectangle { + width: parent.width + height: catalogsColumn.childrenRect.height + Style.margin * 2 + border.width: 1 + border.color: Style.frameColor + clip: true + + Column { + id: catalogsColumn + width: parent.width - Style.margin * 2 + x: Style.margin + y: Style.margin + spacing: Style.margin + + Repeater { + id: catalogsRepeater + model: _addOns.catalogs + delegate: catalogDelegate + } + + ClickableText { + visible: !_addOns.isOfficialHangarRegistered && !addCatalogPanel.isActive + width: parent.width + text : qsTr("The official FlightGear aircraft hangar is not set up. To add it, click here."); + onClicked: { + _addOns.catalogs.installDefaultCatalog() + } + } + + AddCatalogPanel { + id: addCatalogPanel + width: parent.width + } + } + } + + ////////////////////////////////////////////////////////////////// + + Item { + // spacing item + width: parent.width + height: Style.margin * 2 + } + + Item { + id: aircraftHeaderItem + width: parent.width + height: aircraftHeading.height + aircraftDescriptionText.height + Style.margin + + Text { + id: aircraftHeading + text: qsTr("Additional aircraft folders") + font.pixelSize: Style.headingFontPixelSize + + anchors { + left: parent.left + right: addAircraftPathButton.left + rightMargin: Style.margin } } Text { - width: parent.width - text: model.url + id: aircraftDescriptionText + text: qsTr("To use aircraft you download yourself, FlightGear needs to " + + "know the folder(s) containing the aircraft data.") + anchors { + top: aircraftHeading.bottom + topMargin: Style.margin + left: parent.left + right: addAircraftPathButton.left + rightMargin: Style.margin + } + wrapMode: Text.WordWrap } + AddButton { + id: addAircraftPathButton + anchors.right: parent.right + anchors.verticalCenter: parent.verticalCenter + onClicked: { + var newPath =_addOns.addAircraftPath(); + if (newPath !== "") { + _addOns.aircraftPaths.push(newPath) + } + } + } + } // of aircraft header item + + Rectangle { + width: parent.width + height: aircraftPathsColumn.childrenRect.height + 1 + border.width: 1 + border.color: Style.frameColor + clip: true + + Column { + id: aircraftPathsColumn + width: parent.width - Style.margin * 2 + x: Style.margin + + Repeater { + id: aircraftPathsRepeater + model: _addOns.aircraftPaths + delegate: PathListDelegate { + width: aircraftPathsColumn.width + deletePromptText: qsTr("Remove the aircraft folder: '%1' from the list? (The folder contents will not be changed)").arg(modelData); + modelCount: _addOns.aircraftPaths.length + + onPerformDelete: { + var modifiedPaths = _addOns.aircraftPaths.slice() + modifiedPaths.splice(model.index, 1); + _addOns.aircraftPaths = modifiedPaths; + } + + onPerformMove: { + var modifiedPaths = _addOns.aircraftPaths.slice() + modifiedPaths.splice(model.index, 1); + modifiedPaths.splice(newIndex, 0, modelData) + _addOns.aircraftPaths = modifiedPaths; + } + } + } + + Text { + visible: (aircraftPathsRepeater.count == 0) + width: parent.width + text : qsTr("No custom aircraft paths are configured."); + } + } + + } - DeleteButton { - id: catalogDeleteButton - anchors.right: parent.right - anchors.rightMargin: Style.margin - anchors.verticalCenter: parent.verticalCenter - visible: delegateHover.containsMouse + ////////////////////////////////////////////////////////////////// - onClicked: { - confirmDeleteHangar.visible = true; + Item { + // spacing item + width: parent.width + height: Style.margin * 2 + } + + Item { + id: sceneryHeaderItem + width: parent.width + height: sceneryHeading.height + sceneryDescriptionText.height + Style.margin + + Text { + id: sceneryHeading + text: qsTr("Additional scenery folders") + font.pixelSize: Style.headingFontPixelSize + + anchors { + left: parent.left + right: addSceneryPathButton.left + rightMargin: Style.margin + } + } + + Text { + id: sceneryDescriptionText + text: qsTr("To use scenery you download yourself, FlightGear needs " + + "to know the folders containing the scenery data. " + + "Adjust the order of the list to control which scenery is used in a region."); + anchors { + top: sceneryHeading.bottom + topMargin: Style.margin + left: parent.left + right: addSceneryPathButton.left + rightMargin: Style.margin + } + wrapMode: Text.WordWrap + } + + AddButton { + id: addSceneryPathButton + anchors.right: parent.right + anchors.verticalCenter: parent.verticalCenter + onClicked: { + var newPath =_addOns.addSceneryPath(); + if (newPath !== "") { + _addOns.sceneryPaths.push(newPath) + + } + } + } + } // of aircraft header item + + Rectangle { + width: parent.width + height: sceneryPathsColumn.childrenRect.height + 1 + border.width: 1 + border.color: Style.frameColor + clip: true + + Column { + id: sceneryPathsColumn + width: parent.width - Style.margin * 2 + x: Style.margin + + Repeater { + id: sceneryPathsRepeater + model: _addOns.sceneryPaths + + delegate: PathListDelegate { + width: sceneryPathsColumn.width + deletePromptText: qsTr("Remove the scenery folder: '%1' from the list? (The folder contents will not be changed)").arg(modelData); + modelCount: _addOns.sceneryPaths.length + + onPerformDelete: { + var modifiedPaths = _addOns.sceneryPaths.slice() + modifiedPaths.splice(model.index, 1); + _addOns.sceneryPaths = modifiedPaths; + } + + onPerformMove: { + + } + } + } + + Text { + visible: (sceneryPathsRepeater.count == 0) + width: parent.width + text : qsTr("No custom scenery paths are configured."); + } } } - MouseArea { - id: delegateHover - anchors.fill: parent - hoverEnabled: true - acceptedButtons: Qt.NoButton - } + Item { + width: parent.width + height: Math.max(installTarballText.implicitHeight, installTarballButton.height) + Button { + id: installTarballButton + text: "Install add-on scenery" - YesNoPanel { - id: confirmDeleteHangar - visible: false - anchors.fill: parent + onClicked: { + var path = _addOns.installCustomScenery(); + if (path !== "") { + // insert into scenery paths if not already present + for (var p in _addOns.sceneryPaths) { + if (p === path) + return; // found, we are are done + } - yesText: qsTr("Remove") - noText: qsTr("Cancel") - yesIsDestructive: true - promptText: qsTr("Remove this hangar? (Downloaded aircraft will be deleted from your computer)"); - onAccepted: { - _addOns.catalogs.removeCatalog(model.index); + // not found, add it + _addOns.sceneryPaths.push(path); + } + } } - onRejected: { - confirmDeleteHangar.visible = false + Text { + id: installTarballText + anchors { + left: installTarballButton.right + right: parent.right + leftMargin: Style.margin + } + + wrapMode: Text.WordWrap + text: qsTr("If you have downloaded scenery manually from the official FlightGear website, " + + "you can use this button to extract and install it into a suitable folder. " + + "(Scenery downloaded this way should have a file name such as 'w40n020.tar.gz')" + ) } - } + } // of install-tarbal item + } // of column - - } } - Column { - id: contents - width: parent.width - (Style.margin * 2) - x: Style.margin - spacing: Style.margin - -////////////////////////////////////////////////////////////////// -// catalogs ////////////////////////////////////////////////////// - - Item { - id: catalogHeaderItem - width: parent.width - height: catalogHeadingText.height + catalogDescriptionText.height + Style.margin - - Text { - id: catalogHeadingText - text: qsTr("Aircraft hangars") - font.pixelSize: Style.headingFontPixelSize - width: parent.width - } - - Text { - id: catalogDescriptionText - text: qsTr("Aircraft hangars are managed collections of aircraft, which can be " + - "downloaded, installed and updated inside FlightGear.") - anchors { - top: catalogHeadingText.bottom - topMargin: Style.margin - } - - width: parent.width - wrapMode: Text.WordWrap - } - - - } // of catalogs header item - - Rectangle { - width: parent.width - height: catalogsColumn.childrenRect.height + Style.margin * 2 - border.width: 1 - border.color: Style.frameColor - clip: true - - Column { - id: catalogsColumn - width: parent.width - Style.margin * 2 - x: Style.margin - y: Style.margin - spacing: Style.margin - - Repeater { - id: catalogsRepeater - model: _addOns.catalogs - delegate: catalogDelegate - } - - ClickableText { - visible: !_addOns.isOfficialHangarRegistered && !addCatalogPanel.isActive - width: parent.width - text : qsTr("The official FlightGear aircraft hangar is not set up. To add it, click here."); - onClicked: { - _addOns.catalogs.installDefaultCatalog() - } - } - - AddCatalogPanel { - id: addCatalogPanel - width: parent.width - } - } - } - -////////////////////////////////////////////////////////////////// - - Item { - // spacing item - width: parent.width - height: Style.margin * 2 - } - - Item { - id: aircraftHeaderItem - width: parent.width - height: aircraftHeading.height + aircraftDescriptionText.height + Style.margin - - Text { - id: aircraftHeading - text: qsTr("Additional aircraft folders") - font.pixelSize: Style.headingFontPixelSize - - anchors { - left: parent.left - right: addAircraftPathButton.left - rightMargin: Style.margin - } - } - - Text { - id: aircraftDescriptionText - text: qsTr("To use aircraft you download yourself, FlightGear needs to " + - "know the folder(s) containing the aircraft data.") - anchors { - top: aircraftHeading.bottom - topMargin: Style.margin - left: parent.left - right: addAircraftPathButton.left - rightMargin: Style.margin - } - wrapMode: Text.WordWrap - } - - AddButton { - id: addAircraftPathButton - anchors.right: parent.right - anchors.verticalCenter: parent.verticalCenter - onClicked: { - var newPath =_addOns.addAircraftPath(); - if (newPath != "") { - _addOns.aircraftPaths.push(newPath) - } - } - } - } // of aircraft header item - - Rectangle { - width: parent.width - height: aircraftPathsColumn.childrenRect.height + 1 - border.width: 1 - border.color: Style.frameColor - clip: true - - Column { - id: aircraftPathsColumn - width: parent.width - Style.margin * 2 - x: Style.margin - - Repeater { - id: aircraftPathsRepeater - model: _addOns.aircraftPaths - delegate: PathListDelegate { - width: aircraftPathsColumn.width - deletePromptText: qsTr("Remove the aircraft folder: '%1' from the list? (The folder contents will not be changed)").arg(modelData); - - onPerformDelete: { - var modifiedPaths = _addOns.aircraftPaths.slice() - modifiedPaths.splice(model.index, 1); - _addOns.aircraftPaths = modifiedPaths; - } - - onPerformMove: { - var modifiedPaths = _addOns.aircraftPaths.slice() - modifiedPaths.splice(model.index, 1); - modifiedPaths.splice(newIndex, 0, modelData) - _addOns.aircraftPaths = modifiedPaths; - } - } - } - - Text { - visible: (aircraftPathsRepeater.count == 0) - width: parent.width - text : qsTr("No custom aircraft paths are configured."); - } - } - - - } - -////////////////////////////////////////////////////////////////// - - Item { - // spacing item - width: parent.width - height: Style.margin * 2 - } - - Item { - id: sceneryHeaderItem - width: parent.width - height: sceneryHeading.height + sceneryDescriptionText.height + Style.margin - - Text { - id: sceneryHeading - text: qsTr("Additional scenery folders") - font.pixelSize: Style.headingFontPixelSize - - anchors { - left: parent.left - right: addSceneryPathButton.left - rightMargin: Style.margin - } - } - - Text { - id: sceneryDescriptionText - text: qsTr("To use scenery you download yourself, FlightGear needs " + - "to know the folders containing the scenery data. " + - "Adjust the order of the list to control which scenery is used in a region."); - anchors { - top: sceneryHeading.bottom - topMargin: Style.margin - left: parent.left - right: addSceneryPathButton.left - rightMargin: Style.margin - } - wrapMode: Text.WordWrap - } - - AddButton { - id: addSceneryPathButton - anchors.right: parent.right - anchors.verticalCenter: parent.verticalCenter - onClicked: { - var newPath =_addOns.addSceneryPath(); - if (newPath !== "") { - _addOns.sceneryPaths.push(newPath) - - } - } - } - } // of aircraft header item - - Rectangle { - width: parent.width - height: sceneryPathsColumn.childrenRect.height + 1 - border.width: 1 - border.color: Style.frameColor - clip: true - - Column { - id: sceneryPathsColumn - width: parent.width - Style.margin * 2 - x: Style.margin - - Repeater { - id: sceneryPathsRepeater - model: _addOns.sceneryPaths - - delegate: PathListDelegate { - width: sceneryPathsColumn.width - deletePromptText: qsTr("Remove the scenery folder: '%1' from the list? (The folder contents will not be changed)").arg(modelData); - - onPerformDelete: { - var modifiedPaths = _addOns.sceneryPaths.slice() - modifiedPaths.splice(model.index, 1); - _addOns.sceneryPaths = modifiedPaths; - } - - onPerformMove: { - - } - } - } - - Text { - visible: (sceneryPathsRepeater.count == 0) - width: parent.width - text : qsTr("No custom scenery paths are configured."); - } - } - } - - Item { - width: parent.width - height: Math.max(installTarballText.implicitHeight, installTarballButton.height) - Button { - id: installTarballButton - text: "Install add-on scenery" - - onClicked: { - var path = _addOns.installCustomScenery(); - if (path != "") { - // insert into scenery paths if not already present - for (var p in _addOns.sceneryPaths) { - if (p === path) - return; // found, we are are done - } - - // not found, add it - _addOns.sceneryPaths.push(path); - } - } - } - - Text { - id: installTarballText - anchors { - left: installTarballButton.right - right: parent.right - leftMargin: Style.margin - } - - wrapMode: Text.WordWrap - text: qsTr("If you have downloaded scenery manually from the official FlightGear website, " + - "you can use this button to extract and install it into a suitable folder. " + - "(Scenery downloaded this way should have a file name such as 'w40n020.tar.gz')" - ) - } - } // of install-tarbal item - } // of column - + Scrollbar { + id: scrollbar + anchors.right: parent.right + height: parent.height + flickable: flick + visible: flick.contentHeight > flick.height + } } + diff --git a/src/GUI/qml/DeleteButton.qml b/src/GUI/qml/DeleteButton.qml index 1a1785a72..88c27a257 100644 --- a/src/GUI/qml/DeleteButton.qml +++ b/src/GUI/qml/DeleteButton.qml @@ -14,7 +14,7 @@ Item { id: icon x: 0 y: 0 - source: "qrc:///cancel-icon" + source: "qrc:///cancel-icon-small" } MouseArea { diff --git a/src/GUI/qml/DragToReorderButton.qml b/src/GUI/qml/DragToReorderButton.qml index 846bd82fd..5842a292d 100644 --- a/src/GUI/qml/DragToReorderButton.qml +++ b/src/GUI/qml/DragToReorderButton.qml @@ -1,9 +1,13 @@ import QtQuick 2.4 +import "." Item { + property bool canMoveUp: true + property bool canMoveDown: true width: height height: icon.implicitHeight + 1 + visible: canMoveDown || canMoveUp signal moveUp(); signal moveDown(); @@ -12,12 +16,14 @@ Item { id: icon x: 0 y: 0 - source: "qrc:///reorder-list-icon" + source: "qrc:///reorder-list-icon-small" } MouseArea { id: moveUpArea + enabled: parent.canMoveUp + hoverEnabled: enabled height: parent.height / 2 width: parent.width onClicked: { @@ -27,6 +33,8 @@ Item { MouseArea { id: moveDownArea + enabled: parent.canMoveDown + hoverEnabled: enabled height: parent.height / 2 width: parent.width anchors.bottom: parent.bottom @@ -34,4 +42,12 @@ Item { parent.moveDown(); } } + + Text { + anchors.verticalCenter: parent.verticalCenter + anchors.right: parent.left + anchors.rightMargin: Style.margin + visible: moveUpArea.containsMouse || moveDownArea.containsMouse + text: moveUpArea.containsMouse ? qsTr("Move up") : qsTr("Move down") + } } diff --git a/src/GUI/qml/PathListDelegate.qml b/src/GUI/qml/PathListDelegate.qml index 8c4fc7beb..a116cb9a5 100644 --- a/src/GUI/qml/PathListDelegate.qml +++ b/src/GUI/qml/PathListDelegate.qml @@ -9,6 +9,7 @@ Item { signal performMove(var newIndex); property alias deletePromptText: confirmDeletePath.promptText + property int modelCount: 0 height: childrenRect.height @@ -72,7 +73,10 @@ Item { id: reorderButton anchors.right: pathDeleteButton.left anchors.rightMargin: Style.margin - visible: pathDelegateHover.containsMouse + visible: pathDelegateHover.containsMouse && (canMoveDown || canMoveUp) + + canMoveUp: model.index > 0 + canMoveDown: model.index < (delegateRoot.modelCount - 1) onMoveUp: { if (model.index === 0) diff --git a/src/GUI/qml/icons8-cancel-25.png b/src/GUI/qml/icons8-cancel-25.png new file mode 100644 index 0000000000000000000000000000000000000000..36d87368d32a2a818a2882d16b11eb3b43e1198b GIT binary patch literal 1717 zcmeAS@N?(olHy`uVBq!ia0vp^k|4~%1|*NXY)uAIjKx9jP7LeL$-D$|I14-?iy0Wi zg+Q1wef}k&7RJ+=ArU1JzCKpT`MG+DDfvmMdKI|^K-CNkHWgMtW^QUpqC!P(PF}H9 zg{=};g%ywu64qBz04piUwpEJo4N!2-FG^J~)icpEP_pAvP*AWbN=dT{a&d!d2l8x{ zGD=Dctn~HE%ggo3jrH=2()A53EiLs8jP#9+bb%^#i!1X=5-W7`ij^UTz|3(;Elw`V zEGWs$&r<-Io0ybeT4JlD1hNPYAnq*5Ohed|R}A$Q(1ZFQ8GS=N1AT1TfS!fB4@Fl+ zVgW=G*jEtCY(Pd?`4?rT0-XzTl%1gs*mx8%gyU?0rdv4|r6!i-7lq{K=h%TlATuw! zI61K(6%-CO`sga4nr-w!-bM00By7Q=z`(WR0_ucClpPn#l^3TO7+9J;T^vI^c$bEq z&W;I{u)n|adta|1f9niCmkDl50t$@n7R-$7p1Wkn%pD&b7lmF~namZfNd)Wp+=nihUJ zCfu4Ma?9QIiR0QQe5>!++5BIV`{VB3_?o?rvf)~+7q-_t-8q%dVqx=?muCLra%RWo zUX7Z|<@)O#57Sb`EdjqSONd&RpSIkZvgOR(`lX*H^Ygt3$Sl6{Or`XJ=(XdYo*&s+ zUbWccy_%ckbD1f;ttN+zIVMDvORSh{VYukY+r>{$Ri9ZP+WvgmF=L&>Qcm%U3WwL_&X%Oq&FEGcr-W&eBxhi zn))RBmEwXY^E7HQYfDn3Y`(4Nd~3Y3XIby!ldq4~@bUhf=cUlJVx0r`uZ8~{PI9nK z>lgU{L~n|gWAHbg-A`DZWV3zV?OT2S&xwIC!eyyuaEMNP84Uf-#yu&@V@oJTD1xLlqJ7P%slda zb<_I~bv&7$uP%2I6FPXyVdj>aj>d|-4SPOydQE!lE{EjKf0-P!zufve zWv=wInX5gD#eX(W%eyj*?aUG3qDvh*7ZVn(lh3uQEVB6hbi29Pd@IYI1xJwCZBR$_s0y}OH;few$;r?rz$9$dXTd%xJ{<81cvv4^kDQJ7z} z!i;&b?N7gy=@Lh-*Uf&kVC$Mhk(FncO}-(^*JgChk4HDuZe8EA`R6-+wffIH>3=bj z_rKR~+ch#4k;)t&O|P5Y-+CjvG`n0N^6-Ig59AVTmTmIZp1vx%mGgw&LjFVQ=btFA z*}Qk5eD$LZAwkFex?jJND(pPZSiZ-EIXvu|pzF-t97mpUck^bhvzj*l(y6n-4GxzA zi#}gXs^eM{^QLAF&$$b7sv7nmLYKbMR~D$@Fi}hFdbZ)sytXorihEDi1@yZ|^*8hL zR)xM1oPTLHXL@qBwD~+$j_e41jmI)id>57bzx;k6!P4)$>%rZ3Tm^o3cd9#DI{N;d za$O?U${=FW!?P+g<)UKd;R-#f;LO7UBNylz{CBH<=Xo{lqXiR+~9Y-)cmDsB0{O(uRS+b}& kL+$^UYbW09|M%_}x5Cf#sEwR52SIg-r>mdKI;Vst02>hGod5s; literal 0 HcmV?d00001 diff --git a/src/GUI/qml/icons8-drag-reorder-filled-25.png b/src/GUI/qml/icons8-drag-reorder-filled-25.png new file mode 100644 index 0000000000000000000000000000000000000000..f3b422b1190f0a2c0e61a129639aaede7e7ce425 GIT binary patch literal 1039 zcmeAS@N?(olHy`uVBq!ia0vp^k|4~%1|*NXY)uAIjKx9jP7LeL$-D$|I14-?i-C%- zgD|6$#_S59g43BH5hW46K32*3xq68y`AMmI6}bgK)eHl#hD=EpgRf_NpP;kyKN>wn`Gto0pvg1-vP_QXVNwW%aaf50H@@$nd zN=gc>^!3Zj%k|2Q_413-^$jg8E%gnI^o@*kfhu&1EAvVcD|GXUl_7?}%yCIAPA&<7|MYTR9h{CYIzEh2-bw*nvVIGcUV1 zIk6xW6b?4}=qjL^ZS+CjMe;r*Y{8V!p<9T&@$7pH;Ide_s%F~o!SZP;nA z!vO+kS4Xr4{cW#vxc^|8h^E%MJ70`rc6>0u^FuOLTp-fCR?Yn5 zoC%z@OBOECXo}+~em~bZ{nV zb1lns{-kW7Zo8A66PM&{zn!-Jda+~0lGndD|Uy?TNn141cUiWm=iAs+dQ6J7tNXs>wEgP{d*WdT@o+6p_rz)AY9&8mt zpO!!USzFdAKHu!l&yv6KHMex?*58%iSy3svePyiux1;Q$=IiD^P&PXD_#^wQFy`Ku zGRrHSx5mCyzp>j{zmjM5&h3A=HqK}9)n2!8!{vjV+M64>YCAXW3s@SNI?>PWyNcda zFFos*n}pXbz9+bR%CxBU*ZCd4F|=DgxbgUVg^`8b%kRJao4Oz0$ngK?Hp6VmRlfgW w8qz8Pf8A0%6?Pg6Y&WQ1rV{sUa?Z-%Ob>o|nXc+N+yKg@p00i_>zopr0GVo+!~g&Q literal 0 HcmV?d00001 diff --git a/src/GUI/resources.qrc b/src/GUI/resources.qrc index ef40a4588..8b11184c4 100644 --- a/src/GUI/resources.qrc +++ b/src/GUI/resources.qrc @@ -78,6 +78,8 @@ qml/AddButton.qml qml/icons8-cancel-50.png qml/icons8-drag-reorder-filled-50.png + qml/icons8-cancel-25.png + qml/icons8-drag-reorder-filled-25.png qml/icons8-plus-26.png qml/DeleteButton.qml qml/YesNoPanel.qml