diff --git a/CMakeLists.txt b/CMakeLists.txt --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -80,6 +80,7 @@ find_package(KSMServerDBusInterface CONFIG REQUIRED) find_package(KF5ItemModels CONFIG REQUIRED) find_package(KF5Emoticons CONFIG REQUIRED) +find_package(KF5 REQUIRED COMPONENTS SysGuard) find_package(KF5Baloo ${KF5_MIN_VERSION}) set_package_properties(KF5Baloo PROPERTIES DESCRIPTION "File Searching" diff --git a/applets/icontasks/metadata.desktop b/applets/icontasks/metadata.desktop --- a/applets/icontasks/metadata.desktop +++ b/applets/icontasks/metadata.desktop @@ -24,6 +24,7 @@ Name[ja]=アイコンだけのタスクマネージャ Name[ko]=아이콘만 있는 작업 관리자 Name[lt]=Tik piktogramų užduočių tvarkytuvė +Name[ml]=ചിഹ്നങ്ങൾക്കായുള്ള ടാസ്ക് മാനേജര്‍ Name[mr]=फक्त-चिन्ह कार्य व्यवस्थापक Name[nb]=Oppgavebehandler med bare ikoner Name[nds]=Lüttbild-Opgavenpleger diff --git a/applets/kicker/package/contents/ui/ActionMenu.qml b/applets/kicker/package/contents/ui/ActionMenu.qml --- a/applets/kicker/package/contents/ui/ActionMenu.qml +++ b/applets/kicker/package/contents/ui/ActionMenu.qml @@ -131,7 +131,7 @@ checked : actionItem.checked ? actionItem.checked : false onClicked: { - actionClicked(actionItem.actionId, actionItem.actionArgument); + root.actionClicked(actionItem.actionId, actionItem.actionArgument); } } } diff --git a/applets/kicker/package/contents/ui/CompactRepresentation.qml b/applets/kicker/package/contents/ui/CompactRepresentation.qml --- a/applets/kicker/package/contents/ui/CompactRepresentation.qml +++ b/applets/kicker/package/contents/ui/CompactRepresentation.qml @@ -69,28 +69,28 @@ Connections { target: units.iconSizeHints - onPanelChanged: updateSizeHints() + onPanelChanged: root.updateSizeHints() } PlasmaCore.IconItem { id: buttonIcon anchors.fill: parent - readonly property double aspectRatio: (vertical ? implicitHeight / implicitWidth + readonly property double aspectRatio: (root.vertical ? implicitHeight / implicitWidth : implicitWidth / implicitHeight) - source: useCustomButtonImage ? plasmoid.configuration.customButtonImage : plasmoid.configuration.icon + source: root.useCustomButtonImage ? plasmoid.configuration.customButtonImage : plasmoid.configuration.icon active: mouseArea.containsMouse && !justOpenedTimer.running smooth: true // A custom icon could also be rectangular. However, if a square, custom, icon is given, assume it // to be an icon and round it to the nearest icon size again to avoid scaling artifacts. - roundToIconSize: !useCustomButtonImage || aspectRatio === 1 + roundToIconSize: !root.useCustomButtonImage || aspectRatio === 1 - onSourceChanged: updateSizeHints() + onSourceChanged: root.updateSizeHints() } MouseArea @@ -100,7 +100,7 @@ anchors.fill: parent - hoverEnabled: !dashWindow || !dashWindow.visible + hoverEnabled: !root.dashWindow || !root.dashWindow.visible onPressed: { if (!isDash) { @@ -110,7 +110,7 @@ onClicked: { if (isDash) { - dashWindow.toggle(); + root.dashWindow.toggle(); justOpenedTimer.start(); } else { plasmoid.expanded = !wasExpanded; diff --git a/applets/kicker/package/contents/ui/ConfigGeneral.qml b/applets/kicker/package/contents/ui/ConfigGeneral.qml --- a/applets/kicker/package/contents/ui/ConfigGeneral.qml +++ b/applets/kicker/package/contents/ui/ConfigGeneral.qml @@ -104,8 +104,8 @@ id: iconDialog function setCustomButtonImage(image) { - cfg_customButtonImage = image || cfg_icon || "start-here-kde" - cfg_useCustomButtonImage = true; + configGeneral.cfg_customButtonImage = image || configGeneral.cfg_icon || "start-here-kde" + configGeneral.cfg_useCustomButtonImage = true; } onIconNameChanged: setCustomButtonImage(iconName); @@ -123,7 +123,7 @@ anchors.centerIn: parent width: units.iconSizes.large height: width - source: cfg_useCustomButtonImage ? cfg_customButtonImage : cfg_icon + source: configGeneral.cfg_useCustomButtonImage ? configGeneral.cfg_customButtonImage : configGeneral.cfg_icon } } @@ -144,8 +144,8 @@ text: i18nc("@item:inmenu Reset icon to default", "Clear Icon") icon.name: "edit-clear" onClicked: { - cfg_icon = "start-here-kde" - cfg_useCustomButtonImage = false + configGeneral.cfg_icon = "start-here-kde" + configGeneral.cfg_useCustomButtonImage = false } } } @@ -187,7 +187,7 @@ CheckBox { id: showIconsRootLevel - visible: !isDash + visible: !configGeneral.isDash text: i18n("Show icons on the root level of the menu") } @@ -244,7 +244,7 @@ CheckBox { id: alignResultsToBottom - visible: !isDash + visible: !configGeneral.isDash text: i18n("Align search results to bottom") } diff --git a/applets/kicker/package/contents/ui/DashboardRepresentation.qml b/applets/kicker/package/contents/ui/DashboardRepresentation.qml --- a/applets/kicker/package/contents/ui/DashboardRepresentation.qml +++ b/applets/kicker/package/contents/ui/DashboardRepresentation.qml @@ -124,7 +124,7 @@ target: kicker onReset: { - if (!searching) { + if (!root.searching) { filterList.applyFilter(); if (tabBar.activeTab == 0) { @@ -211,7 +211,7 @@ repeat: false onTriggered: { - if (done || searching) { + if (done || root.searching) { return; } @@ -247,11 +247,11 @@ visible: (plasmoid.immutability !== PlasmaCore.Types.SystemImmutable) onActiveTabChanged: { - updateWidgetExplorer(); - reset(); + root.updateWidgetExplorer(); + root.reset(); } - onHoveredTabChanged: updateWidgetExplorer() + onHoveredTabChanged: root.updateWidgetExplorer() Keys.onDownPressed: { mainColumn.tryActivate(0, 0); @@ -272,7 +272,7 @@ if (tabBar.activeTab == 0) { runnerModel.query = searchField.text; } else { - widgetExplorer.widgetsModel.searchTerm = searchField.text; + root.widgetExplorer.widgetsModel.searchTerm = searchField.text; } } @@ -291,7 +291,7 @@ horizontalCenter: parent.horizontalCenter } - y: (middleRow.anchors.topMargin / 2) - (smallScreen ? (height/10) : 0) + y: (middleRow.anchors.topMargin / 2) - (root.smallScreen ? (height/10) : 0) font.pointSize: dummyHeading.font.pointSize * 1.5 wrapMode: Text.NoWrap @@ -302,7 +302,7 @@ color: "white" - text: searching ? i18n("Searching for '%1'", searchField.text) : i18n("Type to search...") + text: root.searching ? i18n("Searching for '%1'", searchField.text) : i18n("Type to search...") function updateSelection() { if (!searchField.selectedText) { @@ -333,7 +333,7 @@ onClicked: searchField.clear(); - Keys.onPressed: { + Keys.onPressed: event => { if (event.key === Qt.Key_Tab) { event.accepted = true; @@ -367,7 +367,7 @@ horizontalCenter: parent.horizontalCenter } - width: (root.columns * cellSize) + (2 * spacing) + width: (root.columns * root.cellSize) + (2 * spacing) spacing: units.gridUnit * 2 @@ -379,7 +379,7 @@ bottom: parent.bottom } - width: (columns * cellSize) + units.gridUnit + width: (columns * root.cellSize) + units.gridUnit property int columns: 3 @@ -440,14 +440,14 @@ } property int rows: (Math.floor((parent.height - favoritesColumnLabel.height - - favoritesColumnLabelUnderline.height - units.largeSpacing) / cellSize) + - favoritesColumnLabelUnderline.height - units.largeSpacing) / root.cellSize) - systemFavoritesGrid.rows) width: parent.width - height: rows * cellSize + height: rows * root.cellSize - cellWidth: cellSize - cellHeight: cellSize + cellWidth: root.cellSize + cellHeight: root.cellSize iconSize: root.iconSize model: globalFavorites @@ -471,13 +471,13 @@ systemFavoritesGrid.tryActivate(0, currentCol()); } - Keys.onPressed: { + Keys.onPressed: event => { if (event.key === Qt.Key_Tab) { event.accepted = true; if (tabBar.visible) { tabBar.focus = true; - } else if (searching) { + } else if (root.searching) { cancelSearchButton.focus = true; } else { mainColumn.tryActivate(0, 0); @@ -502,13 +502,13 @@ top: globalFavoritesGrid.bottom } - property int rows: Math.ceil(count / Math.floor(width / cellSize)) + property int rows: Math.ceil(count / Math.floor(width / root.cellSize)) width: parent.width - height: rows * cellSize + height: rows * root.cellSize - cellWidth: cellSize - cellHeight: cellSize + cellWidth: root.cellSize + cellHeight: root.cellSize iconSize: root.iconSize model: systemFavorites @@ -528,15 +528,15 @@ globalFavoritesGrid.tryActivate(globalFavoritesGrid.rows - 1, currentCol()); } - Keys.onPressed: { + Keys.onPressed: event => { if (event.key === Qt.Key_Tab) { event.accepted = true; if (globalFavoritesGrid.enabled) { globalFavoritesGrid.tryActivate(0, 0); } else if (tabBar.visible) { tabBar.focus = true; - } else if (searching && !runnerModel.count) { + } else if (root.searching && !runnerModel.count) { cancelSearchButton.focus = true; } else { mainColumn.tryActivate(0, 0); @@ -546,7 +546,7 @@ if (filterList.enabled) { filterList.forceActiveFocus(); - } else if (searching && !runnerModel.count) { + } else if (root.searching && !runnerModel.count) { cancelSearchButton.focus = true; } else { mainColumn.tryActivate(0, 0); @@ -561,8 +561,8 @@ anchors.top: parent.top - width: (columns * cellSize) + units.gridUnit - height: Math.floor(parent.height / cellSize) * cellSize + mainGridContainer.headerHeight + width: (columns * root.cellSize) + units.gridUnit + height: Math.floor(parent.height / root.cellSize) * root.cellSize + mainGridContainer.headerHeight property int columns: root.columns - favoritesColumn.columns - filterListColumn.columns property Item visibleGrid: mainGrid @@ -584,7 +584,7 @@ property int headerHeight: mainColumnLabel.height + mainColumnLabelUnderline.height + units.largeSpacing opacity: { - if (tabBar.activeTab == 0 && searching) { + if (tabBar.activeTab == 0 && root.searching) { return 0.0; } @@ -649,7 +649,7 @@ width: parent.width height: systemFavoritesGrid.y + systemFavoritesGrid.height - mainGridContainer.headerHeight - cellWidth: (tabBar.activeTab == 0 ? cellSize : cellSize * 2) + cellWidth: (tabBar.activeTab == 0 ? root.cellSize : root.cellSize * 2) cellHeight: cellWidth iconSize: (tabBar.activeTab == 0 ? root.iconSize : cellWidth - (units.largeSpacing * 2)) @@ -747,7 +747,7 @@ grabFocus: true - opacity: (tabBar.activeTab == 0 && searching) ? 1.0 : 0.0 + opacity: (tabBar.activeTab == 0 && root.searching) ? 1.0 : 0.0 onOpacityChanged: { if (opacity == 1.0) { @@ -770,7 +770,7 @@ } } - Keys.onPressed: { + Keys.onPressed: event => { if (event.key === Qt.Key_Tab) { event.accepted = true; @@ -782,7 +782,7 @@ } else if (event.key === Qt.Key_Backtab) { event.accepted = true; - if (searching) { + if (root.searching) { cancelSearchButton.focus = true; } else if (tabBar.visible) { tabBar.focus = true; @@ -804,7 +804,7 @@ bottom: parent.bottom } - width: columns * cellSize + width: columns * root.cellSize property int columns: 3 @@ -818,11 +818,11 @@ width: parent.width height: mainGrid.height - enabled: !searching + enabled: !root.searching property alias currentIndex: filterList.currentIndex - opacity: root.visible ? (searching ? 0.30 : 1.0) : 0.3 + opacity: root.visible ? (root.searching ? 0.30 : 1.0) : 0.3 Behavior on opacity { SmoothedAnimation { duration: units.longDuration; velocity: 0.01 } } @@ -886,7 +886,7 @@ } } - onPositionChanged: { // Lazy menu implementation. + onPositionChanged: mouse => { // Lazy menu implementation. mouseCol = mouse.x; if (justOpenedTimer.running || ListView.view.currentIndex === 0 || index === ListView.view.currentIndex) { @@ -904,15 +904,15 @@ updateCurrentItemTimer.restart(); } - onPressed: { + onPressed: mouse => { if (mouse.buttons & Qt.RightButton) { if (hasActionList) { openActionMenu(item, mouse.x, mouse.y); } } } - onClicked: { + onClicked: mouse => { if (mouse.button == Qt.LeftButton) { updateCurrentItem(); } @@ -1012,12 +1012,12 @@ } } - filterListColumn.columns = Math.ceil(width / cellSize); + filterListColumn.columns = Math.ceil(width / root.cellSize); filterListScrollArea.width = width + hItemMargins + (units.gridUnit * 2); } function applyFilter() { - if (!searching && currentIndex >= 0) { + if (!root.searching && currentIndex >= 0) { if (tabBar.activeTab == 1) { root.widgetExplorer.widgetsModel.filterQuery = currentItem.m.filterData; root.widgetExplorer.widgetsModel.filterType = currentItem.m.filterType; @@ -1049,7 +1049,7 @@ } } - Keys.onPressed: { + Keys.onPressed: event => { if (event.key === Qt.Key_Left) { event.accepted = true; @@ -1068,13 +1068,13 @@ } } - onPressed: { + onPressed: mouse => { if (mouse.button == Qt.RightButton) { contextMenu.open(mouse.x, mouse.y); } } - onClicked: { + onClicked: mouse => { if (mouse.button == Qt.LeftButton) { root.toggle(); } diff --git a/applets/kicker/package/contents/ui/DashboardTabBar.qml b/applets/kicker/package/contents/ui/DashboardTabBar.qml --- a/applets/kicker/package/contents/ui/DashboardTabBar.qml +++ b/applets/kicker/package/contents/ui/DashboardTabBar.qml @@ -28,7 +28,7 @@ signal containsMouseChanged(int index, bool containsMouse) - onContainsMouseChanged: { + onContainsMouseChanged: (index, containsMouse) => { if (containsMouse) { hoveredTab = index; } else { @@ -58,19 +58,19 @@ focus: parent.focus & active } - Keys.onLeftPressed: { + Keys.onLeftPressed: event => { if (activeTab == 1) { activeTab = 0; } } - Keys.onRightPressed: { + Keys.onRightPressed: event => { if (activeTab == 0) { activeTab = 1; } } - Keys.onPressed: { + Keys.onPressed: event => { if (event.key === Qt.Key_Tab) { event.accepted = true; diff --git a/applets/kicker/package/contents/ui/DashboardTabButton.qml b/applets/kicker/package/contents/ui/DashboardTabButton.qml --- a/applets/kicker/package/contents/ui/DashboardTabButton.qml +++ b/applets/kicker/package/contents/ui/DashboardTabButton.qml @@ -39,7 +39,7 @@ color: tab.parent.focus ? theme.highlightColor : "black" - opacity: active ? 0.4 : 0.15 + opacity: tab.active ? 0.4 : 0.15 Behavior on opacity { SmoothedAnimation { duration: units.shortDuration; velocity: 0.01 } } } @@ -50,7 +50,7 @@ elide: Text.ElideNone wrapMode: Text.NoWrap - opacity: active ? 1.0 : 0.6 + opacity: tab.active ? 1.0 : 0.6 Behavior on opacity { SmoothedAnimation { duration: units.shortDuration; velocity: 0.01 } } color: tab.parent.focus ? theme.highlightedTextColor : "white" @@ -68,7 +68,7 @@ } onContainsMouseChanged: { - tab.parent.containsMouseChanged(index, containsMouse); + tab.parent.containsMouseChanged(tab.index, containsMouse); } } } diff --git a/applets/kicker/package/contents/ui/ItemGridDelegate.qml b/applets/kicker/package/contents/ui/ItemGridDelegate.qml --- a/applets/kicker/package/contents/ui/ItemGridDelegate.qml +++ b/applets/kicker/package/contents/ui/ItemGridDelegate.qml @@ -61,10 +61,10 @@ PlasmaCore.IconItem { id: icon - y: showLabel ? (2 * highlightItemSvg.margins.top) : undefined + y: item.showLabel ? (2 * highlightItemSvg.margins.top) : undefined anchors.horizontalCenter: parent.horizontalCenter - anchors.verticalCenter: showLabel ? undefined : parent.verticalCenter + anchors.verticalCenter: item.showLabel ? undefined : parent.verticalCenter width: iconSize height: width @@ -80,7 +80,7 @@ PlasmaComponents.Label { id: label - visible: showLabel + visible: item.showLabel anchors { top: icon.bottom @@ -114,7 +114,7 @@ onContainsMouseChanged: item.GridView.view.itemContainsMouseChanged(containsMouse) } - Keys.onPressed: { + Keys.onPressed: event => { if (event.key === Qt.Key_Menu && hasActionList) { event.accepted = true; openActionMenu(item); diff --git a/applets/kicker/package/contents/ui/ItemGridView.qml b/applets/kicker/package/contents/ui/ItemGridView.qml --- a/applets/kicker/package/contents/ui/ItemGridView.qml +++ b/applets/kicker/package/contents/ui/ItemGridView.qml @@ -70,25 +70,25 @@ return -1; } - return Math.floor(currentIndex / Math.floor(width / cellWidth)); + return Math.floor(currentIndex / Math.floor(width / itemGrid.cellWidth)); } function currentCol() { if (currentIndex == -1) { return -1; } - return currentIndex - (currentRow() * Math.floor(width / cellWidth)); + return currentIndex - (currentRow() * Math.floor(width / itemGrid.cellWidth)); } function lastRow() { - var columns = Math.floor(width / cellWidth); + var columns = Math.floor(width / itemGrid.cellWidth); return Math.ceil(count / columns) - 1; } function tryActivate(row, col) { if (count) { - var columns = Math.floor(width / cellWidth); + var columns = Math.floor(width / itemGrid.cellWidth); var rows = Math.ceil(count / columns); row = Math.min(row, rows - 1); col = Math.min(col, columns - 1); @@ -118,55 +118,55 @@ anchors.fill: parent onDragMove: { - if (!dropEnabled || gridView.animating || !kicker.dragSource) { + if (!itemGrid.dropEnabled || gridView.animating || !kicker.dragSource) { return; } - var x = Math.max(0, event.x - (width % cellWidth)); + var x = Math.max(0, event.x - (width % itemGrid.cellWidth)); var cPos = mapToItem(gridView.contentItem, x, event.y); var item = gridView.itemAt(cPos.x, cPos.y); if (item) { if (kicker.dragSource.parent === gridView.contentItem) { if (item !== kicker.dragSource) { item.GridView.view.model.moveRow(dragSource.itemIndex, item.itemIndex); } - } else if (kicker.dragSource.GridView.view.model.favoritesModel === model - && !model.isFavorite(kicker.dragSource.favoriteId)) { - var hasPlaceholder = (model.dropPlaceholderIndex !== -1); + } else if (kicker.dragSource.GridView.view.model.favoritesModel === itemGrid.model + && !itemGrid.model.isFavorite(kicker.dragSource.favoriteId)) { + var hasPlaceholder = (itemGrid.model.dropPlaceholderIndex !== -1); - model.dropPlaceholderIndex = item.itemIndex; + itemGrid.model.dropPlaceholderIndex = item.itemIndex; if (!hasPlaceholder) { gridView.currentIndex = (item.itemIndex - 1); } } } else if (kicker.dragSource.parent !== gridView.contentItem - && kicker.dragSource.GridView.view.model.favoritesModel === model - && !model.isFavorite(kicker.dragSource.favoriteId)) { - var hasPlaceholder = (model.dropPlaceholderIndex !== -1); + && kicker.dragSource.GridView.view.model.favoritesModel === itemGrid.model + && !itemGrid.model.isFavorite(kicker.dragSource.favoriteId)) { + var hasPlaceholder = (itemGrid.model.dropPlaceholderIndex !== -1); - model.dropPlaceholderIndex = hasPlaceholder ? model.count - 1 : model.count; + itemGrid.model.dropPlaceholderIndex = hasPlaceholder ? itemGrid.model.count - 1 : itemGrid.model.count; if (!hasPlaceholder) { - gridView.currentIndex = (model.count - 1); + gridView.currentIndex = (itemGrid.model.count - 1); } } else { - model.dropPlaceholderIndex = -1; + itemGrid.model.dropPlaceholderIndex = -1; gridView.currentIndex = -1; } } onDragLeave: { - if ("dropPlaceholderIndex" in model) { - model.dropPlaceholderIndex = -1; + if ("dropPlaceholderIndex" in itemGrid.model) { + itemGrid.model.dropPlaceholderIndex = -1; gridView.currentIndex = -1; } } onDrop: { - if (kicker.dragSource && kicker.dragSource.parent !== gridView.contentItem && kicker.dragSource.GridView.view.model.favoritesModel === model) { - model.addFavorite(kicker.dragSource.favoriteId, model.dropPlaceholderIndex); + if (kicker.dragSource && kicker.dragSource.parent !== gridView.contentItem && kicker.dragSource.GridView.view.model.favoritesModel === itemGrid.model) { + itemGrid.model.addFavorite(kicker.dragSource.favoriteId, itemGrid.model.dropPlaceholderIndex); gridView.currentIndex = -1; } } @@ -201,7 +201,7 @@ property int iconSize: units.iconSizes.huge property bool animating: false - property int animationDuration: dropEnabled ? resetAnimationDurationTimer.interval : 0 + property int animationDuration: itemGrid.dropEnabled ? resetAnimationDurationTimer.interval : 0 focus: true @@ -243,11 +243,11 @@ boundsBehavior: Flickable.StopAtBounds delegate: ItemGridDelegate { - showLabel: showLabels + showLabel: itemGrid.showLabels } highlight: Item { - property bool isDropPlaceHolder: "dropPlaceholderIndex" in model && currentIndex === model.dropPlaceholderIndex + property bool isDropPlaceHolder: "dropPlaceholderIndex" in itemGrid.model && itemGrid.currentIndex === itemGrid.model.dropPlaceholderIndex PlasmaComponents.Highlight { visible: gridView.currentItem && !isDropPlaceHolder @@ -302,7 +302,7 @@ } Keys.onLeftPressed: { - if (currentCol() !== 0) { + if (itemGrid.currentCol() !== 0) { event.accepted = true; moveCurrentIndexLeft(); } else { @@ -313,16 +313,16 @@ Keys.onRightPressed: { var columns = Math.floor(width / cellWidth); - if (currentCol() !== columns - 1 && currentIndex != count -1) { + if (itemGrid.currentCol() !== columns - 1 && currentIndex != count -1) { event.accepted = true; moveCurrentIndexRight(); } else { itemGrid.keyNavRight(); } } Keys.onUpPressed: { - if (currentRow() !== 0) { + if (itemGrid.currentRow() !== 0) { event.accepted = true; moveCurrentIndexUp(); positionViewAtIndex(currentIndex, GridView.Contain); @@ -332,7 +332,7 @@ } Keys.onDownPressed: { - if (currentRow() < itemGrid.lastRow()) { + if (itemGrid.currentRow() < itemGrid.lastRow()) { // Fix moveCurrentIndexDown()'s lack of proper spatial nav down // into partial columns. event.accepted = true; @@ -397,13 +397,13 @@ pressedItem = null; } else { gridView.currentIndex = item.itemIndex; - itemGrid.focus = (currentIndex != -1) + itemGrid.focus = (itemGrid.currentIndex != -1) } return item; } - onPressed: { + onPressed: mouse => { mouse.accepted = true; updatePositionProperties(mouse.x, mouse.y); @@ -426,7 +426,7 @@ } } - onReleased: { + onReleased: mouse => { mouse.accepted = true; updatePositionProperties(mouse.x, mouse.y); @@ -446,11 +446,11 @@ pressedItem = null; } - onPositionChanged: { + onPositionChanged: mouse => { var item = pressedItem? pressedItem : updatePositionProperties(mouse.x, mouse.y); if (gridView.currentIndex != -1) { - if (dragEnabled && pressX != -1 && dragHelper.isDrag(pressX, pressY, mouse.x, mouse.y)) { + if (itemGrid.dragEnabled && pressX != -1 && dragHelper.isDrag(pressX, pressY, mouse.x, mouse.y)) { if ("pluginName" in item.m) { dragHelper.startDrag(kicker, item.url, item.icon, "text/x-plasmoidservicename", item.m.pluginName); diff --git a/applets/kicker/package/contents/ui/ItemListDelegate.qml b/applets/kicker/package/contents/ui/ItemListDelegate.qml --- a/applets/kicker/package/contents/ui/ItemListDelegate.qml +++ b/applets/kicker/package/contents/ui/ItemListDelegate.qml @@ -53,7 +53,7 @@ } onAboutToShowActionMenu: { - var actionList = hasActionList ? model.actionList : []; + var actionList = item.hasActionList ? model.actionList : []; Tools.fillActionMenu(i18n, actionMenu, actionList, ListView.view.model.favoritesModel, model.favoriteId); } @@ -73,7 +73,7 @@ id: actionMenu onActionClicked: { - actionTriggered(actionId, actionArgument); + item.actionTriggered(actionId, actionArgument); } } @@ -96,20 +96,20 @@ hoverEnabled: true acceptedButtons: Qt.LeftButton | Qt.RightButton - onPressed: { + onPressed: mouse => { if (mouse.buttons & Qt.RightButton) { - if (hasActionList) { - openActionMenu(mouseArea, mouse.x, mouse.y); + if (item.hasActionList) { + item.openActionMenu(mouseArea, mouse.x, mouse.y); } } else { pressed = true; pressX = mouse.x; pressY = mouse.y; } } - onReleased: { - if (pressed && !hasChildren) { + onReleased: mouse => { + if (pressed && !item.hasChildren) { item.ListView.view.model.trigger(index, "", null); plasmoid.expanded = false; } @@ -119,7 +119,7 @@ pressY = -1; } - onPositionChanged: { + onPositionChanged: mouse => { if (pressX != -1 && model.url && dragHelper.isDrag(pressX, pressY, mouse.x, mouse.y)) { dragHelper.startDrag(kicker, model.url, model.decoration); pressed = false; @@ -130,7 +130,7 @@ } // FIXME: Correct escape angle calc for right screen edge. - if (justOpenedTimer.running || !hasChildren) { + if (justOpenedTimer.running || !item.hasChildren) { item.ListView.view.currentIndex = index; } else { mouseCol = mouse.x; @@ -140,11 +140,11 @@ } else if ((index == item.ListView.view.currentIndex - 1) && mouse.y < (itemHeight - 6) || (index == item.ListView.view.currentIndex + 1) && mouse.y > 5) { - if ((childDialog != null && childDialog.facingLeft) + if ((item.childDialog != null && item.childDialog.facingLeft) ? mouse.x > item.ListView.view.eligibleWidth - 5 : mouse.x < item.ListView.view.eligibleWidth + 5) { updateCurrentItem(); } - } else if ((childDialog != null && childDialog.facingLeft) + } else if ((item.childDialog != null && item.childDialog.facingLeft) ? mouse.x > item.ListView.view.eligibleWidth : mouse.x < item.ListView.view.eligibleWidth) { updateCurrentItem(); } @@ -211,7 +211,7 @@ PlasmaComponents.Label { id: label - enabled: !isParent || (isParent && hasChildren) + enabled: !isParent || (isParent && item.hasChildren) anchors.verticalCenter: parent.verticalCenter @@ -234,7 +234,7 @@ width: visible ? units.iconSizes.small : 0 height: width - visible: hasChildren + visible: item.hasChildren opacity: (item.ListView.view.currentIndex === index) ? 1.0 : 0.4 svg: arrows @@ -263,18 +263,18 @@ anchors.rightMargin: highlightItemSvg.margins.right anchors.verticalCenter: parent.verticalCenter - active: isSeparator + active: item.isSeparator asynchronous: false sourceComponent: separatorComponent } Keys.onPressed: { - if (event.key === Qt.Key_Menu && hasActionList) { + if (event.key === Qt.Key_Menu && item.hasActionList) { event.accepted = true; - openActionMenu(mouseArea); - } else if ((event.key === Qt.Key_Enter || event.key === Qt.Key_Return) && !hasChildren) { - if (!hasChildren) { + item.openActionMenu(mouseArea); + } else if ((event.key === Qt.Key_Enter || event.key === Qt.Key_Return) && !item.hasChildren) { + if (!item.hasChildren) { event.accepted = true; item.ListView.view.model.trigger(index, "", null); plasmoid.expanded = false; diff --git a/applets/kicker/package/contents/ui/ItemListDialog.qml b/applets/kicker/package/contents/ui/ItemListDialog.qml --- a/applets/kicker/package/contents/ui/ItemListDialog.qml +++ b/applets/kicker/package/contents/ui/ItemListDialog.qml @@ -48,10 +48,10 @@ mainItem: ItemListView { id: itemListView - height: model !== undefined ? Math.min(((Math.floor((itemDialog.availableScreenRectForItem(itemListView).height + height: itemDialog.model !== undefined ? Math.min(((Math.floor((itemDialog.availableScreenRectForItem(itemListView).height - itemDialog.margins.top - itemDialog.margins.bottom) / itemHeight) - 1) - * itemHeight) - (model.separatorCount * itemHeight) + (model.separatorCount * separatorHeight), - ((model.count - model.separatorCount) * itemHeight) + (model.separatorCount * separatorHeight)) : 0 + * itemHeight) - (itemDialog.model.separatorCount * itemHeight) + (itemDialog.model.separatorCount * separatorHeight), + ((itemDialog.model.count - itemDialog.model.separatorCount) * itemHeight) + (itemDialog.model.separatorCount * separatorHeight)) : 0 iconsEnabled: true diff --git a/applets/kicker/package/contents/ui/ItemListView.qml b/applets/kicker/package/contents/ui/ItemListView.qml --- a/applets/kicker/package/contents/ui/ItemListView.qml +++ b/applets/kicker/package/contents/ui/ItemListView.qml @@ -72,26 +72,26 @@ return; } - if (childDialog != null) { - childDialog.delayedDestroy(); + if (itemList.childDialog != null) { + itemList.childDialog.delayedDestroy(); } // Gets reenabled after the dialog spawn causes a focus-in on the dialog window. plasmoid.hideOnWindowDeactivate = false; - childDialog = itemListDialogComponent.createObject(itemList); - childDialog.focusParent = itemList; - childDialog.visualParent = listView.currentItem; - childDialog.model = model.modelForRow(listView.currentIndex); - childDialog.visible = true; + itemList.childDialog = itemListDialogComponent.createObject(itemList); + itemList.childDialog.focusParent = itemList; + itemList.childDialog.visualParent = listView.currentItem; + itemList.childDialog.model = model.modelForRow(listView.currentIndex); + itemList.childDialog.visible = true; - windowSystem.forceActive(childDialog.mainItem); - childDialog.mainItem.focus = true; + windowSystem.forceActive(itemList.childDialog.mainItem); + itemList.childDialog.mainItem.focus = true; if (focusOnSpawn) { - childDialog.mainItem.showChildDialogs = false; - childDialog.mainItem.currentIndex = 0; - childDialog.mainItem.showChildDialogs = true; + itemList.childDialog.mainItem.showChildDialogs = false; + itemList.childDialog.mainItem.currentIndex = 0; + itemList.childDialog.mainItem.showChildDialogs = true; } } } @@ -103,7 +103,7 @@ repeat: false onTriggered: { - if (focus && (!childDialog || !childDialog.mainItem.containsMouse)) { + if (focus && (!itemList.childDialog || !itemList.childDialog.mainItem.containsMouse)) { currentIndex = -1; itemList.exited(); } @@ -123,7 +123,7 @@ if (containsMouse) { resetIndexTimer.stop(); itemList.forceActiveFocus(); - } else if ((!childDialog || !dialog) + } else if ((!itemList.childDialog || !dialog) && (!currentItem || !currentItem.menu.opened)) { resetIndexTimer.start(); } @@ -165,13 +165,13 @@ onCurrentIndexChanged: { if (currentIndex != -1) { - if (childDialog) { + if (itemList.childDialog) { if (currentItem && currentItem.hasChildren) { - childDialog.mainItem.width = itemList.minimumWidth; - childDialog.model = model.modelForRow(currentIndex); - childDialog.visualParent = listView.currentItem; + itemList.childDialog.mainItem.width = itemList.minimumWidth; + itemList.childDialog.model = model.modelForRow(currentIndex); + itemList.childDialog.visualParent = listView.currentItem; } else { - childDialog.delayedDestroy(); + itemList.childDialog.delayedDestroy(); } return; @@ -187,9 +187,9 @@ dialogSpawnTimer.focusOnSpawn = false; dialogSpawnTimer.restart(); } - } else if (childDialog != null) { - childDialog.delayedDestroy(); - childDialog = null; + } else if (itemList.childDialog != null) { + itemList.childDialog.delayedDestroy(); + itemList.childDialog = null; } } @@ -199,7 +199,7 @@ } } - Keys.onPressed: { + Keys.onPressed: event => { if (event.key === Qt.Key_Up) { event.accepted = true; @@ -234,11 +234,11 @@ } showChildDialogs = true; - } else if ((event.key === Qt.Key_Right || event.key === Qt.Key_Return || event.key === Qt.Key_Enter) && childDialog != null) { - windowSystem.forceActive(childDialog.mainItem); - childDialog.mainItem.focus = true; - childDialog.mainItem.currentIndex = 0; - } else if ((event.key === Qt.Key_Right || event.key === Qt.Key_Return || event.key === Qt.Key_Enter) && childDialog == null + } else if ((event.key === Qt.Key_Right || event.key === Qt.Key_Return || event.key === Qt.Key_Enter) && itemList.childDialog != null) { + windowSystem.forceActive(itemList.childDialog.mainItem); + itemList.childDialog.mainItem.focus = true; + itemList.childDialog.mainItem.currentIndex = 0; + } else if ((event.key === Qt.Key_Right || event.key === Qt.Key_Return || event.key === Qt.Key_Enter) && itemList.childDialog == null && currentItem != null && currentItem.hasChildren) { dialogSpawnTimer.focusOnSpawn = true; dialogSpawnTimer.restart(); diff --git a/applets/kicker/package/contents/ui/MenuRepresentation.qml b/applets/kicker/package/contents/ui/MenuRepresentation.qml --- a/applets/kicker/package/contents/ui/MenuRepresentation.qml +++ b/applets/kicker/package/contents/ui/MenuRepresentation.qml @@ -243,7 +243,7 @@ } } - Keys.onPressed: { + Keys.onPressed: event => { var target = null; if (event.key === Qt.Key_Right) { @@ -374,7 +374,7 @@ } }] - Keys.onPressed: { + Keys.onPressed: event => { if (event.key === Qt.Key_Up) { if (rootList.visible) { rootList.showChildDialogs = false; @@ -443,7 +443,7 @@ } } - Keys.onPressed: { + Keys.onPressed: event => { if (event.key === Qt.Key_Escape) { plasmoid.expanded = false; } diff --git a/applets/kicker/package/contents/ui/SideBarItem.qml b/applets/kicker/package/contents/ui/SideBarItem.qml --- a/applets/kicker/package/contents/ui/SideBarItem.qml +++ b/applets/kicker/package/contents/ui/SideBarItem.qml @@ -37,12 +37,12 @@ || (("hasActionList" in model) && (model.hasActionList !== null))) property int itemIndex: model.index - onAboutToShowActionMenu: { + onAboutToShowActionMenu: actionMenu => { var actionList = (model.hasActionList !== null) ? model.actionList : []; Tools.fillActionMenu(i18n, actionMenu, actionList, repeater.model, model.favoriteId); } - onActionTriggered: { + onActionTriggered: (actionId, actionArgument) => { if (Tools.triggerAction(repeater.model, model.index, actionId, actionArgument) === true) { plasmoid.expanded = false; } diff --git a/applets/kicker/package/contents/ui/SideBarSection.qml b/applets/kicker/package/contents/ui/SideBarSection.qml --- a/applets/kicker/package/contents/ui/SideBarSection.qml +++ b/applets/kicker/package/contents/ui/SideBarSection.qml @@ -35,7 +35,7 @@ property alias model: repeater.model property alias usesPlasmaTheme: repeater.usesPlasmaTheme - onDragMove: { + onDragMove: event => { if (flow.animating) { return; } diff --git a/applets/kicker/package/contents/ui/main.qml b/applets/kicker/package/contents/ui/main.qml --- a/applets/kicker/package/contents/ui/main.qml +++ b/applets/kicker/package/contents/ui/main.qml @@ -81,14 +81,14 @@ autoPopulate: false appNameFormat: plasmoid.configuration.appNameFormat - flat: isDash ? true : plasmoid.configuration.limitDepth + flat: kicker.isDash ? true : plasmoid.configuration.limitDepth sorted: plasmoid.configuration.alphaSort - showSeparators: !isDash + showSeparators: !kicker.isDash appletInterface: plasmoid - showAllApps: isDash + showAllApps: kicker.isDash showAllAppsCategorized: true - showTopLevelItems: !isDash + showTopLevelItems: !kicker.isDash showRecentApps: plasmoid.configuration.showRecentApps showRecentDocs: plasmoid.configuration.showRecentDocs showRecentContacts: plasmoid.configuration.showRecentContacts @@ -160,7 +160,7 @@ runners: { var runners = new Array("services"); - if (isDash) { + if (kicker.isDash) { runners = runners.concat(new Array("desktopsessions", "PowerDevil", "calculator", "unitconverter")); } @@ -172,7 +172,7 @@ return runners; } - deleteWhenEmpty: isDash + deleteWhenEmpty: kicker.isDash } Kicker.DragHelper { @@ -263,7 +263,7 @@ Component.onCompleted: { if (plasmoid.hasOwnProperty("activationTogglesExpanded")) { - plasmoid.activationTogglesExpanded = !isDash + plasmoid.activationTogglesExpanded = !kicker.isDash } windowSystem.focusIn.connect(enableHideOnWindowDeactivate); diff --git a/applets/kicker/package/metadata.desktop b/applets/kicker/package/metadata.desktop --- a/applets/kicker/package/metadata.desktop +++ b/applets/kicker/package/metadata.desktop @@ -26,6 +26,7 @@ Name[ja]=アプリケーションメニュー Name[ko]=프로그램 메뉴 Name[lt]=Programų meniu +Name[ml]=പ്രയോഗസൂചിക Name[mr]=अनुप्रयोग मेन्यु Name[nb]=Programmeny Name[nds]=Programmmenü diff --git a/applets/kimpanel/backend/ibus/emojier/emojier.cpp b/applets/kimpanel/backend/ibus/emojier/emojier.cpp --- a/applets/kimpanel/backend/ibus/emojier/emojier.cpp +++ b/applets/kimpanel/backend/ibus/emojier/emojier.cpp @@ -138,12 +138,15 @@ return; } - const QString genericDictName = "ibus/dicts/emoji-" + bcp.left(bcp.indexOf(QLatin1Char('-'))) + ".dict"; - const QString genericPath = QStandardPaths::locate(QStandardPaths::GenericDataLocation, genericDictName); - QVector dicts = {path}; - if (!genericPath.isEmpty()) { - dicts << genericPath; + const auto idxSpecific = bcp.indexOf(QLatin1Char('-')); + if (idxSpecific > 0) { + const QString genericDictName = "ibus/dicts/emoji-" + bcp.left(idxSpecific) + ".dict"; + const QString genericPath = QStandardPaths::locate(QStandardPaths::GenericDataLocation, genericDictName); + + if (!genericPath.isEmpty()) { + dicts << genericPath; + } } QSet categories; @@ -162,7 +165,6 @@ const QString emoji = QString::fromUtf8(ibus_emoji_data_get_emoji(data)); const QString description = ibus_emoji_data_get_description(data); - qDebug() << "ooo" << dictPath << emoji << description << processedEmoji.contains(emoji); if (description == QString::fromUtf8("↑↑↑") || description.isEmpty() || processedEmoji.contains(emoji)) { continue; } @@ -179,6 +181,7 @@ m_categories = categories.values(); m_categories.sort(); m_categories.prepend({}); + m_categories.prepend(QStringLiteral(":find:")); m_categories.prepend(QStringLiteral(":recent:")); } @@ -335,9 +338,9 @@ KCrash::initialize(); KQuickAddons::QtQuickSettings::init(); - KLocalizedString::setApplicationDomain("plasma.emojier"); + KLocalizedString::setApplicationDomain("org.kde.plasma.emojier"); - KAboutData about(QStringLiteral("plasma.emojier"), i18n("Emoji Picker"), QStringLiteral(WORKSPACE_VERSION_STRING), i18n("Emoji Picker"), + KAboutData about(QStringLiteral("org.kde.plasma.emojier"), i18n("Emoji Picker"), QStringLiteral(WORKSPACE_VERSION_STRING), i18n("Emoji Picker"), KAboutLicense::GPL, i18n("(C) 2019 Aleix Pol i Gonzalez")); about.addAuthor( QStringLiteral("Aleix Pol i Gonzalez"), QString(), QStringLiteral("aleixpol@kde.org") ); about.setTranslator(i18nc("NAME OF TRANSLATORS", "Your names"), i18nc("EMAIL OF TRANSLATORS", "Your emails")); diff --git a/applets/kimpanel/backend/ibus/emojier/org.kde.plasma.emojier.desktop b/applets/kimpanel/backend/ibus/emojier/org.kde.plasma.emojier.desktop --- a/applets/kimpanel/backend/ibus/emojier/org.kde.plasma.emojier.desktop +++ b/applets/kimpanel/backend/ibus/emojier/org.kde.plasma.emojier.desktop @@ -4,27 +4,31 @@ Name[ast]=Seleutor de fustaxes Name[ca]=Selector dels emoji Name[cs]=Selektor emoji +Name[de]=Emoji-Auswahl Name[en_GB]=Emoji Selector Name[es]=Selector de emojis Name[et]=Emojide valija Name[eu]=Emoji hautatzailea Name[fi]=Emoji-valitsin +Name[fr]=Sélecteur d'Emoji Name[gl]=Selector de cariñas Name[hu]=Emodzsiválasztó Name[id]=Pemilih Emoji Name[it]=Selettore di emoji Name[lt]=Jaustukų parinkiklis Name[nl]=Emoji selectieprogramma Name[nn]=Emoji-veljar +Name[pa]=ਇਮੋਜ਼ੀ ਚੋਣਕਾਰ Name[pl]=Wybierak Emoji Name[pt]=Selector de Emojis Name[pt_BR]=Seletor de Emojis +Name[ru]=Панель выбора эмодзи Name[sk]=Výber emoji Name[sv]=Väljare av emoji Name[uk]=Вибір емодзі Name[x-test]=xxEmoji Selectorxx Name[zh_CN]=绘文字选取器 -Name[zh_TW]=Emoji 選擇工具 +Name[zh_TW]=顏文字選擇工具 OnlyShowIn=KDE; Type=Application Icon=preferences-desktop-emoticons diff --git a/applets/kimpanel/backend/ibus/emojier/resources.qrc b/applets/kimpanel/backend/ibus/emojier/resources.qrc --- a/applets/kimpanel/backend/ibus/emojier/resources.qrc +++ b/applets/kimpanel/backend/ibus/emojier/resources.qrc @@ -3,5 +3,6 @@ ui/emojier.qml ui/CategoryPage.qml + ui/CategoryAction.qml diff --git a/applets/kimpanel/backend/ibus/emojier/ui/CategoryAction.qml b/applets/kimpanel/backend/ibus/emojier/ui/CategoryAction.qml new file mode 100644 --- /dev/null +++ b/applets/kimpanel/backend/ibus/emojier/ui/CategoryAction.qml @@ -0,0 +1,32 @@ +/* + * Copyright (C) 2019 Aleix Pol Gonzalez + * + * 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) version 3 or any later version + * accepted by the membership of KDE e.V. (or its successor approved + * by the membership of KDE e.V.), which shall act as a proxy + * defined in Section 14 of version 3 of the license. + * + * 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 org.kde.kirigami 2.6 as Kirigami + +Kirigami.Action { + property string category + checked: window.pageStack.get(0).title === text + text: i18nd("ibus10", category) //Get the translation of emoji categories from ibus10.mo installed by ibus + + icon.name: "image://text/" + emoji.findFirstEmojiForCategory(category) + onTriggered: { + window.pageStack.replace("qrc:/ui/CategoryPage.qml", {title: text, category: category, model: emoji }) + } +} diff --git a/applets/kimpanel/backend/ibus/emojier/ui/CategoryPage.qml b/applets/kimpanel/backend/ibus/emojier/ui/CategoryPage.qml --- a/applets/kimpanel/backend/ibus/emojier/ui/CategoryPage.qml +++ b/applets/kimpanel/backend/ibus/emojier/ui/CategoryPage.qml @@ -29,18 +29,10 @@ id: view property alias model: emojiModel.sourceModel property alias category: filter.category + property bool showSearch: false leftPadding: 0 rightPadding: 0 - actions.main: Kirigami.Action { - icon.name: "search" - tooltip: i18n("Search...") - shortcut: StandardKey.Find - onTriggered: { - checked = !checked - } - } - titleDelegate: RowLayout { Layout.fillWidth: true Layout.preferredWidth: view.width @@ -53,6 +45,7 @@ id: searchField Layout.fillWidth: true placeholderText: i18n("Search...") + visible: view.showSearch onTextChanged: { emojiModel.search = text if (emojiView.currentIndex < 0) { @@ -63,11 +56,9 @@ if (emojiView.currentItem) emojiView.currentItem.reportEmoji() } - visible: view.actions.main.checked - onVisibleChanged: if (visible) forceActiveFocus() + Component.onCompleted: if (visible) Qt.callLater(forceActiveFocus) Keys.onEscapePressed: { - text = "" - view.actions.main.checked = false + selectAll() } } } diff --git a/applets/kimpanel/backend/ibus/emojier/ui/emojier.qml b/applets/kimpanel/backend/ibus/emojier/ui/emojier.qml --- a/applets/kimpanel/backend/ibus/emojier/ui/emojier.qml +++ b/applets/kimpanel/backend/ibus/emojier/ui/emojier.qml @@ -28,6 +28,9 @@ { id: window + width: Kirigami.Units.gridUnit * 25 + height: Kirigami.Units.gridUnit * 25 + EmojiModel { id: emoji } @@ -42,14 +45,44 @@ console.log("Copied to clipboard:", thing) CopyHelper.copyTextToClipboard(thing) recentEmojiModel.includeRecent(thing, description); - visible = false + window.showPassiveNotification(i18n("%1 copied to the clipboard", thing)) } onVisibilityChanged: { if (visible) globalDrawer.actions[recentEmojiModel.count === 0 ? 1 : 0].trigger() } + Kirigami.Action { + id: recentAction + checked: window.pageStack.get(0).title === text + text: i18n("Recent") + enabled: recentEmojiModel.count > 0 + + icon.name: "document-open-recent-symbolic" + onTriggered: { + window.pageStack.replace("qrc:/ui/CategoryPage.qml", {title: text, category: "", model: recentEmojiModel}) + } + } + Kirigami.Action { + id: searchAction + checked: window.pageStack.get(0).title === text + text: i18n("Search") + icon.name: "search" + shortcut: StandardKey.Find + + onTriggered: { + window.pageStack.replace("qrc:/ui/CategoryPage.qml", {title: text, category: "", model: emoji, showSearch: true }) + } + } + + CategoryAction { + id: allAction + text: i18n("All") + icon.name: "view-list-icons" + category: "" + } + globalDrawer: Kirigami.GlobalDrawer { id: drawer title: i18n("Categories") @@ -60,33 +93,20 @@ function createCategoryActions(categories) { var actions = [] for(var i in categories) { - var cat = categories[i]; - var catAction = categoryActionComponent.createObject(drawer, { category: cat }); - actions.push(catAction) + var cat = categories[i] + actions.push(cat === ":recent:" ? recentAction : + cat === ":find:" ? searchAction : + cat.length === 0 ? allAction + : categoryActionComponent.createObject(drawer, { category: cat })) } return actions; } actions: createCategoryActions(emoji.categories) Component { id: categoryActionComponent - Kirigami.Action { - readonly property bool isRecent: category === ":recent:" - property string category - checked: window.pageStack.get(0).title === text - text: category.length === 0 ? i18n("All") - : isRecent ? i18n("Recent") - : category; - enabled: !isRecent || recentEmojiModel.count > 0 - - icon.name: isRecent ? "document-open-recent-symbolic" - : category.length === 0 ? "view-list-icons" - : "image://text/" + emoji.findFirstEmojiForCategory(category) - onTriggered: { - window.pageStack.replace("qrc:/ui/CategoryPage.qml", {title: text, category: isRecent ? "" : category, model: isRecent ? recentEmojiModel : emoji }) - } - } + CategoryAction {} } } } diff --git a/applets/kimpanel/package/contents/ui/main.qml b/applets/kimpanel/package/contents/ui/main.qml --- a/applets/kimpanel/package/contents/ui/main.qml +++ b/applets/kimpanel/package/contents/ui/main.qml @@ -206,7 +206,7 @@ if (list.count == 0 && !nodata) { var itemData = {'key': 'kimpanel-placeholder', 'icon': 'draw-freehand', - 'label': i18n('Input Method Panel'), + 'label': i18n("Input Method Panel"), 'tip': '', 'hint': ''}; list.append(itemData); diff --git a/applets/minimizeall/package/metadata.desktop b/applets/minimizeall/package/metadata.desktop --- a/applets/minimizeall/package/metadata.desktop +++ b/applets/minimizeall/package/metadata.desktop @@ -3,6 +3,7 @@ Name[ca]=Minimitza totes les finestres Name[ca@valencia]=Minimitza totes les finestres Name[cs]=Minimalizovat všechna okna +Name[da]=Minimér alle vinduer Name[de]=Alle Fenster minimieren Name[en_GB]=Minimise all Windows Name[es]=Minimizar todas las ventanas @@ -16,8 +17,10 @@ Name[it]=Minimizza tutte le finestre Name[ko]=모든 창 최소화 Name[lt]=Suskleisti visus langus +Name[ml]=എല്ലാ ജാലകങ്ങളും ചെറുതാക്കുക Name[nl]=Alle vensters minimaliseren Name[nn]=Minimer alle vindauge +Name[pa]=ਸਭ ਵਿੰਡੋਆਂ ਨੂੰ ਘੱਟੋ-ਘੱਟ ਕਰੋ Name[pl]=Minimalizacja wszystkich okien Name[pt]=Minimizar Todas as Janelas Name[pt_BR]=Minimizar todas as janelas @@ -33,6 +36,7 @@ Comment[ca]=Mostra l'escriptori minimitzant totes les finestres Comment[ca@valencia]=Mostra l'escriptori minimitzant totes les finestres Comment[cs]=Zobrazit plochu minimalizací všech oken +Comment[da]=Viser skrivebordet ved at minimere alle vinduer Comment[de]=Zeigt die Arbeitsfläche an, indem alle Fenster minimiert werden Comment[en_GB]=Shows the desktop by minimising all windows Comment[es]=Muestra el escritorio minimizando todas las ventanas diff --git a/applets/pager/package/contents/ui/main.qml b/applets/pager/package/contents/ui/main.qml --- a/applets/pager/package/contents/ui/main.qml +++ b/applets/pager/package/contents/ui/main.qml @@ -53,7 +53,7 @@ property bool dragging: false property string dragId - property string dragSwitchDesktopId + property int dragSwitchDesktopIndex: -1 property int wheelDelta: 0 @@ -224,8 +224,8 @@ id: dragTimer interval: 1000 onTriggered: { - if (dragSwitchDesktopId !== -1 && dragSwitchDesktopId !== pagerModel.currentPage) { - pagerModel.changePage(dragSwitchDesktopId); + if (dragSwitchDesktopIndex !== -1 && dragSwitchDesktopIndex !== pagerModel.currentPage) { + pagerModel.changePage(dragSwitchDesktopIndex); } } } @@ -390,16 +390,16 @@ preventStealing: true onDragEnter: { - root.dragSwitchDesktopId = desktop.desktopId; + root.dragSwitchDesktopIndex = index; dragTimer.start(); } onDragLeave: { - root.dragSwitchDesktopId = ""; + root.dragSwitchDesktopIndex = -1; dragTimer.stop(); } onDrop: { pagerModel.drop(event.mimeData, desktop.desktopId); - root.dragSwitchDesktopId = -1; + root.dragSwitchDesktopIndex = -1; dragTimer.stop(); } } diff --git a/applets/pager/plugin/windowmodel.cpp b/applets/pager/plugin/windowmodel.cpp --- a/applets/pager/plugin/windowmodel.cpp +++ b/applets/pager/plugin/windowmodel.cpp @@ -77,7 +77,7 @@ if (role == AbstractTasksModel::Geometry) { QRect windowGeo = TaskFilterProxyModel::data(index, role).toRect(); QList screens = QGuiApplication::screens(); - const QRect desktopGeo = screens.at(0)->geometry(); + const QRect desktopGeo = screens.at(0)->virtualGeometry(); if (KWindowSystem::mapViewport()) { int x = windowGeo.center().x() % desktopGeo.width(); diff --git a/applets/showActivityManager/package/metadata.desktop b/applets/showActivityManager/package/metadata.desktop --- a/applets/showActivityManager/package/metadata.desktop +++ b/applets/showActivityManager/package/metadata.desktop @@ -32,6 +32,7 @@ Name[ko]=활동 Name[lt]=Veiklos Name[lv]=Aktivitātes +Name[ml]=പ്രവര്‍ത്തികള്‍ Name[mr]=कार्यपध्दती Name[nb]=Aktiviteter Name[nds]=Aktiviteten diff --git a/applets/showdesktop/package/metadata.desktop b/applets/showdesktop/package/metadata.desktop --- a/applets/showdesktop/package/metadata.desktop +++ b/applets/showdesktop/package/metadata.desktop @@ -3,6 +3,7 @@ Name[ca]=Mostra l'escriptori Name[ca@valencia]=Mostra l'escriptori Name[cs]=Zobrazit plochu +Name[da]=Vis skrivebord Name[de]=Arbeitsfläche anzeigen Name[en_GB]=Show Desktop Name[es]=Mostrar el escritorio @@ -16,8 +17,10 @@ Name[it]=Mostra il desktop Name[ko]=바탕 화면 표시 Name[lt]=Rodyti darbalaukį +Name[ml]=പണിയിടം കാണിക്കുക Name[nl]=Bureaublad tonen Name[nn]=Vis skrivebord +Name[pa]=ਡੈਸਕਟਾਪ ਨੂੰ ਵੇਖਾਓ Name[pl]=Pokaż pulpit Name[pt]=Mostrar o Ecrã Name[pt_BR]=Mostrar a área de trabalho @@ -34,6 +37,7 @@ Comment[ca]=Mostra l'escriptori Plasma Comment[ca@valencia]=Mostra l'escriptori Plasma Comment[cs]=Zobrazení plochy Plasmy +Comment[da]=Viser Plasmas skrivebord Comment[de]=Die Plasma-Arbeitsfläche anzeigen Comment[en_GB]=Show the Plasma desktop Comment[es]=Mostrar el escritorio Plasma @@ -47,8 +51,10 @@ Comment[it]=Mostra il desktop di Plasma Comment[ko]=Plasma 바탕 화면 표시 Comment[lt]=Rodyti Plasma darbalaukį +Comment[ml]=പ്ലാസ്മ പണിയിടം കാണിക്കുക Comment[nl]=Toont het Plasma-bureaublad Comment[nn]=Vis Plasma-skrivebordet +Comment[pa]=ਪਲਾਜ਼ਮਾ ਡੈਸਕਟਾਪ ਵੇਖੋ Comment[pl]=Pokaż pulpit Plazmy Comment[pt]=Mostra toda a área de trabalho do Plasma no ecrã Comment[pt_BR]=Mostra a área de trabalho Plasma diff --git a/applets/taskmanager/CMakeLists.txt b/applets/taskmanager/CMakeLists.txt --- a/applets/taskmanager/CMakeLists.txt +++ b/applets/taskmanager/CMakeLists.txt @@ -28,6 +28,7 @@ KF5::KIOWidgets KF5::KIOFileWidgets # KFilePlacesModel KF5::Plasma + KF5::ProcessCore KF5::Service KF5::WindowSystem PW::LibNotificationManager) diff --git a/applets/taskmanager/package/contents/ui/AudioStream.qml b/applets/taskmanager/package/contents/ui/AudioStream.qml --- a/applets/taskmanager/package/contents/ui/AudioStream.qml +++ b/applets/taskmanager/package/contents/ui/AudioStream.qml @@ -36,7 +36,7 @@ } PropertyChanges { target: audioStreamIcon - source: "audio-volume-high" + elementId: "audio-volume-high" } }, State { @@ -48,7 +48,7 @@ } PropertyChanges { target: audioStreamIcon - source: "audio-volume-muted" + elementId: "audio-volume-muted" } } ] @@ -88,13 +88,85 @@ ] opacity: 0 - // The indicator should still shown even if the label is hidden, - // but only if there's enough room for it. - visible: opacity > 0 && (task.width > icon.paintedWidth + audioStreamIconBox.width) + visible: opacity > 0 - PlasmaCore.IconItem { + PlasmaCore.Svg { + id: audioSvg + imagePath: "icons/audio" + } + + PlasmaCore.SvgItem { id: audioStreamIcon - anchors.fill: parent + svg: audioSvg + smooth: false + + height: Math.round(Math.min(parent.height * 1.4, units.iconSizes.smallMedium) / 2) * 2 + width: height + + anchors { + verticalCenter: parent.verticalCenter + right: parent.right + // Avoid overlap to the right. + rightMargin: (parent.width - width) / 2 + units.smallSpacing / 4 + } + + states: [ + State { + name: "horizontal" + // When there is enough space for the audio icon, to fit right of the centered task icon. + when: (frame.width > Math.min(iconBox.width, iconBox.height) + + Math.min(Math.min(iconBox.width, iconBox.height), units.iconSizes.smallMedium) * 2) + + AnchorChanges { + target: audioStreamIconLoader + + anchors.top: undefined + anchors.verticalCenter: frame.verticalCenter + } + + PropertyChanges { + target: audioStreamIconLoader + + anchors.rightMargin: iconBox.adjustMargin(true, parent.width, taskFrame.margins.right) + width: units.roundToIconSize(Math.min(Math.min(iconBox.width, iconBox.height), units.iconSizes.smallMedium)) + } + + PropertyChanges { + target: audioStreamIcon + + height: parent.height + width: parent.width + } + }, + + State { + name: "vertical" + // When audio icon can fit above the centered task icon. + when: (frame.height > Math.min(iconBox.width, iconBox.height) + + Math.min(Math.min(iconBox.width, iconBox.height), units.iconSizes.smallMedium) * 2) + + AnchorChanges { + target: audioStreamIconLoader + + anchors.right: undefined + anchors.horizontalCenter: frame.horizontalCenter + } + + PropertyChanges { + target: audioStreamIconLoader + + anchors.topMargin: iconBox.adjustMargin(false, frame.height, taskFrame.margins.top) + width: units.roundToIconSize(Math.min(Math.min(iconBox.width, iconBox.height), units.iconSizes.smallMedium)) + } + + PropertyChanges { + target: audioStreamIcon + + height: parent.height + width: parent.width + } + } + ] } MouseArea { diff --git a/applets/taskmanager/package/contents/ui/MouseHandler.qml b/applets/taskmanager/package/contents/ui/MouseHandler.qml --- a/applets/taskmanager/package/contents/ui/MouseHandler.qml +++ b/applets/taskmanager/package/contents/ui/MouseHandler.qml @@ -95,7 +95,7 @@ // TODO: This restriction (minus the timer, which improves things) // has been proven out in the EITM fork, but could be improved later // by tracking the cursor movement vector and allowing the drag if - // the movement direction has reversed, etablishing user intent to + // the movement direction has reversed, establishing user intent to // move back. if (!plasmoid.configuration.separateLaunchers && tasks.dragSource != null && tasks.dragSource.m.IsLauncher === true && above.m.IsLauncher !== true diff --git a/applets/taskmanager/package/contents/ui/PulseAudio.qml b/applets/taskmanager/package/contents/ui/PulseAudio.qml --- a/applets/taskmanager/package/contents/ui/PulseAudio.qml +++ b/applets/taskmanager/package/contents/ui/PulseAudio.qml @@ -62,7 +62,23 @@ } function streamsForPid(pid) { - return findStreams("pid", pid); + var streams = findStreams("pid", pid); + + if (streams.length === 0) { + for (var i = 0, length = instantiator.count; i < length; ++i) { + var stream = instantiator.objectAt(i); + + if (stream.parentPid === -1) { + stream.parentPid = backend.parentPid(stream.pid); + } + + if (stream.parentPid === pid) { + streams.push(stream); + } + } + } + + return streams; } // QtObject has no default property, hence adding the Instantiator to one explicitly. @@ -74,6 +90,8 @@ delegate: QtObject { readonly property int pid: Client ? Client.properties["application.process.id"] : 0 + // Determined on demand. + property int parentPid: -1 readonly property string appName: Client ? Client.properties["application.name"] : "" readonly property bool muted: Muted // whether there is nothing actually going on on that stream diff --git a/applets/taskmanager/package/contents/ui/Task.qml b/applets/taskmanager/package/contents/ui/Task.qml --- a/applets/taskmanager/package/contents/ui/Task.qml +++ b/applets/taskmanager/package/contents/ui/Task.qml @@ -457,7 +457,7 @@ // the text label margin, which derives from the icon width. State { name: "standalone" - when: !label.visible && !audioStreamIconLoader.shown + when: !label.visible AnchorChanges { target: iconBox @@ -494,13 +494,14 @@ readonly property bool shown: item && item.visible source: "AudioStream.qml" - width: units.roundToIconSize(Math.min(Math.min(iconBox.width, iconBox.height), units.iconSizes.smallMedium)) + width: Math.min(Math.min(iconBox.width, iconBox.height) * 0.45, units.iconSizes.smallMedium) height: width anchors { - right: parent.right - rightMargin: iconBox.adjustMargin(true, parent.width, taskFrame.margins.right) - verticalCenter: parent.verticalCenter + right: frame.right + top: frame.top + rightMargin: iconBox.adjustMargin(true, parent.width, taskFrame.margins.right) + units.smallSpacing / 2 + topMargin: iconBox.adjustMargin(true, parent.width, taskFrame.margins.top) + units.smallSpacing / 2 } } diff --git a/applets/taskmanager/package/contents/ui/ToolTipInstance.qml b/applets/taskmanager/package/contents/ui/ToolTipInstance.qml --- a/applets/taskmanager/package/contents/ui/ToolTipInstance.qml +++ b/applets/taskmanager/package/contents/ui/ToolTipInstance.qml @@ -147,6 +147,7 @@ // close button PlasmaComponents.ToolButton { + id: closeButton Layout.alignment: Qt.AlignRight | Qt.AlignTop visible: isWin iconSource: "window-close" @@ -177,8 +178,15 @@ // TODO: this causes XCB error message when being visible the first time property int winId: isWin && windows[flatIndex] !== undefined ? windows[flatIndex] : 0 + PlasmaComponents.Highlight { + anchors.fill: parent + visible: hoverHandler.containsMouse + pressed: hoverHandler.containsPress + } + PlasmaCore.WindowThumbnail { anchors.fill: parent + anchors.margins: units.smallSpacing visible: !albumArtImage.visible && !thumbnailSourceItem.isMinimized winId: thumbnailSourceItem.winId @@ -226,6 +234,7 @@ } ToolTipWindowMouseArea { + id: hoverHandler anchors.fill: parent rootTask: parentTask modelIndex: submodelIndex diff --git a/applets/taskmanager/package/contents/ui/code/layout.js b/applets/taskmanager/package/contents/ui/code/layout.js --- a/applets/taskmanager/package/contents/ui/code/layout.js +++ b/applets/taskmanager/package/contents/ui/code/layout.js @@ -83,7 +83,12 @@ var length = tasks.vertical ? height : width; var maximum = tasks.vertical ? preferredMaxHeight() : preferredMaxWidth(); - return (Math.ceil(length / maximum) * maxStripes()); + if (!tasks.vertical) { + // Fit more tasks in this case, that is possible to cut text, before combining tasks. + return Math.ceil(length / maximum) * maxStripes() + 1; + } + + return Math.floor(length / maximum) * maxStripes(); } function layoutWidth() { diff --git a/applets/taskmanager/plugin/backend.h b/applets/taskmanager/plugin/backend.h --- a/applets/taskmanager/plugin/backend.h +++ b/applets/taskmanager/plugin/backend.h @@ -89,6 +89,8 @@ Q_INVOKABLE void cancelHighlightWindows(); + Q_INVOKABLE qint64 parentPid(qint64 pid) const; + static QUrl tryDecodeApplicationsUrl(const QUrl &launcherUrl); public Q_SLOTS: diff --git a/applets/taskmanager/plugin/backend.cpp b/applets/taskmanager/plugin/backend.cpp --- a/applets/taskmanager/plugin/backend.cpp +++ b/applets/taskmanager/plugin/backend.cpp @@ -45,6 +45,9 @@ #include #include +#include +#include + namespace KAStats = KActivities::Stats; using namespace KAStats; @@ -536,6 +539,19 @@ updateWindowHighlight(); } +qint64 Backend::parentPid(qint64 pid) const +{ + KSysGuard::Processes procs; + procs.updateOrAddProcess(pid); + + KSysGuard::Process *proc = procs.getProcess(pid); + if (!proc) { + return -1; + } + + return proc->parentPid(); +} + void Backend::windowsHovered(const QVariant &_winIds, bool hovered) { m_windowsToHighlight.clear(); diff --git a/applets/window-list/metadata.desktop b/applets/window-list/metadata.desktop --- a/applets/window-list/metadata.desktop +++ b/applets/window-list/metadata.desktop @@ -27,6 +27,7 @@ Name[kk]=Терезе тізімі Name[ko]=창 목록 Name[lt]=Langų sąrašas +Name[ml]=ജാലകപട്ടിക Name[mr]=चौकट यादी Name[nb]=Vindusliste Name[nds]=Finsterlist @@ -85,7 +86,7 @@ Comment[lt]=Plasma įskiepis, skirtas rodyti atvertų langų sąrašą. Comment[lv]=Plazmoīds, kas rāda atvērto logu sarakstu. Comment[mk]=Плазмоид за прикажување листа од отворените прозорци -Comment[ml]=തുറന്ന ജാലകങ്ങളുടെ പട്ടിക കാണിയ്ക്കാനുള്ള പ്ലാസ്മോയിഡ് +Comment[ml]=തുറന്ന ജാലകങ്ങളുടെ പട്ടിക കാണിയ്ക്കാനുള്ള പ്ലാസ്മോയിഡ്. Comment[mr]=उघडलेल्या चौकटींची यादी दर्शविणारे प्लाज्मोइड Comment[nb]=Plasmoide som viser en liste over åpne vinduer. Comment[nds]=Plasma-Lüttprogramm, dat de List mit opmaakt Finstern wiest diff --git a/containments/desktop/package/contents/ui/ConfigOverlay.qml b/containments/desktop/package/contents/ui/ConfigOverlay.qml --- a/containments/desktop/package/contents/ui/ConfigOverlay.qml +++ b/containments/desktop/package/contents/ui/ConfigOverlay.qml @@ -228,7 +228,7 @@ Layout.minimumHeight: units.gridUnit * 3 Layout.fillHeight: true Layout.fillWidth: true - cursorShape: Qt.DragMoveCursor + cursorShape: containsPress? Qt.DragMoveCursor : Qt.OpenHandCursor hoverEnabled: true onPressed: appletsLayout.releaseSpace(overlay.itemContainer); onPositionChanged: { diff --git a/containments/desktop/package/contents/ui/FolderView.qml b/containments/desktop/package/contents/ui/FolderView.qml --- a/containments/desktop/package/contents/ui/FolderView.qml +++ b/containments/desktop/package/contents/ui/FolderView.qml @@ -459,8 +459,8 @@ dragY = -1; clearPressState(); } else { - // Disable rubberband in popup list view mode. - if (root.useListViewMode) { + // Disable rubberband in popup list view mode or while renaming + if (root.useListViewMode || (editor && editor.targetItem)) { return; } diff --git a/containments/desktop/plugins/folder/autotests/positionertest.cpp b/containments/desktop/plugins/folder/autotests/positionertest.cpp --- a/containments/desktop/plugins/folder/autotests/positionertest.cpp +++ b/containments/desktop/plugins/folder/autotests/positionertest.cpp @@ -254,7 +254,7 @@ auto ensureUnique = [](const QHash mapping) { auto values = mapping.values(); std::sort(values.begin(), values.end()); - auto uniqueValues = values.toSet().toList(); + auto uniqueValues = values.toSet().values(); std::sort(uniqueValues.begin(), uniqueValues.end()); QVERIFY(uniqueValues == values); }; diff --git a/containments/desktop/plugins/folder/foldermodel.cpp b/containments/desktop/plugins/folder/foldermodel.cpp --- a/containments/desktop/plugins/folder/foldermodel.cpp +++ b/containments/desktop/plugins/folder/foldermodel.cpp @@ -620,7 +620,7 @@ QStringList FolderModel::filterMimeTypes() const { - return m_mimeSet.toList(); + return m_mimeSet.values(); } void FolderModel::setFilterMimeTypes(const QStringList &mimeList) diff --git a/containments/panel/contents/ui/ConfigOverlay.qml b/containments/panel/contents/ui/ConfigOverlay.qml --- a/containments/panel/contents/ui/ConfigOverlay.qml +++ b/containments/panel/contents/ui/ConfigOverlay.qml @@ -16,7 +16,7 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 2.010-1301, USA. */ -import QtQuick 2.1 +import QtQuick 2.5 import QtQuick.Layouts 1.0 import org.kde.plasma.core 2.0 as PlasmaCore @@ -64,7 +64,11 @@ } } } else { - configurationArea.cursorShape = Qt.ArrowCursor; + if (configurationArea.containsPress) { + configurationArea.cursorShape = Qt.ClosedHandCursor; + } else { + configurationArea.cursorShape = Qt.OpenHandCursor; + } } if (pressed) { diff --git a/design/plasmoids b/design/plasmoids --- a/design/plasmoids +++ b/design/plasmoids @@ -3,9 +3,9 @@ What is a widget? ================ -In the context of Plasma, a "widget" is a single, self-contained graphical object on the canvas. They can be added and removed individually, configured separately from other widgets, etc. These "mini appliations" are sometimes referred to in other widget platforms as "applets", "apps", "gadgets", "karambas", "desklets". We chose the word "widget" for Plasma as it is used by other some other existing systems. +In the context of Plasma, a "widget" is a single, self-contained graphical object on the canvas. They can be added and removed individually, configured separately from other widgets, etc. These "mini applications" are sometimes referred to in other widget platforms as "applets", "apps", "gadgets", "karambas", "desklets". We chose the word "widget" for Plasma as it is used by other some other existing systems. -The API of a widget is defined by the host "ScriptEngine", with the exception of native Plasma widgets written in C++ which allows plugins in loadable librareis which use the API of the Plasma library directly. Currently Plasma supports both such "native" widgets written in C++, ones written in various dynamic languages (Plasmoids) as well as: +The API of a widget is defined by the host "ScriptEngine", with the exception of native Plasma widgets written in C++ which allows plugins in loadable libraries which use the API of the Plasma library directly. Currently Plasma supports both such "native" widgets written in C++, ones written in various dynamic languages (Plasmoids) as well as: * SuperKaramba's karambas * Enlightenment 17 edje content @@ -15,15 +15,15 @@ What is a Plasmoid? ================== -A Plasmoid is a widget that can be loaded into Plasma that uses the native Plasma API and comes packaged in a single archive file that includes the code, metadata, images, configuration defintions, etc. Plasmoids may be currently written in the following languages / APIs: +A Plasmoid is a widget that can be loaded into Plasma that uses the native Plasma API and comes packaged in a single archive file that includes the code, metadata, images, configuration definitions, etc. Plasmoids may be currently written in the following languages / APIs: * HTML/JavaScript widgets (essentially "web pages for Plasma"): they are limited to a small subset of the Plasma library API and DataEngines * Simplified JavaScript: these are written in JavaScript but use a managed set of API from the Plasma library and elsewhere; these are the most likely to be widely portable between Plasma instances and are the most securable. * Full JavaScript: a work in progress, this provides full access to the Plasma, KDE and Qt APIs * Ruby: full access to the Plasma, KDE, Qt and other Ruby APIs are provided * Python: full access to the Plasma, KDE, Qt and other Python APIs are provided -There are tutorials for the various APIs avaiable here: http://techbase.kde.org/Development/Tutorials/Plasma +There are tutorials for the various APIs available here: https://techbase.kde.org/Development/Tutorials/Plasma The Plasmoid Package ==================== diff --git a/imports/activitymanager/CMakeLists.txt b/imports/activitymanager/CMakeLists.txt --- a/imports/activitymanager/CMakeLists.txt +++ b/imports/activitymanager/CMakeLists.txt @@ -1,6 +1,3 @@ -find_package (ECM 0.0.8 REQUIRED NO_MODULE) -set (CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${ECM_MODULE_PATH}) - find_package (Qt5 REQUIRED NO_MODULE COMPONENTS Widgets Qml X11Extras Quick) find_package (KF5I18n ${KF5_DEP_VERSION} CONFIG REQUIRED) find_package (KF5Config ${KF5_DEP_VERSION} CONFIG REQUIRED) diff --git a/kcms/access/kcmaccess.desktop b/kcms/access/kcmaccess.desktop --- a/kcms/access/kcmaccess.desktop +++ b/kcms/access/kcmaccess.desktop @@ -67,7 +67,7 @@ Name[lv]=Pieejamība Name[mai]=अभिगम्यता Name[mk]=Пристапливост -Name[ml]=സാമീപ്യത +Name[ml]=പ്രാപ്യത Name[mr]=सुलभता Name[ms]=Kebolehcapaian Name[nb]=Tilgjengelighet @@ -132,6 +132,7 @@ Comment[ja]=アクセシビリティオプション Comment[ko]=내게 필요한 설정 Comment[lt]=Prieinamumo parinktys +Comment[ml]=പ്രാപ്യതാസാധ്യതകൾ Comment[mr]=सुलभता पर्याय Comment[nb]=Valg for tilgjengelighet Comment[nds]=Toganghülp-Optschonen diff --git a/kcms/activities/BlacklistedApplicationsModel.cpp b/kcms/activities/BlacklistedApplicationsModel.cpp --- a/kcms/activities/BlacklistedApplicationsModel.cpp +++ b/kcms/activities/BlacklistedApplicationsModel.cpp @@ -120,7 +120,7 @@ } } - auto applications = (blockedApplications + allowedApplications).toList(); + auto applications = (blockedApplications + allowedApplications).values(); if (applications.length() > 0) { std::sort(applications.begin(), applications.end()); diff --git a/kcms/activities/CMakeLists.txt b/kcms/activities/CMakeLists.txt --- a/kcms/activities/CMakeLists.txt +++ b/kcms/activities/CMakeLists.txt @@ -33,8 +33,6 @@ BlacklistedApplicationsModel.cpp ExtraActivitiesInterface.cpp - - utils/dbusfuture_p.cpp ) ki18n_wrap_ui ( @@ -51,6 +49,9 @@ features_interface ) +kconfig_add_kcfg_files(KAMD_KCM_SRCS kactivitymanagerd_settings.kcfgc GENERATE_MOC) +kconfig_add_kcfg_files(KAMD_KCM_SRCS kactivitymanagerd_plugins_settings.kcfgc GENERATE_MOC) + add_library (kcm_activities MODULE ${KAMD_KCM_SRCS}) target_link_libraries (kcm_activities @@ -87,3 +88,5 @@ DESTINATION ${KAMD_KCM_DATADIR}/qml ) +install(FILES kactivitymanagerd_settings.kcfg DESTINATION ${KDE_INSTALL_KCFGDIR}) +install(FILES kactivitymanagerd_plugins_settings.kcfg DESTINATION ${KDE_INSTALL_KCFGDIR}) diff --git a/kcms/activities/ExtraActivitiesInterface.cpp b/kcms/activities/ExtraActivitiesInterface.cpp --- a/kcms/activities/ExtraActivitiesInterface.cpp +++ b/kcms/activities/ExtraActivitiesInterface.cpp @@ -29,9 +29,7 @@ #include #include -#include "utils/dbusfuture_p.h" #include "features_interface.h" -#include "definitions.h" #include "common/dbus/common.h" #define ENABLE_QJSVALUE_CONTINUATION diff --git a/kcms/activities/MainConfigurationWidget.h b/kcms/activities/MainConfigurationWidget.h --- a/kcms/activities/MainConfigurationWidget.h +++ b/kcms/activities/MainConfigurationWidget.h @@ -42,6 +42,12 @@ void load() override; void save() override; +private Q_SLOTS: + void onChanged(); + +private: + void checkDefault(); + private: D_PTR; }; diff --git a/kcms/activities/MainConfigurationWidget.cpp b/kcms/activities/MainConfigurationWidget.cpp --- a/kcms/activities/MainConfigurationWidget.cpp +++ b/kcms/activities/MainConfigurationWidget.cpp @@ -47,15 +47,26 @@ d->tabs->insertTab(1, d->tabSwitching = new SwitchingTab(d->tabs), i18n("Switching")); d->tabs->insertTab(2, d->tabPrivacy = new PrivacyTab(d->tabs), i18n("Privacy")); - connect(d->tabActivities, SIGNAL(changed()), this, SLOT(changed())); - connect(d->tabSwitching, SIGNAL(changed()), this, SLOT(changed())); - connect(d->tabPrivacy, SIGNAL(changed()), this, SLOT(changed())); + connect(d->tabActivities, &ActivitiesTab::changed, this, &MainConfigurationWidget::onChanged); + connect(d->tabSwitching, &SwitchingTab::changed, this, &MainConfigurationWidget::onChanged); + connect(d->tabPrivacy, &PrivacyTab::changed, this, &MainConfigurationWidget::onChanged); } MainConfigurationWidget::~MainConfigurationWidget() { } +void MainConfigurationWidget::checkDefault() +{ + defaulted(d->tabSwitching->isDefault() && d->tabPrivacy->isDefault()); +} + +void MainConfigurationWidget::onChanged() +{ + checkDefault(); + markAsChanged(); +} + void MainConfigurationWidget::defaults() { d->tabActivities->defaults(); @@ -68,6 +79,8 @@ d->tabActivities->load(); d->tabPrivacy->load(); d->tabSwitching->load(); + + checkDefault(); } void MainConfigurationWidget::save() diff --git a/kcms/activities/PrivacyTab.h b/kcms/activities/PrivacyTab.h --- a/kcms/activities/PrivacyTab.h +++ b/kcms/activities/PrivacyTab.h @@ -34,6 +34,8 @@ explicit PrivacyTab(QWidget *parent); ~PrivacyTab() override; + bool isDefault(); + public Q_SLOTS: void defaults(); void load(); diff --git a/kcms/activities/PrivacyTab.cpp b/kcms/activities/PrivacyTab.cpp --- a/kcms/activities/PrivacyTab.cpp +++ b/kcms/activities/PrivacyTab.cpp @@ -19,6 +19,8 @@ */ #include "PrivacyTab.h" +#include "kactivitymanagerd_settings.h" +#include "kactivitymanagerd_plugins_settings.h" #include #include @@ -34,7 +36,6 @@ #include "ui_PrivacyTabBase.h" #include "BlacklistedApplicationsModel.h" -#include "definitions.h" #include @@ -46,29 +47,28 @@ class PrivacyTab::Private : public Ui::PrivacyTabBase { public: - KSharedConfig::Ptr mainConfig; - KSharedConfig::Ptr pluginConfig; + KActivityManagerdSettings *mainConfig; + KActivityManagerdPluginsSettings *pluginConfig; BlacklistedApplicationsModel *blacklistedApplicationsModel; QObject *viewBlacklistedApplicationsRoot; std::unique_ptr viewBlacklistedApplications; - Private() - : viewBlacklistedApplicationsRoot(nullptr) + Private(QObject *parent) + : mainConfig(new KActivityManagerdSettings(parent)) + , pluginConfig(new KActivityManagerdPluginsSettings(parent)) + , viewBlacklistedApplicationsRoot(nullptr) , viewBlacklistedApplications(nullptr) { } }; PrivacyTab::PrivacyTab(QWidget *parent) : QWidget(parent) - , d() + , d(this) { d->setupUi(this); - d->mainConfig = KSharedConfig::openConfig(QStringLiteral("kactivitymanagerdrc")); - d->pluginConfig = KSharedConfig::openConfig(QStringLiteral("kactivitymanagerd-pluginsrc")); - // Keep history initialization d->spinKeepHistory->setRange(0, INT_MAX); @@ -116,11 +116,7 @@ connect(d->radioRememberSpecificApplications, &QAbstractButton::toggled, d->blacklistedApplicationsModel, &BlacklistedApplicationsModel::setEnabled); - connect(d->radioRememberSpecificApplications, &QAbstractButton::toggled, - d->viewBlacklistedApplicationsContainer, &QWidget::setEnabled); - - connect(d->radioRememberSpecificApplications, &QAbstractButton::toggled, - d->checkBlacklistAllNotOnList, &QWidget::setEnabled); + connect(d->checkBlacklistAllNotOnList, &QAbstractButton::toggled, this, &PrivacyTab::changed); defaults(); @@ -135,56 +131,53 @@ { } +bool PrivacyTab::isDefault() +{ + return d->radioRememberAllApplications->isChecked() && + d->spinKeepHistory->value() == d->pluginConfig->defaultKeepHistoryForValue() && + d->checkBlacklistAllNotOnList->isChecked() == d->pluginConfig->defaultBlockedByDefaultValue(); +} + void PrivacyTab::defaults() { - d->radioRememberAllApplications->click(); - d->spinKeepHistory->setValue(0); d->blacklistedApplicationsModel->defaults(); + + d->radioRememberAllApplications->click(); + d->spinKeepHistory->setValue(d->pluginConfig->defaultKeepHistoryForValue()); + d->checkBlacklistAllNotOnList->setChecked(d->pluginConfig->defaultBlockedByDefaultValue()); } void PrivacyTab::load() { d->blacklistedApplicationsModel->load(); - const auto statisticsConfig - = d->pluginConfig->group(SQLITE_PLUGIN_CONFIG_KEY); - - const auto whatToRemember = static_cast(statisticsConfig.readEntry( - "what-to-remember", static_cast(AllApplications))); + const auto whatToRemember = static_cast(d->pluginConfig->whatToRemember()); d->radioRememberAllApplications->setChecked(whatToRemember == AllApplications); d->radioRememberSpecificApplications->setChecked(whatToRemember == SpecificApplications); d->radioDontRememberApplications->setChecked(whatToRemember == NoApplications); - d->spinKeepHistory->setValue( - statisticsConfig.readEntry("keep-history-for", 0)); - d->checkBlacklistAllNotOnList->setChecked( - statisticsConfig.readEntry("blocked-by-default", false)); + d->spinKeepHistory->setValue(d->pluginConfig->keepHistoryFor()); + d->checkBlacklistAllNotOnList->setChecked(d->pluginConfig->blockedByDefault()); } void PrivacyTab::save() { d->blacklistedApplicationsModel->save(); - auto statisticsConfig = d->pluginConfig->group(SQLITE_PLUGIN_CONFIG_KEY); - const auto whatToRemember = d->radioRememberSpecificApplications->isChecked() ? SpecificApplications : d->radioDontRememberApplications->isChecked() ? NoApplications : /* otherwise */ AllApplications; - statisticsConfig.writeEntry("what-to-remember", static_cast(whatToRemember)); - statisticsConfig.writeEntry("keep-history-for", d->spinKeepHistory->value()); - statisticsConfig.writeEntry("blocked-by-default", d->checkBlacklistAllNotOnList->isChecked()); - - statisticsConfig.sync(); - - auto pluginListConfig = d->mainConfig->group("Plugins"); + d->pluginConfig->setWhatToRemember(static_cast(whatToRemember)); + d->pluginConfig->setKeepHistoryFor(d->spinKeepHistory->value()); + d->pluginConfig->setBlockedByDefault(d->checkBlacklistAllNotOnList->isChecked()); - pluginListConfig.writeEntry("org.kde.ActivityManager.ResourceScoringEnabled", - whatToRemember != NoApplications); + d->pluginConfig->save(); - pluginListConfig.sync(); + d->mainConfig->setResourceScoringEnabled(whatToRemember != NoApplications); + d->mainConfig->save(); } void PrivacyTab::forget(int count, const QString &what) diff --git a/kcms/activities/SwitchingTab.h b/kcms/activities/SwitchingTab.h --- a/kcms/activities/SwitchingTab.h +++ b/kcms/activities/SwitchingTab.h @@ -36,6 +36,8 @@ explicit SwitchingTab(QWidget *parent); ~SwitchingTab() override; + bool isDefault(); + public Q_SLOTS: void defaults(); void load(); diff --git a/kcms/activities/SwitchingTab.cpp b/kcms/activities/SwitchingTab.cpp --- a/kcms/activities/SwitchingTab.cpp +++ b/kcms/activities/SwitchingTab.cpp @@ -19,6 +19,7 @@ */ #include "SwitchingTab.h" +#include "kactivitymanagerd_settings.h" #include #include @@ -32,18 +33,19 @@ class SwitchingTab::Private : public Ui::SwitchingTabBase { public: - KSharedConfig::Ptr mainConfig; + KActivityManagerdSettings mainConfig; KActionCollection *mainActionCollection; KActivities::Consumer activities; void createAction(const QString &actionName, const QString &actionText, - const QList &sequence) + const QList &defaultSequence) { auto action = mainActionCollection->addAction(actionName); action->setProperty("isConfigurationAction", true); action->setText(actionText); - KGlobalAccel::self()->setShortcut(action, sequence); + KGlobalAccel::self()->setShortcut(action, defaultSequence); + KGlobalAccel::self()->setDefaultShortcut(action, defaultSequence); } Private() @@ -58,8 +60,6 @@ { d->setupUi(this); - d->mainConfig = KSharedConfig::openConfig(QStringLiteral("kactivitymanagerdrc")); - // Shortcut config. The shortcut belongs to the component "plasmashell"! d->mainActionCollection = new KActionCollection(this, QStringLiteral("plasmashell")); d->mainActionCollection->setComponentDisplayName(i18n("Activity switching")); @@ -87,6 +87,11 @@ { } +bool SwitchingTab::isDefault() +{ + return !d->checkRememberVirtualDesktop->isChecked(); +} + void SwitchingTab::shortcutChanged(const QKeySequence &sequence) { QString actionName = sender() @@ -111,19 +116,12 @@ void SwitchingTab::load() { - auto pluginListConfig = d->mainConfig->group("Plugins"); - d->checkRememberVirtualDesktop->setChecked(pluginListConfig.readEntry( - "org.kde.ActivityManager.VirtualDesktopSwitchEnabled", false)); + d->checkRememberVirtualDesktop->setChecked(d->mainConfig.virtualDesktopSwitchEnabled()); } void SwitchingTab::save() { - auto pluginListConfig = d->mainConfig->group("Plugins"); - - pluginListConfig.writeEntry( - "org.kde.ActivityManager.VirtualDesktopSwitchEnabled", - d->checkRememberVirtualDesktop->isChecked()); - - pluginListConfig.sync(); + d->mainConfig.setVirtualDesktopSwitchEnabled(d->checkRememberVirtualDesktop->isChecked()); + d->mainConfig.save(); } diff --git a/kcms/activities/kactivitymanagerd_plugins_settings.kcfg b/kcms/activities/kactivitymanagerd_plugins_settings.kcfg new file mode 100644 --- /dev/null +++ b/kcms/activities/kactivitymanagerd_plugins_settings.kcfg @@ -0,0 +1,21 @@ + + + + + + + + 0 + + + false + + + + 0 + + + diff --git a/kcms/activities/kactivitymanagerd_plugins_settings.kcfgc b/kcms/activities/kactivitymanagerd_plugins_settings.kcfgc new file mode 100644 --- /dev/null +++ b/kcms/activities/kactivitymanagerd_plugins_settings.kcfgc @@ -0,0 +1,6 @@ +File=kactivitymanagerd_plugins_settings.kcfg +ClassName=KActivityManagerdPluginsSettings +Mutators=true +DefaultValueGetters=true +ParentInConstructor=true +GlobalEnums=true diff --git a/kcms/activities/kactivitymanagerd_settings.kcfg b/kcms/activities/kactivitymanagerd_settings.kcfg new file mode 100644 --- /dev/null +++ b/kcms/activities/kactivitymanagerd_settings.kcfg @@ -0,0 +1,16 @@ + + + + + + + false + + + false + + + diff --git a/kcms/activities/kactivitymanagerd_settings.kcfgc b/kcms/activities/kactivitymanagerd_settings.kcfgc new file mode 100644 --- /dev/null +++ b/kcms/activities/kactivitymanagerd_settings.kcfgc @@ -0,0 +1,5 @@ +File=kactivitymanagerd_settings.kcfg +ClassName=KActivityManagerdSettings +Mutators=true +DefaultValueGetters=true +ParentInConstructor=true diff --git a/kcms/activities/kcm_activities.desktop b/kcms/activities/kcm_activities.desktop --- a/kcms/activities/kcm_activities.desktop +++ b/kcms/activities/kcm_activities.desktop @@ -45,6 +45,7 @@ Name[ko]=활동 Name[lt]=Veiklos Name[lv]=Aktivitātes +Name[ml]=പ്രവര്‍ത്തികള്‍ Name[mr]=कार्यपध्दती Name[nb]=Aktiviteter Name[nds]=Aktiviteten diff --git a/kcms/activities/qml/activitiesTab/ActivitiesView.qml b/kcms/activities/qml/activitiesTab/ActivitiesView.qml --- a/kcms/activities/qml/activitiesTab/ActivitiesView.qml +++ b/kcms/activities/qml/activitiesTab/ActivitiesView.qml @@ -52,8 +52,6 @@ height: Kirigami.Units.iconSizes.medium width: height source: model.icon - sourceSize.width: model.icon.width - sourceSize.height: model.icon.height } QQC2.Label { diff --git a/kcms/activities/ui/PrivacyTabBase.ui b/kcms/activities/ui/PrivacyTabBase.ui --- a/kcms/activities/ui/PrivacyTabBase.ui +++ b/kcms/activities/ui/PrivacyTabBase.ui @@ -122,5 +122,38 @@ - + + + radioRememberSpecificApplications + toggled(bool) + viewBlacklistedApplicationsContainer + setEnabled(bool) + + + 352 + 167 + + + 249 + 363 + + + + + radioRememberSpecificApplications + toggled(bool) + checkBlacklistAllNotOnList + setEnabled(bool) + + + 352 + 167 + + + 252 + 481 + + + + diff --git a/kcms/activities/utils/dbusfuture_p.h b/kcms/activities/utils/dbusfuture_p.h deleted file mode 100644 --- a/kcms/activities/utils/dbusfuture_p.h +++ /dev/null @@ -1,175 +0,0 @@ -/* - * Copyright (C) 2013 - 2016 by Ivan Cukic - * - * 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) version 3 or any later version - * accepted by the membership of KDE e.V. (or its successor approved - * by the membership of KDE e.V.), which shall act as a proxy - * defined in Section 14 of version 3 of the license. - * - * 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 . - */ - -#ifndef ACTIVITIES_DBUSFUTURE_P_H -#define ACTIVITIES_DBUSFUTURE_P_H - -#include -#include -#include -#include -#include -#include -#include - -namespace DBusFuture { - -namespace detail { //_ - -template -class DBusCallFutureInterface : public QObject, - public QFutureInterface<_Result> { -public: - DBusCallFutureInterface(QDBusPendingReply<_Result> reply) - : reply(reply), - replyWatcher(nullptr) - { - } - - ~DBusCallFutureInterface() override - { - delete replyWatcher; - } - - void callFinished(); - - QFuture<_Result> start() - { - replyWatcher = new QDBusPendingCallWatcher(reply); - - QObject::connect(replyWatcher, - &QDBusPendingCallWatcher::finished, - [this] () { callFinished(); }); - - this->reportStarted(); - - if (reply.isFinished()) { - this->callFinished(); - } - - return this->future(); - } - -private: - QDBusPendingReply<_Result> reply; - QDBusPendingCallWatcher * replyWatcher; -}; - -template -void DBusCallFutureInterface<_Result>::callFinished() -{ - deleteLater(); - - if (!reply.isError()) { - this->reportResult(reply.value()); - } - - this->reportFinished(); -} - -template <> -void DBusCallFutureInterface::callFinished(); - -template -class ValueFutureInterface : public QObject, QFutureInterface<_Result> { -public: - ValueFutureInterface(const _Result & value) - : value(value) - { - } - - QFuture<_Result> start() - { - auto future = this->future(); - - this->reportResult(value); - this->reportFinished(); - - deleteLater(); - - return future; - } - -private: - _Result value; - -}; - -template <> -class ValueFutureInterface : public QObject, QFutureInterface { -public: - ValueFutureInterface(); - - QFuture start(); - // { - // auto future = this->future(); - // this->reportFinished(); - // deleteLater(); - // return future; - // } -}; - -} //^ namespace detail - -template -QFuture<_Result> -asyncCall(QDBusAbstractInterface *interface, const QString &method, - const QVariant &arg1 = QVariant(), const QVariant &arg2 = QVariant(), - const QVariant &arg3 = QVariant(), const QVariant &arg4 = QVariant(), - const QVariant &arg5 = QVariant(), const QVariant &arg6 = QVariant(), - const QVariant &arg7 = QVariant(), const QVariant &arg8 = QVariant()) -{ - using namespace detail; - - auto callFutureInterface = new DBusCallFutureInterface - <_Result>(interface->asyncCall(method, arg1, arg2, arg3, arg4, arg5, - arg6, arg7, arg8)); - - return callFutureInterface->start(); -} - -template -QFuture<_Result> -fromValue(const _Result & value) -{ - using namespace detail; - - auto valueFutureInterface = new ValueFutureInterface<_Result>(value); - - return valueFutureInterface->start(); -} - -template -QFuture<_Result> -fromReply(const QDBusPendingReply<_Result> &reply) -{ - using namespace detail; - - auto callFutureInterface = new DBusCallFutureInterface<_Result>(reply); - - return callFutureInterface->start(); -} - -QFuture fromVoid(); - -} // namespace DBusFuture - -#endif /* DBUSFUTURE_P_H */ - diff --git a/kcms/activities/utils/dbusfuture_p.cpp b/kcms/activities/utils/dbusfuture_p.cpp deleted file mode 100644 --- a/kcms/activities/utils/dbusfuture_p.cpp +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Copyright (C) 2013 - 2016 by Ivan Cukic - * - * 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) version 3 or any later version - * accepted by the membership of KDE e.V. (or its successor approved - * by the membership of KDE e.V.), which shall act as a proxy - * defined in Section 14 of version 3 of the license. - * - * 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 . - */ - -#include "dbusfuture_p.h" - -namespace DBusFuture { - -namespace detail { //_ - -template <> -void DBusCallFutureInterface::callFinished() -{ - deleteLater(); - - // qDebug() << "This is call end"; - - this->reportFinished(); -} - -ValueFutureInterface::ValueFutureInterface() -{ -} - -QFuture ValueFutureInterface::start() -{ - auto future = this->future(); - - this->reportFinished(); - - deleteLater(); - - return future; -} - -} //^ namespace detail - -QFuture fromVoid() -{ - using namespace detail; - - auto valueFutureInterface = new ValueFutureInterface(); - - return valueFutureInterface->start(); -} - -} // namespace DBusFuture - diff --git a/kcms/autostart/autostart.cpp b/kcms/autostart/autostart.cpp --- a/kcms/autostart/autostart.cpp +++ b/kcms/autostart/autostart.cpp @@ -222,7 +222,7 @@ //add scripts - foreach (const QString& path, m_paths) { + for (const QString& path : qAsConst(m_paths)) { QDir d(path); if (!d.exists()) d.mkpath(path); diff --git a/kcms/autostart/autostart.desktop b/kcms/autostart/autostart.desktop --- a/kcms/autostart/autostart.desktop +++ b/kcms/autostart/autostart.desktop @@ -125,6 +125,7 @@ Comment[ja]=自動的に起動されるアプリケーション Comment[ko]=자동으로 시작되는 프로그램 Comment[lt]=Automatiškai paleidžiamos programos +Comment[ml]=താനേ തുടങ്ങിയ പ്രയോഗങ്ങൾ Comment[mr]=स्वप्रारंभअनुप्रयोग Comment[nb]=Programmer som startes automatisk Comment[nds]=Automaatsch opropen Programmen diff --git a/kcms/baloo/CMakeLists.txt b/kcms/baloo/CMakeLists.txt --- a/kcms/baloo/CMakeLists.txt +++ b/kcms/baloo/CMakeLists.txt @@ -1,4 +1,4 @@ -add_definitions(-DTRANSLATION_DOMAIN=\"kcm5_baloofile\") +add_definitions(-DTRANSLATION_DOMAIN=\"kcm_baloofile\") set(kcm_file_SRCS kcm.cpp diff --git a/kcms/baloo/Messages.sh b/kcms/baloo/Messages.sh old mode 100755 new mode 100644 --- a/kcms/baloo/Messages.sh +++ b/kcms/baloo/Messages.sh @@ -1,4 +1,2 @@ #! /usr/bin/env bash -$EXTRACTRC `find . -name "*.ui"` >> rc.cpp || exit 11 -$XGETTEXT `find . -name "*.cpp"` -o $podir/kcm5_baloofile.pot -rm -f rc.cpp +$XGETTEXT `find . -name "*.cpp" -o -name "*.qml"` -o $podir/kcm_baloofile.pot diff --git a/kcms/baloo/filteredfoldermodel.cpp b/kcms/baloo/filteredfoldermodel.cpp --- a/kcms/baloo/filteredfoldermodel.cpp +++ b/kcms/baloo/filteredfoldermodel.cpp @@ -132,7 +132,7 @@ QSet::fromList(m_mountPoints) - QSet::fromList(m_excludeList); - return mountPointSet.toList(); + return mountPointSet.values(); } QStringList FilteredFolderModel::excludeFolders() const diff --git a/kcms/baloo/kcm_baloofile.desktop b/kcms/baloo/kcm_baloofile.desktop --- a/kcms/baloo/kcm_baloofile.desktop +++ b/kcms/baloo/kcm_baloofile.desktop @@ -36,6 +36,7 @@ Name[ja]=ファイルの検索 Name[ko]=파일 검색 Name[lt]=Failų paieška +Name[ml]=ഫയൽ തിരയുക Name[mr]=फाईल शोध Name[nl]=Bestanden zoeken Name[nn]=Filsøk @@ -81,6 +82,7 @@ Comment[ja]=ファイルの検索を設定 Comment[ko]=파일 검색 설정 Comment[lt]=Konfigūruoti failų paiešką +Comment[ml]=ഫയൽ തിരച്ചിൽ ക്രമീകരിക്കുക Comment[mr]=फाईल शोध संयोजीत करा Comment[nl]=Bestanden zoeken instellen Comment[nn]=Set opp filsøk diff --git a/kcms/baloo/package/metadata.desktop b/kcms/baloo/package/metadata.desktop --- a/kcms/baloo/package/metadata.desktop +++ b/kcms/baloo/package/metadata.desktop @@ -8,16 +8,20 @@ Name[et]=Otsing Name[eu]=Bilatu Name[fi]=Etsi +Name[fr]=Rechercher Name[gl]=Buscar Name[hu]=Keresés Name[id]=Pencarian Name[it]=Ricerca Name[lt]=Paieška +Name[ml]=തിരയുക Name[nl]=Zoeken Name[nn]=Søk +Name[pa]=ਖੋਜੋ Name[pl]=Szukaj Name[pt]=Pesquisa Name[pt_BR]=Pesquisar +Name[ru]=Поиск Name[sk]=Hľadať Name[sv]=Sök Name[uk]=Пошук @@ -34,16 +38,20 @@ Comment[et]=Failide indekseerimise seadistamine Comment[eu]=Konfiguratu fitxategi indexatzailea Comment[fi]=Tiedostoindeksoinnin asetukset +Comment[fr]=Configurer l'indexation de fichiers Comment[gl]=Configurar o indexador de ficheiros Comment[hu]=A fájlindexelés beállítása Comment[id]=Konfigurasikan Pengindeks File Comment[it]=Configura l'indicizzatore dei file Comment[lt]=Konfigūruoti failų indeksatorių +Comment[ml]=ഫയൽ സൂചിക ക്രമീകരിക്കുക Comment[nl]=De bestandenindexering configureren Comment[nn]=Set opp filindeksering +Comment[pa]=ਫਾਇਲ ਇੰਡੈਕਸਰ ਦੀ ਸੰਰਚਨਾ Comment[pl]=Ustawienia indeksera plików Comment[pt]=Configurar a Indexação de Ficheiros Comment[pt_BR]=Configura o Indexador de Arquivos +Comment[ru]=Настройка службы индексирования файлов Comment[sk]=Nastaviť indexer súborov Comment[sv]=Anpassa filindexering Comment[uk]=Налаштовування індексування файлів diff --git a/kcms/colors/CMakeLists.txt b/kcms/colors/CMakeLists.txt --- a/kcms/colors/CMakeLists.txt +++ b/kcms/colors/CMakeLists.txt @@ -23,7 +23,7 @@ KF5::I18n KF5::KIOCore KF5::KIOWidgets - KF5::NewStuff + KF5::NewStuffCore KF5::QuickAddons KF5::WindowSystem ) diff --git a/kcms/colors/colors.h b/kcms/colors/colors.h --- a/kcms/colors/colors.h +++ b/kcms/colors/colors.h @@ -23,10 +23,10 @@ #include #include +#include #include -#include #include @@ -74,7 +74,7 @@ ColorsSettings *colorsSettings() const; bool downloadingFile() const; - Q_INVOKABLE void getNewStuff(QQuickItem *ctx); + Q_INVOKABLE void reloadModel(const QQmlListReference &changedEntries); Q_INVOKABLE void installSchemeFromFile(const QUrl &url); Q_INVOKABLE void editScheme(const QString &schemeName, QQuickItem *ctx); @@ -92,6 +92,8 @@ void showSchemeNotInstalledWarning(const QString &schemeName); private: + bool isSaveNeeded() const override; + void saveColors(); void processPendingDeletions(); @@ -105,8 +107,6 @@ bool m_applyToAlien = true; - QPointer m_newStuffDialog; - QProcess *m_editDialogProcess = nullptr; KSharedConfigPtr m_config; diff --git a/kcms/colors/colors.cpp b/kcms/colors/colors.cpp --- a/kcms/colors/colors.cpp +++ b/kcms/colors/colors.cpp @@ -47,6 +47,11 @@ #include #include +#include +#if KNEWSTUFFCORE_VERSION_MAJOR==5 && KNEWSTUFFCORE_VERSION_MINOR>=67 +#include +#endif + #include #include "../krdb/krdb.h" @@ -74,9 +79,7 @@ about->addAuthor(i18n("Kai Uwe Broulik"), QString(), QStringLiteral("kde@privat.broulik.de")); setAboutData(about); - connect(m_model, &ColorsModel::pendingDeletionsChanged, this, [this] { - setNeedsSave(true); - }); + connect(m_model, &ColorsModel::pendingDeletionsChanged, this, &KCMColors::settingsChanged); connect(m_model, &ColorsModel::selectedSchemeChanged, this, [this](const QString &scheme) { m_selectedSchemeDirty = true; @@ -116,25 +119,21 @@ return m_tempCopyJob; } -void KCMColors::getNewStuff(QQuickItem *ctx) +void KCMColors::reloadModel(const QQmlListReference &changedEntries) { - if (!m_newStuffDialog) { - m_newStuffDialog = new KNS3::DownloadDialog(QStringLiteral("colorschemes.knsrc")); - m_newStuffDialog.data()->setWindowTitle(i18n("Download New Color Schemes")); - m_newStuffDialog->setWindowModality(Qt::WindowModal); - m_newStuffDialog->winId(); // so it creates the windowHandle(); - - connect(m_newStuffDialog.data(), &KNS3::DownloadDialog::accepted, this, [this] { - m_model->load(); + m_model->load(); - const auto newEntries = m_newStuffDialog->installedEntries(); - // If one new theme was installed, select the first color file in it - if (newEntries.count() == 1) { - QStringList installedThemes; +#if KNEWSTUFFCORE_VERSION_MAJOR==5 && KNEWSTUFFCORE_VERSION_MINOR>=67 + // If one new theme was installed, select the first color file in it + if (changedEntries.count() > 1) { + QStringList installedThemes; - const QString suffix = QStringLiteral(".colors"); + const QString suffix = QStringLiteral(".colors"); - for (const QString &path : newEntries.first().installedFiles()) { + for (int i = 0; i < changedEntries.count(); ++i) { + KNSCore::EntryWrapper* entry = qobject_cast(changedEntries.at(i)); + if (entry && entry->entry().status() == KNS3::Entry::Installed) { + for (const QString &path : entry->entry().installedFiles()) { const QString fileName = path.section(QLatin1Char('/'), -1, -1); const int suffixPos = fileName.indexOf(suffix); @@ -152,15 +151,12 @@ m_model->setSelectedScheme(installedThemes.constFirst()); } + // Only do this for the first newly installed theme we find + break; } - }); - } - - if (ctx && ctx->window()) { - m_newStuffDialog->windowHandle()->setTransientParent(ctx->window()); + } } - - m_newStuffDialog.data()->show(); +#endif } void KCMColors::installSchemeFromFile(const QUrl &url) @@ -303,6 +299,12 @@ m_editDialogProcess->start(QStringLiteral("kcolorschemeeditor"), args); } +bool KCMColors::isSaveNeeded() const +{ + return !m_model->match(m_model->index(0, 0), ColorsModel::PendingDeletionRole, true).isEmpty(); +} + + void KCMColors::load() { ManagedConfigModule::load(); diff --git a/kcms/colors/colorsmodel.cpp b/kcms/colors/colorsmodel.cpp --- a/kcms/colors/colorsmodel.cpp +++ b/kcms/colors/colorsmodel.cpp @@ -85,10 +85,12 @@ item.pendingDeletion = pendingDeletion; emit dataChanged(index, index, {PendingDeletionRole}); - // move to the next non-pending theme - const auto nonPending = match(index, PendingDeletionRole, false); - if (!nonPending.isEmpty()) { - setSelectedScheme(nonPending.first().data(SchemeNameRole).toString()); + if (index.row() == selectedSchemeIndex() && pendingDeletion) { + // move to the next non-pending theme + const auto nonPending = match(index, PendingDeletionRole, false); + if (!nonPending.isEmpty()) { + setSelectedScheme(nonPending.first().data(SchemeNameRole).toString()); + } } emit pendingDeletionsChanged(); @@ -123,12 +125,9 @@ return; } - const bool firstTime = m_selectedScheme.isNull(); m_selectedScheme = scheme; - if (!firstTime) { - emit selectedSchemeChanged(scheme); - } + emit selectedSchemeChanged(scheme); emit selectedSchemeIndexChanged(); } diff --git a/kcms/colors/editor/org.kde.kcolorschemeeditor.desktop b/kcms/colors/editor/org.kde.kcolorschemeeditor.desktop --- a/kcms/colors/editor/org.kde.kcolorschemeeditor.desktop +++ b/kcms/colors/editor/org.kde.kcolorschemeeditor.desktop @@ -62,6 +62,7 @@ Name[lt]=KColorSchemeEditor Name[nl]=KColorSchemeEditor Name[nn]=KColorSchemeEditor +Name[pa]=ਕੇ-ਰੰਗ-ਸਕੀਮ-ਐਡੀਟਰ Name[pl]=KColorSchemeEditor Name[pt]=KColorSchemeEditor Name[pt_BR]=KColorSchemeEditor diff --git a/kcms/colors/filterproxymodel.cpp b/kcms/colors/filterproxymodel.cpp --- a/kcms/colors/filterproxymodel.cpp +++ b/kcms/colors/filterproxymodel.cpp @@ -40,12 +40,9 @@ return; } - const bool firstTime = m_selectedScheme.isNull(); m_selectedScheme = scheme; - if (!firstTime) { - emit selectedSchemeChanged(); - } + emit selectedSchemeChanged(); emit selectedSchemeIndexChanged(); } diff --git a/kcms/colors/kcm_colors.desktop b/kcms/colors/kcm_colors.desktop --- a/kcms/colors/kcm_colors.desktop +++ b/kcms/colors/kcm_colors.desktop @@ -108,6 +108,7 @@ Comment[ca]=Trieu l'esquema de colors Comment[ca@valencia]=Trieu l'esquema de colors Comment[cs]=Vyberte barevné schéma +Comment[da]=Vælg farveskema Comment[de]=Farbschema auswählen Comment[en_GB]=Choose colour scheme Comment[es]=Escoger un esquema de color @@ -124,6 +125,7 @@ Comment[lt]=Pasirinkti spalvų rinkinį Comment[nl]=Kleurenschema kiezen Comment[nn]=Vel fargeoppsett +Comment[pa]=ਰੰਗ ਸਕੀਮ ਚੁਣੋ Comment[pl]=Wybierz zestaw kolorów Comment[pt]=Escolher o esquema de cores Comment[pt_BR]=Escolha o esquema de cores diff --git a/kcms/colors/package/contents/ui/main.qml b/kcms/colors/package/contents/ui/main.qml --- a/kcms/colors/package/contents/ui/main.qml +++ b/kcms/colors/package/contents/ui/main.qml @@ -24,7 +24,7 @@ import QtQuick.Dialogs 1.0 as QtDialogs import QtQuick.Controls 2.3 as QtControls import org.kde.kirigami 2.4 as Kirigami -import org.kde.kconfig 1.0 // for KAuthorized +import org.kde.newstuff 1.62 as NewStuff import org.kde.kcm 1.1 as KCM import org.kde.private.kcms.colors 1.0 as Private @@ -52,7 +52,7 @@ Component.onCompleted: { // The thumbnails are a bit more elaborate and need more room, especially when translated view.implicitCellWidth = Kirigami.Units.gridUnit * 13; - view.implicitCellHeight = Kirigami.Units.gridUnit * 11; + view.implicitCellHeight = Kirigami.Units.gridUnit * 12; } DropArea { @@ -348,11 +348,12 @@ onClicked: fileDialogLoader.active = true } - QtControls.Button { - text: i18n("Get New Color Schemes...") - icon.name: "get-hot-new-stuff" - onClicked: kcm.getNewStuff(this) - visible: KAuthorized.authorize("ghns") + NewStuff.Button { + id: newStuffButton + downloadNewWhat: i18n("Color Schemes") + configFile: "colorschemes.knsrc" + viewMode: NewStuff.Page.ViewMode.Tiles + onChangedEntriesChanged: kcm.reloadModel(newStuffButton.changedEntries); } } } diff --git a/kcms/colors/package/metadata.desktop b/kcms/colors/package/metadata.desktop --- a/kcms/colors/package/metadata.desktop +++ b/kcms/colors/package/metadata.desktop @@ -95,6 +95,7 @@ Comment[ca]=Trieu l'esquema de colors Comment[ca@valencia]=Trieu l'esquema de colors Comment[cs]=Vyberte barevné schéma +Comment[da]=Vælg farveskema Comment[de]=Farbschema auswählen Comment[en_GB]=Choose colour scheme Comment[es]=Escoger un esquema de color @@ -111,6 +112,7 @@ Comment[lt]=Pasirinkti spalvų rinkinį Comment[nl]=Kleurenschema kiezen Comment[nn]=Vel fargeoppsett +Comment[pa]=ਰੰਗ ਸਕੀਮ ਚੁਣੋ Comment[pl]=Wybierz zestaw kolorów Comment[pt]=Escolher o esquema de cores Comment[pt_BR]=Escolha o esquema de cores diff --git a/kcms/componentchooser/CMakeLists.txt b/kcms/componentchooser/CMakeLists.txt --- a/kcms/componentchooser/CMakeLists.txt +++ b/kcms/componentchooser/CMakeLists.txt @@ -15,6 +15,8 @@ componentchooserterminal.cpp kcm_componentchooser.cpp ) +kconfig_add_kcfg_files(kcm_componentchooser_SRCS browser_settings.kcfgc GENERATE_MOC) +kconfig_add_kcfg_files(kcm_componentchooser_SRCS terminal_settings.kcfgc GENERATE_MOC) ki18n_wrap_ui(kcm_componentchooser_SRCS browserconfig_ui.ui @@ -46,4 +48,6 @@ ########### install files ############### install( FILES componentchooser.desktop DESTINATION ${KDE_INSTALL_KSERVICES5DIR} ) +install(FILES browser_settings.kcfg DESTINATION ${KDE_INSTALL_KCFGDIR}) +install(FILES terminal_settings.kcfg DESTINATION ${KDE_INSTALL_KCFGDIR}) diff --git a/kcms/componentchooser/EXAMPLE.desktop b/kcms/componentchooser/EXAMPLE.desktop deleted file mode 100644 --- a/kcms/componentchooser/EXAMPLE.desktop +++ /dev/null @@ -1,177 +0,0 @@ -Name=A nice name you have chosen for your interface -Name[af]='n oulike naam jy het gekies vir jou koppelvlak -Name[ar]=اسم جميل اخترته لواجهتك -Name[be]=Файная назва, якую вы выбралі для свайго інтэрфейса -Name[be@latin]=Nazva, vybranaja dla tvajho interfejsu -Name[bg]=Име на компонент -Name[bn]=আপনার ইন্টারফেসের জন্য আপনার পছন্দ করা সুন্দর একটা নাম -Name[bn_IN]=ইন্টারফেসের জন্য একটি ভাল নাম নির্ধারিত হয়েছে -Name[bs]=Lijepo ime koje ste izabrali za svoje sučelje -Name[ca]=Un bonic nom que heu triat per a la interfície -Name[ca@valencia]=Un bonic nom que heu triat per a la interfície -Name[cs]=Hezký název pro vaše rozhraní -Name[csb]=Miłé miono, jaczé òstało wëbróné dlô programë -Name[cy]=Enw neis yr ydych wedi dewis am eich rhyngwyneb -Name[da]=Et godt navn som du har valgt for din grænseflade -Name[de]=Der von Ihnen gewählte Name für die Schnittstelle -Name[el]=Ένα όμορφο όνομα που έχετε επιλέξει για τη διασύνδεσή σας -Name[en_GB]=A nice name you have chosen for your interface -Name[eo]=Plaĉa nomo, kiun vi elektis por via interfaco -Name[es]=Un bonito nombre de su elección para su interfaz -Name[et]=Mõni kena nimi, mille sa oma liidesele valinud oled -Name[eu]=Zure interfazerako aukeratu duzun izen polit bat -Name[fa]=لقبی که برای واسط خود انتخاب کرده‌اید -Name[fi]=Valitsemasi nimi rajapinnalle -Name[fr]=Un nom sympathique que vous avez choisi pour votre interface. -Name[fy]=In namme dy jo koazen ha foar jo ynterface -Name[ga]=Ainm deas a chuir tú ar do chomhéadan -Name[gl]=Un bo nome que escolleu para a súa interface -Name[gu]=તમારા ઇન્ટરફેસ માટે તમે પસંદ કરેલ સરસ નામ -Name[he]=שם נחמד שבחרת לממשק שלך -Name[hi]=आपने अपने इंटरफेस के लिए एक अच्छा नाम चुना है -Name[hne]=आप मन अपन इंटरफेस बर एक अच्छा नाम चुने हव -Name[hr]=Naziv koji ste odabrali za vaše sučelje -Name[hsb]=Rjane mjeno sće wubrali za Waš interfejs -Name[hu]=Egy Ön által választott név a felülethez -Name[ia]=Un nomine gratiose que tu ha seligite pro tu interfacie -Name[id]=Anda telah memilih sebuah nama yang bagus untuk antarmuka anda -Name[is]=Vingjarnlegt nafn þú hefur valið fyrir umhverfið þitt -Name[it]=Un bel nome che hai scelto per la tua interfaccia -Name[ja]=あなたのインターフェースに素敵な名前を付けてください -Name[ka]=მშვენიერი სახელია ინტერფეისისთვის -Name[kk]=Интерфейсіңізге таңдаған атауыңыз -Name[km]=ឈ្មោះ​ដ៏​ល្អ​មួយ​ដែល​អ្នក​បាន​ជ្រើស​សម្រាប់​ចំណុច​ប្រទាក់​របស់​អ្នក -Name[kn]=ನಿನ್ನ ಸಂಪರ್ಕತಟ (ಇಂಟರ್ಫೇಸ್) ಗೆ ನೀನು ಆರಿಸಿರುವ ಒಂದು ಒಳ್ಳೆಯ ಹೆಸರು -Name[ko]=인터페이스에 붙일 이름 -Name[ku]=te ji bo navrûyê navelî xweş hilbijart -Name[lt]=Gražus pavadinimas, kurį pasirinkote savo sąsajai -Name[lv]=Jauks nosaukums, ko jūs izvēlējāties savai saskarnei -Name[mai]=अहाँ अपन इंटरफेस क' लेल एकटा नीक नाम चुननै छी -Name[mk]=Убаво име што сте го избрале за вашиот интерфејс -Name[ml]=നിങ്ങളുടെ വിനിമയതലത്തിനു് നിങ്ങള്‍ തെരഞ്ഞെടുത്ത മനോഹരമായൊരു പേരു് -Name[mr]=तुम्ही संवादपट करिता एक चांगले नाव निवडले आहे -Name[ms]=Nama yang anda pilih untuk antara muka anda -Name[nb]=Et fint navn som du har valgt for grensesnittet -Name[nds]=En smucken Naam, de Du för Dien Koppelsteed utsöcht hest -Name[ne]=तपाईँले इन्टरफेसका लागि रोजेको नाम राम्रो छ -Name[nl]=Een naam die u hebt gekozen voor uw interface -Name[nn]=Eit fint namn du har valt for grensesnittet -Name[or]=ଆପଣ ଆପଣଙ୍କର ଅନ୍ତରାପୃଷ୍ଠ ପାଇଁ ପସନ୍ଦ କରିଥିବା ଗୋଟିଏ ସୁନ୍ଦର ନାମ -Name[pa]=ਆਪਣੇ ਇੰਟਰਫੇਸ ਲਈ ਸੋਹਣਾ ਨਾਂ ਚੁਣੋ -Name[pl]=Zgrabna nazwa, którą wybrano dla interfejsu -Name[pt]=Um nome bonito que escolheu para a sua interface -Name[pt_BR]=Um bom nome que você escolheu para a sua interface -Name[ro]=Un nume drăguț ales de dumneavoastră pentru interfață -Name[ru]=Имя, которое вы выбрали для своего интерфейса -Name[si]=ඔබේ අතුරුමුහුණතෙහි භාවිත වන නාමය. -Name[sk]=Pekný názov pre vaše rozhranie -Name[sl]=Lepo ime, ki ste ga izbrali za svoj vmesnik -Name[sr]=Лепо име које сте изабрали за своје сучеље -Name[sr@ijekavian]=Лијепо име које сте изабрали за своје сучеље -Name[sr@ijekavianlatin]=Lijepo ime koje ste izabrali za svoje sučelje -Name[sr@latin]=Lepo ime koje ste izabrali za svoje sučelje -Name[sv]=Ett bra namn som du har valt för gränssnittet -Name[ta]=உங்கள் இடைமுகத்துக்கு நல்ல பெயரை தேர்ந்தெடுத்துள்ளீர்கள் -Name[te]=మీ ఇంటర్‌ఫేస్ కొరకు ఒక మంచిపేరును మీరు ఎంచుకొనినారు -Name[th]=ชื่อดี ๆ ที่คุณเลือกสำหรับระบบติดต่อผู้ใช้ของคุณ -Name[tr]=Arayüzünüz için seçtiğiniz güzel isim -Name[ug]=ئارايۈزگە ئاتتىن بىرنى تاللاڭ -Name[uk]=Гарна назва, вибрана вами для вашого інтерфейсу -Name[uz]=Interfeysingiz uchun chiroyli nom -Name[uz@cyrillic]=Интерфейсингиз учун чиройли ном -Name[vi]=Một cái tên đẹp bạn đã chọn cho giao diện của mình -Name[wa]=On clapant no ki vos avoz tchoezi po voste eterface -Name[xh]=Igama elihle olikhetileyo kujongano lwakho -Name[x-test]=xxA nice name you have chosen for your interfacexx -Name[zh_CN]=您为界面选择的好名字 -Name[zh_TW]=您為您的界面選擇的好名字 -Comment=A helpful description of the interface for the top right info box -Comment[af]='n hulpvaardig beskrywing van die koppelvlak vir die bo regterkant inligting boks -Comment[be]=Карыснае апісанне інтэрфейсу для інфармацыйнай скрыні ў правым верхнім куце -Comment[be@latin]=Apisańnie dla vierchniaha pravaha pola źviestak -Comment[bg]=Описание на компонент -Comment[bn]=ইন্টারফেসটির সহজবোধ্য বর্ণনা, উপরে ডানদিকের ইনফো বক্স-এর জন্য -Comment[bn_IN]=উপরে ডিনদিকে অবস্থিত পরিচিত নির্দেশকারী বক্সে প্রদর্শনের উদ্দেশ্যে এই ইন্টারফেসের একটি সহায়ক বর্ণনা। -Comment[bs]=Opis sučelja za gornje desno informativno polje -Comment[ca]=Una descripció útil de la interfície per al rètol informatiu superior dret -Comment[ca@valencia]=Una descripció útil de la interfície per al rètol informatiu superior dret -Comment[cs]=Smysluplný popis vašeho rozhraní pro informační box -Comment[csb]=Pòmòcny òpisënk programë (dlô wëdowiédzë w oczénkù w prawim, górnym rogù) -Comment[cy]=Disgrifiad cymorthwyol o'r rhyngwyneb i'r blwch gwybodaeth top de -Comment[da]=En nyttig beskrivelse af grænsefladen for infofeltet øverst til højre -Comment[de]=Hilfreiche Beschreibung der Schnittstelle für das Infofeld rechts oben -Comment[el]=Μια χρήσιμη περιγραφή της διασύνδεσης για το πάνω δεξιά πλαίσιο πληροφοριών -Comment[en_GB]=A helpful description of the interface for the top right info box -Comment[eo]=Helpema priskribo de la interfaco por la supre-dekstra informkesto -Comment[es]=Una descripción útil de la interfaz para el cuadro de información superior derecho -Comment[et]=Abiks kirjeldus -Comment[eu]=Interfazearen deskribapen lagungarria, goian eskuinean azalduko den informazio-koadrorako -Comment[fa]=یک توصیف مفید واسط برای سمت راست بالای جعبه اطلاعات -Comment[fi]=Tässä pitäisi olla pieni kuvaus rajapinnasta oikean yläkulman laatikkoon -Comment[fr]=Une description utile de l'interface pour la boîte d'information située en haut à droite. -Comment[fy]=In helpzame omskriuwing fan de ynterface, Wat bedoelt is foar it ynformaasjefak rjochtboppe -Comment[ga]=Cur síos cabhrach ar chomhéadan an bhosca faisnéise ag an mbarr ar dheis -Comment[gl]=Unha descrición da interface para o botón de información de riba á dereita -Comment[gu]=જમણી બાજુનાં માહિતી ખાનાં માટે ઇન્ટરફેસનું મદદરૂપ વર્ણન -Comment[he]=תיאור שימושי של הממשק בשביל תיבת המידע המוצגת מצד שמאל למעלה -Comment[hi]=ऊपरी दाएँ कोने के जानकारी बाक्स के इंटरफेस का उपयोगी वर्णन. -Comment[hne]=ऊपर के जेवनी कोना के जानकारी डब्बा के इंटरफेस के उपयोगी वर्नन. -Comment[hr]=Koristan opis sučelja u info-okviru gore desno -Comment[hsb]=Spomožne wopisanje interfejsa za informaciski kašćik horjeka naprawo. -Comment[hu]=A felület leírása a jobb felső sarokban található tájékoztató ablakhoz -Comment[ia]=Un description utile del interface pro le cassa de info in alto a dextera -Comment[id]=Deskripsi yang berguna tentang antarmuka untuk kotak info di kanan atas -Comment[is]=Jamm, hér ætti að vera smá lýsing á viðbótinni -Comment[it]=Un'utile descrizione dell'interfaccia per la casella delle informazioni in alto a destra -Comment[ja]=右上の情報ボックスのためのインターフェースに関する説明 -Comment[kk]=Жоғары оң жақтағы мәлімет терезесі үшін интерфейстің сипаттамасы -Comment[km]=សេចក្ដី​ពិពណ៌នា​ដ៏​មាន​ប្រយោជន៍​របស់​ចំណុច​ប្រទាក់​សម្រាប់​ប្រអប់​ព័ត៌មាន​ខាង​ស្ដាំ​កំពូល -Comment[kn]=ಮೇಲ್ಬಲಭಾಗದ ಮಾಹಿತಿ ಚೌಕದ ಸಂಪರ್ಕತಟದ (ಇಂಟರ್ಫೇಸ್) ಬಗೆಗಿನ ಒಂದು ಉಪಯುಕ್ತ ವಿವರಣೆ -Comment[ko]=오른쪽 위 정보 상자 인터페이스 설명 -Comment[ku]=Ravekirineke alîker ji bo agahiya qutîka jor-rastê a navrûyê -Comment[lt]=Naudingas sąsajos aprašas, skirtas viršutinei dešinei informacijos langelio daliai -Comment[lv]=Noderīgs saskarnes apraksts augšējai labajai informācijas rūtij -Comment[mai]=ऊपरका दहिन्ना कोना केर सूचना बाक्स केर इंटरफेस क' उपयोगी वर्णन. -Comment[mk]=Опис со објаснување за интерфејсот за горното десно поле за инфо. -Comment[ml]=വലത്തു് മുകളിലായുള്ള വിവരം നല്‍കുന്ന കളത്തില്‍ കാണിയ്ക്കാനായി നിങ്ങളുടെ വിനിമയതലത്തിനുള്ള സഹായകരമായ ഒരു വിവരണം. -Comment[mr]=वरील उजव्या कोपऱ्या वरील माहिती बॉक्स संवादपट करिता उपयोगी वर्णन -Comment[ms]=Huraian antara muka yang sangat membantu untuk kotak maklumat kanan atas -Comment[nb]=Beskrivelse av grensesnittet for infoboksen øverst til høyre -Comment[nds]=En hölpsche Beschrieven vun de Koppelsteed för den Info-Kasten rechterhand baven -Comment[ne]=माथिको दायाँ सूचना बाकसका लागि इन्टरफेसको उपयोगी वर्णन -Comment[nl]=Een behulpzame omschrijving van de interface, bedoelt voor het informatievak rechts boven -Comment[nn]=Ei hjelpsam skildring av grensesnittet for infoboksen oppe til høgre -Comment[or]=ଡ଼ାହାଣ ପାଖ ଉପର ଅଂଶ ସୂଚନା ବାକ୍ସ ପାଇଁ ଅନ୍ତରାପୃଷ୍ଠର ଗୋଟିଏ ସହାୟକ ବର୍ଣ୍ଣନା -Comment[pa]=ਸੱਜੇ ਜਾਣਕਾਰੀ ਬਕਸੇ ਲਈ ਇੰਟਰਫੇਸ ਲ਼ਈ ਮਦਦ ਵੇਰਵਾ -Comment[pl]=Pomocny opis programu (dla informacji w okienku w prawym, górnym rogu) -Comment[pt]=Uma descrição útil da interface para a zona de informação do canto superior direito -Comment[pt_BR]=Uma descrição útil da interface para a caixa de informação superior direita -Comment[ro]=Aici trebuie să fie descrierea interfeței pentru căsuța din dreapta-sus -Comment[ru]=Полезное описание интерфейса в верхнем правом информационном окне -Comment[si]=ඉහළ දකුණු තොරතුරු කොටුවේ ප්‍රයෝජනවත් විස්තර -Comment[sk]=Pomocný popis rozhrania pre informačný box v pravom hornom rohu -Comment[sl]=Primeren opis vmesnika za gornjo desno okno s podrobnostmi -Comment[sr]=Опис сучеља за горње десно информативно поље -Comment[sr@ijekavian]=Опис сучеља за горње десно информативно поље -Comment[sr@ijekavianlatin]=Opis sučelja za gornje desno informativno polje -Comment[sr@latin]=Opis sučelja za gornje desno informativno polje -Comment[sv]=Hjälpsam beskrivning av gränssnittet för informationsrutan uppe till höger -Comment[ta]=மேல் வலது தகவல் பெட்டிக்கான பயனுள்ள விவர இடைமுகம் -Comment[te]=పైన కుడప్రక్కనగల సమాచార పెట్టె ఇంటర్‌పేస్ యొక్క సహాయకర వివరణ -Comment[th]=คำอธิบายเกี่ยวกับรูปแบบส่วนติดต่อสำหรับกล่องข้อมูลด้านขวาบน -Comment[tr]=Sağ üst bilgi kutucuğu için arayüzün açıklayıcı tanımı -Comment[ug]=ئوڭ ئۈستى ئۇچۇر قۇتىسىدا كۆرۈنىدىغان ئارايۈز ياردەم چۈشەندۈرۈشى -Comment[uk]=Допоміжний опис інтерфейсу для віконця інформації вгорі праворуч -Comment[vi]=Một mô tả giao diện có ích cho hộp thông tin ở trên cùng bên phải -Comment[wa]=Èn ahessåve discrijhaedje di l' eterface, pol boesse d' infôrmåcion del coine å dzeu a droete -Comment[xh]=Uchazo oluluncedo lojongano olungaphezulu ekunene kwebhokisi yolwazi -Comment[x-test]=xxA helpful description of the interface for the top right info boxxx -Comment[zh_CN]=右上方信息框中显示的界面描述 -Comment[zh_TW]=用於右上方資訊方塊界面的有用敘述 - -configurationType=Possible values are component and application. Only component is handled at the moment though -ServiceTypeToConfigure=The service type, which should be configured. If this line is empty you have to provide a plugin (not supported yet) -defaultImplementation=The name of the default implementation as it would be returned by KService::desktopEntryName() -storeInFile=default_components //the file where the setting should be saved (default_components sounds reasonable for a central storage) -valueSection=The desktop section, where the setting should be stored -valueName=the name of the value entry diff --git a/kcms/componentchooser/browser_settings.kcfg b/kcms/componentchooser/browser_settings.kcfg new file mode 100644 --- /dev/null +++ b/kcms/componentchooser/browser_settings.kcfg @@ -0,0 +1,13 @@ + + + + + + + + + + diff --git a/kcms/cursortheme/cursorthemesettings.kcfgc b/kcms/componentchooser/browser_settings.kcfgc copy from kcms/cursortheme/cursorthemesettings.kcfgc copy to kcms/componentchooser/browser_settings.kcfgc --- a/kcms/cursortheme/cursorthemesettings.kcfgc +++ b/kcms/componentchooser/browser_settings.kcfgc @@ -1,5 +1,5 @@ -File=cursorthemesettings.kcfg -ClassName=CursorThemeSettings +File=browser_settings.kcfg +ClassName=BrowserSettings Mutators=true DefaultValueGetters=true GenerateProperties=true diff --git a/kcms/componentchooser/componentchooser.h b/kcms/componentchooser/componentchooser.h --- a/kcms/componentchooser/componentchooser.h +++ b/kcms/componentchooser/componentchooser.h @@ -39,6 +39,7 @@ virtual void load(KConfig *cfg)=0; virtual void save(KConfig *cfg)=0; virtual void defaults()=0; + virtual bool isDefaults() const=0; }; class CfgComponent: public QWidget, public Ui::ComponentConfig_UI, public CfgPlugin @@ -50,14 +51,16 @@ void load(KConfig *cfg) override; void save(KConfig *cfg) override; void defaults() override; + bool isDefaults() const override; protected: QHash m_lookupDict,m_revLookupDict; protected Q_SLOTS: void slotComponentChanged(const QString&); Q_SIGNALS: void changed(bool); + void defaulted(bool); }; class ComponentChooser : public QWidget, public Ui::ComponentChooser_UI @@ -87,6 +90,7 @@ Q_SIGNALS: void changed(bool); + void defaulted(bool); }; diff --git a/kcms/componentchooser/componentchooser.cpp b/kcms/componentchooser/componentchooser.cpp --- a/kcms/componentchooser/componentchooser.cpp +++ b/kcms/componentchooser/componentchooser.cpp @@ -8,7 +8,7 @@ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License verstion 2 as * + * it under the terms of the GNU General Public License version 2 as * * published by the Free Software Foundation * * * ***************************************************************************/ @@ -80,10 +80,10 @@ const KService::List offers = KServiceTypeTrader::self()->query(serviceTypeToConfigure); - for (KService::List::const_iterator tit = offers.begin(); tit != offers.end(); ++tit) { - ComponentSelector->addItem((*tit)->name()); - m_lookupDict.insert((*tit)->name(), (*tit)->desktopEntryName()); - m_revLookupDict.insert((*tit)->desktopEntryName(), (*tit)->name()); + for (const auto &service: offers) { + ComponentSelector->addItem(service->name()); + m_lookupDict.insert(service->name(), service->desktopEntryName()); + m_revLookupDict.insert(service->desktopEntryName(), service->name()); } KConfig store(mainGroup.readPathEntry("storeInFile",QStringLiteral("null"))); @@ -109,6 +109,11 @@ //todo } +bool CfgComponent::isDefaults() const +{ + return false; +} + //END General kpart based Component selection @@ -122,18 +127,25 @@ setupUi(this); static_cast(layout())->setRowStretch(1, 1); - const QStringList services=KGlobal::dirs()->findAllResources( "data",QStringLiteral("kcm_componentchooser/*.desktop"), - KStandardDirs::NoDuplicates); - for (QStringList::const_iterator it=services.constBegin(); it!=services.constEnd(); ++it) + const QStringList directories = QStandardPaths::locateAll(QStandardPaths::GenericDataLocation, QStringLiteral("kcm_componentchooser"), QStandardPaths::LocateDirectory); + QStringList services; + for(const QString &directory : directories) { + const QDir dir(directory); + for(const QString &f: dir.entryList(QStringList("*.desktop"))) { + services += dir.absoluteFilePath(f); + } + } + + for (const QString &service : qAsConst(services)) { - KConfig cfg(*it, KConfig::SimpleConfig); + KConfig cfg(service, KConfig::SimpleConfig); KConfigGroup cg = cfg.group(QByteArray()); QListWidgetItem *item = new QListWidgetItem( QIcon::fromTheme(cg.readEntry("Icon",QStringLiteral("preferences-desktop-default-applications"))), cg.readEntry("Name",i18n("Unknown"))); - item->setData(Qt::UserRole, (*it)); + item->setData(Qt::UserRole, service); ServiceChooser->addItem(item); - loadConfigWidget((*it), cfg.group(QByteArray()).readEntry("configurationType"), item->text()); + loadConfigWidget(service, cfg.group(QByteArray()).readEntry("configurationType"), item->text()); } ServiceChooser->setFixedWidth(ServiceChooser->sizeHintForColumn(0) + 20); ServiceChooser->sortItems(); @@ -189,8 +201,10 @@ configWidget = configWidgetMap.value(service); if (configWidget) { - configContainer->setCurrentWidget(configWidget); - dynamic_cast(configWidget)->load(&cfg); + configContainer->setCurrentWidget(configWidget); + const auto plugin = dynamic_cast(configWidget); + plugin->load(&cfg); + emit defaulted(plugin->isDefaults()); } emitChanged(false); @@ -201,6 +215,9 @@ void ComponentChooser::emitChanged(bool val) { somethingChanged=val; emit changed(val); + + CfgPlugin *plugin = dynamic_cast( configWidget ); + emit defaulted(plugin->isDefaults()); } diff --git a/kcms/componentchooser/componentchooser.desktop b/kcms/componentchooser/componentchooser.desktop --- a/kcms/componentchooser/componentchooser.desktop +++ b/kcms/componentchooser/componentchooser.desktop @@ -21,7 +21,7 @@ Name[bn]=ডিফল্ট অ্যাপলিকেশন Name[bn_IN]=ডিফল্ট অ্যাপ্লিকেশন Name[bs]=Podrazumijevani programi -Name[ca]=Aplicacions per omissió +Name[ca]=Aplicacions predeterminades Name[ca@valencia]=Aplicacions per omissió Name[cs]=Výchozí aplikace Name[csb]=Domëslné programë @@ -100,7 +100,7 @@ Comment[ar]=التّطبيقات الافتراضيّة Comment[ast]=Aplicaciones predeterminaes Comment[bs]=Podrazumijevani programi -Comment[ca]=Aplicacions per omissió +Comment[ca]=Aplicacions predeterminades Comment[ca@valencia]=Aplicacions per omissió Comment[cs]=Výchozí aplikace Comment[da]=Standardprogrammer @@ -151,7 +151,7 @@ X-KDE-Keywords[bg]=default applications,components,component chooser,resources,e-mail,email client,text editor,instant messenger,terminal emulator,web browser,URL,hyperlinks,програми по подразбиране,подразбиране,е-поща,съобщения,моментни съобщения,терминал, конзола,браузър,уеб-браузър X-KDE-Keywords[bn]=default applications,components,component chooser,resources,e-mail,email client,text editor,instant messenger,terminal emulator,web browser,URL,hyperlinks X-KDE-Keywords[bs]=default applications,components,component chooser,resources,e-mail,email client,text editor,instant messenger,terminal emulator,web browser,URL,hyperlinks, podrazumijevani programi, komponente, izbor komponenti, resursi, elektronska pošta, instant poruke -X-KDE-Keywords[ca]=aplicacions per omissió,components,selector de components,recursos,e-mail,client de correu electrònic,editor de text,missatgeria instantània,emulador de terminal,navegador web,URL,hiperenllaços +X-KDE-Keywords[ca]=aplicacions predeterminades,components,selector de components,recursos,e-mail,client de correu electrònic,editor de text,missatgeria instantània,emulador de terminal,navegador web,URL,hiperenllaços X-KDE-Keywords[ca@valencia]=aplicacions per omissió,components,selector de components,recursos,e-mail,client de correu electrònic,editor de text,missatgeria instantània,emulador de terminal,navegador web,URL,hiperenllaços X-KDE-Keywords[cs]=výchozí aplikace,komponenty,výběr komponent,zdroje,e-mail,emailový klient,editor textu,komunikátor,emulátor terminálů,webový prohlížeč,URL,odkazy X-KDE-Keywords[da]=standardprogrammer,komponenter,komponentvælger,ressourcer,e-mail,email klient,teksteditor,instant messenger,terminalemulator,webbrowser,URL,hyperlinks diff --git a/kcms/componentchooser/componentchooserbrowser.h b/kcms/componentchooser/componentchooserbrowser.h --- a/kcms/componentchooser/componentchooserbrowser.h +++ b/kcms/componentchooser/componentchooserbrowser.h @@ -28,6 +28,7 @@ void load(KConfig *cfg) override; void save(KConfig *cfg) override; void defaults() override; + bool isDefaults() const override; protected Q_SLOTS: void selectBrowser(); diff --git a/kcms/componentchooser/componentchooserbrowser.cpp b/kcms/componentchooser/componentchooserbrowser.cpp --- a/kcms/componentchooser/componentchooserbrowser.cpp +++ b/kcms/componentchooser/componentchooserbrowser.cpp @@ -15,14 +15,12 @@ #include "componentchooserbrowser.h" #include -#include +#include "browser_settings.h" #include #include #include -#include "../migrationlib/kdelibs4config.h" - #include #include #include @@ -52,18 +50,38 @@ void CfgBrowser::configChanged() { - emit changed(true); + bool hasChanged = false; + const BrowserSettings settings; + const QString exec = settings.browserApplication(); + + if (exec.isEmpty()) { + hasChanged |= !radioKIO->isChecked(); + } else { + if (exec.startsWith('!')) { + hasChanged |= lineExec->text() != exec; + } else { + hasChanged |= KService::serviceByStorageId(lineExec->text()) != KService::serviceByStorageId( exec ); + } + } + + emit changed(hasChanged); } void CfgBrowser::defaults() { - load(nullptr); + emit changed(!radioKIO->isChecked()); + radioKIO->setChecked(true); +} + +bool CfgBrowser::isDefaults() const +{ + return radioKIO->isChecked(); } void CfgBrowser::load(KConfig *) { - const KConfigGroup config(KSharedConfig::openConfig(QStringLiteral("kdeglobals")), QStringLiteral("General") ); - const QString exec = config.readPathEntry( QStringLiteral("BrowserApplication"), QString() ); + const BrowserSettings settings; + const QString exec = settings.browserApplication(); if (exec.isEmpty()) { radioKIO->setChecked(true); m_browserExec = exec; @@ -87,8 +105,9 @@ browserCombo->clear(); - const auto &browsers = KServiceTypeTrader::self()->query(QStringLiteral("Application"), - QStringLiteral("'WebBrowser' in Categories")); + const auto constraint = QStringLiteral("'WebBrowser' in Categories and" + " ('x-scheme-handler/http' in ServiceTypes or 'x-scheme-handler/https' in ServiceTypes)"); + const auto browsers = KServiceTypeTrader::self()->query(QStringLiteral("Application"), constraint); for (const auto &service : browsers) { browserCombo->addItem(QIcon::fromTheme(service->icon()), service->name(), service->storageId()); @@ -103,8 +122,7 @@ void CfgBrowser::save(KConfig *) { - KSharedConfig::Ptr profile = KSharedConfig::openConfig(QStringLiteral("kdeglobals")); - KConfigGroup config(profile, QStringLiteral("General")); + BrowserSettings settings; QString exec; if (radioService->isChecked()) { if (m_browserService) { @@ -118,8 +136,8 @@ exec = '!' + exec; // Literal command } } - config.writePathEntry( QStringLiteral("BrowserApplication"), exec); // KConfig::Normal|KConfig::Global - config.sync(); + settings.setBrowserApplication(exec); + settings.save(); // Save the default browser as scheme handler for http(s) in mimeapps.list KSharedConfig::Ptr mimeAppList = KSharedConfig::openConfig(QStringLiteral("mimeapps.list"), KConfig::NoGlobals, QStandardPaths::GenericConfigLocation); @@ -138,8 +156,6 @@ KBuildSycocaProgressDialog::rebuildKSycoca(this); } - Kdelibs4SharedConfig::syncConfigGroup(QLatin1String("General"), "kdeglobals"); - QDBusMessage message = QDBusMessage::createMethodCall(QStringLiteral("org.kde.klauncher5"), QStringLiteral("/KLauncher"), QStringLiteral("org.kde.KLauncher"), diff --git a/kcms/componentchooser/componentchooseremail.h b/kcms/componentchooser/componentchooseremail.h --- a/kcms/componentchooser/componentchooseremail.h +++ b/kcms/componentchooser/componentchooseremail.h @@ -30,6 +30,7 @@ void load(KConfig *cfg) override; void save(KConfig *cfg) override; void defaults() override; + bool isDefaults() const override; private: KEMailSettings *pSettings; diff --git a/kcms/componentchooser/componentchooseremail.cpp b/kcms/componentchooser/componentchooseremail.cpp --- a/kcms/componentchooser/componentchooseremail.cpp +++ b/kcms/componentchooser/componentchooseremail.cpp @@ -8,7 +8,7 @@ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License verstion 2 as * + * it under the terms of the GNU General Public License version 2 as * * published by the Free Software Foundation * * * ***************************************************************************/ @@ -57,7 +57,14 @@ void CfgEmailClient::defaults() { - load(nullptr); + kmailCB->setChecked(true); + txtEMailClient->clear(); + chkRunTerminal->setChecked(false); +} + +bool CfgEmailClient::isDefaults() const +{ + return kmailCB->isChecked(); } void CfgEmailClient::load(KConfig *) diff --git a/kcms/componentchooser/componentchooserfilemanager.h b/kcms/componentchooser/componentchooserfilemanager.h --- a/kcms/componentchooser/componentchooserfilemanager.h +++ b/kcms/componentchooser/componentchooserfilemanager.h @@ -33,6 +33,7 @@ void load(KConfig *cfg) override; void save(KConfig *cfg) override; void defaults() override; + bool isDefaults() const override; protected Q_SLOTS: void slotAddFileManager(); @@ -42,7 +43,7 @@ void changed(bool); private: - QList mDynamicWidgets; + QList mDynamicRadioButtons; }; #endif diff --git a/kcms/componentchooser/componentchooserfilemanager.cpp b/kcms/componentchooser/componentchooserfilemanager.cpp --- a/kcms/componentchooser/componentchooserfilemanager.cpp +++ b/kcms/componentchooser/componentchooserfilemanager.cpp @@ -20,15 +20,27 @@ #include "componentchooserfilemanager.h" #include -#include #include #include #include #include #include -#include +#include -#include "../migrationlib/kdelibs4config.h" +namespace { + +QRadioButton *findDolphinRadio(const QList &radioButtons) +{ + auto it = std::find_if(radioButtons.begin(), radioButtons.end(), [=](QRadioButton *radio) { + return radio->property("storageId") == QStringLiteral("org.kde.dolphin.desktop"); + }); + if (it == radioButtons.end()) { + return nullptr; + } + return *it; +} + +} CfgFileManager::CfgFileManager(QWidget *parent) : QWidget(parent), Ui::FileManagerConfig_UI(),CfgPlugin() @@ -48,48 +60,57 @@ void CfgFileManager::defaults() { load(nullptr); + + const auto radio = ::findDolphinRadio(mDynamicRadioButtons); + if (radio) { + radio->setChecked(true); + } +} + +bool CfgFileManager::isDefaults() const +{ + const auto dolphinRadio = ::findDolphinRadio(mDynamicRadioButtons); + // When dolphin is not present, we can't assume any default value + return !dolphinRadio || dolphinRadio->isChecked(); } static KService::List appOffers() { return KMimeTypeTrader::self()->query(QStringLiteral("inode/directory"), QStringLiteral("Application")); } void CfgFileManager::load(KConfig *) { - qDeleteAll(mDynamicWidgets); - mDynamicWidgets.clear(); + qDeleteAll(mDynamicRadioButtons); + mDynamicRadioButtons.clear(); const KService::List apps = appOffers(); bool first = true; - Q_FOREACH(const KService::Ptr& service, apps) - { - QRadioButton* button = new QRadioButton(service->name(), this); + for (const KService::Ptr &service : apps) { + QRadioButton *button = new QRadioButton(service->name(), this); connect(button, &QRadioButton::toggled, this, &CfgFileManager::configChanged); button->setProperty("storageId", service->storageId()); radioLayout->addWidget(button); if (first) { button->setChecked(true); first = false; } - mDynamicWidgets << button; + mDynamicRadioButtons << button; } emit changed(false); } static const char s_DefaultApplications[] = "Default Applications"; static const char s_AddedAssociations[] = "Added Associations"; -static const char s_RemovedAssociations[] = "Removed Associations"; void CfgFileManager::save(KConfig *) { QString storageId; - Q_FOREACH(QRadioButton* button, qFindChildren(this)) { + for (QRadioButton *button : qAsConst(mDynamicRadioButtons)) { if (button->isChecked()) { storageId = button->property("storageId").toString(); } } - qDebug() << storageId; if (!storageId.isEmpty()) { // This is taken from filetypes/mimetypedata.cpp KSharedConfig::Ptr profile = KSharedConfig::openConfig(QStringLiteral("mimeapps.list"), KConfig::NoGlobals, QStandardPaths::GenericConfigLocation); @@ -106,25 +127,8 @@ KConfigGroup defaultApp(profile, s_DefaultApplications); defaultApp.writeXdgListEntry(mime, QStringList(storageId)); - Kdelibs4SharedConfig::syncConfigGroup(QLatin1String("Added Associations"), QStringLiteral("mimeapps.list")); - profile->sync(); - // Clean out any kde-mimeapps.list which would take precedence any cancel our changes. - // (also taken from filetypes/mimetypedata.cpp) - const QString desktops = QString::fromLocal8Bit(qgetenv("XDG_CURRENT_DESKTOP")); - foreach (const QString &desktop, desktops.split(":", QString::SkipEmptyParts)) { - const QString file = QStandardPaths::writableLocation(QStandardPaths::GenericConfigLocation) - + QLatin1Char('/') + desktop.toLower() + QLatin1String("-mimeapps.list"); - if (QFileInfo::exists(file)) { - qDebug() << "Cleaning up" << file; - KConfig conf(file, KConfig::NoGlobals); - KConfigGroup(&conf, s_DefaultApplications).deleteEntry(mime); - KConfigGroup(&conf, s_AddedAssociations).deleteEntry(mime); - KConfigGroup(&conf, s_RemovedAssociations).deleteEntry(mime); - } - } - KBuildSycocaProgressDialog::rebuildKSycoca(this); } diff --git a/kcms/componentchooser/componentchooserterminal.h b/kcms/componentchooser/componentchooserterminal.h --- a/kcms/componentchooser/componentchooserterminal.h +++ b/kcms/componentchooser/componentchooserterminal.h @@ -30,6 +30,7 @@ void load(KConfig *cfg) override; void save(KConfig *cfg) override; void defaults() override; + bool isDefaults() const override; protected Q_SLOTS: void selectTerminalApp(); diff --git a/kcms/componentchooser/componentchooserterminal.cpp b/kcms/componentchooser/componentchooserterminal.cpp --- a/kcms/componentchooser/componentchooserterminal.cpp +++ b/kcms/componentchooser/componentchooserterminal.cpp @@ -8,12 +8,13 @@ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License verstion 2 as * + * it under the terms of the GNU General Public License version 2 as * * published by the Free Software Foundation * * * ***************************************************************************/ #include "componentchooserterminal.h" +#include "terminal_settings.h" #include #include @@ -31,8 +32,6 @@ #include -#include "../migrationlib/kdelibs4config.h" - CfgTerminalEmulator::CfgTerminalEmulator(QWidget *parent) : QWidget(parent), Ui::TerminalEmulatorConfig_UI(), CfgPlugin() { @@ -55,12 +54,19 @@ void CfgTerminalEmulator::defaults() { load(nullptr); + terminalCB->setChecked(true); } +bool CfgTerminalEmulator::isDefaults() const +{ + return terminalCB->isChecked(); +} -void CfgTerminalEmulator::load(KConfig *) { - KConfigGroup config(KSharedConfig::openConfig(QStringLiteral("kdeglobals")), "General"); - QString terminal = config.readPathEntry("TerminalApplication",QStringLiteral("konsole")); + +void CfgTerminalEmulator::load(KConfig *) +{ + TerminalSettings settings; + QString terminal = settings.terminalApplication(); if (terminal == QLatin1String("konsole")) { terminalLE->setText(QStringLiteral("xterm")); @@ -77,19 +83,15 @@ void CfgTerminalEmulator::save(KConfig *) { - KSharedConfig::Ptr profile = KSharedConfig::openConfig(QStringLiteral("kdeglobals")); - KConfigGroup config(profile, QStringLiteral("General")); - const QString terminal = terminalCB->isChecked() ? QStringLiteral("konsole") : terminalLE->text(); - config.writePathEntry("TerminalApplication", terminal); // KConfig::Normal|KConfig::Global); - - config.sync(); - Kdelibs4SharedConfig::syncConfigGroup(QLatin1String("General"), "kdeglobals"); - - QDBusMessage message = QDBusMessage::createMethodCall(QStringLiteral("org.kde.klauncher5"), - QStringLiteral("/KLauncher"), - QStringLiteral("org.kde.KLauncher"), - QStringLiteral("reparseConfiguration")); - QDBusConnection::sessionBus().send(message); + TerminalSettings settings; + settings.setTerminalApplication(terminalCB->isChecked() ? settings.defaultTerminalApplicationValue() : terminalLE->text()); + settings.save(); + + QDBusMessage message = QDBusMessage::createMethodCall(QStringLiteral("org.kde.klauncher5"), + QStringLiteral("/KLauncher"), + QStringLiteral("org.kde.KLauncher"), + QStringLiteral("reparseConfiguration")); + QDBusConnection::sessionBus().send(message); emit changed(false); } diff --git a/kcms/componentchooser/componentservices/kcm_browser.desktop b/kcms/componentchooser/componentservices/kcm_browser.desktop --- a/kcms/componentchooser/componentservices/kcm_browser.desktop +++ b/kcms/componentchooser/componentservices/kcm_browser.desktop @@ -81,7 +81,7 @@ Comment[bg]=Избор на предпочитан браузър. Всички програми от KDE, които се нуждаят от достъп до уеб страници, ще ползват този компонент. Comment[bn]=এখানে আপনি আপনার ডিফল্ট ওয়েব ব্রাউজার কনফিগার করতে পারেন। যে কোনো কে.ডি.ই. অ্যাপলিকেশনে একটি হাইপার-লিঙ্ক নির্বাচন করা হলে এই পছন্দটি ব্যবহার করা হবে। Comment[bs]=Ovdje podešavate podrazumijevani veb pregledač. Svi KDE programi u kojima možete kliktati na hiperveze treba da poštuju ovu postavku. -Comment[ca]=Aquí podeu configurar el vostre navegador web per omissió. Totes les aplicacions KDE on podeu seleccionar hiperenllaços haurien de respectar aquest arranjament. +Comment[ca]=Aquí podreu configurar el navegador web predeterminat. Totes les aplicacions KDE on es poden seleccionar hiperenllaços haurien de respectar aquesta opció. Comment[ca@valencia]=Ací podeu configurar el vostre navegador web per omissió. Totes les aplicacions KDE on podeu seleccionar hiperenllaços haurien de respectar aquest arranjament. Comment[cs]=Tato služba umožňuje nastavit si výchozí prohlížeč. Všechny KDE aplikace, které vyžadují přístup k hypertextovým odkazům, by měly používat toto nastavení. Comment[csb]=Tuwò mòżne wëbrac domëslny przezérnik. Wszëtczé programë KDE, w jaczich brëkùje sã z lënkòw, mùszôłëbë ùżëwac tegò ùstôwù. diff --git a/kcms/componentchooser/componentservices/kcm_filemanager.desktop b/kcms/componentchooser/componentservices/kcm_filemanager.desktop --- a/kcms/componentchooser/componentservices/kcm_filemanager.desktop +++ b/kcms/componentchooser/componentservices/kcm_filemanager.desktop @@ -57,7 +57,7 @@ Comment[bg]=Избор на предпочитан файлов мениджър. Отварянето на директориите ще става с него. Comment[bn]=এখানে আপনি আপনার ডিফল্ট ফাইল ম্যানেজার কনফিগার করতে পারেন। যে কোনো কে.ডি.ই. অ্যাপলিকেশন থেকে কোন ফোল্ডার খোলা হলে এই ফাইল ম্যানেজার-টি ব্যবহার করা হবে। Comment[bs]=Ovdje podešavate podrazumijevani menadžer datoteka. Koristiće ga stavke u K‑meniju i svi KDE programi u kojima možete otvarati fascikle. -Comment[ca]=Aquí podeu configurar el gestor de fitxers per omissió. Les entrades del menú K i totes les aplicacions del KDE on podeu obrir carpetes usaran aquest gestor de fitxers. +Comment[ca]=Aquí podreu configurar el gestor de fitxers predeterminat. Les entrades del menú K i totes les aplicacions del KDE on es poden obrir carpetes usaran aquest gestor de fitxers. Comment[ca@valencia]=Ací podeu configurar el gestor de fitxers per omissió. Les entrades del menú K i totes les aplicacions del KDE on podeu obrir carpetes usaran aquest gestor de fitxers. Comment[cs]=Na tomto místě si můžete nastavit výchozího správce souborů. Položky v hlavní nabídce K a všechny aplikace, ve kterých lze otevřít složky, budou tohoto správce používat. Comment[csb]=Tuwò mòżne wëbrac domëslnegò menadżera lopków. Wpisënczi w K menu ë wszëtczé programë KDE, w jaczich mòżesz òtmëkac katalodżi, bãdą ùżëwac tegò menadżera. diff --git a/kcms/componentchooser/componentservices/kcm_kemail.desktop b/kcms/componentchooser/componentservices/kcm_kemail.desktop --- a/kcms/componentchooser/componentservices/kcm_kemail.desktop +++ b/kcms/componentchooser/componentservices/kcm_kemail.desktop @@ -72,16 +72,16 @@ Name[wa]=Cliyint d' emilaedje Name[x-test]=xxEmail Clientxx Name[zh_CN]=电子邮件客户端程序 -Name[zh_TW]=電子郵件客戶端程式 +Name[zh_TW]=電子郵件用戶端程式 Comment=This service allows you to configure your default email client. All KDE applications which need access to an email client application should honor this setting. Comment[af]=Hierdie diens laat jou toe om jou standaard e-pos kliënt op te stel. Al die KDE programme wat toegang tot 'n e-pos kliënt benodig behoort hierdie instelling te gebruik. Comment[ar]=تسمح لك هذه الخدمة بضبط عميل البريد الإلكترونيّ الافتراضيّ. على كلّ تطبيقات كدي التي تحتاج إلى النّفاذ إلى تطبيق عميل بريد الإلكترونيّ احترام هذا الإعداد. Comment[be]=Гэты сервіс дазваляе вызначыць для сябе стандартны кліент электроннай пошты. Усе праграмы KDE, у якіх вы можаце выбраць гіперспасылку, павінны выкарыстоўваць гэтае настаўленне. Comment[be@latin]=Hetaja słužba dazvalaje vybrać sabie zmoŭčany paštar. Usie aplikacyi KDE, jakija karystajucca paštarom, pavinnyja źviartać uvahu na hetuju naładu. Comment[bg]=Избор на предпочитана програма за поща. Всички програми от KDE, които се нуждаят от достъп до електронната поща, ще ползват този компонент. Comment[bn]=এই সার্ভিসটির সাহায্যে আপনার ডিফল্ট ই-মেইল ক্লায়েন্ট কনফিগার করতে পারেন। যে কোনো কে.ডি.ই. অ্যাপলিকেশনের ই-মেইল ক্লায়েন্ট প্রয়োজন হলে এই নির্বাচন মানা উচিত। Comment[bs]=Ovaj servis omogućava da podesite podrazumijevani klijent e‑pošte. Svi KDE programi koji traže pristup e‑pošti treba da poštuju ovu postavku. -Comment[ca]=Aquest servei us permet configurar el vostre client de correu per omissió. Totes les aplicacions KDE que requereixin accés a una aplicació de client de correu hauria de reconèixer aquesta opció. +Comment[ca]=Aquest servei permet configurar el vostre client de correu predeterminat. Totes les aplicacions KDE que requereixin accés a una aplicació de client de correu haurien de reconèixer aquesta opció. Comment[ca@valencia]=Aquest servei vos permet configurar el vostre client de correu per omissió. Totes les aplicacions KDE que requerisquen accés a una aplicació de client de correu hauria de reconèixer aquesta opció. Comment[cs]=Tato služba umožňuje nastavit si výchozího klienta emailu. Všechny KDE aplikace, které vyžadují přístup k e-mailové aplikaci, by měly používat toto nastavení. Comment[csb]=Tuwò mòżne wëbrac domëslną pòcztową programã. Wszëtczé programë KDE, w jaczich brëkùje sã z lënkòw, mùszôłëbë ùżëwac tegò ùstôwù. @@ -157,5 +157,5 @@ Comment[xh]=Lenkonzo ikuvumela ukuba uqwalasele umxhasi wakho we email. Zonke izicelo ezidinga unikezelo kumxhasi we email wesicelo kufuneka yamkele esisicelo. Comment[x-test]=xxThis service allows you to configure your default email client. All KDE applications which need access to an email client application should honor this setting.xx Comment[zh_CN]=此服务允许您配置您的默认电子邮件客户端程序。所有需要访问电子邮件客户端程序的 KDE 应用程序都遵从此设置。 -Comment[zh_TW]=這個服務允許您設定您的預設電子郵件客戶端程式。所有需要使用電子郵件客戶端應用程式的 KDE 應用程式都應該遵從這個設定。 +Comment[zh_TW]=這個服務允許您設定您的預設電子郵件用戶端程式。所有需要使用電子郵件用戶端應用程式的 KDE 應用程式都應該遵從這個設定。 configurationType=internal_email diff --git a/kcms/componentchooser/componentservices/kcm_terminal.desktop b/kcms/componentchooser/componentservices/kcm_terminal.desktop --- a/kcms/componentchooser/componentservices/kcm_terminal.desktop +++ b/kcms/componentchooser/componentservices/kcm_terminal.desktop @@ -81,7 +81,7 @@ Comment[bg]=Избор на предпочитана конзолна програма. Всички програми от KDE, които се нуждаят от достъп до конзолата, ще ползват този компонент. Comment[bn]=এই সার্ভিসটির সাহায্যে আপনার ডিফল্ট টার্মিনাল এমুলেটর কনফিগার করতে পারেন। যে কোনো কে.ডি.ই. অ্যাপলিকেশনের টার্মিনাল এমুলেটর চালানোর প্রয়োজন হলে এই নির্বাচন মানা উচিত। Comment[bs]=Ovaj servis omogućava da podesite podrazumijevani emulator terminala. Svi KDE programi koji pozivaju terminal treba da poštuju ovu postavku. -Comment[ca]=Aquest servei us permet configurar el vostre emulador de terminal per omissió. Totes les aplicacions KDE que requereixin accés a una aplicació de client de correu hauria de reconèixer aquesta opció. +Comment[ca]=Aquest servei permet configurar el vostre emulador de terminal predeterminat. Totes les aplicacions KDE que requereixin accés a una aplicació de client de correu haurien de reconèixer aquesta opció. Comment[ca@valencia]=Aquest servei vos permet configurar el vostre emulador de terminal per omissió. Totes les aplicacions KDE que requerisquen accés a una aplicació de client de correu hauria de reconèixer aquesta opció. Comment[cs]=Tato služba umožňuje nastavit si výchozího emulátor terminálu. Všechny KDE aplikace, které spouští emulátor terminálu, by měly používat toto nastavení. Comment[csb]=Tuwò mòżne wëbrac domëslny emùlator terminala. Wszëtczé programë KDE, w jaczich brëkùje sã z lënkòw, mùszôłëbë ùżëwac tegò ùstôwù. diff --git a/kcms/componentchooser/kcm_componentchooser.cpp b/kcms/componentchooser/kcm_componentchooser.cpp --- a/kcms/componentchooser/kcm_componentchooser.cpp +++ b/kcms/componentchooser/kcm_componentchooser.cpp @@ -37,7 +37,7 @@ m_chooser=new ComponentChooser(this); lay->addWidget(m_chooser); connect(m_chooser,SIGNAL(changed(bool)),this,SIGNAL(changed(bool))); - setButtons( Default|Apply|Help ); + connect(m_chooser, &ComponentChooser::defaulted, this, &KCModule::defaulted); KAboutData *about = new KAboutData( QStringLiteral("kcmcomponentchooser"), i18n("Component Chooser"), QStringLiteral("1.0"), diff --git a/kcms/componentchooser/terminal_settings.kcfg b/kcms/componentchooser/terminal_settings.kcfg new file mode 100644 --- /dev/null +++ b/kcms/componentchooser/terminal_settings.kcfg @@ -0,0 +1,13 @@ + + + + + + + konsole + + + diff --git a/kcms/componentchooser/terminal_settings.kcfgc b/kcms/componentchooser/terminal_settings.kcfgc new file mode 100644 --- /dev/null +++ b/kcms/componentchooser/terminal_settings.kcfgc @@ -0,0 +1,5 @@ +File=terminal_settings.kcfg +ClassName=TerminalSettings +Mutators=true +DefaultValueGetters=true +ParentInConstructor=true diff --git a/kcms/cursortheme/CMakeLists.txt b/kcms/cursortheme/CMakeLists.txt --- a/kcms/cursortheme/CMakeLists.txt +++ b/kcms/cursortheme/CMakeLists.txt @@ -37,7 +37,7 @@ KF5::KIOCore KF5::KIOWidgets KF5::KDELibs4Support - KF5::NewStuff + KF5::NewStuffCore KF5::QuickAddons ${X11_LIBRARIES} XCB::XCB diff --git a/kcms/cursortheme/cursorthemesettings.kcfgc b/kcms/cursortheme/cursorthemesettings.kcfgc --- a/kcms/cursortheme/cursorthemesettings.kcfgc +++ b/kcms/cursortheme/cursorthemesettings.kcfgc @@ -3,3 +3,4 @@ Mutators=true DefaultValueGetters=true GenerateProperties=true +ParentInConstructor=true diff --git a/kcms/cursortheme/kcm_cursortheme.desktop b/kcms/cursortheme/kcm_cursortheme.desktop --- a/kcms/cursortheme/kcm_cursortheme.desktop +++ b/kcms/cursortheme/kcm_cursortheme.desktop @@ -57,6 +57,7 @@ Comment[ca]=Trieu el tema del cursor del ratolí Comment[ca@valencia]=Trieu el tema del cursor del ratolí Comment[cs]=Zvolte motiv ukazatele myši +Comment[da]=Vælg tema for musemarkøren Comment[de]=Design für den Mauszeiger auswählen Comment[en_GB]=Choose mouse cursor theme Comment[es]=Escoger un tema de cursores para el ratón @@ -73,6 +74,7 @@ Comment[lt]=Pasirinkti pelės žymeklio apipavidalinimą Comment[nl]=Muiscursorthema kiezen Comment[nn]=Vel peikartema +Comment[pa]=ਮਾਊਸ ਕਰਸਰ ਥੀਮ ਚੁਣੋ Comment[pl]=Wybierz zestaw wskaźników myszy Comment[pt]=Escolher o tema do cursor do rato Comment[pt_BR]=Escolha o tema do cursor do mouse diff --git a/kcms/cursortheme/kcmcursortheme.h b/kcms/cursortheme/kcmcursortheme.h --- a/kcms/cursortheme/kcmcursortheme.h +++ b/kcms/cursortheme/kcmcursortheme.h @@ -20,9 +20,10 @@ #ifndef KCMCURSORTHEME_H #define KCMCURSORTHEME_H -#include +#include #include +class QQmlListReference; class QStandardItemModel; class QTemporaryFile; @@ -36,7 +37,7 @@ class FileCopyJob; } -class CursorThemeConfig : public KQuickAddons::ConfigModule +class CursorThemeConfig : public KQuickAddons::ManagedConfigModule { Q_OBJECT Q_PROPERTY(CursorThemeSettings *cursorThemeSettings READ cursorThemeSettings CONSTANT) @@ -86,7 +87,6 @@ void canInstallChanged(); void canResizeChanged(); void canConfigureChanged(); - void selectedSizeRowChanged(); void downloadingFileChanged(); void preferredSizeChanged(); void themeApplied(); @@ -96,7 +96,7 @@ void showErrorMessage(const QString &message); public Q_SLOTS: - void getNewClicked(); + void ghnsEntriesChanged(const QQmlListReference &changedEntries); void installThemeFromFile(const QUrl &url); void removeTheme(int row); @@ -143,9 +143,6 @@ QScopedPointer m_tempInstallFile; QPointer m_tempCopyJob; - - int m_currentSize; - QString m_currentTheme; }; #endif diff --git a/kcms/cursortheme/kcmcursortheme.cpp b/kcms/cursortheme/kcmcursortheme.cpp --- a/kcms/cursortheme/kcmcursortheme.cpp +++ b/kcms/cursortheme/kcmcursortheme.cpp @@ -39,8 +39,12 @@ #include #include -#include +#include +#if KNEWSTUFFCORE_VERSION_MAJOR==5 && KNEWSTUFFCORE_VERSION_MINOR>=67 +#include +#endif +#include #include #include @@ -57,20 +61,13 @@ K_PLUGIN_FACTORY_WITH_JSON(CursorThemeConfigFactory, "kcm_cursortheme.json", registerPlugin();) CursorThemeConfig::CursorThemeConfig(QObject *parent, const QVariantList &args) - : KQuickAddons::ConfigModule(parent, args), - m_settings(new CursorThemeSettings), + : KQuickAddons::ManagedConfigModule(parent, args), + m_settings(new CursorThemeSettings(this)), m_canInstall(true), m_canResize(true), m_canConfigure(true) { - // Unfortunately doesn't generate a ctor taking the parent as parameter - m_settings->setParent(this); - m_currentSize = m_settings->cursorSize(); - m_currentTheme = m_settings->cursorTheme(); - m_preferredSize = m_currentSize; - connect(m_settings, &CursorThemeSettings::configChanged, this, &CursorThemeConfig::updateNeedsSave); - connect(m_settings, &CursorThemeSettings::cursorSizeChanged, this, &CursorThemeConfig::updateNeedsSave); - connect(m_settings, &CursorThemeSettings::cursorThemeChanged, this, &CursorThemeConfig::updateNeedsSave); + m_preferredSize = m_settings->cursorSize(); connect(m_settings, &CursorThemeSettings::cursorThemeChanged, this, &CursorThemeConfig::updateSizeComboBox); qmlRegisterType("org.kde.private.kcm_cursortheme", 1, 0, "PreviewWidget"); qmlRegisterType(); @@ -265,9 +262,6 @@ } } } - if (selectItem < 0) { - selectItem = 0; - } m_settings->setCursorSize(size); } } @@ -374,31 +368,26 @@ void CursorThemeConfig::save() { - m_settings->save(); - m_currentTheme = m_settings->cursorTheme(); - m_currentSize = m_settings->cursorSize(); - setPreferredSize(m_currentSize); + ManagedConfigModule::save(); + setPreferredSize(m_settings->cursorSize()); int row = cursorThemeIndex(m_settings->cursorTheme()); QModelIndex selected = m_themeProxyModel->index(row, 0); const CursorTheme *theme = selected.isValid() ? m_themeProxyModel->theme(selected) : nullptr; - if (!applyTheme(theme, m_currentSize)) { + if (!applyTheme(theme, m_settings->cursorSize())) { emit showInfoMessage(i18n("You have to restart the Plasma session for these changes to take effect.")); } KGlobalSettings::self()->emitChange(KGlobalSettings::CursorChanged); - setNeedsSave(false); } void CursorThemeConfig::load() { - m_settings->load(); - m_currentSize = m_settings->cursorSize(); - m_currentTheme = m_settings->cursorTheme(); - setPreferredSize(m_currentSize); - // Get the name of the theme KDE is configured to use + ManagedConfigModule::load(); + setPreferredSize(m_settings->cursorSize()); + // Get the name of the theme KDE is configured to use QString currentTheme = m_settings->cursorTheme(); // Disable the listview and the buttons if we're in kiosk mode @@ -415,52 +404,46 @@ void CursorThemeConfig::defaults() { - m_settings->setDefaults(); + ManagedConfigModule::defaults(); m_preferredSize = m_settings->cursorSize(); } -void CursorThemeConfig::updateNeedsSave() -{ - setNeedsSave(m_settings->cursorTheme() != m_currentTheme || m_settings->cursorSize() != m_currentSize); -} - -void CursorThemeConfig::getNewClicked() +void CursorThemeConfig::ghnsEntriesChanged(const QQmlListReference &changedEntries) { - KNS3::DownloadDialog dialog("xcursor.knsrc", nullptr); - if (dialog.exec()) { - KNS3::Entry::List list = dialog.changedEntries(); - if (!list.isEmpty()) { - for (const KNS3::Entry& entry : list) { - if (entry.status() == KNS3::Entry::Deleted) { - for (const QString& deleted : entry.uninstalledFiles()) { - QVector list = deleted.splitRef(QLatin1Char('/')); - if (list.last() == QLatin1Char('*')) { - list.takeLast(); - } - QModelIndex idx = m_themeModel->findIndex(list.last().toString()); - if (idx.isValid()) { - m_themeModel->removeTheme(idx); - } +#if KNEWSTUFFCORE_VERSION_MAJOR==5 && KNEWSTUFFCORE_VERSION_MINOR>=67 + for (int i = 0; i < changedEntries.count(); ++i) { + KNSCore::EntryWrapper* entry = qobject_cast(changedEntries.at(i)); + if (entry) { + if (entry->entry().status() == KNS3::Entry::Deleted) { + for (const QString& deleted : entry->entry().uninstalledFiles()) { + QVector list = deleted.splitRef(QLatin1Char('/')); + if (list.last() == QLatin1Char('*')) { + list.takeLast(); + } + QModelIndex idx = m_themeModel->findIndex(list.last().toString()); + if (idx.isValid()) { + m_themeModel->removeTheme(idx); } - } else if (entry.status() == KNS3::Entry::Installed) { - for (const QString& created : entry.installedFiles()) { - QStringList list = created.split(QLatin1Char('/')); - if (list.last() == QLatin1Char('*')) { - list.takeLast(); - } - // Because we sometimes get some extra slashes in the installed files list - list.removeAll({}); - // Because we'll also get the containing folder, if it was not already there - // we need to ignore it. - if (list.last() == QLatin1String(".icons")) { - continue; - } - m_themeModel->addTheme(list.join(QLatin1Char('/'))); + } + } else if (entry->entry().status() == KNS3::Entry::Installed) { + for (const QString& created : entry->entry().installedFiles()) { + QStringList list = created.split(QLatin1Char('/')); + if (list.last() == QLatin1Char('*')) { + list.takeLast(); + } + // Because we sometimes get some extra slashes in the installed files list + list.removeAll({}); + // Because we'll also get the containing folder, if it was not already there + // we need to ignore it. + if (list.last() == QLatin1String(".icons")) { + continue; } + m_themeModel->addTheme(list.join(QLatin1Char('/'))); } } } } +#endif } void CursorThemeConfig::installThemeFromFile(const QUrl &url) @@ -579,7 +562,7 @@ const CursorTheme *theme = m_themeProxyModel->theme(idx); // Don't let the user delete the currently configured theme - if (theme->name() == m_currentTheme) { + if (theme->name() == m_settings->cursorTheme()) { KMessageBox::sorry(nullptr, i18n("You cannot delete the theme you are currently " "using.
You have to switch to another theme first.
")); return; diff --git a/kcms/cursortheme/package/contents/ui/main.qml b/kcms/cursortheme/package/contents/ui/main.qml --- a/kcms/cursortheme/package/contents/ui/main.qml +++ b/kcms/cursortheme/package/contents/ui/main.qml @@ -22,7 +22,7 @@ import QtQuick.Controls 2.2 as QtControls import QtQuick.Dialogs 1.1 as QtDialogs import org.kde.kirigami 2.4 as Kirigami -import org.kde.kconfig 1.0 // for KAuthorized +import org.kde.newstuff 1.62 as NewStuff import org.kde.kcm 1.1 as KCM import org.kde.private.kcm_cursortheme 1.0 @@ -144,12 +144,13 @@ onClicked: fileDialogLoader.active = true; enabled: kcm.canInstall } - QtControls.Button { - icon.name: "get-hot-new-stuff" - text: i18n("&Get New Cursors...") - onClicked: kcm.getNewClicked(); + NewStuff.Button { + id: newStuffButton enabled: kcm.canInstall - visible: KAuthorized.authorize("ghns") + downloadNewWhat: i18n("Cursors") + configFile: "xcursor.knsrc" + viewMode: NewStuff.Page.ViewMode.Tiles + onChangedEntriesChanged: kcm.ghnsEntriesChanged(newStuffButton.changedEntries); } } } diff --git a/kcms/cursortheme/package/metadata.desktop b/kcms/cursortheme/package/metadata.desktop --- a/kcms/cursortheme/package/metadata.desktop +++ b/kcms/cursortheme/package/metadata.desktop @@ -45,6 +45,7 @@ Comment[ca]=Trieu el tema del cursor del ratolí Comment[ca@valencia]=Trieu el tema del cursor del ratolí Comment[cs]=Zvolte motiv ukazatele myši +Comment[da]=Vælg tema for musemarkøren Comment[de]=Design für den Mauszeiger auswählen Comment[en_GB]=Choose mouse cursor theme Comment[es]=Escoger un tema de cursores para el ratón @@ -61,6 +62,7 @@ Comment[lt]=Pasirinkti pelės žymeklio apipavidalinimą Comment[nl]=Muiscursorthema kiezen Comment[nn]=Vel peikartema +Comment[pa]=ਮਾਊਸ ਕਰਸਰ ਥੀਮ ਚੁਣੋ Comment[pl]=Wybierz zestaw wskaźników myszy Comment[pt]=Escolher o tema do cursor do rato Comment[pt_BR]=Escolha o tema do cursor do mouse diff --git a/kcms/cursortheme/xcursor/thememodel.cpp b/kcms/cursortheme/xcursor/thememodel.cpp --- a/kcms/cursortheme/xcursor/thememodel.cpp +++ b/kcms/cursortheme/xcursor/thememodel.cpp @@ -89,7 +89,7 @@ } } - // Numbered vertical header lables + // Numbered vertical header labels return QString(section); } diff --git a/kcms/cursortheme/xcursor/xcursortheme.cpp b/kcms/cursortheme/xcursor/xcursortheme.cpp --- a/kcms/cursortheme/xcursor/xcursortheme.cpp +++ b/kcms/cursortheme/xcursor/xcursortheme.cpp @@ -102,7 +102,7 @@ // Qt uses non-standard names for some core cursors. // If Xcursor fails to load the cursor, Qt creates it with the correct name using the - // core protcol instead (which in turn calls Xcursor). We emulate that process here. + // core protocol instead (which in turn calls Xcursor). We emulate that process here. // Note that there's a core cursor called cross, but it's not the one Qt expects. alternatives.insert(QStringLiteral("cross"), QStringLiteral("crosshair")); alternatives.insert(QStringLiteral("up_arrow"), QStringLiteral("center_ptr")); diff --git a/kcms/dateandtime/dtime.cpp b/kcms/dateandtime/dtime.cpp --- a/kcms/dateandtime/dtime.cpp +++ b/kcms/dateandtime/dtime.cpp @@ -43,7 +43,6 @@ #include #include #include -#include #include #include #include @@ -154,15 +153,17 @@ envpath.remove(0, 1); } - QString path = QStringLiteral("/sbin:/usr/sbin:"); + QStringList path = {"/sbin", "/usr/sbin"}; if (!envpath.isEmpty()) { - path += QFile::decodeName(envpath); + path += QFile::decodeName(envpath).split(QLatin1Char(':')); } else { - path += QLatin1String("/bin:/usr/bin"); + path += {"/bin", "/usr/bin"}; } - foreach(const QString &possible_ntputility, QStringList() << "ntpdate" << "rdate" ) { - if( !((ntpUtility = KStandardDirs::findExe(possible_ntputility, path)).isEmpty()) ) { + const auto possible_ntputilities = {"ntpdate", "rdate"}; + for (const QString &possible_ntputility : possible_ntputilities) { + auto ntpUtility = QStandardPaths::findExecutable(possible_ntputility, path); + if (!ntpUtility.isEmpty()) { qDebug() << "ntpUtility = " << ntpUtility; return; } diff --git a/kcms/dateandtime/helper.cpp b/kcms/dateandtime/helper.cpp --- a/kcms/dateandtime/helper.cpp +++ b/kcms/dateandtime/helper.cpp @@ -227,7 +227,7 @@ void ClockHelper::toHwclock() { - QString hwclock = KStandardDirs::findExe(QStringLiteral("hwclock"), exePath); + QString hwclock = QStandardPaths::findExecutable(QStringLiteral("hwclock"), exePath.split(QLatin1Char(':'))); if (!hwclock.isEmpty()) { KProcess::execute(hwclock, QStringList() << QStringLiteral("--systohc")); } diff --git a/kcms/desktoppaths/CMakeLists.txt b/kcms/desktoppaths/CMakeLists.txt --- a/kcms/desktoppaths/CMakeLists.txt +++ b/kcms/desktoppaths/CMakeLists.txt @@ -3,16 +3,18 @@ set(kcm_desktoppaths_PART_SRCS globalpaths.cpp + desktoppathssettings.cpp ) +ki18n_wrap_ui(kcm_desktoppaths_PART_SRCS globalpaths.ui) + add_library(kcm_desktoppaths MODULE ${kcm_desktoppaths_PART_SRCS}) target_link_libraries(kcm_desktoppaths KF5::KCMUtils KF5::I18n KF5::KIOCore KF5::KIOWidgets - KF5::KDELibs4Support # kglobalsettings ) install(TARGETS kcm_desktoppaths DESTINATION ${KDE_INSTALL_PLUGINDIR}) diff --git a/kcms/desktoppaths/desktoppathssettings.h b/kcms/desktoppaths/desktoppathssettings.h new file mode 100644 --- /dev/null +++ b/kcms/desktoppaths/desktoppathssettings.h @@ -0,0 +1,63 @@ +/** + * Copyright 2020 Kevin Ottens + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef DESKTOPPATHSSETTINGS_H +#define DESKTOPPATHSSETTINGS_H + +#include + +class PathsSettingsStore; +class XdgPathsSettingsStore; + +class DesktopPathsSettings : public KCoreConfigSkeleton +{ + Q_OBJECT +public: + DesktopPathsSettings(QObject *parent = nullptr); + + QUrl autostartLocation() const; + void setAutostartLocation(const QUrl &url); + + QUrl desktopLocation() const; + void setDesktopLocation(const QUrl &url); + + QUrl documentsLocation() const; + void setDocumentsLocation(const QUrl &url); + + QUrl downloadsLocation() const; + void setDownloadsLocation(const QUrl &url); + + QUrl musicLocation() const; + void setMusicLocation(const QUrl &url); + + QUrl picturesLocation() const; + void setPicturesLocation(const QUrl &url); + + QUrl videosLocation() const; + void setVideosLocation(const QUrl &url); + +private: + bool usrSave() override; + +private: + PathsSettingsStore *m_pathsStore; + XdgPathsSettingsStore *m_xdgPathsStore; +}; + +#endif + diff --git a/kcms/desktoppaths/desktoppathssettings.cpp b/kcms/desktoppaths/desktoppathssettings.cpp new file mode 100644 --- /dev/null +++ b/kcms/desktoppaths/desktoppathssettings.cpp @@ -0,0 +1,316 @@ +/** + * Copyright 2020 Kevin Ottens + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "desktoppathssettings.h" + +#include + +namespace { + //save in XDG user-dirs.dirs config file, this is where KGlobalSettings/QDesktopServices reads from. + KSharedConfig::Ptr userDirsConfig() + { + const QString userDirsFilePath = QStandardPaths::writableLocation(QStandardPaths::ConfigLocation) + QStringLiteral("/user-dirs.dirs"); + return KSharedConfig::openConfig(userDirsFilePath, KConfig::SimpleConfig); + } + + QUrl defaultAutostartLocation() + { + return QUrl::fromLocalFile(QDir::homePath() + QStringLiteral("/.config/autostart")); + } + + QUrl defaultDesktopLocation() + { + return QUrl::fromLocalFile(QDir::homePath() + QStringLiteral("/Desktop")); + } + + QUrl defaultDocumentsLocation() + { + return QUrl::fromLocalFile(QDir::homePath() + QStringLiteral("/Documents")); + } + + QUrl defaultDownloadsLocation() + { + return QUrl::fromLocalFile(QDir::homePath() + QStringLiteral("/Downloads")); + } + + QUrl defaultMusicLocation() + { + return QUrl::fromLocalFile(QDir::homePath() + QStringLiteral("/Music")); + } + + QUrl defaultPicturesLocation() + { + return QUrl::fromLocalFile(QDir::homePath() + QStringLiteral("/Pictures")); + } + + QUrl defaultVideosLocation() + { + return QUrl::fromLocalFile(QDir::homePath() + QStringLiteral("/Videos")); + } +} + +class PathsSettingsStore : public QObject +{ + Q_OBJECT + Q_PROPERTY(QUrl autostartLocation READ autostartLocation WRITE setAutostartLocation) +public: + PathsSettingsStore(QObject *parent = nullptr) + : QObject(parent) + , m_config(KSharedConfig::openConfig()) + { + } + + QUrl autostartLocation() const + { + return readUrl(QStringLiteral("Autostart"), defaultAutostartLocation()); + } + + void setAutostartLocation(const QUrl &url) + { + if (url.matches(defaultAutostartLocation(), QUrl::StripTrailingSlash)) { + resetUrl(QStringLiteral("Autostart")); + } else { + writeUrl(QStringLiteral("Autostart"), url); + } + } + + void save() + { + if (m_config->isDirty()) { + m_config->sync(); + } + } + +private: + QUrl readUrl(const QString &key, const QUrl &defaultValue) const + { + KConfigGroup group(m_config, QStringLiteral("Paths")); + const auto path = group.readPathEntry(key, QString()); + if (path.isEmpty()) { + return defaultValue; + } else { + return QUrl::fromLocalFile(path); + } + } + + void writeUrl(const QString &key, const QUrl &url) + { + KConfigGroup group(m_config, QStringLiteral("Paths")); + group.writePathEntry(key, url.toLocalFile(), KConfig::Normal | KConfig::Global); + } + + void resetUrl(const QString &key) + { + KConfigGroup group(m_config, QStringLiteral("Paths")); + group.revertToDefault(key, KConfig::Normal | KConfig::Global); + } + + KSharedConfig::Ptr m_config; +}; + +class XdgPathsSettingsStore : public QObject +{ + Q_OBJECT + Q_PROPERTY(QUrl desktopLocation READ desktopLocation WRITE setDesktopLocation) + Q_PROPERTY(QUrl documentsLocation READ documentsLocation WRITE setDocumentsLocation) + Q_PROPERTY(QUrl downloadsLocation READ downloadsLocation WRITE setDownloadsLocation) + Q_PROPERTY(QUrl musicLocation READ musicLocation WRITE setMusicLocation) + Q_PROPERTY(QUrl picturesLocation READ picturesLocation WRITE setPicturesLocation) + Q_PROPERTY(QUrl videosLocation READ videosLocation WRITE setVideosLocation) +public: + XdgPathsSettingsStore(DesktopPathsSettings *parent = nullptr) + : QObject(parent) + , m_settings(parent) + { + } + + QUrl desktopLocation() const + { + return readUrl(QStringLiteral("XDG_DESKTOP_DIR"), defaultDesktopLocation()); + } + + void setDesktopLocation(const QUrl &url) + { + writeUrl(QStringLiteral("XDG_DESKTOP_DIR"), url); + } + + QUrl documentsLocation() const + { + return readUrl(QStringLiteral("XDG_DOCUMENTS_DIR"), defaultDocumentsLocation()); + } + + void setDocumentsLocation(const QUrl &url) + { + writeUrl(QStringLiteral("XDG_DOCUMENTS_DIR"), url); + } + + QUrl downloadsLocation() const + { + return readUrl(QStringLiteral("XDG_DOWNLOAD_DIR"), defaultDownloadsLocation()); + } + + void setDownloadsLocation(const QUrl &url) + { + writeUrl(QStringLiteral("XDG_DOWNLOAD_DIR"), url); + } + + QUrl musicLocation() const + { + return readUrl(QStringLiteral("XDG_MUSIC_DIR"), defaultMusicLocation()); + } + + void setMusicLocation(const QUrl &url) + { + writeUrl(QStringLiteral("XDG_MUSIC_DIR"), url); + } + + QUrl picturesLocation() const + { + return readUrl(QStringLiteral("XDG_PICTURES_DIR"), defaultPicturesLocation()); + } + + void setPicturesLocation(const QUrl &url) + { + writeUrl(QStringLiteral("XDG_PICTURES_DIR"), url); + } + + QUrl videosLocation() const + { + return readUrl(QStringLiteral("XDG_VIDEOS_DIR"), defaultVideosLocation()); + } + + void setVideosLocation(const QUrl &url) + { + writeUrl(QStringLiteral("XDG_VIDEOS_DIR"), url); + } + +private: + QUrl readUrl(const QString &key, const QUrl &defaultValue) const + { + KConfigGroup group(m_settings->config(), QString()); + const auto path = group.readPathEntry(key, QString()); + if (path.isEmpty()) { + return defaultValue; + } else { + return QUrl::fromLocalFile(path.mid(1, path.length() - 2)); + } + } + + void writeUrl(const QString &key, const QUrl &url) + { + KConfigGroup group(m_settings->config(), QString()); + // HACK to benefit from path translation (thus unexpanding $HOME) + group.writePathEntry(key, url.toLocalFile()); + const auto path = group.readEntryUntranslated(key, QString()); + group.writeEntry(key, QString(QStringLiteral("\"") + path + QStringLiteral("\""))); + } + + DesktopPathsSettings *m_settings; +}; + +DesktopPathsSettings::DesktopPathsSettings(QObject *parent) + : KCoreConfigSkeleton(userDirsConfig(), parent) + , m_pathsStore(new PathsSettingsStore(this)) + , m_xdgPathsStore(new XdgPathsSettingsStore(this)) +{ + addItem(new KPropertySkeletonItem(m_xdgPathsStore, "desktopLocation", defaultDesktopLocation()), "desktopLocation"); + addItem(new KPropertySkeletonItem(m_pathsStore, "autostartLocation", defaultAutostartLocation()), "autostartLocation"); + addItem(new KPropertySkeletonItem(m_xdgPathsStore, "documentsLocation", defaultDocumentsLocation()), "documentsLocation"); + addItem(new KPropertySkeletonItem(m_xdgPathsStore, "downloadsLocation", defaultDownloadsLocation()), "downloadsLocation"); + addItem(new KPropertySkeletonItem(m_xdgPathsStore, "musicLocation", defaultMusicLocation()), "musicLocation"); + addItem(new KPropertySkeletonItem(m_xdgPathsStore, "picturesLocation", defaultPicturesLocation()), "picturesLocation"); + addItem(new KPropertySkeletonItem(m_xdgPathsStore, "videosLocation", defaultVideosLocation()), "videosLocation"); +} + +QUrl DesktopPathsSettings::autostartLocation() const +{ + return findItem("autostartLocation")->property().toUrl(); +} + +void DesktopPathsSettings::setAutostartLocation(const QUrl &url) +{ + findItem("autostartLocation")->setProperty(url); +} + +QUrl DesktopPathsSettings::desktopLocation() const +{ + return findItem("desktopLocation")->property().toUrl(); +} + +void DesktopPathsSettings::setDesktopLocation(const QUrl &url) +{ + findItem("desktopLocation")->setProperty(url); +} + +QUrl DesktopPathsSettings::documentsLocation() const +{ + return findItem("documentsLocation")->property().toUrl(); +} + +void DesktopPathsSettings::setDocumentsLocation(const QUrl &url) +{ + findItem("documentsLocation")->setProperty(url); +} + +QUrl DesktopPathsSettings::downloadsLocation() const +{ + return findItem("downloadsLocation")->property().toUrl(); +} + +void DesktopPathsSettings::setDownloadsLocation(const QUrl &url) +{ + findItem("downloadsLocation")->setProperty(url); +} + +QUrl DesktopPathsSettings::musicLocation() const +{ + return findItem("musicLocation")->property().toUrl(); +} + +void DesktopPathsSettings::setMusicLocation(const QUrl &url) +{ + findItem("musicLocation")->setProperty(url); +} + +QUrl DesktopPathsSettings::picturesLocation() const +{ + return findItem("picturesLocation")->property().toUrl(); +} + +void DesktopPathsSettings::setPicturesLocation(const QUrl &url) +{ + findItem("picturesLocation")->setProperty(url); +} + +QUrl DesktopPathsSettings::videosLocation() const +{ + return findItem("videosLocation")->property().toUrl(); +} + +void DesktopPathsSettings::setVideosLocation(const QUrl &url) +{ + findItem("videosLocation")->setProperty(url); +} + +bool DesktopPathsSettings::usrSave() +{ + m_pathsStore->save(); + return KCoreConfigSkeleton::usrSave(); +} + +#include "desktoppathssettings.moc" diff --git a/kcms/desktoppaths/globalpaths.h b/kcms/desktoppaths/globalpaths.h --- a/kcms/desktoppaths/globalpaths.h +++ b/kcms/desktoppaths/globalpaths.h @@ -31,15 +31,10 @@ #define __GLOBALPATHS_H #include -#include -#include -#include -class QFormLayout; -class KJob; -class KUrlRequester; +namespace Ui { class DesktopPathsView; } -namespace KIO { class Job; } +class DesktopPathsSettings; //----------------------------------------------------------------------------- // The "Path" Tab contains : @@ -49,34 +44,12 @@ { Q_OBJECT public: - DesktopPathConfig( QWidget *parent, const QVariantList &args ); - void load() override; - void save() override; - void defaults() override; - -private Q_SLOTS: - void slotEntries( KIO::Job * job, const KIO::UDSEntryList& list); + DesktopPathConfig(QWidget *parent, const QVariantList &args); + ~DesktopPathConfig() override; private: - KUrlRequester* addRow(QFormLayout *lay, const QString& label, const QString& whatsThis); - bool xdgSavePath(KUrlRequester* ur, const QUrl& currentUrl, const char* xdgKey, const QString& type); - - // Desktop Paths - KUrlRequester *urDesktop; - KUrlRequester *urAutostart; - KUrlRequester *urDocument; - KUrlRequester *urDownload; - KUrlRequester *urMovie; - KUrlRequester *urPicture; - KUrlRequester *urMusic; - - bool moveDir( const QUrl & src, const QUrl & dest, const QString & type ); - bool m_ok; - QUrl m_copyToDest; // used when the destination directory already exists - QUrl m_copyFromSrc; - -private Q_SLOTS: - void slotResult( KJob * job ); + QScopedPointer m_ui; + DesktopPathsSettings *m_pathsSettings; }; #endif diff --git a/kcms/desktoppaths/globalpaths.cpp b/kcms/desktoppaths/globalpaths.cpp --- a/kcms/desktoppaths/globalpaths.cpp +++ b/kcms/desktoppaths/globalpaths.cpp @@ -37,420 +37,30 @@ // Own #include "globalpaths.h" +#include "ui_globalpaths.h" +#include "desktoppathssettings.h" -// Qt -#include -#include -#include -#include -#include -#include -#include -#include - -// KDE -#include -#include -#include //KDELibs4Support -#include -#include -#include -#include -#include -#include -#include -#include #include -#include -#include - -Q_LOGGING_CATEGORY(KCM_DESKTOPPATH, "kcm_desktoppath") K_PLUGIN_FACTORY(KcmDesktopPathsFactory, registerPlugin();) //----------------------------------------------------------------------------- -static QUrl desktopLocation() -{ - return QUrl::fromLocalFile(QStandardPaths::writableLocation(QStandardPaths::DesktopLocation)); -} - -static QUrl autostartLocation() -{ - return QUrl::fromLocalFile(QStandardPaths::writableLocation(QStandardPaths::GenericConfigLocation) + QStringLiteral("/autostart")); -} - -static QUrl documentsLocation() -{ - return QUrl::fromLocalFile(QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation)); -} - -static QUrl downloadLocation() -{ - return QUrl::fromLocalFile(QStandardPaths::writableLocation(QStandardPaths::DownloadLocation)); -} - -static QUrl moviesLocation() -{ - return QUrl::fromLocalFile(QStandardPaths::writableLocation(QStandardPaths::MoviesLocation)); -} - -static QUrl picturesLocation() -{ - return QUrl::fromLocalFile(QStandardPaths::writableLocation(QStandardPaths::PicturesLocation)); -} - -static QUrl musicLocation() -{ - return QUrl::fromLocalFile(QStandardPaths::writableLocation(QStandardPaths::MusicLocation)); -} - DesktopPathConfig::DesktopPathConfig(QWidget *parent, const QVariantList &) : KCModule( parent ) + , m_ui(new Ui::DesktopPathsView) + , m_pathsSettings(new DesktopPathsSettings(this)) { - QFormLayout *lay = new QFormLayout(this); - lay->setVerticalSpacing(0); - lay->setContentsMargins(0, 0, 0, 0); - - setQuickHelp( i18n("

Paths

\n" - "This module allows you to choose where in the filesystem the " - "files on your desktop should be stored.\n" - "Use the \"Whats This?\" (Shift+F1) to get help on specific options.")); - - urDesktop = addRow(lay, i18n("Desktop path:"), - i18n("This folder contains all the files" - " which you see on your desktop. You can change the location of this" - " folder if you want to, and the contents will move automatically" - " to the new location as well.")); - - urAutostart = addRow(lay, i18n("Autostart path:"), - i18n("This folder contains applications or" - " links to applications (shortcuts) that you want to have started" - " automatically whenever the session starts. You can change the location of this" - " folder if you want to, and the contents will move automatically" - " to the new location as well.")); - - urDocument = addRow(lay, i18n("Documents path:"), - i18n("This folder will be used by default to " - "load or save documents from or to.")); - - urDownload = addRow(lay, i18n("Downloads path:"), - i18n("This folder will be used by default to " - "save your downloaded items.")); - - urMovie = addRow(lay, i18n("Movies path:"), - i18n("This folder will be used by default to " - "load or save movies from or to.")); - - urPicture = addRow(lay, i18n("Pictures path:"), - i18n("This folder will be used by default to " - "load or save pictures from or to.")); - - urMusic = addRow(lay, i18n("Music path:"), - i18n("This folder will be used by default to " - "load or save music from or to.")); -} - -KUrlRequester* DesktopPathConfig::addRow(QFormLayout *lay, const QString& label, const QString& whatsThis) -{ - KUrlRequester* ur = new KUrlRequester(this); - ur->setMode(KFile::Directory | KFile::LocalOnly); - lay->addRow(label, ur); - connect(ur, SIGNAL(textChanged(QString)), this, SLOT(changed())); - lay->labelForField(ur)->setWhatsThis(whatsThis); - ur->setWhatsThis(whatsThis); - return ur; -} - -void DesktopPathConfig::load() -{ - // Desktop Paths - urDesktop->setUrl(desktopLocation()); - urAutostart->setUrl(autostartLocation()); - urDocument->setUrl(documentsLocation()); - urDownload->setUrl(downloadLocation()); - urMovie->setUrl(moviesLocation()); - urPicture->setUrl(picturesLocation()); - urMusic->setUrl(musicLocation()); - emit changed(false); -} - -void DesktopPathConfig::defaults() -{ - // Desktop Paths - keep defaults in sync with kglobalsettings.cpp - urDesktop->setUrl(QUrl::fromLocalFile(QDir::homePath() + QStringLiteral("/Desktop"))); - urAutostart->setUrl(QUrl::fromLocalFile(QDir::homePath() + QStringLiteral("/.config/autostart"))); - urDocument->setUrl(QUrl::fromLocalFile(QDir::homePath() + QStringLiteral("/Documents"))); - urDownload->setUrl(QUrl::fromLocalFile(QDir::homePath() + QStringLiteral("/Downloads"))); - urMovie->setUrl(QUrl::fromLocalFile(QDir::homePath() + QStringLiteral("/Movies"))); - urPicture->setUrl(QUrl::fromLocalFile(QDir::homePath() + QStringLiteral("/Pictures"))); - urMusic->setUrl(QUrl::fromLocalFile(QDir::homePath() + QStringLiteral("/Music"))); -} - -// the following method is copied from kdelibs/kdecore/config/kconfiggroup.cpp -static bool cleanHomeDirPath( QString &path, const QString &homeDir ) -{ -#ifdef Q_WS_WIN //safer - if (!QDir::convertSeparators(path).startsWith(QDir::convertSeparators(homeDir))) - return false; -#else - if (!path.startsWith(homeDir)) - return false; -#endif - - int len = homeDir.length(); - // replace by "$HOME" if possible - if (len && (path.length() == len || path[len] == '/')) { - path.replace(0, len, QStringLiteral("$HOME")); - return true; - } else - return false; -} - -// TODO this functionality is duplicated in libkonq - keep it only there and export - -static QString translatePath( QString path ) // krazy:exclude=passbyvalue -{ - // keep only one single '/' at the beginning - needed for cleanHomeDirPath() - while (path.length() >= 2 && path[0] == '/' && path[1] == '/') - path.remove(0,1); - - // we probably should escape any $ ` and \ characters that may occur in the path, but the Qt code that reads back - // the file doesn't unescape them so not much point in doing so - - // All of the 3 following functions to return the user's home directory - // can return different paths. We have to test all them. - const QString homeDir0 = QFile::decodeName(qgetenv("HOME")); - const QString homeDir1 = QDir::homePath(); - const QString homeDir2 = QDir(homeDir1).canonicalPath(); - if (cleanHomeDirPath(path, homeDir0) || - cleanHomeDirPath(path, homeDir1) || - cleanHomeDirPath(path, homeDir2) ) { - // qCDebug(KCM_DESKTOPPATH) << "Path was replaced\n"; - } - - return path; -} - -void DesktopPathConfig::save() -{ - KSharedConfig::Ptr config = KSharedConfig::openConfig(); - KConfigGroup configGroup( config, "Paths" ); - - bool pathChanged = false; - bool autostartMoved = false; - - QUrl desktopURL(desktopLocation()); - - QUrl autostartURL(autostartLocation()); - QUrl newAutostartURL = urAutostart->url(); - - if ( !urDesktop->url().matches( desktopURL, QUrl::StripTrailingSlash ) ) - { - // Test which other paths were inside this one (as it is by default) - // and for each, test where it should go. - // * Inside destination -> let them be moved with the desktop (but adjust name if necessary) - // * Not inside destination -> move first - // !!! - qCDebug(KCM_DESKTOPPATH) << "desktopURL=" << desktopURL; - QString urlDesktop = urDesktop->url().toLocalFile(); - if ( !urlDesktop.endsWith(QLatin1Char('/'))) - urlDesktop+=QLatin1Char('/'); - - if ( desktopURL.isParentOf( autostartURL ) ) - { - qCDebug(KCM_DESKTOPPATH) << "Autostart is on the desktop"; - - // Either the Autostart field wasn't changed (-> need to update it) - if ( newAutostartURL.matches(autostartURL, QUrl::StripTrailingSlash) ) - { - // Hack. It could be in a subdir inside desktop. Hmmm... Argl. - urAutostart->setUrl(QUrl::fromLocalFile(urlDesktop + QStringLiteral("Autostart/"))); - qCDebug(KCM_DESKTOPPATH) << "Autostart is moved with the desktop"; - autostartMoved = true; - } - // or it has been changed (->need to move it from here) - else - { - QUrl futureAutostartURL = QUrl::fromLocalFile(urlDesktop + QStringLiteral("Autostart/")); - if ( newAutostartURL.matches( futureAutostartURL, QUrl::StripTrailingSlash ) ) - autostartMoved = true; - else - autostartMoved = moveDir( autostartLocation(), urAutostart->url(), i18n("Autostart") ); - } - } - - if ( moveDir( desktopLocation(), QUrl::fromLocalFile( urlDesktop ), i18n("Desktop") ) ) - { - //save in XDG path - const QString userDirsFile(QStandardPaths::writableLocation(QStandardPaths::ConfigLocation) + QStringLiteral("/user-dirs.dirs")); - KConfig xdgUserConf( userDirsFile, KConfig::SimpleConfig ); - KConfigGroup g( &xdgUserConf, "" ); - g.writeEntry( "XDG_DESKTOP_DIR", QString("\"" + translatePath( urlDesktop ) + "\"") ); - pathChanged = true; - } - } - - if ( !newAutostartURL.matches( autostartURL, QUrl::StripTrailingSlash ) ) - { - if (!autostartMoved) - autostartMoved = moveDir( autostartLocation(), urAutostart->url(), i18n("Autostart") ); - if (autostartMoved) - { - configGroup.writePathEntry( "Autostart", urAutostart->url().toLocalFile(), KConfigBase::Normal | KConfigBase::Global ); - pathChanged = true; - } - } - - config->sync(); - - if (xdgSavePath(urDocument, documentsLocation(), "XDG_DOCUMENTS_DIR", i18n("Documents"))) - pathChanged = true; - - if (xdgSavePath(urDownload, downloadLocation(), "XDG_DOWNLOAD_DIR", i18n("Downloads"))) - pathChanged = true; - - if (xdgSavePath(urMovie, moviesLocation(), "XDG_VIDEOS_DIR", i18n("Movies"))) - pathChanged = true; - - if (xdgSavePath(urPicture, picturesLocation(), "XDG_PICTURES_DIR", i18n("Pictures"))) - pathChanged = true; - - if (xdgSavePath(urMusic, musicLocation(), "XDG_MUSIC_DIR", i18n("Music"))) - pathChanged = true; - - if (pathChanged) { - qCDebug(KCM_DESKTOPPATH) << "sending message SettingsChanged"; - KGlobalSettings::self()->emitChange(KGlobalSettings::SettingsChanged, KGlobalSettings::SETTINGS_PATHS); - } -} - -bool DesktopPathConfig::xdgSavePath(KUrlRequester* ur, const QUrl& currentUrl, const char* xdgKey, const QString& type) -{ - QUrl newUrl = ur->url(); - //url might be empty, use QDir::homePath (the default for xdg) then - if (!newUrl.isValid()) { - newUrl = QUrl(QUrl::fromLocalFile(QDir::homePath())); - } - if (!newUrl.matches(currentUrl, QUrl::StripTrailingSlash)) { - const QString path = newUrl.toLocalFile(); - if (!QDir(path).exists()) { - // Check permissions - if (QDir().mkpath(path)) { - QDir().rmdir(path); // rmdir again, so that we get a fast rename - } else { - KMessageBox::sorry(this, KIO::buildErrorString(KIO::ERR_CANNOT_MKDIR, path)); - ur->setUrl(currentUrl); // revert - return false; - } - } - if (moveDir(currentUrl, newUrl, type)) { - //save in XDG user-dirs.dirs config file, this is where KGlobalSettings/QDesktopServices reads from. - const QString userDirsFile(QStandardPaths::writableLocation(QStandardPaths::ConfigLocation) + QStringLiteral("/user-dirs.dirs")); - KConfig xdgUserConf(userDirsFile, KConfig::SimpleConfig); - KConfigGroup g(&xdgUserConf, ""); - g.writeEntry(xdgKey, QString("\"" + translatePath(path) + "\"")); - return true; - } - } - return false; + m_ui->setupUi(this); + setQuickHelp(i18n("

Paths

\n" + "This module allows you to choose where in the filesystem the " + "files on your desktop should be stored.\n" + "Use the \"Whats This?\" (Shift+F1) to get help on specific options.")); + addConfig(m_pathsSettings, this); } -bool DesktopPathConfig::moveDir( const QUrl & src, const QUrl & dest, const QString & type ) +DesktopPathConfig::~DesktopPathConfig() { - if (!src.isLocalFile() || !dest.isLocalFile()) - return true; - if (!QFile::exists(src.toLocalFile())) - return true; - // Do not move $HOME! #193057 - const QString translatedPath = translatePath(src.toLocalFile()); - if (translatedPath == QLatin1String("$HOME") || translatedPath == QLatin1String("$HOME/")) { - return true; - } - - m_ok = true; - - QString question; - KGuiItem yesItem; - KGuiItem noItem; - if (QFile::exists(dest.toLocalFile())) { - // TODO: check if the src dir is empty? Nothing to move, then... - question = i18n("The path for '%1' has been changed.\nDo you want the files to be moved from '%2' to '%3'?", - type, src.toLocalFile(), - dest.toLocalFile()); - yesItem = KGuiItem(i18nc("Move files from old to new place", "Move")); - noItem = KGuiItem(i18nc("Use the new directory but do not move files", "Do not Move")); - } else { - question = i18n("The path for '%1' has been changed.\nDo you want to move the directory '%2' to '%3'?", - type, src.toLocalFile(), - dest.toLocalFile()); - yesItem = KGuiItem(i18nc("Move the directory", "Move")); - noItem = KGuiItem(i18nc("Use the new directory but do not move anything", "Do not Move")); - } - - // Ask for confirmation before moving the files - if (KMessageBox::questionYesNo(this, question, i18n("Confirmation Required"), - yesItem, noItem) - == KMessageBox::Yes ) - { - if (QFile::exists(dest.toLocalFile())) { - // Destination already exists -- should always be the case, for most types, - // but maybe not for the complex autostart case (to be checked...) - m_copyToDest = dest; - m_copyFromSrc = src; - KIO::ListJob* job = KIO::listDir( src ); - job->setAutoDelete(false); // see below - KJobWidgets::setWindow(job, this); - job->uiDelegate()->setAutoErrorHandlingEnabled(true); - connect(job, &KIO::ListJob::entries, this, &DesktopPathConfig::slotEntries); - // slotEntries will move every file/subdir individually into the dest - job->exec(); - if (m_ok) { - QDir().rmdir(src.toLocalFile()); // hopefully it's empty by now - } - delete job; - } - else - { - qCDebug(KCM_DESKTOPPATH) << "Direct move from" << src << "to" << dest; - KIO::Job * job = KIO::move( src, dest ); - KJobWidgets::setWindow(job, this); - connect(job, &KIO::Job::result, this, &DesktopPathConfig::slotResult); - job->exec(); - } - } - qCDebug(KCM_DESKTOPPATH) << "DesktopPathConfig::slotResult returning " << m_ok; - return m_ok; -} - -void DesktopPathConfig::slotEntries(KIO::Job*, const KIO::UDSEntryList& list) -{ - QListIterator it(list); - while (it.hasNext()) { - KFileItem file(it.next(), m_copyFromSrc, true, true); - qCDebug(KCM_DESKTOPPATH) << file.url(); - if (file.url() == m_copyFromSrc || file.name() == QLatin1String("..")) { - continue; - } - - KIO::Job * moveJob = KIO::move(file.url(), m_copyToDest); - KJobWidgets::setWindow(moveJob, this); - connect(moveJob, &KIO::Job::result, this, &DesktopPathConfig::slotResult); - moveJob->exec(); // sub-event loop here. : the main job is not autodeleted because it would be deleted here - } -} - -void DesktopPathConfig::slotResult( KJob * job ) -{ - if (job->error()) { - if ( job->error() != KIO::ERR_DOES_NOT_EXIST ) - m_ok = false; - - // If the source doesn't exist, no wonder we couldn't move the dir. - // In that case, trust the user and set the new setting in any case. - - static_cast(job)->uiDelegate()->showErrorMessage(); - } } #include "globalpaths.moc" diff --git a/kcms/desktoppaths/globalpaths.ui b/kcms/desktoppaths/globalpaths.ui new file mode 100644 --- /dev/null +++ b/kcms/desktoppaths/globalpaths.ui @@ -0,0 +1,126 @@ + + + DesktopPathsView + + + + 0 + 0 + 400 + 313 + + + + Form + + + + + + Desktop path: + + + + + + + This folder contains all the files which you see on your desktop. You can change the location of this folder if you want to, and the contents will move automatically to the new location as well. + + + + + + + Autostart path: + + + + + + + This folder contains applications or links to applications (shortcuts) that you want to have started automatically whenever the session starts. You can change the location of this folder if you want to, and the contents will move automatically to the new location as well. + + + + + + + Documents path: + + + + + + + This folder will be used by default to load or save documents from or to. + + + + + + + Downloads path: + + + + + + + This folder will be used by default to save your downloaded items. + + + + + + + Videos path: + + + + + + + This folder will be used by default to load or save movies from or to. + + + + + + + Pictures path: + + + + + + + This folder will be used by default to load or save pictures from or to. + + + + + + + Music path: + + + + + + + This folder will be used by default to load or save music from or to. + + + + + + + + KUrlRequester + QWidget +
kurlrequester.h
+
+
+ + +
diff --git a/kcms/desktoptheme/CMakeLists.txt b/kcms/desktoptheme/CMakeLists.txt --- a/kcms/desktoptheme/CMakeLists.txt +++ b/kcms/desktoptheme/CMakeLists.txt @@ -3,6 +3,8 @@ set(kcm_desktoptheme_SRCS kcm.cpp + themesmodel.cpp + filterproxymodel.cpp ) kconfig_add_kcfg_files(kcm_desktoptheme_SRCS desktopthemesettings.kcfgc GENERATE_MOC) @@ -18,7 +20,6 @@ KF5::Plasma KF5::Declarative KF5::QuickAddons - KF5::NewStuff ) kcoreaddons_desktop_to_json(kcm_desktoptheme "kcm_desktoptheme.desktop" SERVICE_TYPES kcmodule.desktop) diff --git a/kcms/desktoptheme/filterproxymodel.h b/kcms/desktoptheme/filterproxymodel.h new file mode 100644 --- /dev/null +++ b/kcms/desktoptheme/filterproxymodel.h @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2019 Kai Uwe Broulik + * Copyright (c) 2019 David Redondo + * + * 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) version 3 or any later version + * accepted by the membership of KDE e.V. (or its successor approved + * by the membership of KDE e.V.), which shall act as a proxy + * defined in Section 14 of version 3 of the license. + * + * 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 . + */ + +#pragma once + +#include + +#include "kcm.h" + +class FilterProxyModel : public QSortFilterProxyModel +{ + Q_OBJECT + +public: + + enum ThemeFilter { + AllThemes, + LightThemes, + DarkThemes, + ThemesFollowingColors + }; + Q_ENUM(ThemeFilter) + + Q_PROPERTY(QString selectedTheme READ selectedTheme WRITE setSelectedTheme NOTIFY selectedThemeChanged) + Q_PROPERTY(int selectedThemeIndex READ selectedThemeIndex NOTIFY selectedThemeIndexChanged) + Q_PROPERTY(QString query READ query WRITE setQuery NOTIFY queryChanged) + Q_PROPERTY(ThemeFilter filter READ filter WRITE setFilter NOTIFY filterChanged) + + FilterProxyModel(QObject *parent = nullptr); + ~FilterProxyModel() override; + + QString selectedTheme() const; + void setSelectedTheme(const QString &pluginName); + + int selectedThemeIndex() const; + + QString query() const; + void setQuery(const QString &query); + + ThemeFilter filter() const; + void setFilter(ThemeFilter filter); + + bool filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const override; + +Q_SIGNALS: + void filterChanged(); + void queryChanged(); + + void selectedThemeChanged(); + void selectedThemeIndexChanged(); + +private: + QString m_selectedTheme; + QString m_query; + ThemeFilter m_filter = AllThemes; +}; diff --git a/kcms/colors/filterproxymodel.cpp b/kcms/desktoptheme/filterproxymodel.cpp copy from kcms/colors/filterproxymodel.cpp copy to kcms/desktoptheme/filterproxymodel.cpp --- a/kcms/colors/filterproxymodel.cpp +++ b/kcms/desktoptheme/filterproxymodel.cpp @@ -1,5 +1,6 @@ /* * Copyright (C) 2019 Kai Uwe Broulik + * Copyright (c) 2019 David Redondo * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as @@ -20,39 +21,39 @@ #include "filterproxymodel.h" -#include "colorsmodel.h" +#include "themesmodel.h" FilterProxyModel::FilterProxyModel(QObject *parent) : QSortFilterProxyModel(parent) { } FilterProxyModel::~FilterProxyModel() = default; -QString FilterProxyModel::selectedScheme() const +QString FilterProxyModel::selectedTheme() const { - return m_selectedScheme; + return m_selectedTheme; } -void FilterProxyModel::setSelectedScheme(const QString &scheme) +void FilterProxyModel::setSelectedTheme(const QString &pluginName) { - if (m_selectedScheme == scheme) { + if (m_selectedTheme == pluginName) { return; } - const bool firstTime = m_selectedScheme.isNull(); - m_selectedScheme = scheme; + const bool firstTime = m_selectedTheme.isNull(); + m_selectedTheme = pluginName; if (!firstTime) { - emit selectedSchemeChanged(); + emit selectedThemeChanged(); } - emit selectedSchemeIndexChanged(); + emit selectedThemeIndexChanged(); } -int FilterProxyModel::selectedSchemeIndex() const +int FilterProxyModel::selectedThemeIndex() const { // We must search in the source model and then map the index to our proxy model. - const auto results = sourceModel()->match(sourceModel()->index(0, 0), ColorsModel::SchemeNameRole, m_selectedScheme); + const auto results = sourceModel()->match(sourceModel()->index(0, 0), ThemesModel::PluginNameRole, m_selectedTheme); if (results.count() == 1) { const QModelIndex result = mapFromSource(results.first()); @@ -72,61 +73,61 @@ void FilterProxyModel::setQuery(const QString &query) { if (m_query != query) { - const int oldIndex = selectedSchemeIndex(); + const int oldIndex = selectedThemeIndex(); m_query = query; invalidateFilter(); emit queryChanged(); - if (selectedSchemeIndex() != oldIndex) { - emit selectedSchemeIndexChanged(); + if (selectedThemeIndex() != oldIndex) { + emit selectedThemeIndexChanged(); } } } -KCMColors::SchemeFilter FilterProxyModel::filter() const +FilterProxyModel::ThemeFilter FilterProxyModel::filter() const { return m_filter; } -void FilterProxyModel::setFilter(KCMColors::SchemeFilter filter) +void FilterProxyModel::setFilter(ThemeFilter filter) { if (m_filter != filter) { - const int oldIndex = selectedSchemeIndex(); + const int oldIndex = selectedThemeIndex(); m_filter = filter; invalidateFilter(); emit filterChanged(); - if (selectedSchemeIndex() != oldIndex) { - emit selectedSchemeIndexChanged(); + if (selectedThemeIndex() != oldIndex) { + emit selectedThemeIndexChanged(); } } } -bool FilterProxyModel::filterAcceptsRow(int source_row, const QModelIndex &source_parent) const +bool FilterProxyModel::filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const { - const QModelIndex idx = sourceModel()->index(source_row, 0, source_parent); + const QModelIndex idx = sourceModel()->index(sourceRow, 0, sourceParent); if (!m_query.isEmpty()) { if (!idx.data(Qt::DisplayRole).toString().contains(m_query, Qt::CaseInsensitive) - && !idx.data(KCMColors::SchemeNameRole).toString().contains(m_query, Qt::CaseInsensitive)) { + && !idx.data(ThemesModel::PluginNameRole).toString().contains(m_query, Qt::CaseInsensitive)) { return false; } } - if (m_filter != KCMColors::AllSchemes) { - const QPalette palette = idx.data(KCMColors::PaletteRole).value(); - - const int windowBackgroundGray = qGray(palette.window().color().rgb()); - - if (m_filter == KCMColors::DarkSchemes) { - return windowBackgroundGray < 192; - } else if (m_filter == KCMColors::LightSchemes) { - return windowBackgroundGray >= 192; - } + const auto type = idx.data(ThemesModel::ColorTypeRole).value(); + switch (m_filter) { + case AllThemes: + return true; + case LightThemes: + return type == ThemesModel::LightTheme; + case DarkThemes: + return type == ThemesModel::DarkTheme; + case ThemesFollowingColors: + return type == ThemesModel::FollowsColorTheme; } return true; diff --git a/kcms/desktoptheme/kcm.h b/kcms/desktoptheme/kcm.h --- a/kcms/desktoptheme/kcm.h +++ b/kcms/desktoptheme/kcm.h @@ -25,8 +25,6 @@ #include -#include - class QTemporaryFile; namespace Plasma { @@ -39,44 +37,35 @@ } class QQuickItem; -class QStandardItemModel; class DesktopThemeSettings; +class FilterProxyModel; +class ThemesModel; class KCMDesktopTheme : public KQuickAddons::ManagedConfigModule { Q_OBJECT + Q_PROPERTY(DesktopThemeSettings *desktopThemeSettings READ desktopThemeSettings CONSTANT) - Q_PROPERTY(QStandardItemModel *desktopThemeModel READ desktopThemeModel CONSTANT) + Q_PROPERTY(FilterProxyModel *filteredModel READ filteredModel CONSTANT) + Q_PROPERTY(ThemesModel *desktopThemeModel READ desktopThemeModel CONSTANT) Q_PROPERTY(bool downloadingFile READ downloadingFile NOTIFY downloadingFileChanged) Q_PROPERTY(bool canEditThemes READ canEditThemes CONSTANT) public: - enum Roles { - PluginNameRole = Qt::UserRole + 1, - ThemeNameRole, - DescriptionRole, - IsLocalRole, - PendingDeletionRole - }; - Q_ENUM(Roles) KCMDesktopTheme(QObject *parent, const QVariantList &args); ~KCMDesktopTheme() override; DesktopThemeSettings *desktopThemeSettings() const; - QStandardItemModel *desktopThemeModel() const; - - Q_INVOKABLE int pluginIndex(const QString &pluginName) const; + ThemesModel *desktopThemeModel() const; + FilterProxyModel *filteredModel() const; bool downloadingFile() const; bool canEditThemes() const; - Q_INVOKABLE void getNewStuff(QQuickItem *ctx); Q_INVOKABLE void installThemeFromFile(const QUrl &url); - Q_INVOKABLE void setPendingDeletion(int index, bool pending); - Q_INVOKABLE void applyPlasmaTheme(QQuickItem *item, const QString &themeName); Q_INVOKABLE void editTheme(const QString &themeName); @@ -101,13 +90,11 @@ DesktopThemeSettings *m_settings; - QStandardItemModel *m_model; - QStringList m_pendingRemoval; + ThemesModel *m_model; + FilterProxyModel *m_filteredModel; QHash m_themes; bool m_haveThemeExplorerInstalled; - QPointer m_newStuffDialog; - QScopedPointer m_tempInstallFile; QPointer m_tempCopyJob; }; diff --git a/kcms/desktoptheme/kcm.cpp b/kcms/desktoptheme/kcm.cpp --- a/kcms/desktoptheme/kcm.cpp +++ b/kcms/desktoptheme/kcm.cpp @@ -25,7 +25,6 @@ #include #include #include -#include #include #include @@ -41,38 +40,46 @@ #include #include -#include - #include "desktopthemesettings.h" +#include "filterproxymodel.h" +#include "themesmodel.h" Q_LOGGING_CATEGORY(KCM_DESKTOP_THEME, "kcm_desktoptheme") K_PLUGIN_FACTORY_WITH_JSON(KCMDesktopThemeFactory, "kcm_desktoptheme.json", registerPlugin();) KCMDesktopTheme::KCMDesktopTheme(QObject *parent, const QVariantList &args) : KQuickAddons::ManagedConfigModule(parent, args) , m_settings(new DesktopThemeSettings(this)) + , m_model(new ThemesModel(this)) + , m_filteredModel(new FilterProxyModel(this)) , m_haveThemeExplorerInstalled(false) { qmlRegisterType(); - qmlRegisterType(); + qmlRegisterUncreatableType("org.kde.private.kcms.desktoptheme", 1, 0, "ThemesModel", "Cannot create ThemesModel"); + qmlRegisterUncreatableType("org.kde.private.kcms.desktoptheme", 1, 0, "FilterProxyModel", "Cannot create FilterProxyModel"); KAboutData* about = new KAboutData(QStringLiteral("kcm_desktoptheme"), i18n("Plasma Style"), QStringLiteral("0.1"), QString(), KAboutLicense::LGPL); about->addAuthor(i18n("David Rosca"), QString(), QStringLiteral("nowrep@gmail.com")); setAboutData(about); setButtons(Apply | Default | Help); - m_model = new QStandardItemModel(this); - QHash roles = m_model->roleNames(); - roles[PluginNameRole] = QByteArrayLiteral("pluginName"); - roles[ThemeNameRole] = QByteArrayLiteral("themeName"); - roles[DescriptionRole] = QByteArrayLiteral("description"); - roles[IsLocalRole] = QByteArrayLiteral("isLocal"); - roles[PendingDeletionRole] = QByteArrayLiteral("pendingDeletion"); - m_model->setItemRoleNames(roles); - m_haveThemeExplorerInstalled = !QStandardPaths::findExecutable(QStringLiteral("plasmathemeexplorer")).isEmpty(); + + connect(m_model, &ThemesModel::pendingDeletionsChanged, this, &KCMDesktopTheme::settingsChanged); + + connect(m_model, &ThemesModel::selectedThemeChanged, this, [this](const QString &pluginName) { + m_settings->setName(pluginName); + }); + + connect(m_settings, &DesktopThemeSettings::nameChanged, this, [this] { + m_model->setSelectedTheme(m_settings->name()); + }); + + connect(m_model, &ThemesModel::selectedThemeChanged, m_filteredModel, &FilterProxyModel::setSelectedTheme); + + m_filteredModel->setSourceModel(m_model); } KCMDesktopTheme::~KCMDesktopTheme() @@ -84,58 +91,21 @@ return m_settings; } -QStandardItemModel *KCMDesktopTheme::desktopThemeModel() const +ThemesModel *KCMDesktopTheme::desktopThemeModel() const { return m_model; } -int KCMDesktopTheme::pluginIndex(const QString &pluginName) const +FilterProxyModel *KCMDesktopTheme::filteredModel() const { - const auto results = m_model->match(m_model->index(0, 0), PluginNameRole, pluginName); - if (results.count() == 1) { - return results.first().row(); - } - - return -1; + return m_filteredModel; } bool KCMDesktopTheme::downloadingFile() const { return m_tempCopyJob; } -void KCMDesktopTheme::setPendingDeletion(int index, bool pending) -{ - QModelIndex idx = m_model->index(index, 0); - - m_model->setData(idx, pending, PendingDeletionRole); - - if (pending && pluginIndex(m_settings->name()) == index) { - // move to the next non-pending theme - const auto nonPending = m_model->match(idx, PendingDeletionRole, false); - m_settings->setName(nonPending.first().data(PluginNameRole).toString()); - } - - settingsChanged(); -} - -void KCMDesktopTheme::getNewStuff(QQuickItem *ctx) -{ - if (!m_newStuffDialog) { - m_newStuffDialog = new KNS3::DownloadDialog(QStringLiteral("plasma-themes.knsrc")); - m_newStuffDialog.data()->setWindowTitle(i18n("Download New Plasma Styles")); - m_newStuffDialog->setWindowModality(Qt::WindowModal); - m_newStuffDialog->winId(); // so it creates the windowHandle(); - connect(m_newStuffDialog.data(), &KNS3::DownloadDialog::accepted, this, &KCMDesktopTheme::load); - } - - if (ctx && ctx->window()) { - m_newStuffDialog->windowHandle()->setTransientParent(ctx->window()); - } - - m_newStuffDialog.data()->show(); -} - void KCMDesktopTheme::installThemeFromFile(const QUrl &url) { if (url.isLocalFile()) { @@ -222,60 +192,8 @@ void KCMDesktopTheme::load() { ManagedConfigModule::load(); - - m_pendingRemoval.clear(); - - // Get all desktop themes - QStringList themes; - const QStringList &packs = QStandardPaths::locateAll(QStandardPaths::GenericDataLocation, QStringLiteral("plasma/desktoptheme"), QStandardPaths::LocateDirectory); - Q_FOREACH (const QString &ppath, packs) { - const QDir cd(ppath); - const QStringList &entries = cd.entryList(QDir::Dirs | QDir::Hidden | QDir::NoDotAndDotDot); - Q_FOREACH (const QString &pack, entries) { - const QString _metadata = ppath + QLatin1Char('/') + pack + QStringLiteral("/metadata.desktop"); - if (QFile::exists(_metadata)) { - themes << _metadata; - } - } - } - - m_model->clear(); - - Q_FOREACH (const QString &theme, themes) { - int themeSepIndex = theme.lastIndexOf(QLatin1Char('/'), -1); - const QString themeRoot = theme.left(themeSepIndex); - int themeNameSepIndex = themeRoot.lastIndexOf(QLatin1Char('/'), -1); - const QString packageName = themeRoot.right(themeRoot.length() - themeNameSepIndex - 1); - - KDesktopFile df(theme); - - if (df.noDisplay()) { - continue; - } - - QString name = df.readName(); - if (name.isEmpty()) { - name = packageName; - } - const bool isLocal = QFileInfo(theme).isWritable(); - - if (m_model->findItems(packageName).isEmpty()) { - QStandardItem *item = new QStandardItem; - item->setText(packageName); - item->setData(packageName, PluginNameRole); - item->setData(name, ThemeNameRole); - item->setData(df.readComment(), DescriptionRole); - item->setData(isLocal, IsLocalRole); - item->setData(false, PendingDeletionRole); - m_model->appendRow(item); - } - } - - m_model->setSortRole(ThemeNameRole); // FIXME the model should really be just using Qt::DisplayRole - m_model->sort(0 /*column*/); - - // Model has been cleared so pretend the theme name changed to force view update - emit m_settings->nameChanged(); + m_model->load(); + m_model->setSelectedTheme(m_settings->name()); } void KCMDesktopTheme::save() @@ -290,9 +208,9 @@ ManagedConfigModule::defaults(); // can this be done more elegantly? - const auto pendingDeletions = m_model->match(m_model->index(0, 0), PendingDeletionRole, true); + const auto pendingDeletions = m_model->match(m_model->index(0, 0), ThemesModel::PendingDeletionRole, true); for (const QModelIndex &idx : pendingDeletions) { - m_model->setData(idx, false, PendingDeletionRole); + m_model->setData(idx, false, ThemesModel::PendingDeletionRole); } } @@ -308,23 +226,23 @@ bool KCMDesktopTheme::isSaveNeeded() const { - return !m_model->match(m_model->index(0, 0), PendingDeletionRole, true).isEmpty(); + return !m_model->match(m_model->index(0, 0), ThemesModel::PendingDeletionRole, true).isEmpty(); } void KCMDesktopTheme::processPendingDeletions() { const QString program = QStringLiteral("plasmapkg2"); - const auto pendingDeletions = m_model->match(m_model->index(0, 0), PendingDeletionRole, true, -1 /*all*/); + const auto pendingDeletions = m_model->match(m_model->index(0, 0), ThemesModel::PendingDeletionRole, true, -1 /*all*/); QVector persistentPendingDeletions; // turn into persistent model index so we can delete as we go std::transform(pendingDeletions.begin(), pendingDeletions.end(), std::back_inserter(persistentPendingDeletions), [](const QModelIndex &idx) { return QPersistentModelIndex(idx); }); for (const QPersistentModelIndex &idx : persistentPendingDeletions) { - const QString pluginName = idx.data(PluginNameRole).toString(); + const QString pluginName = idx.data(ThemesModel::PluginNameRole).toString(); const QString displayName = idx.data(Qt::DisplayRole).toString(); Q_ASSERT(pluginName != m_settings->name()); @@ -340,7 +258,7 @@ } else { emit showErrorMessage(i18n("Removing theme failed: %1", QString::fromLocal8Bit(process->readAllStandardOutput().trimmed()))); - m_model->setData(idx, false, PendingDeletionRole); + m_model->setData(idx, false, ThemesModel::PendingDeletionRole); } process->deleteLater(); }); diff --git a/kcms/desktoptheme/kcm_desktoptheme.desktop b/kcms/desktoptheme/kcm_desktoptheme.desktop --- a/kcms/desktoptheme/kcm_desktoptheme.desktop +++ b/kcms/desktoptheme/kcm_desktoptheme.desktop @@ -13,6 +13,7 @@ Name=Plasma Style Name[ca]=Estil del Plasma Name[cs]=Styl Plasma +Name[da]=Plasma-stil Name[de]=Plasma-Stil Name[en_GB]=Plasma Style Name[es]=Estilo de Plasma @@ -29,6 +30,7 @@ Name[lt]=Plasma stilius Name[nl]=Plasma-stijl Name[nn]=Plasma-stil +Name[pa]=ਪਲਾਜ਼ਮਾ ਸਟਾਈਲ Name[pl]=Wygląd Plazmy Name[pt]=Estilo do Plasma Name[pt_BR]=Estilo do Plasma @@ -43,6 +45,7 @@ Comment=Choose Plasma style Comment[ca]=Trieu l'estil del Plasma Comment[cs]=Zvolte styl Plasma +Comment[da]=Vælg Plasma-stil Comment[de]=Plasma-Stil auswählen Comment[en_GB]=Choose Plasma style Comment[es]=Escoger el estilo de Plasma @@ -59,6 +62,7 @@ Comment[lt]=Pasirinkti Plasma stilių Comment[nl]=Plasma-stijl kiezen Comment[nn]=Vel Plasma-stil +Comment[pa]=ਪਲਾਜ਼ਮਾ ਸਟਾਈਲ ਚੁਣੋ Comment[pl]=Wybierz wygląd Plazmy Comment[pt]=Escolher o estilo do Plasma Comment[pt_BR]=Escolha o estilo do Plasma @@ -73,6 +77,7 @@ X-KDE-Keywords=Desktop Theme,Plasma Theme X-KDE-Keywords[ca]=Tema d'escriptori, Tema del Plasma X-KDE-Keywords[cs]=Motiv plochy, motiv Plasma +X-KDE-Keywords[da]=Skrivebordstema,Plasma-tema X-KDE-Keywords[de]=Arbeitsflächen-Design, Plasma-Design X-KDE-Keywords[en_GB]=Desktop Theme,Plasma Theme X-KDE-Keywords[es]=Tema de escritorio,Tema de Plasma @@ -88,6 +93,7 @@ X-KDE-Keywords[lt]=Darbalaukio apipavidalinimas,Plasma apipavidalinimas X-KDE-Keywords[nl]=Bureaubladthema,Plasma-thema X-KDE-Keywords[nn]=Skrivebordstema,Plasma-tema +X-KDE-Keywords[pa]=ਡੈਸਕਟਾਪ ਥੀਮ,ਪਲਾਜ਼ਮਾ ਸਟਾਈਲ X-KDE-Keywords[pl]=Wygląd pulpitu,Wygląd Plazmy X-KDE-Keywords[pt]=Tema do Ambiente de Trabalho,Tema do Plasma X-KDE-Keywords[pt_BR]=Tema da área de trabalho,tema do Plasma diff --git a/kcms/desktoptheme/package/contents/ui/ThemePreview.qml b/kcms/desktoptheme/package/contents/ui/ThemePreview.qml --- a/kcms/desktoptheme/package/contents/ui/ThemePreview.qml +++ b/kcms/desktoptheme/package/contents/ui/ThemePreview.qml @@ -20,6 +20,7 @@ import org.kde.plasma.core 2.0 as PlasmaCore import org.kde.kirigami 2.4 as Kirigami import org.kde.plasma.components 2.0 as PlasmaComponents +import org.kde.private.kcms.desktoptheme 1.0 as Private Item { id: root @@ -52,6 +53,7 @@ RowLayout { id: contents + spacing: 0 anchors { fill: parent topMargin: background.generalMargin @@ -84,16 +86,13 @@ } } - Item { - Layout.fillWidth: true - } - // Analog clock Item { id: clock Layout.fillHeight: true + Layout.fillWidth: true Layout.preferredWidth: height - + Layout.alignment: Qt.AlignHCenter property int hours: 9 property int minutes: 5 @@ -177,6 +176,13 @@ height: naturalSize.height * clock.svgScale } } + Kirigami.Icon { + visible: model.colorType === Private.ThemesModel.FollowsColorTheme + source: "color-profile" + width: Kirigami.Units.iconSizes.smallMedium + height: width + Layout.alignment: Qt.AlignRight && Qt.AlignTop + } } Component.onCompleted: { diff --git a/kcms/desktoptheme/package/contents/ui/main.qml b/kcms/desktoptheme/package/contents/ui/main.qml --- a/kcms/desktoptheme/package/contents/ui/main.qml +++ b/kcms/desktoptheme/package/contents/ui/main.qml @@ -24,14 +24,28 @@ import QtQuick.Dialogs 1.0 import QtQuick.Controls 2.3 as QtControls import org.kde.kirigami 2.4 as Kirigami -import org.kde.kconfig 1.0 // for KAuthorized +import org.kde.newstuff 1.62 as NewStuff import org.kde.kcm 1.1 as KCM +import org.kde.private.kcms.desktoptheme 1.0 as Private + KCM.GridViewKCM { KCM.ConfigModule.quickHelp: i18n("This module lets you choose the Plasma style.") - view.model: kcm.desktopThemeModel - view.currentIndex: kcm.pluginIndex(kcm.desktopThemeSettings.name) + view.model: kcm.filteredModel + view.currentIndex: kcm.filteredModel.selectedThemeIndex + + Binding { + target: kcm.filteredModel + property: "query" + value: searchField.text + } + + Binding { + target: kcm.filteredModel + property: "filter" + value: filterCombo.model[filterCombo.currentIndex].filter + } enabled: !kcm.downloadingFile && !kcm.desktopThemeSettings.isImmutable("name") @@ -44,12 +58,81 @@ } onDropped: kcm.installThemeFromFile(drop.urls[0]) } + header: RowLayout { + Layout.fillWidth: true + + QtControls.TextField { + id: searchField + Layout.fillWidth: true + placeholderText: i18n("Search...") + leftPadding: LayoutMirroring.enabled ? clearButton.width : undefined + rightPadding: LayoutMirroring.enabled ? undefined : clearButton.width + // this could be useful as a component + MouseArea { + id: clearButton + anchors { + top: parent.top + topMargin: parent.topPadding + right: parent.right + // the TextField's padding is taking into account the clear button's size + // so we just use the opposite one for positioning the clear button + rightMargin: LayoutMirroring.enabled ? parent.rightPadding: parent.leftPadding + bottom: parent.bottom + bottomMargin: parent.bottomPadding + } + width: height + + opacity: searchField.length > 0 ? 1 : 0 + onClicked: searchField.clear() + + Kirigami.Icon { + anchors.fill: parent + active: parent.pressed + source: "edit-clear-locationbar-" + (LayoutMirroring.enabled ? "ltr" : "rtl") + } + + Behavior on opacity { + NumberAnimation { duration: Kirigami.Units.longDuration } + } + } + } + QtControls.ComboBox { + id: filterCombo + textRole: "text" + model: [ + {text: i18n("All Themes"), filter: Private.FilterProxyModel.AllThemes}, + {text: i18n("Light Themes"), filter: Private.FilterProxyModel.LightThemes}, + {text: i18n("Dark Themes"), filter: Private.FilterProxyModel.DarkThemes}, + {text: i18n("Color scheme compatible"), filter: Private.FilterProxyModel.ThemesFollowingColors} + ] + + // HACK QQC2 doesn't support icons, so we just tamper with the desktop style ComboBox's background + // and inject a nice little filter icon. + Component.onCompleted: { + if (!background || !background.hasOwnProperty("properties")) { + // not a KQuickStyleItem + return; + } + + var props = background.properties || {}; + + background.properties = Qt.binding(function() { + var newProps = props; + newProps.currentIcon = "view-filter"; + newProps.iconColor = Kirigami.Theme.textColor; + return newProps; + }); + } + } + } view.delegate: KCM.GridDelegate { id: delegate - text: model.themeName - toolTip: model.description || model.themeName + text: model.display + subtitle: model.colorType == Private.ThemesModel.FollowsColorTheme + && view.model.filter != Private.FilterProxyModel.ThemesFollowingColors ? i18n("Follows color scheme") : "" + toolTip: model.description || model.display opacity: model.pendingDeletion ? 0.3 : 1 Behavior on opacity { @@ -76,13 +159,13 @@ tooltip: i18n("Remove Theme") enabled: model.isLocal visible: !model.pendingDeletion - onTriggered: kcm.setPendingDeletion(model.index, true); + onTriggered: model.pendingDeletion = true; }, Kirigami.Action { iconName: "edit-undo" tooltip: i18n("Restore Theme") visible: model.pendingDeletion - onTriggered: kcm.setPendingDeletion(model.index, false); + onTriggered: model.pendingDeletion = false; } ] @@ -123,11 +206,12 @@ onClicked: fileDialogLoader.active = true; } - QtControls.Button { - text: i18n("Get New Plasma Styles...") - icon.name: "get-hot-new-stuff" - onClicked: kcm.getNewStuff(this) - visible: KAuthorized.authorize("ghns") + NewStuff.Button { + id: newStuffButton + downloadNewWhat: i18n("Plasma Styles") + configFile: "plasma-themes.knsrc" + viewMode: NewStuff.Page.ViewMode.Preview + onChangedEntriesChanged: kcm.load(); } } } diff --git a/kcms/desktoptheme/package/metadata.desktop b/kcms/desktoptheme/package/metadata.desktop --- a/kcms/desktoptheme/package/metadata.desktop +++ b/kcms/desktoptheme/package/metadata.desktop @@ -2,6 +2,7 @@ Name=Plasma Style Name[ca]=Estil del Plasma Name[cs]=Styl Plasma +Name[da]=Plasma-stil Name[de]=Plasma-Stil Name[en_GB]=Plasma Style Name[es]=Estilo de Plasma @@ -18,6 +19,7 @@ Name[lt]=Plasma stilius Name[nl]=Plasma-stijl Name[nn]=Plasma-stil +Name[pa]=ਪਲਾਜ਼ਮਾ ਸਟਾਈਲ Name[pl]=Wygląd Plazmy Name[pt]=Estilo do Plasma Name[pt_BR]=Estilo do Plasma @@ -33,6 +35,7 @@ Comment[ca]=Trieu el tema del Plasma Comment[ca@valencia]=Trieu el tema del Plasma Comment[cs]=Zvolte motiv Plasma +Comment[da]=Vælg Plasma-tema Comment[de]=Plasma-Design auswählen Comment[en_GB]=Choose Plasma theme Comment[es]=Escoger un tema de Plasma @@ -49,6 +52,7 @@ Comment[lt]=Pasirinkti Plasma apipavidalinimą Comment[nl]=Plasma-thema kiezen Comment[nn]=Vel Plasma-tema +Comment[pa]=ਪਲਾਜ਼ਮਾ ਸਟਾਈਲ ਚੁਣੋ Comment[pl]=Wybierz wygląd Plazmy Comment[pt]=Escolher o tema do Plasma Comment[pt_BR]=Escolha o tema do Plasma diff --git a/kcms/desktoptheme/plasma-themes.knsrc b/kcms/desktoptheme/plasma-themes.knsrc --- a/kcms/desktoptheme/plasma-themes.knsrc +++ b/kcms/desktoptheme/plasma-themes.knsrc @@ -2,6 +2,7 @@ Name=Plasma Styles Name[ca]=Estils del Plasma Name[cs]=Styly Plasma +Name[da]=Plasma-stile Name[de]=Plasma-Stile Name[en_GB]=Plasma Styles Name[es]=Estilos de Plasma @@ -18,6 +19,7 @@ Name[lt]=Plasma stiliai Name[nl]=Plasma-stijlen Name[nn]=Plasma-stilar +Name[pa]=ਪਲਾਜ਼ਮਾ ਸਟਾਈਲ Name[pl]=Wyglądy Plazmy Name[pt]=Estilos do Plasma Name[pt_BR]=Estilos do Plasma diff --git a/kcms/desktoptheme/themesmodel.h b/kcms/desktoptheme/themesmodel.h new file mode 100644 --- /dev/null +++ b/kcms/desktoptheme/themesmodel.h @@ -0,0 +1,102 @@ +/* + * Copyright (C) 2007 Matthew Woehlke + * Copyright (C) 2007 Jeremy Whiting + * Copyright (C) 2016 Olivier Churlaud + * Copyright (C) 2019 Kai Uwe Broulik + * Copyright (C) 2019 David Redondo + * + * 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) version 3 or any later version + * accepted by the membership of KDE e.V. (or its successor approved + * by the membership of KDE e.V.), which shall act as a proxy + * defined in Section 14 of version 3 of the license. + * + * 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 . + */ + +#pragma once + +#include +#include +#include +#include + +#include + +struct ThemesModelData; + +class ThemesModel : public QAbstractListModel +{ + Q_OBJECT + + Q_PROPERTY(QString selectedTheme READ selectedTheme WRITE setSelectedTheme NOTIFY selectedThemeChanged) + Q_PROPERTY(int selectedThemeIndex READ selectedThemeIndex NOTIFY selectedThemeChanged) + +public: + ThemesModel(QObject *parent); + ~ThemesModel() override; + + enum Roles { + PluginNameRole = Qt::UserRole + 1, + ThemeNameRole, + DescriptionRole, + FollowsSystemColorsRole, + ColorTypeRole, + IsLocalRole, + PendingDeletionRole + }; + Q_ENUM(Roles) + enum ColorType { + LightTheme, + DarkTheme, + FollowsColorTheme + }; + Q_ENUM(ColorType) + + + int rowCount(const QModelIndex &parent = QModelIndex()) const override; + QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override; + bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole) override; + QHash roleNames() const override; + + QString selectedTheme() const; + void setSelectedTheme(const QString &pluginName); + + int pluginIndex(const QString &pluginName) const; + int selectedThemeIndex() const; + + QStringList pendingDeletions() const; + void removeRow(int row); + + void load(); + +Q_SIGNALS: + void selectedThemeChanged(const QString &pluginName); + void selectedThemeIndexChanged(); + + void pendingDeletionsChanged(); + +private: + QString m_selectedTheme; + //Can't use QVector because unique_ptr causes deletion of copy-ctor + QVector m_data; + +}; + +struct ThemesModelData +{ + QString display; + QString pluginName; + QString description; + ThemesModel::ColorType type; + bool isLocal; + bool pendingDeletion; +}; diff --git a/kcms/desktoptheme/themesmodel.cpp b/kcms/desktoptheme/themesmodel.cpp new file mode 100644 --- /dev/null +++ b/kcms/desktoptheme/themesmodel.cpp @@ -0,0 +1,251 @@ +/* + * Copyright (C) 2007 Matthew Woehlke + * Copyright (C) 2007 Jeremy Whiting + * Copyright (C) 2016 Olivier Churlaud + * Copyright (C) 2019 Kai Uwe Broulik + * Copyright (C) 2019 David Redondo + * + * 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) version 3 or any later version + * accepted by the membership of KDE e.V. (or its successor approved + * by the membership of KDE e.V.), which shall act as a proxy + * defined in Section 14 of version 3 of the license. + * + * 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 . + */ + +#include "themesmodel.h" + +#include +#include +#include + +#include +#include + +#include +#include + +#include +#include + +ThemesModel::ThemesModel(QObject *parent) : QAbstractListModel(parent) +{ + +} + +ThemesModel::~ThemesModel() = default; + +int ThemesModel::rowCount(const QModelIndex &parent) const +{ + if (parent.isValid()) { + return 0; + } + + return m_data.count(); +} + +QVariant ThemesModel::data(const QModelIndex &index, int role) const +{ + if (!index.isValid() || index.row() >= m_data.count()) { + return QVariant(); + } + + const auto &item = m_data.at(index.row()); + + switch (role) { + case Qt::DisplayRole: return item.display; + case PluginNameRole: return item.pluginName; + case DescriptionRole: return item.description; + case ColorTypeRole: return item.type; + case IsLocalRole: return item.isLocal; + case PendingDeletionRole: return item.pendingDeletion; + } + return QVariant(); +} + +bool ThemesModel::setData(const QModelIndex &index, const QVariant &value, int role) +{ + if (!index.isValid() || index.row() >= m_data.count()) { + return false; + } + + if (role == PendingDeletionRole) { + auto &item = m_data[index.row()]; + + const bool pendingDeletion = value.toBool(); + + if (item.pendingDeletion != pendingDeletion) { + item.pendingDeletion = pendingDeletion; + emit dataChanged(index, index, {PendingDeletionRole}); + + if (index.row() == selectedThemeIndex() && pendingDeletion) { + // move to the next non-pending theme + const auto nonPending = match(index, PendingDeletionRole, false); + if (!nonPending.isEmpty()) { + setSelectedTheme(nonPending.first().data(PluginNameRole).toString()); + } + } + + emit pendingDeletionsChanged(); + return true; + } + } + + return false; +} + +QHash ThemesModel::roleNames() const +{ + return { + {Qt::DisplayRole, QByteArrayLiteral("display")}, + {PluginNameRole, QByteArrayLiteral("pluginName")}, + {DescriptionRole, QByteArrayLiteral("description")}, + {ColorTypeRole, QByteArrayLiteral("colorType")}, + {IsLocalRole, QByteArrayLiteral("isLocal")}, + {PendingDeletionRole, QByteArrayLiteral("pendingDeletion")} + }; +} + +QString ThemesModel::selectedTheme() const +{ + return m_selectedTheme; +} + +void ThemesModel::setSelectedTheme(const QString &pluginName) +{ + if (m_selectedTheme == pluginName) { + return; + } + + m_selectedTheme = pluginName; + + emit selectedThemeChanged(pluginName); + + emit selectedThemeIndexChanged(); +} + +int ThemesModel::pluginIndex(const QString &pluginName) const +{ + const auto results = match(index(0, 0), PluginNameRole, pluginName); + if (results.count() == 1) { + return results.first().row(); + } + + return -1; +} + +int ThemesModel::selectedThemeIndex() const +{ + return pluginIndex(m_selectedTheme); +} + +void ThemesModel::load() +{ + beginResetModel(); + + const int oldCount = m_data.count(); + + m_data.clear(); + + // Get all desktop themes + QStringList themes; + const QStringList packs = QStandardPaths::locateAll(QStandardPaths::GenericDataLocation, QStringLiteral("plasma/desktoptheme"), QStandardPaths::LocateDirectory); + for(const QString &ppath : packs) { + const QDir cd(ppath); + const QStringList &entries = cd.entryList(QDir::Dirs | QDir::Hidden | QDir::NoDotAndDotDot); + for (const QString &pack : entries) { + const QString _metadata = ppath + QLatin1Char('/') + pack + QStringLiteral("/metadata.desktop"); + if (QFile::exists(_metadata)) { + themes << _metadata; + } + } + } + + for (const QString &theme : qAsConst(themes)) { + int themeSepIndex = theme.lastIndexOf(QLatin1Char('/'), -1); + const QString themeRoot = theme.left(themeSepIndex); + int themeNameSepIndex = themeRoot.lastIndexOf(QLatin1Char('/'), -1); + const QString packageName = themeRoot.right(themeRoot.length() - themeNameSepIndex - 1); + + KDesktopFile df(theme); + + if (df.noDisplay()) { + continue; + } + + QString name = df.readName(); + if (name.isEmpty()) { + name = packageName; + } + const bool isLocal = QFileInfo(theme).isWritable(); + bool hasPluginName = std::any_of(m_data.begin(), m_data.end(), [&] (const ThemesModelData &item) { + return item.pluginName == packageName; + }); + if (!hasPluginName) { + // Plasma Theme creates a KColorScheme out of the "color" file and falls back to system colors if there is none + const QString colorsPath = themeRoot + QLatin1String("/colors"); + const bool followsSystemColors = !QFileInfo::exists(colorsPath); + ColorType type = FollowsColorTheme; + if (!followsSystemColors) { + const KSharedConfig::Ptr config = KSharedConfig::openConfig(colorsPath); + const QPalette palette = KColorScheme::createApplicationPalette(config); + const int windowBackgroundGray = qGray(palette.window().color().rgb()); + if (windowBackgroundGray < 192) { + type = DarkTheme; + } else { + type = LightTheme; + } + } + ThemesModelData item { + name, + packageName, + df.readComment(), + type, + isLocal, + false + }; + m_data.append(item); + } + } + + QCollator collator; + std::sort(m_data.begin(), m_data.end(), [&collator](const ThemesModelData &a, const ThemesModelData &b) { + return collator.compare(a.display, b.display) < 0; + }); + + endResetModel(); + + // an item might have been added before the currently selected one + if (oldCount != m_data.count()) { + emit selectedThemeIndexChanged(); + } +} + +QStringList ThemesModel::pendingDeletions() const +{ + QStringList pendingDeletions; + + for (const auto &item : qAsConst(m_data)) { + if (item.pendingDeletion) { + pendingDeletions.append(item.pluginName); + } + } + + return pendingDeletions; +} + +void ThemesModel::removeRow(int row) +{ + beginRemoveRows(QModelIndex(), row, row); + m_data.erase(m_data.begin() + row); + endRemoveRows(); +} diff --git a/kcms/emoticons/emoticons.desktop b/kcms/emoticons/emoticons.desktop --- a/kcms/emoticons/emoticons.desktop +++ b/kcms/emoticons/emoticons.desktop @@ -98,6 +98,7 @@ Comment[ca]=Trieu el tema de les emoticones Comment[ca@valencia]=Trieu el tema de les emoticones Comment[cs]=Vyberte motiv emotikonů +Comment[da]=Vælg emotikontema Comment[de]=Emoticon-Design auswählen Comment[en_GB]=Choose emoticon theme Comment[es]=Escoger un tema de emoticonos @@ -114,6 +115,7 @@ Comment[lt]=Pasirinkti jaustukų apipavidalinimą Comment[nl]=Emoticonthema kiezen Comment[nn]=Vel fjesingtema +Comment[pa]=ਈਮੋਸ਼ਨ ਥੀਮ ਚੁਣੋ Comment[pl]=Wybierz zestaw emotikon Comment[pt]=Escolher o tema de ícones emotivos Comment[pt_BR]=Escolha o tema de emoticons diff --git a/kcms/fonts/fonts.h b/kcms/fonts/fonts.h --- a/kcms/fonts/fonts.h +++ b/kcms/fonts/fonts.h @@ -31,7 +31,7 @@ #include #include -#include +#include #include "kxftconfig.h" @@ -134,7 +134,7 @@ /** * The Desktop/fonts tab in kcontrol. */ -class KFonts : public KQuickAddons::ConfigModule +class KFonts : public KQuickAddons::ManagedConfigModule { Q_OBJECT Q_PROPERTY(FontsSettings *fontsSettings READ fontsSettings CONSTANT) @@ -158,7 +158,7 @@ void fontsHaveChanged(); private: - void updateNeedsSave(); + bool isSaveNeeded() const override ; QFont applyFontDiff(const QFont &fnt, const QFont &newFont, int fontDiffFlags); void setNearestExistingFonts(); diff --git a/kcms/fonts/fonts.cpp b/kcms/fonts/fonts.cpp --- a/kcms/fonts/fonts.cpp +++ b/kcms/fonts/fonts.cpp @@ -45,7 +45,6 @@ #include #include #include -#include #include "../krdb/krdb.h" #include "previewimageprovider.h" @@ -498,7 +497,7 @@ /**** KFonts ****/ KFonts::KFonts(QObject *parent, const QVariantList &args) - : KQuickAddons::ConfigModule(parent, args) + : KQuickAddons::ManagedConfigModule(parent, args) , m_settings(new FontsSettings(this)) , m_fontAASettings(new FontAASettings(this)) { @@ -515,14 +514,6 @@ setNeedsSave(m_fontAASettings->needsSave()); }; - connect(m_settings, &FontsSettings::configChanged, this, &KFonts::updateNeedsSave); - connect(m_settings, &FontsSettings::fontChanged, this, &KFonts::updateNeedsSave); - connect(m_settings, &FontsSettings::fixedChanged, this, &KFonts::updateNeedsSave); - connect(m_settings, &FontsSettings::smallestReadableFontChanged, this, &KFonts::updateNeedsSave); - connect(m_settings, &FontsSettings::toolBarFontChanged, this, &KFonts::updateNeedsSave); - connect(m_settings, &FontsSettings::menuFontChanged, this, &KFonts::updateNeedsSave); - connect(m_settings, &FontsSettings::activeFontChanged, this, &KFonts::updateNeedsSave); - connect(m_fontAASettings, &FontAASettings::subPixelCurrentIndexChanged, this, updateState); connect(m_fontAASettings, &FontAASettings::hintingCurrentIndexChanged, this, updateState); connect(m_fontAASettings, &FontAASettings::excludeChanged, this, updateState); @@ -544,7 +535,7 @@ void KFonts::defaults() { - m_settings->setDefaults(); + ManagedConfigModule::defaults(); m_fontAASettings->defaults(); } @@ -561,7 +552,7 @@ void KFonts::load() { // first load all the settings - m_settings->load(); + ManagedConfigModule::load(); m_fontAASettings->load(); // Then set the existing fonts based on those settings @@ -573,12 +564,13 @@ // previews engine()->addImageProvider("preview", new PreviewImageProvider(m_settings->font())); - setNeedsSave(false); + // reload state after loading by emiting a settings signal + emit m_settings->activeFontChanged(); } void KFonts::save() { - m_settings->save(); + ManagedConfigModule::save(); KConfig _cfgfonts("kcmfonts"); KConfigGroup cfgfonts(&_cfgfonts, "General"); @@ -602,12 +594,11 @@ runRdb(KRdbExportXftSettings | KRdbExportGtkTheme); emit fontsHaveChanged(); - setNeedsSave(false); } -void KFonts::updateNeedsSave() +bool KFonts::isSaveNeeded() const { - setNeedsSave(m_settings->isSaveNeeded() || m_fontAASettings->needsSave()); + return m_fontAASettings->needsSave(); } void KFonts::adjustAllFonts() @@ -617,13 +608,23 @@ int ret = KFontDialog::getFontDiff(font, fontDiffFlags, KFontChooser::NoDisplayFlags); if (ret == KDialog::Accepted && fontDiffFlags) { - m_settings->setFont(applyFontDiff(m_settings->font(), font, fontDiffFlags)); - m_settings->setMenuFont(applyFontDiff(m_settings->menuFont(), font, fontDiffFlags)); - m_settings->setToolBarFont(applyFontDiff(m_settings->toolBarFont(), font, fontDiffFlags)); - m_settings->setActiveFont(applyFontDiff(m_settings->activeFont(), font, fontDiffFlags)); - m_settings->setSmallestReadableFont(applyFontDiff(m_settings->smallestReadableFont(), font, fontDiffFlags)); + if (!m_settings->isImmutable("font")) { + m_settings->setFont(applyFontDiff(m_settings->font(), font, fontDiffFlags)); + } + if (!m_settings->isImmutable("menuFont")) { + m_settings->setMenuFont(applyFontDiff(m_settings->menuFont(), font, fontDiffFlags)); + } + if (!m_settings->isImmutable("toolBarFont")) { + m_settings->setToolBarFont(applyFontDiff(m_settings->toolBarFont(), font, fontDiffFlags)); + } + if (!m_settings->isImmutable("activeFont")) { + m_settings->setActiveFont(applyFontDiff(m_settings->activeFont(), font, fontDiffFlags)); + } + if (!m_settings->isImmutable("smallestReadableFont")) { + m_settings->setSmallestReadableFont(applyFontDiff(m_settings->smallestReadableFont(), font, fontDiffFlags)); + } const QFont adjustedFont = applyFontDiff(m_settings->fixed(), font, fontDiffFlags); - if (QFontInfo(adjustedFont).fixedPitch()) { + if (QFontInfo(adjustedFont).fixedPitch() && !m_settings->isImmutable("fixed")) { m_settings->setFixed(adjustedFont); } } diff --git a/kcms/fonts/kcm_fonts.desktop b/kcms/fonts/kcm_fonts.desktop --- a/kcms/fonts/kcm_fonts.desktop +++ b/kcms/fonts/kcm_fonts.desktop @@ -108,6 +108,7 @@ Comment[ca]=Configura els tipus de lletra de l'usuari Comment[ca@valencia]=Configura els tipus de lletra de l'usuari Comment[cs]=Nastavte písmo uživatelského rozhraní +Comment[da]=Indstil brugerfladens skrifttyper Comment[de]=Benutzerdefinierte Schriften einrichten Comment[en_GB]=Configure user interface fonts Comment[es]=Configurar los tipos de letra de la interfaz de usuario @@ -124,6 +125,7 @@ Comment[lt]=Konfigūruoti naudotojo sąsajos šriftus Comment[nl]=Lettertypen van gebruikersinterface configureren Comment[nn]=Set opp skrifter for brukargrensesnittet +Comment[pa]=ਵਰਤੋਂਕਾਰ ਇੰਟਰਫੇਸ ਫ਼ੋਂਟਾਂ ਦੀ ਸੰਰਚਨਾ Comment[pl]=Ustawienia czcionek interfejsu użytkownika Comment[pt]=Configurar os tipos de letra da interface do utilizador Comment[pt_BR]=Configurar as fontes da interface do usuário @@ -139,7 +141,7 @@ X-KDE-Keywords=fonts,font size,styles,charsets,character sets,panel,control panel,desktops,FileManager,Toolbars,Menu,Window Title,Title,DPI,anti-aliasing,desktop fonts,toolbar fonts,character,general fonts X-KDE-Keywords[ar]=خطوط,حجم الخط,أنماط,طقم محارف,طقوم محارف,لوحة,لوحة تحكّم,أسطح المكتب,مدير ملفات,أشرطة أدوات,قائمة,عنوان نافذة,عنوان,نقطة/بوصة,DPI,إزالة التسنّن,خطوط سطح المكتب,خطوط شريط الأدوات,محرف,خطوط عامة X-KDE-Keywords[bs]=slova,veličina slova,stil,znakovi,postaviti znakove,ploča,kontrolna ploča,pozadina,upravitelj datoteka,alatne trake,meni,naslov prozora,naslov,DPI,niskopropusni,slova pozadine,slova na alatnoj traci,obilježja,opći fontovi -X-KDE-Keywords[ca]=tipus de lletres,mida de tipus de lletra,estils,joc de caràcters,jocs de caràcters,plafó,plafó de control,escriptoris,Gestor de fitxers,Barres d'eines,Menú,Títol de la finestra,Títol,DPI,antialiàsing,tipus de lletra d'escriptori,tipus de lletra de barra d'eines,caràcter,tipus de lletra general +X-KDE-Keywords[ca]=tipus de lletra,mida de tipus de lletra,estils,joc de caràcters,jocs de caràcters,plafó,plafó de control,escriptoris,Gestor de fitxers,Barres d'eines,Menú,Títol de la finestra,Títol,DPI,antialiàsing,tipus de lletra d'escriptori,tipus de lletra de barra d'eines,caràcter,tipus de lletra general X-KDE-Keywords[ca@valencia]=tipus de lletres,mida de tipus de lletra,estils,joc de caràcters,jocs de caràcters,plafó,plafó de control,escriptoris,Gestor de fitxers,Barres d'eines,Menú,Títol de la finestra,Títol,DPI,antialiàsing,tipus de lletra d'escriptori,tipus de lletra de barra d'eines,caràcter,tipus de lletra general X-KDE-Keywords[da]=skrifttyper,skriftstørrelse,stile,tegnsæt,panel,kontrolpanel,skriveborde,filhåndtering,værktøjslinjer,menu,vinduestitel,titel,DPI,anti-aliasing,værktøjslinjer,tegn X-KDE-Keywords[de]=Schriftarten,Schriftgrößen,Stile,Zeichensätze,Kontrollleiste,Stile,Dateiverwaltung,Arbeitsflächen,Werkzeugleisten,Menüs,Fenstertitel,Titel,DPI,Antialiasing,Arbeitsflächenschriften,Werkzeugleistenschriften,Zeichen,Allgemeine Schriftarten diff --git a/kcms/fonts/package/contents/ui/main.qml b/kcms/fonts/package/contents/ui/main.qml --- a/kcms/fonts/package/contents/ui/main.qml +++ b/kcms/fonts/package/contents/ui/main.qml @@ -55,38 +55,50 @@ text: i18n("&Adjust All Fonts...") onClicked: kcm.adjustAllFonts(); + enabled: !kcm.fontsSettings.isImmutable("font") + || !kcm.fontsSettings.isImmutable("fixed") + || !kcm.fontsSettings.isImmutable("smallestReadableFont") + || !kcm.fontsSettings.isImmutable("toolBarFont") + || !kcm.fontsSettings.isImmutable("menuFont") + || !kcm.fontsSettings.isImmutable("activeFont") } FontWidget { id: generalFontWidget label: i18n("General:") category: "font" font: kcm.fontsSettings.font + enabled: !kcm.fontsSettings.isImmutable("font") } FontWidget { label: i18n("Fixed width:") category: "fixed" font: kcm.fontsSettings.fixed + enabled: !kcm.fontsSettings.isImmutable("fixed") } FontWidget { label: i18n("Small:") category: "smallestReadableFont" font: kcm.fontsSettings.smallestReadableFont + enabled: !kcm.fontsSettings.isImmutable("smallestReadableFont") } FontWidget { label: i18n("Toolbar:") category: "toolBarFont" font: kcm.fontsSettings.toolBarFont + enabled: !kcm.fontsSettings.isImmutable("toolBarFont") } FontWidget { label: i18n("Menu:") category: "menuFont" font: kcm.fontsSettings.menuFont + enabled: !kcm.fontsSettings.isImmutable("menuFont") } FontWidget { label: i18n("Window title:") category: "activeFont" font: kcm.fontsSettings.activeFont + enabled: !kcm.fontsSettings.isImmutable("activeFont") } Kirigami.Separator { diff --git a/kcms/fonts/package/metadata.desktop b/kcms/fonts/package/metadata.desktop --- a/kcms/fonts/package/metadata.desktop +++ b/kcms/fonts/package/metadata.desktop @@ -96,6 +96,7 @@ Comment[ca]=Configura els tipus de lletra de l'usuari Comment[ca@valencia]=Configura els tipus de lletra de l'usuari Comment[cs]=Nastavte písmo uživatelského rozhraní +Comment[da]=Indstil brugerfladens skrifttyper Comment[de]=Benutzerdefinierte Schriften einrichten Comment[en_GB]=Configure user interface fonts Comment[es]=Configurar los tipos de letra de la interfaz de usuario @@ -112,6 +113,7 @@ Comment[lt]=Konfigūruoti naudotojo sąsajos šriftus Comment[nl]=Lettertypen van gebruikersinterface configureren Comment[nn]=Set opp skrifter for brukargrensesnittet +Comment[pa]=ਵਰਤੋਂਕਾਰ ਇੰਟਰਫੇਸ ਫ਼ੋਂਟਾਂ ਦੀ ਸੰਰਚਨਾ Comment[pl]=Ustawienia czcionek interfejsu użytkownika Comment[pt]=Configurar os tipos de letra da interface do utilizador Comment[pt_BR]=Configurar as fontes da interface do usuário diff --git a/kcms/formats/formats.desktop b/kcms/formats/formats.desktop --- a/kcms/formats/formats.desktop +++ b/kcms/formats/formats.desktop @@ -86,7 +86,7 @@ Comment[nds]=Tallen-, Geld- un Tietformaten Comment[nl]=Indeling voor numerieke getallen, valuta en tijd Comment[nn]=Format for tal, valuta og tid -Comment[pa]=ਅੰਕ, ਮੁਦਰਾ ਅਤੇ ਸਮਾਂ ਫਾਰਮੈਟ +Comment[pa]=ਅੰਕੀ, ਕਰੰਸੀ ਅਤੇ ਸਮੇਂ ਦੇ ਫਾਰਮੈਟ Comment[pl]=Formaty liczb, waluty i czasu Comment[pt]=Formatos Numéricos, Monetários e de Datas Comment[pt_BR]=Formatos de data/hora, numérico e monetário @@ -141,7 +141,7 @@ X-KDE-Keywords[nds]=Spraak,Översetten,Tallenformaat,Spraakkoderen,Regiooninstellen,Land,Tekensett,Tekensetten,Dezimaalteken,Trennteken för Dusend,Trenner,Vörteken,positiv,negativ,positiev,negatiev,Geldsort,Geld,Brooktallen,Nakommasteden,Kalenner,Tiet,Datum,Formaten,Week,Wekenanfang,eerst,Papeer,Papeergrött,A4,Meten,Maat,metersch,Eenheit,engelsch X-KDE-Keywords[nl]=taal,vertaling,getalformaat,locale,land,tekensets,decimaalsymbool,duizendscheidingsteken,symbool,scheidingsteken,teken,positief,negatief,valuta,geld,decimale cijfers,agenda,tijd,datum,formaten,week,weekbegin,eerst,papier,grootte,letter,A4,afmeting,metrisch,Engels,Imperiaal X-KDE-Keywords[nn]=språk,omsetjing,talformat,lokale,locale,land,teiknkodingar,teiknsett,desimalskiljeteikn,tusenskiljeteikn,symbol,skiljeteikn,tein,positiv,negativ,valuta,pengar,siffer,kalender,tid,dato,klokkeslett,format,veke,vekestart,første,papir,storleik,letter,A4,mål,metrisk,engelsk -X-KDE-Keywords[pa]=ਭਾਸ਼ਾ,ਅਨੁਵਾਦ,ਨੰਬਰ ਫਾਰਮੈਟ,ਅੰਕ ਫਾਰਮੈਟ,ਲੋਕੇਲ,ਦੇਸ਼,ਅੱਖਰਸੈੱਟ,ਅੱਖਰ-ਸੈੱਟ,ਦਸ਼ਮਵਲ ਨਿਸ਼ਾਨ,ਹਜ਼ਾਰ,ਨਿਸ਼ਾਨ,ਵੱਖਰੇਵਾਂ,ਸਾਈਨ,ਧਨਾਤਮਕ,ਰਿਣਾਤਮਕ,ਮੁਦਰਾ,ਪੈਸਾ,ਧਨ,ਭਿੰਨ ਅੰਕ,ਕੈਲੰਡਰ,ਸਮਾਂ,ਮਿਤੀ,ਤਿਥੀ,ਤਾਰੀਖ,ਫਾਰਮੈਟ,ਹਫ਼ਤਾ,ਹਫ਼ਤਾ ਸ਼ੁਰੂ,ਪਹਿਲਾਂ,ਪੇਪਰ,ਸਫ਼ਾ,ਆਕਾਰ,ਸਾਈਜ਼,ਪੱਤਰ,ਲੈਟਰ,A4,ਏ4,ਮਾਪ,ਮਾਪਕ,ਅੰਗਰੇਜ਼ੀ,ਮੀਟਰ +X-KDE-Keywords[pa]=ਭਾਸ਼ਾ,ਅਨੁਵਾਦ,ਨੰਬਰ ਫਾਰਮੈਟ,ਅੰਕ,ਲੋਕੇਲ,ਦੇਸ਼,ਅੱਖਰਸੈੱਟ,ਅੱਖਰ-ਸੈੱਟ,ਦਸ਼ਮਵਲ ਨਿਸ਼ਾਨ,ਹਜ਼ਾਰ,ਨਿਸ਼ਾਨ,ਵੱਖਰੇਵਾਂ,ਸਾਈਨ,ਧਨਾਤਮਕ,ਰਿਣਾਤਮਕ,ਮੁਦਰਾ,ਪੈਸਾ,ਧਨ,ਭਿੰਨ ਅੰਕ,ਕੈਲੰਡਰ,ਸਮਾਂ,ਮਿਤੀ,ਤਿਥੀ,ਤਾਰੀਖ,ਹਫ਼ਤਾ,ਹਫ਼ਤਾ ਸ਼ੁਰੂ,ਪਹਿਲਾਂ,ਪੇਪਰ,ਸਫ਼ਾ,ਆਕਾਰ,ਸਾਈਜ਼,ਪੱਤਰ,ਲੈਟਰ,A4,ਏ4,ਮਾਪ,ਮਾਪਕ,ਅੰਗਰੇਜ਼ੀ,ਮੀਟਰ X-KDE-Keywords[pl]=język,tłumaczenie,format liczb,regionalność,kraj,zestaw znaków,symbol dziesiętny,separator tysięcy,symbol,separator,znak,dodatni,ujemny,waluta,pieniądze,ułamkowe cyfry,kalendarz,czas,data,formaty,tydzień,początek tygodnia,pierwszy,papier,rozmiar,list,A4,miara,metryczna,Angielski,Cesarskie X-KDE-Keywords[pt]=língua,tradução,formato de números,localização,país,codificações,codificações de caracteres,símbolo decimal,separador de milhares,símbolo,separador,sinal,positivo,negativo,moeda,monetário,casas decimais,hora,data,formatos,semana,início da semana,primeiro,papel,tamanho,carta,A4,medida,medir,Inglês,Imperial X-KDE-Keywords[pt_BR]=idioma,tradução,formato de números,localização,país,codificações,codificações de caracteres,símbolo decimal,separador de milhares,símbolo,separador,sinal,positivo,negativo,moeda,monetário,casas decimais,calendário,hora,data,formatos,semana,início da semana,primeiro,papel,tamanho,carta,A4,medida,medir,Inglês,Imperial diff --git a/kcms/hardware/joystick/joystick.desktop b/kcms/hardware/joystick/joystick.desktop --- a/kcms/hardware/joystick/joystick.desktop +++ b/kcms/hardware/joystick/joystick.desktop @@ -17,6 +17,7 @@ Comment=Calibrate Game Controller Comment[ca]=Calibratge del controlador de jocs Comment[cs]=Kalibrace herního ovladače +Comment[da]=Kalibrér spil-controller Comment[de]=Gamecontroller kalibrieren Comment[en_GB]=Calibrate Game Controller Comment[es]=Calibrar el mando de juegos @@ -32,6 +33,7 @@ Comment[lt]=Kalibruoti žaidimų valdiklį Comment[nl]=Spelbesturing kalibreren Comment[nn]=Kalibrer spelkontrollar +Comment[pa]=ਖੇਡ ਕੰਟਰੋਲਰ ਕੈਲੀਬਰੇਸ਼ਨ Comment[pl]=Skalibruj pada do gier Comment[pt]=Calibrar o Controlador de Jogos Comment[pt_BR]=Calibrar o controlador de jogos @@ -46,6 +48,7 @@ Name[ast]=Mandu de xuegu Name[ca]=Controlador de jocs Name[cs]=Herní ovladač +Name[da]=Spil-kontroller Name[de]=Gamecontroller Name[en_GB]=Game Controller Name[es]=Mando de juegos @@ -61,6 +64,7 @@ Name[lt]=Žaidimų valdiklis Name[nl]=Spelbesturing Name[nn]=Spelkontrollar +Name[pa]=ਖੇਡ ਕੰਟਰੋਲਰ Name[pl]=Pad do gier Name[pt]=Controlador de Jogos Name[pt_BR]=Controlador de jogos diff --git a/kcms/icons/CMakeLists.txt b/kcms/icons/CMakeLists.txt --- a/kcms/icons/CMakeLists.txt +++ b/kcms/icons/CMakeLists.txt @@ -2,8 +2,9 @@ ########### next target ############### -set(kcm_icons_PART_SRCS main.cpp iconsmodel.cpp) +set(kcm_icons_PART_SRCS main.cpp iconsmodel.cpp iconsizecategorymodel.cpp iconssettings.cpp) +kconfig_add_kcfg_files(kcm_icons_PART_SRCS iconssettingsbase.kcfgc GENERATE_MOC) add_library(kcm_icons MODULE ${kcm_icons_PART_SRCS}) target_link_libraries(kcm_icons @@ -13,17 +14,22 @@ KF5::I18n KF5::IconThemes KF5::Archive - KF5::NewStuff KF5::KIOWidgets KF5::QuickAddons ) file(GENERATE OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/config.h CONTENT "#define CMAKE_INSTALL_FULL_LIBEXECDIR \"${CMAKE_INSTALL_FULL_LIBEXECDIR}\"") -add_executable(plasma-changeicons changeicons.cpp) -target_link_libraries(plasma-changeicons PRIVATE Qt5::Core KF5::KIOWidgets KF5::IconThemes) +set(changeicons_SRCS changeicons.cpp iconssettings.cpp) + +kconfig_add_kcfg_files(changeicons_SRCS iconssettingsbase.kcfgc GENERATE_MOC) + +add_executable(plasma-changeicons ${changeicons_SRCS}) +target_link_libraries(plasma-changeicons PRIVATE Qt5::Core KF5::KIOWidgets KF5::KCMUtils KF5::IconThemes) kcoreaddons_desktop_to_json(kcm_icons "kcm_icons.desktop") + +install(FILES iconssettingsbase.kcfg DESTINATION ${KDE_INSTALL_KCFGDIR}) install(FILES icons_remove_effects.upd DESTINATION ${KDE_INSTALL_DATADIR}/kconf_update) install(FILES kcm_icons.desktop DESTINATION ${KDE_INSTALL_KSERVICES5DIR}) install(TARGETS kcm_icons DESTINATION ${KDE_INSTALL_PLUGINDIR}/kcms) diff --git a/kcms/icons/changeicons.cpp b/kcms/icons/changeicons.cpp --- a/kcms/icons/changeicons.cpp +++ b/kcms/icons/changeicons.cpp @@ -18,12 +18,7 @@ */ #include -#include -#include -#include -#include -#include -#include +#include "iconssettings.h" int main(int argc, char** argv) { @@ -33,28 +28,15 @@ return 1; } - { - //KNS will give us a path - QString themeName = app.arguments().last(); - int idx = themeName.lastIndexOf('/'); - if (idx>=0) { - themeName = themeName.mid(idx); - } - - KConfigGroup config(KSharedConfig::openConfig(QStringLiteral("kdeglobals"), KConfig::SimpleConfig), "Icons"); - config.writeEntry("Theme", themeName); - config.sync(); - } - - KIconTheme::reconfigure(); - - KSharedDataCache::deleteCache(QStringLiteral("icon-cache")); - - for (int i=0; i=0) { + themeName = themeName.mid(idx + 1); } - KBuildSycocaProgressDialog::rebuildKSycoca(nullptr); + IconsSettings settings; + settings.setTheme(themeName); + settings.save(); return 0; } diff --git a/kcms/icons/iconsizecategorymodel.h b/kcms/icons/iconsizecategorymodel.h new file mode 100644 --- /dev/null +++ b/kcms/icons/iconsizecategorymodel.h @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2019 Benjamin Port + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include +#include +#include + +struct IconSizeCategoryModelData +{ + QString configKey; + QString display; + QString configSection; +}; + +Q_DECLARE_TYPEINFO(IconSizeCategoryModelData, Q_MOVABLE_TYPE); + +class IconSizeCategoryModel : public QAbstractListModel +{ + Q_OBJECT + +public: + IconSizeCategoryModel(QObject *parent); + ~IconSizeCategoryModel() override; + + enum Roles { + ConfigKeyRole = Qt::UserRole + 1, + ConfigSectionRole + }; + + int rowCount(const QModelIndex &parent = QModelIndex()) const override; + QVariant data(const QModelIndex &index, int role) const override; + QHash roleNames() const override; + + void load(); + +signals: + void categorySelectedIndexChanged(); + +private: + QVector m_data; +}; diff --git a/kcms/icons/iconsizecategorymodel.cpp b/kcms/icons/iconsizecategorymodel.cpp new file mode 100644 --- /dev/null +++ b/kcms/icons/iconsizecategorymodel.cpp @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2019 Benjamin Port + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "iconsizecategorymodel.h" +#include + +IconSizeCategoryModel::IconSizeCategoryModel(QObject *parent) + : QAbstractListModel(parent) + , m_data({ + {QStringLiteral("desktopSize"), I18N_NOOP("Desktop"), QStringLiteral("Desktop")}, + {QStringLiteral("toolbarSize"), I18N_NOOP("Toolbar"), QStringLiteral("Toolbar")}, + {QStringLiteral("mainToolbarSize"), I18N_NOOP("Main Toolbar"), QStringLiteral("MainToolbar")}, + {QStringLiteral("smallSize"), I18N_NOOP("Small Icons"), QStringLiteral("Small")}, + {QStringLiteral("panelSize"), I18N_NOOP("Panel"), QStringLiteral("Panel")}, + {QStringLiteral("dialogSize"), I18N_NOOP("Dialogs"), QStringLiteral("Dialog")} + }) +{ +} + +IconSizeCategoryModel::~IconSizeCategoryModel() = default; + +int IconSizeCategoryModel::rowCount(const QModelIndex &parent) const +{ + if (parent.isValid()) { + return 0; + } + + return m_data.count(); +} + +QVariant IconSizeCategoryModel::data(const QModelIndex &index, int role) const +{ + if (!index.isValid() || index.row() >= m_data.count()) { + return QVariant(); + } + + const auto &item = m_data.at(index.row()); + + switch (role) { + case Qt::DisplayRole: + return item.display; + case ConfigKeyRole: + return item.configKey; + case ConfigSectionRole: + return item.configSection; + } + + return QVariant(); +} + +QHash IconSizeCategoryModel::roleNames() const +{ + QHash roleNames = QAbstractListModel::roleNames(); + roleNames[ConfigKeyRole] = QByteArrayLiteral("configKey"); + roleNames[ConfigSectionRole] = QByteArrayLiteral("configSectionRole"); + return roleNames; +} diff --git a/kcms/icons/iconsmodel.h b/kcms/icons/iconsmodel.h --- a/kcms/icons/iconsmodel.h +++ b/kcms/icons/iconsmodel.h @@ -27,6 +27,8 @@ #include #include +class IconsSettings; + struct IconsModelData { QString display; @@ -41,11 +43,8 @@ { Q_OBJECT - Q_PROPERTY(QString selectedTheme READ selectedTheme WRITE setSelectedTheme NOTIFY selectedThemeChanged) - Q_PROPERTY(int selectedThemeIndex READ selectedThemeIndex NOTIFY selectedThemeIndexChanged) - public: - IconsModel(QObject *parent); + IconsModel(IconsSettings *iconsSettings, QObject *parent = nullptr); ~IconsModel() override; enum Roles { @@ -60,25 +59,16 @@ bool setData(const QModelIndex &index, const QVariant &value, int role) override; QHash roleNames() const override; - QString selectedTheme() const; - void setSelectedTheme(const QString &theme); - - int selectedThemeIndex() const; - QStringList pendingDeletions() const; void removeItemsPendingDeletion(); void load(); signals: - void selectedThemeChanged(); - void selectedThemeIndexChanged(); - void pendingDeletionsChanged(); private: - QString m_selectedTheme; - QVector m_data; + IconsSettings *m_settings; }; diff --git a/kcms/icons/iconsmodel.cpp b/kcms/icons/iconsmodel.cpp --- a/kcms/icons/iconsmodel.cpp +++ b/kcms/icons/iconsmodel.cpp @@ -29,7 +29,11 @@ #include -IconsModel::IconsModel(QObject *parent) : QAbstractListModel(parent) +#include "iconssettings.h" + +IconsModel::IconsModel(IconsSettings *iconsSettings, QObject *parent) + : QAbstractListModel(parent) + , m_settings(iconsSettings) { } @@ -79,12 +83,11 @@ item.pendingDeletion = pendingDeletion; emit dataChanged(index, index, {PendingDeletionRole}); - // move to the next non-pending theme + // if we delete current selected theme move to the next non-pending theme const auto nonPending = match(index, PendingDeletionRole, false); - if (!nonPending.isEmpty()) { - setSelectedTheme(nonPending.first().data(ThemeNameRole).toString()); + if (m_settings->theme() == index.data(ThemeNameRole) && !nonPending.isEmpty()) { + m_settings->setTheme(nonPending.first().data(ThemeNameRole).toString()); } - emit pendingDeletionsChanged(); return true; } @@ -104,45 +107,10 @@ }; } -QString IconsModel::selectedTheme() const -{ - return m_selectedTheme; -} - -void IconsModel::setSelectedTheme(const QString &theme) -{ - if (m_selectedTheme == theme) { - return; - } - - const bool firstTime = m_selectedTheme.isNull(); - m_selectedTheme = theme; - - if (!firstTime) { - emit selectedThemeChanged(); - } - emit selectedThemeIndexChanged(); -} - -int IconsModel::selectedThemeIndex() const -{ - auto it = std::find_if(m_data.begin(), m_data.end(), [this](const IconsModelData &item) { - return item.themeName == m_selectedTheme; - }); - - if (it != m_data.end()) { - return std::distance(m_data.begin(), it); - } - - return -1; -} - void IconsModel::load() { beginResetModel(); - const int oldCount = m_data.count(); - m_data.clear(); const QStringList themes = KIconTheme::list(); @@ -175,11 +143,6 @@ }); endResetModel(); - - // an item might have been added before the currently selected one - if (oldCount != m_data.count()) { - emit selectedThemeIndexChanged(); - } } QStringList IconsModel::pendingDeletions() const diff --git a/kcms/icons/iconssettings.h b/kcms/icons/iconssettings.h new file mode 100644 --- /dev/null +++ b/kcms/icons/iconssettings.h @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2019 Benjamin Port + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef PLASMA_DESKTOP_ICONSSETTINGS_H +#define PLASMA_DESKTOP_ICONSSETTINGS_H + +#include "iconssettingsbase.h" + +class IconsSettings : public IconsSettingsBase { + Q_OBJECT +public: + IconsSettings(QObject *parent = nullptr); + ~IconsSettings() override; +public slots: + void updateIconTheme(); + void updateThemeDirty(); +private: + bool m_themeDirty; +}; + + +#endif //PLASMA_DESKTOP_ICONSSETTINGS_H diff --git a/kcms/icons/iconssettings.cpp b/kcms/icons/iconssettings.cpp new file mode 100644 --- /dev/null +++ b/kcms/icons/iconssettings.cpp @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2019 Benjamin Port + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include +#include + +#include +#include +#include + +#include "iconssettings.h" + +IconsSettings::IconsSettings(QObject *parent) + : IconsSettingsBase(parent) + , m_themeDirty(false) +{ + connect(this, &IconsSettings::configChanged, this, &IconsSettings::updateIconTheme); + connect(this, &IconsSettings::ThemeChanged, this, &IconsSettings::updateThemeDirty); +} + +IconsSettings::~IconsSettings() +{ +} + +void IconsSettings::updateThemeDirty() +{ + m_themeDirty = theme() != KIconTheme::current(); +} + +void IconsSettings::updateIconTheme() +{ + if (m_themeDirty) { + KIconTheme::reconfigure(); + + KSharedDataCache::deleteCache(QStringLiteral("icon-cache")); + + for (int i = 0; i < KIconLoader::LastGroup; i++) { + KIconLoader::emitChange(KIconLoader::Group(i)); + } + + KBuildSycocaProgressDialog::rebuildKSycoca(nullptr); + } +} diff --git a/kcms/icons/iconssettingsbase.kcfg b/kcms/icons/iconssettingsbase.kcfg new file mode 100644 --- /dev/null +++ b/kcms/icons/iconssettingsbase.kcfg @@ -0,0 +1,49 @@ + + + + + + + breeze + + + + + + 32 + + + + + + 22 + + + + + + 22 + + + + + + 16 + + + + + + 48 + + + + + + 32 + + + diff --git a/kcms/icons/iconssettingsbase.kcfgc b/kcms/icons/iconssettingsbase.kcfgc new file mode 100644 --- /dev/null +++ b/kcms/icons/iconssettingsbase.kcfgc @@ -0,0 +1,6 @@ +File=iconssettingsbase.kcfg +ClassName=IconsSettingsBase +Mutators=true +DefaultValueGetters=true +GenerateProperties=true +ParentInConstructor=true diff --git a/kcms/icons/kcm_icons.desktop b/kcms/icons/kcm_icons.desktop --- a/kcms/icons/kcm_icons.desktop +++ b/kcms/icons/kcm_icons.desktop @@ -108,6 +108,7 @@ Comment[ca]=Trieu el tema d'icones Comment[ca@valencia]=Trieu el tema d'icones Comment[cs]=Vyberte motiv ikon +Comment[da]=Vælg ikontema Comment[de]=Symbol-Design auswählen Comment[en_GB]=Choose icon theme Comment[es]=Escoger un tema de iconos @@ -124,6 +125,7 @@ Comment[lt]=Pasirinkti piktogramų apipavidalinimą Comment[nl]=Pictogramthema kiezen Comment[nn]=Vel ikontema +Comment[pa]=ਆਈਕਾਨ ਥੀਮ ਚੁਣੋ Comment[pl]=Wybierz zestaw ikon Comment[pt]=Escolher o tema de ícones Comment[pt_BR]=Escolha o tema de ícones @@ -174,7 +176,7 @@ X-KDE-Keywords[nds]=Lüttbiller,Effekten,Grött,HiColor,LoColor,Klören,Klöör X-KDE-Keywords[nl]=pictoogrammen,effecten,grootte,hi-kleur,lo-kleur X-KDE-Keywords[nn]=ikon,effektar,storleik,hicolor,locolor -X-KDE-Keywords[pa]=ਆਈਕਾਨ,ਪ੍ਰਭਾਵ,ਪਰਭਾਵ,ਆਕਾਰ,ਵੱਧ-ਰੰਗ,ਘੱਟਰੰਗ +X-KDE-Keywords[pa]=ਆਈਕਾਨ,ਪ੍ਰਭਾਵ,ਪਰਭਾਵ,ਆਕਾਰ,ਵੱਧ-ਰੰਗ,ਘੱਟ-ਰੰਗ X-KDE-Keywords[pl]=ikony,efekty,rozmiar,hicolor,locolor X-KDE-Keywords[pt]=ícones,efeitos,tamanho,muitas cores,poucas cores X-KDE-Keywords[pt_BR]=ícones,efeitos,tamanho,muitas cores,poucas cores diff --git a/kcms/icons/main.h b/kcms/icons/main.h --- a/kcms/icons/main.h +++ b/kcms/icons/main.h @@ -4,6 +4,7 @@ * Copyright (c) 1999 Matthias Hoelzer-Kluepfel * KDE Frameworks 5 port Copyright (C) 2013 Jonathan Riddell * Copyright (c) 2018 Kai Uwe Broulik + * Copyright (C) 2019 Benjamin Port * * Requires the Qt widget libraries, available at no cost at * https://www.qt.io/ @@ -25,13 +26,15 @@ #pragma once -#include +#include -#include +#include #include +#include class KIconTheme; +class IconsSettings; class QQuickItem; class QTemporaryFile; @@ -42,15 +45,14 @@ } class IconsModel; +class IconSizeCategoryModel; -class IconModule : public KQuickAddons::ConfigModule +class IconModule : public KQuickAddons::ManagedConfigModule { Q_OBJECT - + Q_PROPERTY(IconsSettings *iconsSettings READ iconsSettings CONSTANT) Q_PROPERTY(IconsModel *iconsModel READ iconsModel CONSTANT) - - Q_PROPERTY(QStringList iconGroups READ iconGroups CONSTANT) - + Q_PROPERTY(IconSizeCategoryModel *iconSizeCategoryModel READ iconSizeCategoryModel CONSTANT) Q_PROPERTY(bool downloadingFile READ downloadingFile NOTIFY downloadingFileChanged) public: @@ -64,28 +66,26 @@ PendingDeletionRole }; + IconsSettings *iconsSettings() const; IconsModel *iconsModel() const; - - QStringList iconGroups() const; + IconSizeCategoryModel *iconSizeCategoryModel() const; bool downloadingFile() const; void load() override; void save() override; - void defaults() override; - Q_INVOKABLE void getNewStuff(QQuickItem *ctx); + Q_INVOKABLE void ghnsEntriesChanged(const QQmlListReference &changedEntries); Q_INVOKABLE void installThemeFromFile(const QUrl &url); - Q_INVOKABLE int iconSize(int group) const; - Q_INVOKABLE void setIconSize(int group, int size); Q_INVOKABLE QList availableIconSizes(int group) const; + Q_INVOKABLE int pluginIndex(const QString &pluginName) const; + // QML doesn't understand QList, hence wrapped in a QVariantList Q_INVOKABLE QVariantList previewIcons(const QString &themeName, int size, qreal dpr, int limit = -1); signals: - void iconSizesChanged(); void downloadingFileChanged(); void showSuccessMessage(const QString &message); @@ -95,7 +95,7 @@ void hideProgress(); private: - void loadIconSizes(); + bool isSaveNeeded() const override; void processPendingDeletions(); @@ -107,18 +107,12 @@ static QPixmap getBestIcon(KIconTheme &theme, const QStringList &iconNames, int size, qreal dpr); + IconsSettings *m_settings; IconsModel *m_model; - // so we avoid launching changeicon process when theme didn't change (but only e.g. pending deletions) - bool m_selectedThemeDirty = false; - bool m_iconSizesDirty = false; - - QVector m_iconSizes; + IconSizeCategoryModel *m_iconSizeCategoryModel; - QStringList m_iconGroups; + mutable QCache m_kiconThemeCache; QScopedPointer m_tempInstallFile; QPointer m_tempCopyJob; - - QPointer m_newStuffDialog; - }; diff --git a/kcms/icons/main.cpp b/kcms/icons/main.cpp --- a/kcms/icons/main.cpp +++ b/kcms/icons/main.cpp @@ -6,6 +6,7 @@ * Copyright (C) 2000 Geert Jansen * KDE Frameworks 5 port Copyright (C) 2013 Jonathan Riddell * Copyright (C) 2018 Kai Uwe Broulik + * Copyright (C) 2019 Benjamin Port * * Requires the Qt widget libraries, available at no cost at * https://www.qt.io/ @@ -55,29 +56,23 @@ #include #include // for unlink +#include "iconssettings.h" #include "iconsmodel.h" +#include "iconsizecategorymodel.h" #include "config.h" // for CMAKE_INSTALL_FULL_LIBEXECDIR -static const QVector s_defaultIconSizes = { 32, 22, 22, 16, 48, 32 }; -// we try to use KIconTheme::defaultThemeName() but that could be "hicolor" which isn't a "real" theme -static const QString s_defaultThemeName = QStringLiteral("breeze"); - K_PLUGIN_FACTORY_WITH_JSON(IconsFactory, "kcm_icons.json", registerPlugin();) IconModule::IconModule(QObject *parent, const QVariantList &args) - : KQuickAddons::ConfigModule(parent, args) - , m_model(new IconsModel(this)) - , m_iconGroups{ - QStringLiteral("Desktop"), - QStringLiteral("Toolbar"), - QStringLiteral("MainToolbar"), - QStringLiteral("Small"), - QStringLiteral("Panel"), - QStringLiteral("Dialog") - } + : KQuickAddons::ManagedConfigModule(parent, args) + , m_settings(new IconsSettings(this)) + , m_model(new IconsModel(m_settings, this)) + , m_iconSizeCategoryModel(new IconSizeCategoryModel(this)) { + qmlRegisterType(); qmlRegisterType(); + qmlRegisterType(); // to be able to access its enums qmlRegisterUncreatableType("org.kde.private.kcms.icons", 1, 0, "KIconLoader", QString()); @@ -94,105 +89,79 @@ setButtons(Apply | Default); - connect(m_model, &IconsModel::selectedThemeChanged, this, [this] { - m_selectedThemeDirty = true; - setNeedsSave(true); - }); - connect(m_model, &IconsModel::pendingDeletionsChanged, this, [this] { - setNeedsSave(true); - }); + connect(m_model, &IconsModel::pendingDeletionsChanged, this, &IconModule::settingsChanged); // When user has a lot of themes installed, preview pixmaps might get evicted prematurely QPixmapCache::setCacheLimit(50 * 1024); // 50 MiB } IconModule::~IconModule() { +} +IconsSettings *IconModule::iconsSettings() const +{ + return m_settings; } IconsModel *IconModule::iconsModel() const { return m_model; } -QStringList IconModule::iconGroups() const +IconSizeCategoryModel *IconModule::iconSizeCategoryModel() const { - return m_iconGroups; + return m_iconSizeCategoryModel; } bool IconModule::downloadingFile() const { return m_tempCopyJob; } -int IconModule::iconSize(int group) const -{ - return m_iconSizes[group]; -} - -void IconModule::setIconSize(int group, int size) -{ - if (iconSize(group) == size) { - return; - } - - m_iconSizes[group] = size; - setNeedsSave(true); - m_iconSizesDirty = true; - emit iconSizesChanged(); -} - QList IconModule::availableIconSizes(int group) const { - return KIconLoader::global()->theme()->querySizes(static_cast(group)); + const auto themeName = m_settings->theme(); + if (!m_kiconThemeCache.contains(m_settings->theme())) { + m_kiconThemeCache.insert(themeName, new KIconTheme(themeName)); + } + return m_kiconThemeCache[themeName]->querySizes(static_cast(group)); } void IconModule::load() { + ManagedConfigModule::load(); m_model->load(); - loadIconSizes(); - m_model->setSelectedTheme(KIconTheme::current()); - setNeedsSave(false); - m_selectedThemeDirty = false; - m_iconSizesDirty = false; + // Model has been cleared so pretend the theme name changed to force view update + emit m_settings->ThemeChanged(); } void IconModule::save() { - if (m_selectedThemeDirty) { - QProcess::startDetached(CMAKE_INSTALL_FULL_LIBEXECDIR "/plasma-changeicons", {m_model->selectedTheme()}); - } + bool needToExportToKDE4 = m_settings->isSaveNeeded(); - if (m_iconSizesDirty) { - auto cfg = KSharedConfig::openConfig(); - for (int i = 0; i < m_iconGroups.count(); ++i) { - const QString &group = m_iconGroups.at(i); - KConfigGroup cg(cfg, group + QLatin1String("Icons")); - cg.writeEntry("Size", m_iconSizes.at(i), KConfig::Normal | KConfig::Global); - } - cfg->sync(); - } + ManagedConfigModule::save(); - if (m_selectedThemeDirty || m_iconSizesDirty) { + if (needToExportToKDE4) { exportToKDE4(); } processPendingDeletions(); KIconLoader::global()->newIconLoader(); +} - setNeedsSave(false); - m_selectedThemeDirty = false; - m_iconSizesDirty = false; +bool IconModule::isSaveNeeded() const +{ + return !m_model->pendingDeletions().isEmpty(); } void IconModule::processPendingDeletions() { const QStringList pendingDeletions = m_model->pendingDeletions(); for (const QString &themeName : pendingDeletions) { - Q_ASSERT(themeName != m_model->selectedTheme()); + Q_ASSERT(themeName != m_settings->theme()); KIconTheme theme(themeName); auto *job = KIO::del(QUrl::fromLocalFile(theme.dir()), KIO::HideProgressInfo); @@ -203,79 +172,16 @@ m_model->removeItemsPendingDeletion(); } -void IconModule::defaults() -{ - if (m_iconSizes != s_defaultIconSizes) { - m_iconSizes = s_defaultIconSizes; - emit iconSizesChanged(); - } - - auto setThemeIfAvailable = [this](const QString &themeName) { - const auto results = m_model->match(m_model->index(0, 0), ThemeNameRole, themeName); - if (results.isEmpty()) { - return false; - } - - m_model->setSelectedTheme(themeName); - return true; - }; - - if (!setThemeIfAvailable(KIconTheme::defaultThemeName())) { - setThemeIfAvailable(QStringLiteral("breeze")); - } - - setNeedsSave(true); -} - -void IconModule::loadIconSizes() +void IconModule::ghnsEntriesChanged(const QQmlListReference &changedEntries) { - auto cfg = KSharedConfig::openConfig(); - - QVector iconSizes(6, 0); // why doesn't KIconLoader::LastGroup - 1 work here?! - - int i = KIconLoader::FirstGroup; - for (const QString &group : qAsConst(m_iconGroups)) { - int size = KIconLoader::global()->theme()->defaultSize(static_cast(i)); - - KConfigGroup iconGroup(cfg, group + QLatin1String("Icons")); - size = iconGroup.readEntry("Size", size); - - iconSizes[i] = size; - - ++i; - } - - if (m_iconSizes != iconSizes) { - m_iconSizes = iconSizes; - emit iconSizesChanged(); - } -} - -void IconModule::getNewStuff(QQuickItem *ctx) -{ - if (!m_newStuffDialog) { - m_newStuffDialog = new KNS3::DownloadDialog(QStringLiteral("icons.knsrc")); - m_newStuffDialog->setWindowTitle(i18n("Download New Icon Themes")); - m_newStuffDialog->setWindowModality(Qt::WindowModal); - m_newStuffDialog->winId(); // so it creates the windowHandle(); - // TODO would be lovely to scroll to and select the newly installed scheme, if any - connect(m_newStuffDialog.data(), &KNS3::DownloadDialog::accepted, this, [this] { - if (m_newStuffDialog->changedEntries().isEmpty()) { - return; - } - - // reload the display icontheme items - KIconLoader::global()->newIconLoader(); - m_model->load(); - QPixmapCache::clear(); - }); - } - - if (ctx && ctx->window()) { - m_newStuffDialog->windowHandle()->setTransientParent(ctx->window()); + if (changedEntries.count() == 0) { + return; } - m_newStuffDialog->show(); + // reload the display icontheme items + KIconLoader::global()->newIconLoader(); + m_model->load(); + QPixmapCache::clear(); } void IconModule::installThemeFromFile(const QUrl &url) @@ -347,10 +253,12 @@ KConfig kde4config(configFilePath, KConfig::SimpleConfig); KConfigGroup kde4IconGroup(&kde4config, "Icons"); - kde4IconGroup.writeEntry("Theme", m_model->selectedTheme()); + kde4IconGroup.writeEntry("Theme", m_settings->theme()); //Synchronize icon effects - for (const QString &group : qAsConst(m_iconGroups)) { + for (int row = 0; row < m_iconSizeCategoryModel->rowCount(); row++) { + QModelIndex idx(m_iconSizeCategoryModel->index(row, 0)); + QString group = m_iconSizeCategoryModel->data(idx, IconSizeCategoryModel::ConfigSectionRole).toString(); const QString groupName = group + QLatin1String("Icons"); KConfigGroup cg(kglobalcfg, groupName); KConfigGroup kde4Cg(&kde4config, groupName); @@ -573,4 +481,13 @@ return QPixmap(); } +int IconModule::pluginIndex(const QString &themeName) const +{ + const auto results = m_model->match(m_model->index(0, 0), ThemeNameRole, themeName); + if (results.count() == 1) { + return results.first().row(); + } + return -1; +} + #include "main.moc" diff --git a/kcms/icons/package/contents/ui/IconSizePopup.qml b/kcms/icons/package/contents/ui/IconSizePopup.qml --- a/kcms/icons/package/contents/ui/IconSizePopup.qml +++ b/kcms/icons/package/contents/ui/IconSizePopup.qml @@ -36,13 +36,16 @@ onVisibleChanged: { if (visible) { - iconSizeSlider.updateSizes(); + iconSizeSlider.sizes = kcm.availableIconSizes(iconTypeList.currentIndex); + iconSizeSlider.updateSizes() } } Connections { - target: kcm - onIconSizesChanged: iconSizeSlider.updateSizes() + target: iconTypeList + onCurrentIndexChanged: { + iconSizeSlider.sizes = kcm.availableIconSizes(iconTypeList.currentIndex); + } } RowLayout { @@ -73,7 +76,8 @@ keyNavigationWraps: true highlightMoveDuration: 0 - model: kcm.iconGroups + model: kcm.iconSizeCategoryModel + currentIndex: 0 // Initialize with the first item Keys.onLeftPressed: { LayoutMirroring.enabled ? iconSizeSlider.increase() : iconSizeSlider.decrease() @@ -87,15 +91,8 @@ delegate: QtControls.ItemDelegate { width: ListView.view.width highlighted: ListView.isCurrentItem - text: [ - i18n("Desktop"), - i18n("Toolbar"), - i18n("Main Toolbar"), - i18n("Small Icons"), - i18n("Panel"), - i18n("Dialogs") - ][index] - + text: model.display + readonly property string configKey: model.configKey onClicked: { ListView.view.currentIndex = index; ListView.view.forceActiveFocus(); @@ -106,23 +103,24 @@ QtControls.Slider { id: iconSizeSlider - readonly property var sizes: kcm.availableIconSizes(iconTypeList.currentIndex) - readonly property int currentSize: iconSizeSlider.sizes[iconSizeSlider.value] || 0 + property var sizes: kcm.availableIconSizes(iconTypeList.currentIndex) Layout.fillWidth: true from: 0 to: sizes.length - 1 stepSize: 1.0 snapMode: QtControls.Slider.SnapAlways - enabled: sizes.length > 0 + enabled: sizes.length > 0 && !kcm.iconsSettings.isImmutable(iconTypeList.currentItem.configKey) - onMoved: kcm.setIconSize(iconTypeList.currentIndex, currentSize) + onMoved: { + kcm.iconsSettings[iconTypeList.currentItem.configKey] = iconSizeSlider.sizes[iconSizeSlider.value] || 0 + } function updateSizes() { // since the icon sizes are queried using invokables, always force an update when opening // in case the user clicked Default or something value = Qt.binding(function() { - var iconSize = kcm.iconSize(iconTypeList.currentIndex) + var iconSize = kcm.iconsSettings[iconTypeList.currentItem.configKey] // I have no idea what this code does but it works and is just copied from the old KCM var index = -1; @@ -153,7 +151,7 @@ Kirigami.Icon { anchors.centerIn: parent - width: iconSizeSlider.currentSize + width: kcm.iconsSettings[iconTypeList.currentItem.configKey] height: width source: "folder" } @@ -163,7 +161,7 @@ id: iconSizeLabel Layout.fillWidth: true horizontalAlignment: Text.AlignHCenter - text: iconSizeSlider.currentSize + text: kcm.iconsSettings[iconTypeList.currentItem.configKey] } } } diff --git a/kcms/icons/package/contents/ui/main.qml b/kcms/icons/package/contents/ui/main.qml --- a/kcms/icons/package/contents/ui/main.qml +++ b/kcms/icons/package/contents/ui/main.qml @@ -25,20 +25,21 @@ import QtQuick.Controls 2.3 as QtControls import org.kde.kirigami 2.4 as Kirigami import org.kde.kquickcontrolsaddons 2.0 as KQCAddons -import org.kde.kconfig 1.0 // for KAuthorized +import org.kde.newstuff 1.62 as NewStuff import org.kde.kcm 1.1 as KCM import org.kde.private.kcms.icons 1.0 as Private KCM.GridViewKCM { KCM.ConfigModule.quickHelp: i18n("This module allows you to choose the icons for your desktop.") view.model: kcm.iconsModel - view.currentIndex: kcm.iconsModel.selectedThemeIndex - + view.currentIndex: kcm.pluginIndex(kcm.iconsSettings.theme) enabled: !kcm.downloadingFile + view.enabled: !kcm.iconsSettings.isImmutable("Theme") DropArea { + enabled: !kcm.iconsSettings.isImmutable("Theme") anchors.fill: parent onEntered: { if (!drag.hasUrls) { @@ -166,7 +167,7 @@ ] onClicked: { if (!model.pendingDeletion) { - kcm.iconsModel.selectedTheme = model.themeName; + kcm.iconsSettings.theme = model.themeName; } view.forceActiveFocus(); } @@ -243,17 +244,19 @@ } QtControls.Button { + enabled: !kcm.iconsSettings.isImmutable("Theme") id: installFromFileButton text: i18n("Install from File...") icon.name: "document-import" onClicked: fileDialogLoader.active = true } - QtControls.Button { - text: i18n("Get New Icons...") - icon.name: "get-hot-new-stuff" - onClicked: kcm.getNewStuff(this) - visible: KAuthorized.authorize("ghns") + NewStuff.Button { + id: newStuffButton + downloadNewWhat: i18n("Icons") + configFile: "icons.knsrc" + viewMode: NewStuff.Page.ViewMode.Preview + onChangedEntriesChanged: kcm.ghnsEntriesChanged(newStuffButton.changedEntries); } } } diff --git a/kcms/icons/package/metadata.desktop b/kcms/icons/package/metadata.desktop --- a/kcms/icons/package/metadata.desktop +++ b/kcms/icons/package/metadata.desktop @@ -95,6 +95,7 @@ Comment[ca]=Trieu el tema d'icones Comment[ca@valencia]=Trieu el tema d'icones Comment[cs]=Vyberte motiv ikon +Comment[da]=Vælg ikontema Comment[de]=Symbol-Design auswählen Comment[en_GB]=Choose icon theme Comment[es]=Escoger un tema de iconos @@ -111,6 +112,7 @@ Comment[lt]=Pasirinkti piktogramų apipavidalinimą Comment[nl]=Pictogramthema kiezen Comment[nn]=Vel ikontema +Comment[pa]=ਆਈਕਾਨ ਥੀਮ ਚੁਣੋ Comment[pl]=Wybierz zestaw ikon Comment[pt]=Escolher o tema de ícones Comment[pt_BR]=Escolha o tema de ícones diff --git a/kcms/keyboard/kcm_keyboard.desktop b/kcms/keyboard/kcm_keyboard.desktop --- a/kcms/keyboard/kcm_keyboard.desktop +++ b/kcms/keyboard/kcm_keyboard.desktop @@ -121,7 +121,7 @@ Comment[eu]=Teklatu-hardwarea eta -diseinua Comment[fi]=Näppäimistön laitteisto ja järjestys Comment[fr]=Disposition et matériel du clavier -Comment[gl]=Hardware e disposición do teclado +Comment[gl]=Soporte físico e disposición do teclado Comment[he]=חומרה ופריסת מקלדת Comment[hu]=Billentyűzetkiosztás Comment[id]=Tata Letak dan Perangkat Keras Keyboard diff --git a/kcms/keyboard/tastenbrett/qml/ShapeCanvas.qml b/kcms/keyboard/tastenbrett/qml/ShapeCanvas.qml --- a/kcms/keyboard/tastenbrett/qml/ShapeCanvas.qml +++ b/kcms/keyboard/tastenbrett/qml/ShapeCanvas.qml @@ -55,7 +55,7 @@ // they extend to the left and right of the path, so with a // lineWidth of 8 we'll need the entire scene scooted so // 0,0 becomes 4,4. Since that also would screw up our absolute - // cordinates towards the right (e.g. our width bounds as reported + // coordinates towards the right (e.g. our width bounds as reported // by XKB) we also need to then adjust the scale so the entire // coordinate system so the scene leaves sufficient space at all // borders. diff --git a/kcms/keyboard/tastenbrett/qml/main.qml b/kcms/keyboard/tastenbrett/qml/main.qml --- a/kcms/keyboard/tastenbrett/qml/main.qml +++ b/kcms/keyboard/tastenbrett/qml/main.qml @@ -156,7 +156,7 @@ x: section.left y: section.top z: section.priority - // Dimension defintions can be a bit wonky for sections but overally should not + // Dimension definitions can be a bit wonky for sections but overally should not // cause problems even when they are (so long as we don't actually render the // sections themself) width: section.width diff --git a/kcms/keys/kglobalshortcutseditor.cpp b/kcms/keys/kglobalshortcutseditor.cpp --- a/kcms/keys/kglobalshortcutseditor.cpp +++ b/kcms/keys/kglobalshortcutseditor.cpp @@ -34,7 +34,7 @@ #include #include #include -#include +#include #include #include #include @@ -235,7 +235,8 @@ connect(ui.addButton, &QToolButton::clicked, [this]() { if (!selectApplicationDialogUi.treeView->model()) { - KRecursiveFilterProxyModel *filterModel = new KRecursiveFilterProxyModel(selectApplicationDialogUi.treeView); + QSortFilterProxyModel *filterModel = new QSortFilterProxyModel(selectApplicationDialogUi.treeView); + filterModel->setRecursiveFilteringEnabled(true); QStandardItemModel *appModel = new QStandardItemModel(selectApplicationDialogUi.treeView); selectApplicationDialogUi.kfilterproxysearchline->setProxy(filterModel); filterModel->setSourceModel(appModel); diff --git a/kcms/kfontinst/apps/Viewer.cpp b/kcms/kfontinst/apps/Viewer.cpp --- a/kcms/kfontinst/apps/Viewer.cpp +++ b/kcms/kfontinst/apps/Viewer.cpp @@ -118,8 +118,6 @@ ViewerApplication(int &argc, char **argv) : QApplication(argc, argv) { - cmdParser.addVersionOption(); - cmdParser.addHelpOption(); cmdParser.addPositionalArgument(QLatin1String("[URL]"), i18n("URL to open")); } diff --git a/kcms/kfontinst/dbus/fontinst.actions b/kcms/kfontinst/dbus/fontinst.actions --- a/kcms/kfontinst/dbus/fontinst.actions +++ b/kcms/kfontinst/dbus/fontinst.actions @@ -130,13 +130,13 @@ Name[lt]=Tvarkyti sistemos masto šriftus. Name[lv]=Pārvaldīt sistēmas fontus. Name[mk]=Менаџирање на системските фонтови. -Name[ml]=സിസ്റ്റത്തിനു് മുഴുവനായുള്ള അക്ഷരസഞ്ചയങ്ങളുടെ നോക്കിനടത്തല്‍ +Name[ml]=സിസ്റ്റത്തിനു് മുഴുവനായുള്ള അക്ഷരസഞ്ചയങ്ങളുടെ നോക്കിനടത്തല്‍. Name[mr]=प्रणालीतील फॉन्ट व्यवस्थापन Name[nb]=Håndter skrifter for hele systemet. Name[nds]=Systeemschriftoorden plegen Name[nl]=Beheer van systeembrede lettertypen. Name[nn]=Handsam skrifter for heile systemet. -Name[pa]=ਸਿਸਟਮ ਦੇ ਫੋਂਟ ਪਰਬੰਧ +Name[pa]=ਸਿਸਟਮ ਦੇ ਫੋਂਟਾਂ ਦਾ ਇੰਤਜ਼ਾਮ ਕਰੋ। Name[pl]=Zarządzanie czcionkami ogólnosystemowymi. Name[pt]=Gerir os tipos de letra do sistema. Name[pt_BR]=Gerenciar as fontes do sistema. diff --git a/kcms/kfontinst/kcmfontinst/fontinst.desktop b/kcms/kfontinst/kcmfontinst/fontinst.desktop --- a/kcms/kfontinst/kcmfontinst/fontinst.desktop +++ b/kcms/kfontinst/kcmfontinst/fontinst.desktop @@ -49,7 +49,7 @@ Name[nds]=Schriftpleeg Name[nl]=Lettertypenbeheer Name[nn]=Skrift­handsaming -Name[pa]=ਫੋਂਟ ਪਰਬੰਧ +Name[pa]=ਫੋਂਟ ਇੰਤਜ਼ਾਮ Name[pl]=Zarządzanie czcionkami Name[pt]=Gestão dos Tipos de Letra Name[pt_BR]=Gerenciamento de fontes @@ -72,9 +72,10 @@ Comment=Install, manage and preview fonts Comment[ast]=Instala, xestiona y previsualiza fontes -Comment[ca]=Instal·la, gestiona i visualitza els tipus de lletres +Comment[ca]=Instal·la, gestiona i previsualitza els tipus de lletra Comment[ca@valencia]=Instal·la, gestiona i visualitza els tipus de lletres Comment[cs]=Instalace, správa a náhled písem +Comment[da]=Installér, håndtér og forhåndsvis skrifttyper Comment[de]=Schriftarten installieren, verwalten und betrachten Comment[en_GB]=Install, manage and preview fonts Comment[es]=Instalación, gestión y vista previa de tipos de letra @@ -91,6 +92,7 @@ Comment[lt]=Įdiegti, tvarkyti ir peržiūrėti šriftus Comment[nl]=Lettertypen installeren, beheren en bekijken Comment[nn]=Installer, handter og vis skrifter +Comment[pa]=ਫੋਂਟ ਇੰਸਟਾਲ, ਇੰਤਜ਼ਾਮ ਕਰੋ ਅਤੇ ਝਲਕ ਵੇਖੋ Comment[pl]=Wgrywanie, zarządzanie i podgląd czcionek Comment[pt]=Instalar, gerir e antever os tipos de letra Comment[pt_BR]=Instale, gerencie e visualize fontes @@ -132,6 +134,7 @@ X-KDE-Keywords[nds]=Schrift,Schriften,Schriftoort,Schriftoorden,TrueType,Type1,Bitmap X-KDE-Keywords[nl]=lettertype,lettertypen,installatieprogramma,truetype,type1,bitmap X-KDE-Keywords[nn]=skrift,skrifter,font,installer,truetype,type1,bitmap,punktskrift +X-KDE-Keywords[pa]=ਫੋਂਟ,ਫੌਂਟ,ਇੰਸਟਾਲਰ,ਟਰੂਟਾਈਪ,ਟਾਈਪ 1,ਬਿਟਮੈਪ X-KDE-Keywords[pl]=czcionki,czcionka,instalator,truetype,typ1,mapa bitowa X-KDE-Keywords[pt]=tipo de letra,tipos de letra,instalador,truetype,type1,imagem X-KDE-Keywords[pt_BR]=fonte,fontes,instalador,truetype,type1,bitmap,imagem diff --git a/kcms/kfontinst/lib/Fc.cpp b/kcms/kfontinst/lib/Fc.cpp --- a/kcms/kfontinst/lib/Fc.cpp +++ b/kcms/kfontinst/lib/Fc.cpp @@ -24,7 +24,7 @@ #include "Fc.h" #include #include - +#include // // KDE font chooser always seems to use Italic - for both Oblique, and Italic. So I guess // the fonts:/ should do too - so as to appear more unified. diff --git a/kcms/ksmserver/kcmsmserver.desktop b/kcms/ksmserver/kcmsmserver.desktop --- a/kcms/ksmserver/kcmsmserver.desktop +++ b/kcms/ksmserver/kcmsmserver.desktop @@ -106,6 +106,7 @@ X-KDE-Keywords=ksmserver,session,logout,confirmation,save,restore,efi,uefi,bios X-KDE-Keywords[ca]=ksmserver,sessió,sortida,confirmació,desa,restaura,efi,uefi,bios X-KDE-Keywords[ca@valencia]=ksmserver,sessió,eixida,confirmació,guarda,restaura,efi,uefi,bios +X-KDE-Keywords[da]=ksmserver,session,log ud,bekræftelse,gem,genskab,efi,uefi,bios X-KDE-Keywords[de]=Ksmserver,Sitzung,Abmelden,Logout,Bestätigung,Speichern,Wiederherstellen,efi,uefi,bios X-KDE-Keywords[en_GB]=ksmserver,session,logout,confirmation,save,restore,efi,uefi,bios X-KDE-Keywords[es]=ksmserver,sesión,cerrar sesión,confirmación,guardar,restaurar,efi,uefi,bios diff --git a/kcms/ksmserver/smserverconfigdlg.ui b/kcms/ksmserver/smserverconfigdlg.ui --- a/kcms/ksmserver/smserverconfigdlg.ui +++ b/kcms/ksmserver/smserverconfigdlg.ui @@ -57,16 +57,16 @@ - + - &Turn off computer + &Restart computer - + - &Restart computer + &Turn off computer diff --git a/kcms/ksplash/CMakeLists.txt b/kcms/ksplash/CMakeLists.txt --- a/kcms/ksplash/CMakeLists.txt +++ b/kcms/ksplash/CMakeLists.txt @@ -12,11 +12,11 @@ target_link_libraries(kcm_splashscreen KF5::KIOWidgets KF5::CoreAddons + KF5::ConfigWidgets KF5::QuickAddons KF5::I18n KF5::Plasma KF5::PlasmaQuick - KF5::NewStuff Qt5::DBus Qt5::Widgets diff --git a/kcms/ksplash/kcm.h b/kcms/ksplash/kcm.h --- a/kcms/ksplash/kcm.h +++ b/kcms/ksplash/kcm.h @@ -50,7 +50,7 @@ Q_INVOKABLE int pluginIndex(const QString &pluginName) const; public Q_SLOTS: - void getNewClicked(); + void ghnsEntriesChanged(const QQmlListReference &changedEntries); void save() override; void test(const QString &plugin); diff --git a/kcms/ksplash/kcm.cpp b/kcms/ksplash/kcm.cpp --- a/kcms/ksplash/kcm.cpp +++ b/kcms/ksplash/kcm.cpp @@ -32,8 +32,6 @@ #include -#include - #include "splashscreensettings.h" K_PLUGIN_FACTORY_WITH_JSON(KCMSplashScreenFactory, "kcm_splashscreen.json", registerPlugin();) @@ -93,14 +91,10 @@ return m_model; } -void KCMSplashScreen::getNewClicked() +void KCMSplashScreen::ghnsEntriesChanged(const QQmlListReference &changedEntries) { - KNS3::DownloadDialog dialog("ksplash.knsrc", nullptr); - if (dialog.exec()) { - KNS3::Entry::List list = dialog.changedEntries(); - if (!list.isEmpty()) { - loadModel(); - } + if (changedEntries.count() > 0) { + loadModel(); } } diff --git a/kcms/ksplash/kcm_splashscreen.desktop b/kcms/ksplash/kcm_splashscreen.desktop --- a/kcms/ksplash/kcm_splashscreen.desktop +++ b/kcms/ksplash/kcm_splashscreen.desktop @@ -64,6 +64,7 @@ Comment[ca]=Trieu el tema de la pantalla de presentació Comment[ca@valencia]=Trieu el tema de la pantalla de presentació Comment[cs]=Zvolte motiv uvítací obrazovky +Comment[da]=Vælg tema for opstartsbillede Comment[de]=Startbildschirm-Design auswählen Comment[en_GB]=Choose splash screen theme Comment[es]=Escoger un tema para la pantalla de bienvenida @@ -80,6 +81,7 @@ Comment[lt]=Pasirinkti prisistatymo lango apipavidalinimą Comment[nl]=Opstartschermthema kiezen Comment[nn]=Vel tema for velkomstbilete +Comment[pa]=ਸਵਾਗਤੀ ਸਕਰੀਨ ਥੀਮ ਚੁਣੋ Comment[pl]=Wybierz wygląd ekranu powitalnego Comment[pt]=Escolher o tema do ecrã inicial Comment[pt_BR]=Escolha o tema da tela de apresentação diff --git a/kcms/ksplash/package/contents/ui/main.qml b/kcms/ksplash/package/contents/ui/main.qml --- a/kcms/ksplash/package/contents/ui/main.qml +++ b/kcms/ksplash/package/contents/ui/main.qml @@ -21,7 +21,7 @@ import QtQuick.Layouts 1.1 import QtQuick.Controls 1.0 as QtControls import org.kde.kirigami 2.4 as Kirigami -import org.kde.kconfig 1.0 // for KAuthorized +import org.kde.newstuff 1.62 as NewStuff import org.kde.kcm 1.1 as KCM KCM.GridViewKCM { @@ -80,11 +80,12 @@ Item { Layout.fillWidth: true } - QtControls.Button { - iconName: "get-hot-new-stuff" - text: i18n("&Get New Splash Screens...") - onClicked: kcm.getNewClicked(); - visible: KAuthorized.authorize("ghns") + NewStuff.Button { + id: newStuffButton + downloadNewWhat: i18n("Splash Screens") + configFile: "ksplash.knsrc" + viewMode: NewStuff.Page.ViewMode.Preview + onChangedEntriesChanged: kcm.ghnsEntriesChanged(newStuffButton.changedEntries); } } } diff --git a/kcms/ksplash/package/metadata.desktop b/kcms/ksplash/package/metadata.desktop --- a/kcms/ksplash/package/metadata.desktop +++ b/kcms/ksplash/package/metadata.desktop @@ -51,6 +51,7 @@ Comment[ca]=Trieu el tema de la pantalla de presentació Comment[ca@valencia]=Trieu el tema de la pantalla de presentació Comment[cs]=Zvolte motiv uvítací obrazovky +Comment[da]=Vælg tema for opstartsbillede Comment[de]=Startbildschirm-Design auswählen Comment[en_GB]=Choose splash screen theme Comment[es]=Escoger un tema para la pantalla de bienvenida @@ -67,6 +68,7 @@ Comment[lt]=Pasirinkti prisistatymo lango apipavidalinimą Comment[nl]=Opstartschermthema kiezen Comment[nn]=Vel tema for velkomstbilete +Comment[pa]=ਸਵਾਗਤੀ ਸਕਰੀਨ ਥੀਮ ਚੁਣੋ Comment[pl]=Wybierz wygląd ekranu powitalnego Comment[pt]=Escolher o tema do ecrã inicial Comment[pt_BR]=Escolha o tema da tela de apresentação diff --git a/kcms/lookandfeel/CMakeLists.txt b/kcms/lookandfeel/CMakeLists.txt --- a/kcms/lookandfeel/CMakeLists.txt +++ b/kcms/lookandfeel/CMakeLists.txt @@ -1,17 +1,25 @@ # KI18N Translation Domain for this library add_definitions(-DTRANSLATION_DOMAIN=\"kcm_lookandfeel\") +if(X11_Xcursor_FOUND) + set(HAVE_XCURSOR TRUE) +endif() configure_file (config-kcm.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/config-kcm.h ) - set(kcm_lookandfeel_SRCS - kcmmain.cpp - kcm.cpp - ../krdb/krdb.cpp - ../cursortheme/xcursor/cursortheme.cpp - ../cursortheme/xcursor/xcursortheme.cpp + kcmmain.cpp + kcm.cpp + ../krdb/krdb.cpp ) +if (X11_Xcursor_FOUND) + set(kcm_lookandfeel_SRCS + ${kcm_lookandfeel_SRCS} + ../cursortheme/xcursor/cursortheme.cpp + ../cursortheme/xcursor/xcursortheme.cpp + ) +endif () + set(klauncher_xml ${KINIT_DBUS_INTERFACES_DIR}/kf5_org.kde.KLauncher.xml) qt5_add_dbus_interface(kcm_lookandfeel_SRCS ${klauncher_xml} klauncher_iface) @@ -69,10 +77,16 @@ # TODO: load kcm plugin instead of using code copy kcm.cpp ../krdb/krdb.cpp - ../cursortheme/xcursor/cursortheme.cpp - ../cursortheme/xcursor/xcursortheme.cpp ) +if (X11_Xcursor_FOUND) + set(lookandfeeltool_SRCS + ${lookandfeeltool_SRCS} + ../cursortheme/xcursor/cursortheme.cpp + ../cursortheme/xcursor/xcursortheme.cpp + ) +endif () + qt5_add_dbus_interface(lookandfeeltool_SRCS ${klauncher_xml} klauncher_iface) kconfig_add_kcfg_files(lookandfeeltool_SRCS lookandfeelsettings.kcfgc GENERATE_MOC) diff --git a/kcms/lookandfeel/autotests/CMakeLists.txt b/kcms/lookandfeel/autotests/CMakeLists.txt --- a/kcms/lookandfeel/autotests/CMakeLists.txt +++ b/kcms/lookandfeel/autotests/CMakeLists.txt @@ -6,10 +6,16 @@ kcmtest.cpp ../kcm.cpp ../../krdb/krdb.cpp - ../../cursortheme/xcursor/cursortheme.cpp - ../../cursortheme/xcursor/xcursortheme.cpp ) +if (X11_Xcursor_FOUND) + set(kcmTest_SRCS + ${kcmTest_SRCS} + ../../cursortheme/xcursor/cursortheme.cpp + ../../cursortheme/xcursor/xcursortheme.cpp + ) +endif () + set(klauncher_xml ${KINIT_DBUS_INTERFACES_DIR}/kf5_org.kde.KLauncher.xml) qt5_add_dbus_interface(kcmTest_SRCS ${klauncher_xml} klauncher_iface) diff --git a/kcms/lookandfeel/config-kcm.h.cmake b/kcms/lookandfeel/config-kcm.h.cmake --- a/kcms/lookandfeel/config-kcm.h.cmake +++ b/kcms/lookandfeel/config-kcm.h.cmake @@ -1,2 +1,3 @@ #cmakedefine HAVE_XFIXES 1 - +#cmakedefine HAVE_XCURSOR 1 +#cmakedefine HAVE_BREEZE_DECO 1 diff --git a/kcms/lookandfeel/kcm.cpp b/kcms/lookandfeel/kcm.cpp --- a/kcms/lookandfeel/kcm.cpp +++ b/kcms/lookandfeel/kcm.cpp @@ -20,7 +20,6 @@ #include "kcm.h" #include "../krdb/krdb.h" -#include "../cursortheme/xcursor/xcursortheme.h" #include "config-kcm.h" #include "config-workspace.h" #include @@ -45,10 +44,14 @@ #include #include -#include #include "lookandfeelsettings.h" +#ifdef HAVE_XCURSOR +# include "../cursortheme/xcursor/xcursortheme.h" +# include +#endif + #ifdef HAVE_XFIXES # include #endif @@ -467,10 +470,11 @@ cg.writeEntry("cursorTheme", themeName); cg.sync(); +#ifdef HAVE_XCURSOR // Require the Xcursor version that shipped with X11R6.9 or greater, since // in previous versions the Xfixes code wasn't enabled due to a bug in the // build system (freedesktop bug #975). -#if HAVE_XFIXES && XFIXES_MAJOR >= 2 && XCURSOR_LIB_VERSION >= 10105 +#if defined(HAVE_XFIXES) && XFIXES_MAJOR >= 2 && XCURSOR_LIB_VERSION >= 10105 const int cursorSize = cg.readEntry("cursorSize", 0); QDir themeDir = cursorThemeDir(themeName, 0); @@ -526,6 +530,7 @@ i18n("You have to restart the Plasma session for these changes to take effect."), i18n("Cursor Settings Changed"), "CursorSettingsChanged"); #endif +#endif } QDir KCMLookandFeel::cursorThemeDir(const QString &theme, const int depth) @@ -579,6 +584,7 @@ if (!m_cursorSearchPaths.isEmpty()) return m_cursorSearchPaths; +#ifdef HAVE_XCURSOR #if XCURSOR_LIB_MAJOR == 1 && XCURSOR_LIB_MINOR < 1 // These are the default paths Xcursor will scan for cursor themes QString path("~/.icons:/usr/share/icons:/usr/share/pixmaps:/usr/X11R6/lib/X11/icons"); @@ -609,6 +615,9 @@ // Expand all occurrences of ~/ to the home dir m_cursorSearchPaths.replaceInStrings(QRegExp(QStringLiteral("^~\\/")), QDir::home().path() + QLatin1Char('/')); return m_cursorSearchPaths; +#else + return QStringList(); +#endif } void KCMLookandFeel::setSplashScreen(const QString &theme) diff --git a/kcms/lookandfeel/kcm_lookandfeel.desktop b/kcms/lookandfeel/kcm_lookandfeel.desktop --- a/kcms/lookandfeel/kcm_lookandfeel.desktop +++ b/kcms/lookandfeel/kcm_lookandfeel.desktop @@ -15,6 +15,7 @@ Name[ast]=Estilu global Name[ca]=Tema global Name[cs]=Celkový motiv +Name[da]=Globalt tema Name[de]=Globales Design Name[en_GB]=Global Theme Name[es]=Tema global @@ -31,6 +32,7 @@ Name[lt]=Visuotinis apipavidalinimas Name[nl]=Globaal thema Name[nn]=Globalt tema +Name[pa]=ਗਲੋਬਲ ਥੀਮ Name[pl]=Globalny wygląd Name[pt]=Tema Global Name[pt_BR]=Tema global @@ -45,6 +47,7 @@ Comment=Choose global look and feel Comment[ca]=Trieu l'aspecte i comportament global Comment[cs]=Zvolte celkový vzhled a chování +Comment[da]=Vælg globalt udseende og fremtoning Comment[de]=Globales Erscheinungsbild auswählen Comment[en_GB]=Choose global look and feel Comment[es]=Escoger el aspecto visual global @@ -61,6 +64,7 @@ Comment[lt]=Pasirinkti visuotinę išvaizdą ir turinį Comment[nl]=Globaal uiterlijk en gedrag kiezen Comment[nn]=Vel globalt tema for utsjånad og åtferd +Comment[pa]=ਗਲੋਬਲ ਦਿੱਖ ਅਤੇ ਛੋਹ ਚੁਣੋ Comment[pl]=Nadaj wygląd globalnie Comment[pt]=Escolher a aparência e comportamento globais Comment[pt_BR]=Escolha a aparência e comportamento globais @@ -95,7 +99,7 @@ X-KDE-Keywords[nds]=Muster, Utsehn, Bedenen X-KDE-Keywords[nl]=thema, uiterlijk, gedrag X-KDE-Keywords[nn]=tema, utsjånad, åtferd -X-KDE-Keywords[pa]=ਥੀਮ, ਦਿੱਖ, ਰਵੱਈਆ +X-KDE-Keywords[pa]=ਥੀਮ, ਦਿੱਖ, ਛੋਹ X-KDE-Keywords[pl]=wystrój, wygląd, odczucia, wrażenia X-KDE-Keywords[pt]=tema, aparência, comportamento X-KDE-Keywords[pt_BR]=tema, visual, aparência diff --git a/kcms/lookandfeel/lookandfeel.knsrc b/kcms/lookandfeel/lookandfeel.knsrc --- a/kcms/lookandfeel/lookandfeel.knsrc +++ b/kcms/lookandfeel/lookandfeel.knsrc @@ -3,6 +3,7 @@ Name[ast]=Estilos globales Name[ca]=Temes globals Name[cs]=Celkové motivy +Name[da]=Globale temaer Name[de]=Globale Designs Name[en_GB]=Global Themes Name[es]=Temas globales @@ -19,6 +20,7 @@ Name[lt]=Visuotiniai apipavidalinimai Name[nl]=Globale thema's Name[nn]=Globale tema +Name[pa]=ਗਲੋਬਲ ਥੀਮ Name[pl]=Globalne wyglądy Name[pt]=Temas Globais Name[pt_BR]=Temas globais diff --git a/kcms/lookandfeel/package/metadata.desktop b/kcms/lookandfeel/package/metadata.desktop --- a/kcms/lookandfeel/package/metadata.desktop +++ b/kcms/lookandfeel/package/metadata.desktop @@ -3,6 +3,7 @@ Name[ast]=Estilu global Name[ca]=Tema global Name[cs]=Celkový motiv +Name[da]=Globalt tema Name[de]=Globales Design Name[en_GB]=Global Theme Name[es]=Tema global @@ -19,6 +20,7 @@ Name[lt]=Visuotinis apipavidalinimas Name[nl]=Globaal thema Name[nn]=Globalt tema +Name[pa]=ਗਲੋਬਲ ਥੀਮ Name[pl]=Globalny wygląd Name[pt]=Tema Global Name[pt_BR]=Tema global @@ -33,6 +35,7 @@ Comment=Choose global look and feel Comment[ca]=Trieu l'aspecte i comportament global Comment[cs]=Zvolte celkový vzhled a chování +Comment[da]=Vælg globalt udseende og fremtoning Comment[de]=Globales Erscheinungsbild auswählen Comment[en_GB]=Choose global look and feel Comment[es]=Escoger el aspecto visual global @@ -49,6 +52,7 @@ Comment[lt]=Pasirinkti visuotinę išvaizdą ir turinį Comment[nl]=Globaal uiterlijk en gedrag kiezen Comment[nn]=Vel globalt tema for utsjånad og åtferd +Comment[pa]=ਗਲੋਬਲ ਦਿੱਖ ਅਤੇ ਛੋਹ ਚੁਣੋ Comment[pl]=Nadaj wygląd globalnie Comment[pt]=Escolher a aparência e comportamento globais Comment[pt_BR]=Escolha a aparência e comportamento globais diff --git a/kcms/mouse/kcm/libinput/main.qml b/kcms/mouse/kcm/libinput/main.qml --- a/kcms/mouse/kcm/libinput/main.qml +++ b/kcms/mouse/kcm/libinput/main.qml @@ -33,8 +33,8 @@ spacing: Kirigami.Units.smallSpacing - property size sizeHint: Qt.size(formLayout.width, formLayout.height) - property size minimumSizeHint: Qt.size(formLayout.width/2, deviceSelector.height) + property size sizeHint: Qt.size(formLayout.width, Math.round(1.3 * formLayout.height)) + property size minimumSizeHint: Qt.size(formLayout.width/2, Math.round(1.3 * formLayout.height)) property alias deviceIndex: deviceSelector.currentIndex signal changeSignal() diff --git a/kcms/mouse/kcm/libinput/main_deviceless.qml b/kcms/mouse/kcm/libinput/main_deviceless.qml --- a/kcms/mouse/kcm/libinput/main_deviceless.qml +++ b/kcms/mouse/kcm/libinput/main_deviceless.qml @@ -33,8 +33,8 @@ spacing: Kirigami.Units.smallSpacing - property size sizeHint: Qt.size(formLayout.width, Math.round(1.1 * formLayout.height)) - property size minimumSizeHint: Qt.size(formLayout.width, Math.round(1.1 * formLayout.height)) + property size sizeHint: Qt.size(formLayout.width, Math.round(1.3 * formLayout.height)) + property size minimumSizeHint: Qt.size(formLayout.width, Math.round(1.3 * formLayout.height)) signal changeSignal() diff --git a/kcms/nightcolor/kcm_nightcolor.desktop b/kcms/nightcolor/kcm_nightcolor.desktop --- a/kcms/nightcolor/kcm_nightcolor.desktop +++ b/kcms/nightcolor/kcm_nightcolor.desktop @@ -36,7 +36,7 @@ Name[nl]=Nachtkleur Name[nn]=Nattfargar Name[pa]=ਰਾਤ ਦਾ ਰੰਗ -Name[pl]=Barwa nocy +Name[pl]=Barwy nocą Name[pt]=Cor Nocturna Name[pt_BR]=Cor noturna Name[ru]=Ночная цветовая схема @@ -50,7 +50,7 @@ Name[uk]=Нічні кольори Name[x-test]=xxNight Colorxx Name[zh_CN]=夜晚颜色 -Name[zh_TW]=夜間模式 +Name[zh_TW]=夜色模式 Comment=Adjust color temperature at night to reduce eye strain Comment[ast]=Axusta la temperatura del color pela nueche p'amenorgar el cansanciu de güeyos Comment[ca]=Ajusta la temperatura del color per a la nit per reduir la tensió ocular @@ -72,6 +72,7 @@ Comment[lt]=Reguliuoti naktį spalvos temperatūrą, kad būtų sumažinta akių įtampa Comment[nl]=Kleurtemperatuur bij nacht aanpassen on vermoeidheid van de ogen te vermijden Comment[nn]=Juster fargetemperaturen ved kveldstid for å gjera det mindre anstrengjande for auga +Comment[pa]=ਰਾਤ ਦੇ ਸਮੇਂ ਅੱਖਾਂ ਉੱਤੇ ਦਬਾਅ ਘਟਾਉਣ ਲਈ ਰੰਗ ਦੇ ਤਾਪਮਾਨ ਨੂੰ ਤਰਤੀਬ ਦਿਓ Comment[pl]=Dostosuj temperaturę barwy w nocy, aby zmniejszyć wytężenie oka Comment[pt]=Ajustar a temperatura da cor à noite para reduzir o cansaço dos olhos Comment[pt_BR]=Ajustar a temperatura de cor a noite para reduzir a tensão visual diff --git a/kcms/nightcolor/package/contents/ui/LocationsAutoView.qml b/kcms/nightcolor/package/contents/ui/LocationsAutoView.qml deleted file mode 100644 --- a/kcms/nightcolor/package/contents/ui/LocationsAutoView.qml +++ /dev/null @@ -1,43 +0,0 @@ -/******************************************************************** -Copyright 2017 Roman Gilg - -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.1 -import org.kde.kirigami 2.5 as Kirigami - -Kirigami.FormLayout { - twinFormLayouts: parentLayout - enabled: activator.checked - - property double latitude - property double longitude - - onLatitudeChanged: latitudeField.backend = latitude; - onLongitudeChanged: longitudeField.backend = longitude; - - NumberField { - id: latitudeField - Kirigami.FormData.label: i18n("Latitude:") - backend: locator.latitude - enabled: false - } - - NumberField { - id: longitudeField - Kirigami.FormData.label: i18n("Longitude:") - backend: locator.longitude - enabled: false - } -} diff --git a/kcms/nightcolor/package/contents/ui/LocationsFixedView.qml b/kcms/nightcolor/package/contents/ui/LocationsFixedView.qml --- a/kcms/nightcolor/package/contents/ui/LocationsFixedView.qml +++ b/kcms/nightcolor/package/contents/ui/LocationsFixedView.qml @@ -15,54 +15,61 @@ along with this program. If not, see . *********************************************************************/ import QtQuick 2.1 -import org.kde.kirigami 2.5 as Kirigami +import QtQuick.Layouts 1.1 import QtQuick.Controls 2.5 as QQC2 +import org.kde.kirigami 2.5 as Kirigami Kirigami.FormLayout { twinFormLayouts: parentLayout - enabled: activator.checked Connections { target: root onReset: reset() + onDefaults: { + latitudeFixedField.backend = cA.latitudeFixedDefault; + longitudeFixedField.backend = cA.longitudeFixedDefault; + } } function reset() { latitudeFixedField.backend = cA.latitudeFixed; longitudeFixedField.backend = cA.longitudeFixed; } + QQC2.Button { + text: i18n("Detect Location") + // Match combobox width + Layout.minimumWidth: modeSwitcher.width + icon.name: "find-location" + onClicked: { + latitudeFixedField.backend = locator.latitude; + longitudeFixedField.backend = locator.longitude; + } + } + NumberField { id: latitudeFixedField + // Match combobox width + Layout.minimumWidth: modeSwitcher.width Kirigami.FormData.label: i18n("Latitude:") backend: cA.latitudeFixedStaged validator: DoubleValidator {bottom: -90; top: 90; decimals: 10} onBackendChanged: { cA.latitudeFixedStaged = backend; - manualLocationsViewRow.change(); calcNeedsSave(); } } NumberField { id: longitudeFixedField + // Match combobox width + Layout.minimumWidth: modeSwitcher.width Kirigami.FormData.label: i18n("Longitude:") backend: cA.longitudeFixedStaged validator: DoubleValidator {bottom: -180; top: 180; decimals: 10} onBackendChanged: { cA.longitudeFixedStaged = backend; - manualLocationsViewRow.change(); calcNeedsSave(); } } - - QQC2.Button { - text: i18n("Detect Location") - implicitWidth: longitudeFixedField.width // TODO: see if there is a smarter way for doing this - icon.name: "find-location" - onClicked: { - latitudeFixedField.backend = locator.latitude; - longitudeFixedField.backend = locator.longitude; - } - } } diff --git a/kcms/nightcolor/package/contents/ui/TimingsView.qml b/kcms/nightcolor/package/contents/ui/TimingsView.qml --- a/kcms/nightcolor/package/contents/ui/TimingsView.qml +++ b/kcms/nightcolor/package/contents/ui/TimingsView.qml @@ -20,7 +20,6 @@ Kirigami.FormLayout { twinFormLayouts: parentLayout - enabled: activator.checked property double latitude property double longitude @@ -33,31 +32,33 @@ eveningTimings = sunCalc.getEveningTimings(latitude, longitude); } - TimeField { - id: mornBeginField - Kirigami.FormData.label: i18n("Sunrise begins:") - backend: morningTimings.begin - enabled: false + function prettyTime(date) { + return date.toLocaleString(Qt.locale(), "h:mm"); } - TimeField { - id: mornEndField - Kirigami.FormData.label: i18n("...and ends:") - backend: morningTimings.end - enabled: false + Kirigami.Separator { + Kirigami.FormData.isSection: true } - TimeField { - id: evenBeginField - Kirigami.FormData.label: i18n("Sunset begins:") - backend: eveningTimings.begin - enabled: false + QQC2.Label { + wrapMode: Text.Wrap + text: i18n("Night Color begins at %1", prettyTime(eveningTimings.begin)) + } + QQC2.Label { + wrapMode: Text.Wrap + text: i18n("Color fully changed at %1", prettyTime(eveningTimings.end)) + } + + Item { + Kirigami.FormData.isSection: true } - TimeField { - id: evenEndField - Kirigami.FormData.label: i18n("...and ends:") - backend: eveningTimings.end - enabled: false + QQC2.Label { + wrapMode: Text.Wrap + text: i18n("Night Color begins changing back at %1", prettyTime(morningTimings.begin)) + } + QQC2.Label { + wrapMode: Text.Wrap + text: i18n("Normal coloration restored by %1", prettyTime(morningTimings.end)) } } diff --git a/kcms/nightcolor/package/contents/ui/main.qml b/kcms/nightcolor/package/contents/ui/main.qml --- a/kcms/nightcolor/package/contents/ui/main.qml +++ b/kcms/nightcolor/package/contents/ui/main.qml @@ -28,6 +28,7 @@ property int error: cA.error property bool defaultRequested: false implicitHeight: Kirigami.Units.gridUnit * 29 + implicitWidth: Kirigami.Units.gridUnit * 35 CC.CompositorAdaptor { id: cA @@ -47,12 +48,30 @@ // Default was triggered, only allow a normal // configuration change again: defaultRequested = false; + + calcRepresentsDefault(); + } + function calcRepresentsDefault() { + if (cA.nightColorAvailable) { + kcm.representsDefaults = activator.checked === cA.activeDefault && + tempSlider.value === cA.nightTemperatureDefault && + modeSwitcher.currentIndex === cA.modeDefault && + cA.latitudeFixedStaged === cA.latitudeFixedDefault && + cA.longitudeFixedStaged === cA.longitudeFixedDefault && + cA.morningBeginFixedStaged.toString() === cA.morningBeginFixedDefault.toString() && + cA.eveningBeginFixedStaged.toString() === cA.eveningBeginFixedDefault.toString() && + cA.transitionTimeStaged === cA.transitionTimeDefault; + } else { + kcm.representsDefaults = true; + } } Connections { target: kcm onLoadRelay: cA.reloadData() - onSaveRelay: defaultRequested ? cA.sendConfigurationAll() : cA.sendConfiguration(); + onSaveRelay: { + defaultRequested ? cA.sendConfigurationAll() : cA.sendConfiguration(); + } onDefaultsRelay: { if (!cA.nightColorAvailable) { return; @@ -62,17 +81,20 @@ modeSwitcher.currentIndex = cA.modeDefault; // set everything else to default as well - cA.latitudeFixedStaged = cA.latitudeFixedDefault; - cA.longitudeFixedStaged = cA.longitudeFixedDefault; + defaults() - cA.morningBeginFixedStaged = cA.morningBeginFixedDefault; - cA.eveningBeginFixedStaged = cA.eveningBeginFixedDefault; - cA.transitionTimeStaged = cA.transitionTimeDefault; + mornBeginManField.backend = cA.morningBeginFixedDefault; + evenBeginManField.backend = cA.eveningBeginFixedDefault; + transTimeField.value = cA.transitionTimeDefault; + cA.transitionTimeStaged = transTimeField.value; kcm.needsSave = cA.checkStagedAll(); defaultRequested = true; + + calcRepresentsDefault(); } } + signal defaults() Connections { target: cA @@ -108,13 +130,22 @@ Layout.alignment: Qt.AlignHCenter Layout.maximumWidth: Math.round(root.width * 0.5) - text: i18n("Night Color makes the colors on the screen warmer to reduce eye strain.") + text: i18n("Night Color makes the colors on the screen warmer to reduce eye strain at the time of your choosing.") wrapMode: Text.WordWrap } Kirigami.FormLayout { id: parentLayout + Connections { + target: root + onReset: { + mornBeginManField.backend = cA.morningBeginFixed; + evenBeginManField.backend = cA.eveningBeginFixed; + transTimeField.value = cA.transitionTime; + } + } + QQC2.CheckBox { id: activator text: i18n("Activate Night Color") @@ -132,17 +163,18 @@ } GridLayout { - Kirigami.FormData.label: i18n("Night Color temperature:") + Kirigami.FormData.label: i18n("Night Color Temperature:") Kirigami.FormData.buddyFor: tempSlider enabled: activator.checked columns: 4 QQC2.Slider { id: tempSlider + // Match combobox width + Layout.minimumWidth: modeSwitcher.width enabled: activator.checked from: cA.minimalTemperature - implicitWidth: modeSwitcher.width to: cA.neutralTemperature value: cA.nightTemperature stepSize: 100 @@ -176,201 +208,130 @@ QQC2.ComboBox { id: modeSwitcher - Kirigami.FormData.label: i18n("Operation mode:") + // Work around https://bugs.kde.org/show_bug.cgi?id=403153 + Layout.minimumWidth: Kirigami.Units.gridUnit * 17 + Kirigami.FormData.label: i18n("Activation time:") enabled: activator.checked model: [ - i18n("Automatic"), - i18n("Location"), - i18n("Times"), - i18n("Constant") + i18n("Sunset to sunrise at current location"), + i18n("Sunset to sunrise at manual location"), + i18n("Custom time"), + i18n("Always on") ] currentIndex: cA.mode onCurrentIndexChanged: { cA.modeStaged = currentIndex; - advancedControlLoader.updatePage(currentIndex); calcNeedsSave(); } } - } - Kirigami.FormLayout { + // Show current location in auto mode + QQC2.Label { + visible: modeSwitcher.currentIndex === CC.CompositorAdaptor.ModeAutomatic + enabled: activator.checked + wrapMode: Text.Wrap + text: i18n("Latitude: %1 Longitude: %2", locator.latitude, locator.longitude) + } - Loader { - id: advancedControlLoader - - - function updatePage(index) { - switch (index) { - case CC.CompositorAdaptor.ModeAutomatic: - sourceComponent = automaticView; - break; - case CC.CompositorAdaptor.ModeLocation: - sourceComponent = manualLocationsView; - break; - case CC.CompositorAdaptor.ModeTimings: - sourceComponent = manualTimingsView; - break; - case CC.CompositorAdaptor.ModeConstant: - default: - sourceComponent = undefined; - break; - } + // Show time entry fields in manual timings mode + TimeField { + id: evenBeginManField + // Match combobox width + Layout.minimumWidth: modeSwitcher.width + visible: modeSwitcher.currentIndex === CC.CompositorAdaptor.ModeTimings + Kirigami.FormData.label: i18n("Turn on at:") + backend: cA.eveningBeginFixedStaged + onBackendChanged: { + cA.eveningBeginFixedStaged = backend; + calcNeedsSave(); } - } - Component { - id: automaticView + QQC2.ToolTip { + text: i18n("Input format: HH:MM") + } + } - ColumnLayout { + TimeField { + id: mornBeginManField + // Match combobox width + Layout.minimumWidth: modeSwitcher.width + visible: modeSwitcher.currentIndex === CC.CompositorAdaptor.ModeTimings + Kirigami.FormData.label: i18n("Turn off at:") + backend: cA.morningBeginFixedStaged + onBackendChanged: { + cA.morningBeginFixedStaged = backend; + calcNeedsSave(); + } - Loader { - sourceComponent: TimingsView { - latitude: locator.latitude - longitude: locator.longitude - } - } + QQC2.ToolTip { + text: i18n("Input format: HH:MM") + } + } - Kirigami.Separator { - Layout.fillWidth: true - Kirigami.FormData.isSection: true - } + QQC2.SpinBox { + id: transTimeField + visible: modeSwitcher.currentIndex === CC.CompositorAdaptor.ModeTimings + // Match width of combobox and input fields + Layout.minimumWidth: modeSwitcher.width + Kirigami.FormData.label: i18n("Transition duration:") + from: 1 + to: 600 // less than 12 hours (in minutes: 720) + value: cA.transitionTimeStaged + editable: true + onValueModified: { + cA.transitionTimeStaged = value; + calcNeedsSave(); + } + textFromValue: function(value, locale) { + return i18np("%1 minute", "%1 minutes", value) + } + valueFromText: function(text, locale) { + return parseInt(text); + } - Loader { - sourceComponent: LocationsAutoView { - latitude: locator.latitude - longitude: locator.longitude - } - } + QQC2.ToolTip { + text: i18n("Input minutes - min. 1, max. 600") } } - Component { - id: manualLocationsView - - ColumnLayout { - id: manualLocationsViewRow - signal change() - - Loader { - sourceComponent: TimingsView { - latitude: cA.latitudeFixedStaged - longitude: cA.longitudeFixedStaged - - Connections { - target: manualLocationsViewRow - onChange: { - reset(); - } - } - } - } + QQC2.Label { + id: manualTimingsError1 + visible: evenBeginManField.getNormedDate() - mornBeginManField.getNormedDate() <= 0 + font.italic: true + text: i18n("Error: Morning is before evening.") + } - Kirigami.Separator { - Layout.fillWidth: true - Kirigami.FormData.isSection: true + QQC2.Label { + id: manualTimingsError2 + visible: { + if (manualTimingsError1.visible) { + return false; } + var trTime = transTimeField.backend * 60 * 1000; + var mor = mornBeginManField.getNormedDate(); + var eve = evenBeginManField.getNormedDate(); - Loader { - sourceComponent: LocationsFixedView {} - } + return eve - mor <= trTime || eve - mor >= 86400000 - trTime; } + font.italic: true + text: i18n("Error: Transition time overlaps.") } + } - Component { - id: manualTimingsView - - ColumnLayout { - Loader { - sourceComponent: Kirigami.FormLayout { - twinFormLayouts: parentLayout - enabled: activator.checked && cA.timingsEnabled - - Connections { - target: root - onReset: { - mornBeginManField.backend = cA.morningBeginFixed; - evenBeginManField.backend = cA.eveningBeginFixed; - transTimeField.backend = cA.transitionTime; - } - } - - TimeField { - id: mornBeginManField - Kirigami.FormData.label: i18n("Sunrise begins:") - backend: cA.morningBeginFixedStaged - onBackendChanged: {cA.morningBeginFixedStaged = backend; - calcNeedsSave(); - } - - QQC2.ToolTip { - text: i18n("(Input format: HH:MM)") - } - } - - TimeField { - id: evenBeginManField - Kirigami.FormData.label: i18n("Sunset begins:") - backend: cA.eveningBeginFixedStaged - onBackendChanged: {cA.eveningBeginFixedStaged = backend; - calcNeedsSave(); - } - - QQC2.ToolTip { - text: i18n("Input format: HH:MM") - } - } - - QQC2.SpinBox { - id: transTimeField - // Match width of other text fields - Layout.minimumWidth: 200 - Kirigami.FormData.label: i18n("Transition duration:") - from: 1 - to: 600 // less than 12 hours (in minutes: 720) - value: cA.transitionTimeStaged - editable: true - onValueModified: { - cA.transitionTimeStaged = value; - calcNeedsSave(); - } - textFromValue: function(value, locale) { - return i18np("%1 minute", "%1 minutes", value) - } - valueFromText: function(text, locale) { - return parseInt(text); - } - - QQC2.ToolTip { - text: i18n("Input minutes - min. 1, max. 600") - } - } - - QQC2.Label { - id: manualTimingsError1 - visible: evenBeginManField.getNormedDate() - mornBeginManField.getNormedDate() <= 0 - font.italic: true - text: i18n("Error: Morning is before evening.") - } - - QQC2.Label { - id: manualTimingsError2 - visible: { - if (manualTimingsError1.visible) { - return false; - } - var trTime = transTimeField.backend * 60 * 1000; - var mor = mornBeginManField.getNormedDate(); - var eve = evenBeginManField.getNormedDate(); - - return eve - mor <= trTime || eve - mor >= 86400000 - trTime; - } - font.italic: true - text: i18n("Error: Transition time overlaps.") - } - } - } - } - } + // Show location chooser in manual location mode + LocationsFixedView { + visible: modeSwitcher.currentIndex === CC.CompositorAdaptor.ModeLocation + enabled: activator.checked + } + + // Show start/end times in automatic and manual location modes + TimingsView { + id: timings + visible: modeSwitcher.currentIndex === CC.CompositorAdaptor.ModeAutomatic || + modeSwitcher.currentIndex === CC.CompositorAdaptor.ModeLocation + enabled: activator.checked + latitude: modeSwitcher.currentIndex === CC.CompositorAdaptor.ModeAutomatic ? locator.latitude : cA.latitudeFixedStaged + longitude: modeSwitcher.currentIndex === CC.CompositorAdaptor.ModeAutomatic ? locator.longitude : cA.longitudeFixedStaged } } } diff --git a/kcms/nightcolor/package/metadata.desktop b/kcms/nightcolor/package/metadata.desktop --- a/kcms/nightcolor/package/metadata.desktop +++ b/kcms/nightcolor/package/metadata.desktop @@ -22,7 +22,7 @@ Name[nl]=Nachtkleur Name[nn]=Nattfargar Name[pa]=ਰਾਤ ਦਾ ਰੰਗ -Name[pl]=Barwa nocy +Name[pl]=Barwy nocą Name[pt]=Cor Nocturna Name[pt_BR]=Cor noturna Name[ru]=Ночная цветовая схема @@ -36,7 +36,7 @@ Name[uk]=Нічні кольори Name[x-test]=xxNight Colorxx Name[zh_CN]=夜晚颜色 -Name[zh_TW]=夜間模式 +Name[zh_TW]=夜色模式 Comment=Adjust color temperature at night to reduce eye strain Comment[ast]=Axusta la temperatura del color pela nueche p'amenorgar el cansanciu de güeyos Comment[ca]=Ajusta la temperatura del color per a la nit per reduir la tensió ocular @@ -58,6 +58,7 @@ Comment[lt]=Reguliuoti naktį spalvos temperatūrą, kad būtų sumažinta akių įtampa Comment[nl]=Kleurtemperatuur bij nacht aanpassen on vermoeidheid van de ogen te vermijden Comment[nn]=Juster fargetemperaturen ved kveldstid for å gjera det mindre anstrengjande for auga +Comment[pa]=ਰਾਤ ਦੇ ਸਮੇਂ ਅੱਖਾਂ ਉੱਤੇ ਦਬਾਅ ਘਟਾਉਣ ਲਈ ਰੰਗ ਦੇ ਤਾਪਮਾਨ ਨੂੰ ਤਰਤੀਬ ਦਿਓ Comment[pl]=Dostosuj temperaturę barwy w nocy, aby zmniejszyć wytężenie oka Comment[pt]=Ajustar a temperatura da cor à noite para reduzir o cansaço dos olhos Comment[pt_BR]=Ajustar a temperatura de cor a noite para reduzir a tensão visual diff --git a/kcms/notifications/CMakeLists.txt b/kcms/notifications/CMakeLists.txt --- a/kcms/notifications/CMakeLists.txt +++ b/kcms/notifications/CMakeLists.txt @@ -12,6 +12,7 @@ KF5::KCMUtils KF5::CoreAddons KF5::Declarative + KF5::GlobalAccel KF5::GuiAddons KF5::I18n KF5::QuickAddons diff --git a/kcms/notifications/kcm.h b/kcms/notifications/kcm.h --- a/kcms/notifications/kcm.h +++ b/kcms/notifications/kcm.h @@ -22,6 +22,10 @@ #include +#include + +class QAction; + class SourcesModel; class FilterProxyModel; @@ -38,6 +42,11 @@ Q_PROPERTY(NotificationManager::Settings *settings READ settings CONSTANT) + Q_PROPERTY(QKeySequence toggleDoNotDisturbShortcut + READ toggleDoNotDisturbShortcut + WRITE setToggleDoNotDisturbShortcut + NOTIFY toggleDoNotDisturbShortcutChanged) + // So it can show the respective settings module right away Q_PROPERTY(QString initialDesktopEntry READ initialDesktopEntry WRITE setInitialDesktopEntry NOTIFY initialDesktopEntryChanged) Q_PROPERTY(QString initialNotifyRcName READ initialNotifyRcName WRITE setInitialNotifyRcName NOTIFY initialNotifyRcNameChanged) @@ -52,6 +61,10 @@ NotificationManager::Settings *settings() const; + QKeySequence toggleDoNotDisturbShortcut() const; + void setToggleDoNotDisturbShortcut(const QKeySequence &shortcut); + Q_SIGNAL void toggleDoNotDisturbShortcutChanged(); + QString initialDesktopEntry() const; void setInitialDesktopEntry(const QString &desktopEntry); @@ -81,6 +94,10 @@ NotificationManager::Settings *m_settings; + QAction *m_toggleDoNotDisturbAction; + QKeySequence m_toggleDoNotDisturbShortcut; + bool m_toggleDoNotDisturbShortcutDirty = false; + QString m_initialDesktopEntry; QString m_initialNotifyRcName; QString m_initialEventId; diff --git a/kcms/notifications/kcm.cpp b/kcms/notifications/kcm.cpp --- a/kcms/notifications/kcm.cpp +++ b/kcms/notifications/kcm.cpp @@ -20,6 +20,7 @@ #include "kcm.h" +#include #include #include #include @@ -33,6 +34,7 @@ #include #include +#include #include #include #include @@ -51,12 +53,14 @@ , m_sourcesModel(new SourcesModel(this)) , m_filteredModel(new FilterProxyModel(this)) , m_settings(new NotificationManager::Settings(this)) + , m_toggleDoNotDisturbAction(new QAction(this)) { const char uri[] = "org.kde.private.kcms.notifications"; qmlRegisterUncreatableType(uri, 1, 0, "SourcesModel", QStringLiteral("Cannot create instances of SourcesModel")); qmlRegisterType(); + qmlRegisterType(); qmlProtectModule(uri, 1); KAboutData *about = new KAboutData(QStringLiteral("kcm_notifications"), i18n("Notifications"), @@ -66,6 +70,13 @@ m_filteredModel->setSourceModel(m_sourcesModel); + // for KGlobalAccel... + // keep in sync with globalshortcuts.cpp in notification plasmoid! + m_toggleDoNotDisturbAction->setObjectName(QStringLiteral("toggle do not disturb")); + m_toggleDoNotDisturbAction->setProperty("componentName", QStringLiteral("plasmashell")); + m_toggleDoNotDisturbAction->setText(i18n("Toggle do not disturb")); + m_toggleDoNotDisturbAction->setIcon(QIcon::fromTheme(QStringLiteral("notifications-disabled"))); + QStringList stringArgs; stringArgs.reserve(args.count() + 1); // need to add a fake argv[0] for QCommandLineParser @@ -110,6 +121,23 @@ return m_settings; } +QKeySequence KCMNotifications::toggleDoNotDisturbShortcut() const +{ + return m_toggleDoNotDisturbShortcut; +} + +void KCMNotifications::setToggleDoNotDisturbShortcut(const QKeySequence &shortcut) +{ + if (m_toggleDoNotDisturbShortcut == shortcut) { + return; + } + + m_toggleDoNotDisturbShortcut = shortcut; + m_toggleDoNotDisturbShortcutDirty = true; + emit toggleDoNotDisturbShortcutChanged(); + setNeedsSave(true); +} + QString KCMNotifications::initialDesktopEntry() const { return m_initialDesktopEntry; @@ -194,16 +222,39 @@ void KCMNotifications::load() { m_settings->load(); + + const QKeySequence toggleDoNotDisturbShortcut = KGlobalAccel::self()->globalShortcut( + m_toggleDoNotDisturbAction->property("componentName").toString(), + m_toggleDoNotDisturbAction->objectName()).value(0); + + if (m_toggleDoNotDisturbShortcut != toggleDoNotDisturbShortcut) { + m_toggleDoNotDisturbShortcut = toggleDoNotDisturbShortcut; + emit toggleDoNotDisturbShortcutChanged(); + } + + m_toggleDoNotDisturbShortcutDirty = false; + setNeedsSave(false); } void KCMNotifications::save() { m_settings->save(); + + if (m_toggleDoNotDisturbShortcutDirty) { + // KeySequenceItem will already have checked whether the shortcut is available + KGlobalAccel::self()->setShortcut(m_toggleDoNotDisturbAction, + {m_toggleDoNotDisturbShortcut}, + KGlobalAccel::NoAutoloading); + } + + setNeedsSave(false); } void KCMNotifications::defaults() { m_settings->defaults(); + + setToggleDoNotDisturbShortcut(QKeySequence()); } #include "kcm.moc" diff --git a/kcms/notifications/package/contents/ui/ApplicationConfiguration.qml b/kcms/notifications/package/contents/ui/ApplicationConfiguration.qml --- a/kcms/notifications/package/contents/ui/ApplicationConfiguration.qml +++ b/kcms/notifications/package/contents/ui/ApplicationConfiguration.qml @@ -35,10 +35,12 @@ property var rootIndex - readonly property string appDisplayName: kcm.sourcesModel.data(rootIndex, Qt.DisplayRole) || "" - readonly property string appIconName: kcm.sourcesModel.data(rootIndex, Qt.DecorationRole) || "" - readonly property string desktopEntry: kcm.sourcesModel.data(rootIndex, Private.SourcesModel.DesktopEntryRole) || "" - readonly property string notifyRcName: kcm.sourcesModel.data(rootIndex, Private.SourcesModel.NotifyRcNameRole) || "" + readonly property string otherAppsId: "@other" + + readonly property string appDisplayName: rootIndex ? kcm.sourcesModel.data(rootIndex, Qt.DisplayRole) || "" : "" + readonly property string appIconName: rootIndex ? kcm.sourcesModel.data(rootIndex, Qt.DecorationRole) || "" : "" + readonly property string desktopEntry: rootIndex ? kcm.sourcesModel.data(rootIndex, Private.SourcesModel.DesktopEntryRole) || "" : "" + readonly property string notifyRcName: rootIndex ? kcm.sourcesModel.data(rootIndex, Private.SourcesModel.NotifyRcNameRole) || "" : "" property int behavior: { if (configColumn.desktopEntry) { @@ -117,13 +119,14 @@ QtControls.CheckBox { text: i18n("Show notification badges") - enabled: !!configColumn.desktopEntry + enabled: !!configColumn.desktopEntry && configColumn.desktopEntry !== configColumn.otherAppsId checked: configColumn.behavior & NotificationManager.Settings.ShowBadges onClicked: configColumn.setBehavior(NotificationManager.Settings.ShowBadges, checked) } Kirigami.Separator { Kirigami.FormData.isSection: true + visible: configureEventsButton.visible || noEventsLabel.visible } QtControls.Button { @@ -136,11 +139,12 @@ } QtControls.Label { + id: noEventsLabel Layout.alignment: Qt.AlignHCenter Layout.preferredWidth: form.implicitWidth text: i18n("This application does not support configuring notifications on a per-event basis."); wrapMode: Text.WordWrap - visible: !configColumn.notifyRcName + visible: !configColumn.notifyRcName && configColumn.desktopEntry !== configColumn.otherAppsId } // compact layout diff --git a/kcms/notifications/package/contents/ui/SourcesPage.qml b/kcms/notifications/package/contents/ui/SourcesPage.qml --- a/kcms/notifications/package/contents/ui/SourcesPage.qml +++ b/kcms/notifications/package/contents/ui/SourcesPage.qml @@ -59,17 +59,6 @@ value: searchField.text } - // We need to manually keep track of the index as we store the sourceModel index - // and then use a proxy model to filter it. We don't get any QML change signals anywhere - // and ListView needs a currentIndex number - Connections { - target: kcm.filteredModel - onRowsRemoved: sourcesList.updateCurrentIndex() - onRowsInserted: sourcesList.updateCurrentIndex() - // TODO re-create model index if possible - onModelReset: appConfiguration.rootIndex = undefined - } - RowLayout { id: rootRow anchors.fill: parent @@ -120,26 +109,9 @@ } } - // We need to manually keep track of the index when we filter - function updateCurrentIndex() { - if (!appConfiguration.rootIndex || !appConfiguration.rootIndex.valid) { - currentIndex = -1; - return; - } - - var filteredIdx = kcm.filteredModel.mapFromSource(appConfiguration.rootIndex); - if (!filteredIdx.valid) { - currentIndex = -1; - return; - } - - currentIndex = filteredIdx.row; - } - - onCurrentIndexChanged: { + onCurrentItemChanged: { var sourceIdx = kcm.filteredModel.mapToSource(kcm.filteredModel.index(sourcesList.currentIndex, 0)); appConfiguration.rootIndex = kcm.sourcesModel.makePersistentModelIndex(sourceIdx); - sourcesList.updateCurrentIndex(); } delegate: QtControls.ItemDelegate { @@ -150,7 +122,6 @@ onClicked: { sourcesList.forceActiveFocus(); sourcesList.currentIndex = index; - sourcesList.updateCurrentIndex(); } contentItem: RowLayout { @@ -196,7 +167,6 @@ ApplicationConfiguration { id: appConfiguration anchors.fill: parent - onRootIndexChanged: sourcesList.updateCurrentIndex() visible: typeof appConfiguration.rootIndex !== "undefined" && appConfiguration.rootIndex.valid } diff --git a/kcms/notifications/package/contents/ui/main.qml b/kcms/notifications/package/contents/ui/main.qml --- a/kcms/notifications/package/contents/ui/main.qml +++ b/kcms/notifications/package/contents/ui/main.qml @@ -22,6 +22,7 @@ import QtQuick.Layouts 1.1 import QtQuick.Controls 2.3 as QtControls import org.kde.kirigami 2.4 as Kirigami +import org.kde.kquickcontrols 2.0 as KQuickControls import org.kde.kcm 1.2 as KCM import org.kde.notificationmanager 1.0 as NotificationManager @@ -80,8 +81,8 @@ } QtControls.CheckBox { - Kirigami.FormData.label: i18n("Do not disturb:") - text: i18nc("Do not disturb when screens are mirrored", "When screens are mirrored") + Kirigami.FormData.label: i18n("Do Not Disturb mode:") + text: i18nc("Do not disturb when screens are mirrored", "Enable when screens are mirrored") checked: kcm.settings.inhibitNotificationsWhenScreensMirrored onClicked: kcm.settings.inhibitNotificationsWhenScreensMirrored = checked enabled: root.notificationsAvailable @@ -94,14 +95,35 @@ enabled: root.notificationsAvailable } + RowLayout { + enabled: root.notificationsAvailable + + QtControls.Label { + text: i18nc("Turn do not disturb mode on/off with keyboard shortcut", "Toggle with:") + } + + KQuickControls.KeySequenceItem { + keySequence: kcm.toggleDoNotDisturbShortcut + onKeySequenceChanged: kcm.toggleDoNotDisturbShortcut = keySequence + } + } + + Kirigami.Separator { + Kirigami.FormData.isSection: true + } + QtControls.CheckBox { Kirigami.FormData.label: i18n("Critical notifications:") text: i18n("Always keep on top") checked: kcm.settings.keepCriticalAlwaysOnTop onClicked: kcm.settings.keepCriticalAlwaysOnTop = checked enabled: root.notificationsAvailable } + Item { + Kirigami.FormData.isSection: true + } + QtControls.CheckBox { Kirigami.FormData.label: i18n("Low priority notifications:") text: i18n("Show popup") @@ -122,10 +144,14 @@ buttons: [positionCloseToWidget, positionCustomPosition] } + Kirigami.Separator { + Kirigami.FormData.isSection: true + } + QtControls.RadioButton { id: positionCloseToWidget - Kirigami.FormData.label: i18n("Popup position:") - text: i18nc("Popup position near notification plasmoid", "Near the notification icon") // "widget" + Kirigami.FormData.label: i18n("Popup:") + text: i18nc("Popup position near notification plasmoid", "Show near notification icon") // "widget" checked: kcm.settings.popupPosition === NotificationManager.Settings.CloseToWidget onClicked: kcm.settings.popupPosition = NotificationManager.Settings.CloseToWidget enabled: root.notificationsAvailable @@ -159,23 +185,32 @@ text: i18np("%1 second", "%1 seconds", 888) } - QtControls.SpinBox { - id: timeoutSpinner - Kirigami.FormData.label: i18n("Hide popup after:") - Layout.preferredWidth: timeoutSpinnerMetrics.width + leftPadding + rightPadding - from: 1000 // 1 second - to: 120000 // 2 minutes - stepSize: 1000 - value: kcm.settings.popupTimeout - enabled: root.notificationsAvailable - editable: true - valueFromText: function(text, locale) { - return parseInt(text) * 1000; + Item { + Kirigami.FormData.isSection: true + } + + RowLayout { + QtControls.Label { + text: i18nc("Part of a sentence like, 'Hide popup after n seconds'", "Hide after:") } - textFromValue: function(value, locale) { - return i18np("%1 second", "%1 seconds", Math.round(value / 1000)); + + QtControls.SpinBox { + id: timeoutSpinner + Layout.preferredWidth: timeoutSpinnerMetrics.width + leftPadding + rightPadding + from: 1000 // 1 second + to: 120000 // 2 minutes + stepSize: 1000 + value: kcm.settings.popupTimeout + enabled: root.notificationsAvailable + editable: true + valueFromText: function(text, locale) { + return parseInt(text) * 1000; + } + textFromValue: function(value, locale) { + return i18np("%1 second", "%1 seconds", Math.round(value / 1000)); + } + onValueModified: kcm.settings.popupTimeout = value } - onValueModified: kcm.settings.popupTimeout = value } Kirigami.Separator { @@ -207,6 +242,10 @@ } } + Item { + Kirigami.FormData.isSection: true + } + QtControls.CheckBox { Kirigami.FormData.label: i18n("Notification badges:") text: i18n("Show in task manager") diff --git a/kcms/notifications/sourcesmodel.cpp b/kcms/notifications/sourcesmodel.cpp --- a/kcms/notifications/sourcesmodel.cpp +++ b/kcms/notifications/sourcesmodel.cpp @@ -31,12 +31,15 @@ #include #include +#include #include #include #include #include +static const QString s_plasmaWorkspaceNotifyRcName = QStringLiteral("plasma_workspace"); + SourcesModel::SourcesModel(QObject *parent) : QAbstractItemModel(parent) { @@ -341,12 +344,30 @@ desktopEntries.append(service->desktopEntryName()); } - auto sortData = [&collator](const SourceData &a, const SourceData &b) { + std::sort(appsData.begin(), appsData.end(), [&collator](const SourceData &a, const SourceData &b) { return collator.compare(a.display(), b.display()) < 0; + }); + + // Fake entry for configuring non-identifyable applications + appsData << SourceData{ + i18n("Other Applications"), + {}, + QStringLiteral("applications-other"), + QString(), + QStringLiteral("@other"), + {} }; - std::sort(appsData.begin(), appsData.end(), sortData); - std::sort(servicesData.begin(), servicesData.end(), sortData); + // Sort and make sure plasma_workspace is at the beginning of the list + std::sort(servicesData.begin(), servicesData.end(), [&collator](const SourceData &a, const SourceData &b) { + if (a.notifyRcName == s_plasmaWorkspaceNotifyRcName) { + return true; + } + if (b.notifyRcName == s_plasmaWorkspaceNotifyRcName) { + return false; + } + return collator.compare(a.display(), b.display()) < 0; + }); m_data << appsData << servicesData; diff --git a/kcms/qtquicksettings/qtquicksettings.desktop b/kcms/qtquicksettings/qtquicksettings.desktop --- a/kcms/qtquicksettings/qtquicksettings.desktop +++ b/kcms/qtquicksettings/qtquicksettings.desktop @@ -31,7 +31,7 @@ Name[lt]=Plasma vaizdavimas Name[nl]=Plasma-renderer Name[nn]=Plasma-oppteikning -Name[pa]=ਪਲਾਜ਼ਮਾ ਰੈਂਡਰਰ- +Name[pa]=ਪਲਾਜ਼ਮਾ ਰੈਂਡਰਰ Name[pl]=Renderer Plazmy Name[pt]=Sistema de Desenho do Plasma Name[pt_BR]=Renderizador do Plasma diff --git a/kcms/runners/kcm.cpp b/kcms/runners/kcm.cpp --- a/kcms/runners/kcm.cpp +++ b/kcms/runners/kcm.cpp @@ -18,6 +18,8 @@ #include "kcm.h" +#include "kcmutils_version.h" + #include #include #include @@ -72,9 +74,16 @@ m_pluginSelector = new KPluginSelector(this); - //overload, can't use the new syntax - connect(m_pluginSelector, SIGNAL(changed(bool)), - this, SIGNAL(changed(bool))); + auto markAsChanged = [this] { + emit changed(); + }; + connect(m_pluginSelector, &KPluginSelector::changed, this, markAsChanged); + connect(m_pluginSelector, &KPluginSelector::configCommitted, this, markAsChanged); + +#if KCMUTILS_VERSION >= QT_VERSION_CHECK(5, 67, 0) + connect(m_pluginSelector, &KPluginSelector::defaulted, + this, &KCModule::defaulted); +#endif layout->addLayout(headerLayout); layout->addWidget(m_pluginSelector); @@ -92,6 +101,7 @@ KPluginSelector::ReadConfigFile, i18n("Available Plugins"), QString(), KSharedConfig::openConfig(QLatin1String( "krunnerrc" ))); + m_pluginSelector->load(); } @@ -102,6 +112,7 @@ void SearchConfigModule::defaults() { + m_pluginSelector->defaults(); } #include "kcm.moc" diff --git a/kcms/runners/kcm_plasmasearch.desktop b/kcms/runners/kcm_plasmasearch.desktop --- a/kcms/runners/kcm_plasmasearch.desktop +++ b/kcms/runners/kcm_plasmasearch.desktop @@ -15,6 +15,7 @@ Name[ca]=KRunner Name[ca@valencia]=KRunner Name[cs]=KRunner +Name[da]=KRunner Name[de]=KRunner Name[en_GB]=KRunner Name[es]=KRunner @@ -30,6 +31,7 @@ Name[lt]=KRunner Name[nl]=KRunner Name[nn]=KRunner +Name[pa]=ਕੇ-ਰਨਰ Name[pl]=KRunner Name[pt]=KRunner Name[pt_BR]=KRunner diff --git a/kcms/solid_actions/device-actions/solid-device-Battery.desktop b/kcms/solid_actions/device-actions/solid-device-Battery.desktop --- a/kcms/solid_actions/device-actions/solid-device-Battery.desktop +++ b/kcms/solid_actions/device-actions/solid-device-Battery.desktop @@ -39,13 +39,13 @@ Name[lv]=Uzlādes procenti Name[mai]=चार्ज प्रतिशत Name[mk]=Процент на полнеж -Name[ml]=ചാര്‍ജ്ജ് ശതമാനം +Name[ml]=ചാര്‍ജ്ജ് ശതമാനം Name[mr]=चार्ज टक्केवारी Name[nb]=Prosent lading Name[nds]=Oplaadperzent Name[nl]=Ladingspercentage Name[nn]=Oppladingsprosent -Name[pa]=ਚਾਰਜ ਫੀਸਦੀ +Name[pa]=ਚਾਰਜ ਫ਼ੀਸਦੀ Name[pl]=Poziom naładowania Name[pt]=Percentagem de Carga Name[pt_BR]=Porcentagem de carga @@ -380,7 +380,7 @@ Name[nds]=Solid-Reedschap Name[nl]=Solid-apparaat Name[nn]=Solid-eining -Name[pa]=ਸਾਲਡ ਜੰਤਰ +Name[pa]=ਸਾਲਡ ਡਿਵਾਈਸ Name[pl]=Urządzenie Solid Name[pt]=Dispositivo do Solid Name[pt_BR]=Dispositivo do Solid diff --git a/kcms/solid_actions/device-actions/solid-device-Block.desktop b/kcms/solid_actions/device-actions/solid-device-Block.desktop --- a/kcms/solid_actions/device-actions/solid-device-Block.desktop +++ b/kcms/solid_actions/device-actions/solid-device-Block.desktop @@ -46,7 +46,7 @@ Name[nds]=Reedschap Name[nl]=Apparaat Name[nn]=Eining -Name[pa]=ਜੰਤਰ +Name[pa]=ਡਿਵਾਈਸ Name[pl]=Urządzenie Name[pt]=Dispositivo Name[pt_BR]=Dispositivo @@ -249,7 +249,7 @@ Name[nds]=Solid-Reedschap Name[nl]=Solid-apparaat Name[nn]=Solid-eining -Name[pa]=ਸਾਲਡ ਜੰਤਰ +Name[pa]=ਸਾਲਡ ਡਿਵਾਈਸ Name[pl]=Urządzenie Solid Name[pt]=Dispositivo do Solid Name[pt_BR]=Dispositivo do Solid diff --git a/kcms/solid_actions/device-actions/solid-device-Camera.desktop b/kcms/solid_actions/device-actions/solid-device-Camera.desktop --- a/kcms/solid_actions/device-actions/solid-device-Camera.desktop +++ b/kcms/solid_actions/device-actions/solid-device-Camera.desktop @@ -186,7 +186,7 @@ Name[nds]=Solid-Reedschap Name[nl]=Solid-apparaat Name[nn]=Solid-eining -Name[pa]=ਸਾਲਡ ਜੰਤਰ +Name[pa]=ਸਾਲਡ ਡਿਵਾਈਸ Name[pl]=Urządzenie Solid Name[pt]=Dispositivo do Solid Name[pt_BR]=Dispositivo do Solid diff --git a/kcms/solid_actions/device-actions/solid-device-OpticalDisc.desktop b/kcms/solid_actions/device-actions/solid-device-OpticalDisc.desktop --- a/kcms/solid_actions/device-actions/solid-device-OpticalDisc.desktop +++ b/kcms/solid_actions/device-actions/solid-device-OpticalDisc.desktop @@ -907,7 +907,7 @@ Name[nds]=Solid-Reedschap Name[nl]=Solid-apparaat Name[nn]=Solid-eining -Name[pa]=ਸਾਲਡ ਜੰਤਰ +Name[pa]=ਸਾਲਡ ਡਿਵਾਈਸ Name[pl]=Urządzenie Solid Name[pt]=Dispositivo do Solid Name[pt_BR]=Dispositivo do Solid diff --git a/kcms/solid_actions/device-actions/solid-device-OpticalDrive.desktop b/kcms/solid_actions/device-actions/solid-device-OpticalDrive.desktop --- a/kcms/solid_actions/device-actions/solid-device-OpticalDrive.desktop +++ b/kcms/solid_actions/device-actions/solid-device-OpticalDrive.desktop @@ -120,7 +120,7 @@ Name[nds]=Loopwark-Typ Name[nl]=Apparaattype Name[nn]=Stasjonstype -Name[pa]=ਡਰਾਇਵਰ ਕਿਸਮ +Name[pa]=ਡਰਾਇਵ ਕਿਸਮ Name[pl]=Typ napędu Name[pt]=Tipo de Unidade Name[pt_BR]=Tipo de unidade @@ -694,7 +694,7 @@ Name[nds]=Solid-Reedschap Name[nl]=Solid-apparaat Name[nn]=Solid-eining -Name[pa]=ਸਾਲਡ ਜੰਤਰ +Name[pa]=ਸਾਲਡ ਡਿਵਾਈਸ Name[pl]=Urządzenie Solid Name[pt]=Dispositivo do Solid Name[pt_BR]=Dispositivo do Solid diff --git a/kcms/solid_actions/device-actions/solid-device-PortableMediaPlayer.desktop b/kcms/solid_actions/device-actions/solid-device-PortableMediaPlayer.desktop --- a/kcms/solid_actions/device-actions/solid-device-PortableMediaPlayer.desktop +++ b/kcms/solid_actions/device-actions/solid-device-PortableMediaPlayer.desktop @@ -186,7 +186,7 @@ Name[nds]=Solid-Reedschap Name[nl]=Solid-apparaat Name[nn]=Solid-eining -Name[pa]=ਸਾਲਡ ਜੰਤਰ +Name[pa]=ਸਾਲਡ ਡਿਵਾਈਸ Name[pl]=Urządzenie Solid Name[pt]=Dispositivo do Solid Name[pt_BR]=Dispositivo do Solid diff --git a/kcms/solid_actions/device-actions/solid-device-Processor.desktop b/kcms/solid_actions/device-actions/solid-device-Processor.desktop --- a/kcms/solid_actions/device-actions/solid-device-Processor.desktop +++ b/kcms/solid_actions/device-actions/solid-device-Processor.desktop @@ -324,7 +324,7 @@ Name[nds]=Solid-Reedschap Name[nl]=Solid-apparaat Name[nn]=Solid-eining -Name[pa]=ਸਾਲਡ ਜੰਤਰ +Name[pa]=ਸਾਲਡ ਡਿਵਾਈਸ Name[pl]=Urządzenie Solid Name[pt]=Dispositivo do Solid Name[pt_BR]=Dispositivo do Solid diff --git a/kcms/solid_actions/device-actions/solid-device-StorageAccess.desktop b/kcms/solid_actions/device-actions/solid-device-StorageAccess.desktop --- a/kcms/solid_actions/device-actions/solid-device-StorageAccess.desktop +++ b/kcms/solid_actions/device-actions/solid-device-StorageAccess.desktop @@ -44,7 +44,7 @@ Name[nds]=Togriepbor Name[nl]=Toegankelijk Name[nn]=Tilgjengeleg -Name[pa]=ਸਹੂਲਤਾਂ +Name[pa]=ਸਹੂਲਤਯੋਗ Name[pl]=Dostępny Name[pt]=Acessível Name[pt_BR]=Acessível @@ -185,7 +185,7 @@ Name[nds]=Solid-Reedschap Name[nl]=Solid-apparaat Name[nn]=Solid-eining -Name[pa]=ਸਾਲਡ ਜੰਤਰ +Name[pa]=ਸਾਲਡ ਡਿਵਾਈਸ Name[pl]=Urządzenie Solid Name[pt]=Dispositivo do Solid Name[pt_BR]=Dispositivo do Solid diff --git a/kcms/solid_actions/device-actions/solid-device-StorageDrive.desktop b/kcms/solid_actions/device-actions/solid-device-StorageDrive.desktop --- a/kcms/solid_actions/device-actions/solid-device-StorageDrive.desktop +++ b/kcms/solid_actions/device-actions/solid-device-StorageDrive.desktop @@ -120,7 +120,7 @@ Name[nds]=Loopwark-Typ Name[nl]=Apparaattype Name[nn]=Stasjonstype -Name[pa]=ਡਰਾਇਵਰ ਕਿਸਮ +Name[pa]=ਡਰਾਇਵ ਕਿਸਮ Name[pl]=Typ napędu Name[pt]=Tipo de Unidade Name[pt_BR]=Tipo de unidade @@ -403,7 +403,7 @@ Name[nds]=Solid-Reedschap Name[nl]=Solid-apparaat Name[nn]=Solid-eining -Name[pa]=ਸਾਲਡ ਜੰਤਰ +Name[pa]=ਸਾਲਡ ਡਿਵਾਈਸ Name[pl]=Urządzenie Solid Name[pt]=Dispositivo do Solid Name[pt_BR]=Dispositivo do Solid diff --git a/kcms/solid_actions/device-actions/solid-device-StorageVolume.desktop b/kcms/solid_actions/device-actions/solid-device-StorageVolume.desktop --- a/kcms/solid_actions/device-actions/solid-device-StorageVolume.desktop +++ b/kcms/solid_actions/device-actions/solid-device-StorageVolume.desktop @@ -476,7 +476,7 @@ Name[nds]=Solid-Reedschap Name[nl]=Solid-apparaat Name[nn]=Solid-eining -Name[pa]=ਸਾਲਡ ਜੰਤਰ +Name[pa]=ਸਾਲਡ ਡਿਵਾਈਸ Name[pl]=Urządzenie Solid Name[pt]=Dispositivo do Solid Name[pt_BR]=Dispositivo do Solid diff --git a/kcms/solid_actions/solid-actions.desktop b/kcms/solid_actions/solid-actions.desktop --- a/kcms/solid_actions/solid-actions.desktop +++ b/kcms/solid_actions/solid-actions.desktop @@ -55,7 +55,7 @@ Name[nds]=Reedschap-Akschonen Name[nl]=Apparaatacties Name[nn]=Einingshandlingar -Name[pa]=ਜੰਤਰ ਐਕਸ਼ਨ +Name[pa]=ਡਿਵਾਈਸ ਕਾਰਵਾਈਆਂ Name[pl]=Działania na urządzeniach Name[pt]=Acções do Dispositivo Name[pt_BR]=Ações dos Dispositivos @@ -113,7 +113,7 @@ Comment[nds]=Akschonen plegen, de för Brukers praatstaht, wenn nieg Reedschappen den Reekner tokoppelt warrt Comment[nl]=Beheren van acties die beschikbaar zijn voor de gebruiker bij het aankoppelen van nieuwe apparaten Comment[nn]=Set opp handlingar som er tilgjengelege når ei ny eining vert kopla til datamaskina -Comment[pa]=ਵਰਤੋਂਕਾਰ ਨੂੰ ਮਿਲਣ ਵਾਲੀਆਂ ਕਾਰਵਾਈਆਂ ਦਾ ਪਰਬੰਧ, ਜਦੋਂ ਨਵੇਂ ਜੰਤਰ ਕੁਨੈਕਟ ਕੀਤੇ ਜਾਂਦੇ ਹਨ +Comment[pa]=ਵਰਤੋਂਕਾਰ ਨੂੰ ਮਿਲਣ ਵਾਲੀਆਂ ਕਾਰਵਾਈਆਂ ਦਾ ਇੰਤਜ਼ਾਮ ਕਰੋ, ਜਦੋਂ ਨਵੇਂ ਡਿਵਾਈਸ ਕਨੈਕਟ ਕੀਤੇ ਜਾਂਦੇ ਹਨ Comment[pl]=Określ działania dostępne dla użytkownika po podłączeniu nowych urządzeń Comment[pt]=Gerir as acções disponíveis para o utilizador, quando são ligados dispositivos novos ao computador Comment[pt_BR]=Gerencia as ações disponíveis ao conectar novos dispositivos @@ -166,7 +166,7 @@ X-KDE-Keywords[nds]=Solid,Reedschappen,Akschonen X-KDE-Keywords[nl]=Solid-apparaatacties X-KDE-Keywords[nn]=Handlingar for Solid-einingar -X-KDE-Keywords[pa]=ਸਾਲਡ ਜੰਤਰ ਐਕਸ਼ਨ +X-KDE-Keywords[pa]=ਸਾਲਡ ਡਿਵਾਈਸ ਕਾਰਵਾਈਆਂ X-KDE-Keywords[pl]=Działania na urządzeniach Solid X-KDE-Keywords[pt]=Acções do Dispositivo Solid X-KDE-Keywords[pt_BR]=Ações do dispositivo Solid diff --git a/kcms/solid_actions/solid-device-type.desktop b/kcms/solid_actions/solid-device-type.desktop --- a/kcms/solid_actions/solid-device-type.desktop +++ b/kcms/solid_actions/solid-device-type.desktop @@ -44,7 +44,7 @@ Name[nds]=Solid-Reedschaptyp Name[nl]=Solid-apparaattype Name[nn]=Type Solid-eining -Name[pa]=ਸਾਲਡ ਜੰਤਰ ਕਿਸਮ +Name[pa]=ਸਾਲਡ ਡਿਵਾਈਸ ਕਿਸਮ Name[pl]=Rodzaj urządzenia Solid Name[pt]=Tipo de Dispositivo do Solid Name[pt_BR]=Tipo de dispositivo do Solid diff --git a/kcms/spellchecking/spellchecking.desktop b/kcms/spellchecking/spellchecking.desktop --- a/kcms/spellchecking/spellchecking.desktop +++ b/kcms/spellchecking/spellchecking.desktop @@ -36,12 +36,13 @@ Name[ja]=スペルチェック Name[ko]=맞춤법 검사 Name[lt]=Rašybos tikrinimas +Name[ml]=അക്ഷരത്തെറ്റു് പരിശോധക Name[mr]=शब्द तपासक Name[nb]=Stavekontroll Name[nds]=Klookschriever Name[nl]=Spellingcontrole Name[nn]=Stave­kontroll -Name[pa]=ਸਪੈਲ ਚੈਕ +Name[pa]=ਸ਼ਬਦ-ਜੋੜ ਦੀ ਜਾਂਚ Name[pl]=Sprawdzanie pisowni Name[pt]=Verificação Ortográfica Name[pt_BR]=Verificação ortográfica @@ -88,7 +89,7 @@ Comment[nds]=Wöörböker un Instellen för den Klookschriever Comment[nl]=Woordenboeken voor spellingcontrole en opties Comment[nn]=Ordlister og innstillingar for stavekontroll -Comment[pa]=ਸਪੈਲ ਚੈਕਰ ਸ਼ਬਦਕੋਸ਼ (ਡਿਕਸ਼ਨਰੀਆਂ) ਅਤੇ ਚੋਣਾਂ +Comment[pa]=ਸ਼ਬਦ-ਜੋੜ ਸ਼ਬਦਕੋਸ਼ ਅਤੇ ਚੋਣਾਂ Comment[pl]=Sprawdzanie pisowni - słowniki i opcje Comment[pt]=Dicionários e Definições Ortográficas Comment[pt_BR]=Dicionários e opções da verificação ortográfica @@ -146,7 +147,7 @@ X-KDE-Keywords[nds]=Schrievwies X-KDE-Keywords[nl]=Spelling X-KDE-Keywords[nn]=Stavekontroll -X-KDE-Keywords[pa]=ਸਪੈੱਲ +X-KDE-Keywords[pa]=ਸ਼ਬਦ-ਜੋੜ X-KDE-Keywords[pl]=Pisownia X-KDE-Keywords[pt]=Ortografia X-KDE-Keywords[pt_BR]=Verificação ortográfica diff --git a/kcms/style/CMakeLists.txt b/kcms/style/CMakeLists.txt --- a/kcms/style/CMakeLists.txt +++ b/kcms/style/CMakeLists.txt @@ -1,5 +1,5 @@ # KI18N Translation Domain for this library -add_definitions(-DTRANSLATION_DOMAIN=\"kcmstyle\") +add_definitions(-DTRANSLATION_DOMAIN=\"kcm_style\") ########### next target ############### diff --git a/kcms/style/Messages.sh b/kcms/style/Messages.sh --- a/kcms/style/Messages.sh +++ b/kcms/style/Messages.sh @@ -1,4 +1,4 @@ #! /usr/bin/env bash $EXTRACTRC *.ui >> rc.cpp -$XGETTEXT `find . -name "*.cpp" -o -name "*.qml"` -o $podir/kcmstyle.pot +$XGETTEXT `find . -name "*.cpp" -o -name "*.qml"` -o $podir/kcm_style.pot rm -f rc.cpp diff --git a/kcms/style/kcm_style.desktop b/kcms/style/kcm_style.desktop --- a/kcms/style/kcm_style.desktop +++ b/kcms/style/kcm_style.desktop @@ -18,6 +18,7 @@ Name[ca]=Estil de l'aplicació Name[ca@valencia]=Estil de l'aplicació Name[cs]=Styl aplikací +Name[da]=Programstil Name[de]=Anwendungs-Stil Name[en_GB]=Application Style Name[es]=Estilo de la aplicación @@ -34,6 +35,7 @@ Name[lt]=Programų stilius Name[nl]=Stijl van toepassing Name[nn]=Program­stil +Name[pa]=ਐਪਲੀਕੇਸ਼ਨ ਸਟਾਈਲ Name[pl]=Wygląd aplikacji Name[pt]=Estilo das Aplicações Name[pt_BR]=Estilo do aplicativo @@ -50,6 +52,7 @@ Comment[ca]=Configura l'estil i el comportament de les aplicacions Comment[ca@valencia]=Configura l'estil i el comportament de les aplicacions Comment[cs]=Nastavení stylu a chování oken +Comment[da]=Indstil programmers stil og opførsel Comment[de]=Stil und Verhalten der Anwendungen einrichten Comment[en_GB]=Configure application style and behaviour Comment[es]=Configurar el estilo y el comportamiento de la aplicación @@ -65,6 +68,7 @@ Comment[lt]=Konfigūruoti programų stilių ir elgseną Comment[nl]=Toepassingstijl en gedrag configureren Comment[nn]=Set opp utsjånad og åtferd for program +Comment[pa]=ਐਪਲੀਕੇਸ਼ਨ ਸਟਾਈਲ ਅਤੇ ਰਵੱਈਏ ਦੀ ਸੰਰਚਨਾ Comment[pl]=Ustawienia wyglądu i zachowania aplikacji Comment[pt]=Configurar o estilo e comportamento das aplicações Comment[pt_BR]=Configurar o estilo e comportamento do aplicativo diff --git a/kcms/style/package/contents/ui/main.qml b/kcms/style/package/contents/ui/main.qml --- a/kcms/style/package/contents/ui/main.qml +++ b/kcms/style/package/contents/ui/main.qml @@ -38,7 +38,7 @@ Component.onCompleted: { // The widget thumbnails are a bit more elaborate and need more room, especially when translated view.implicitCellWidth = Kirigami.Units.gridUnit * 20; - view.implicitCellHeight = Kirigami.Units.gridUnit * 14; + view.implicitCellHeight = Kirigami.Units.gridUnit * 15; } // putting the InlineMessage as header item causes it to show up initially despite visible false diff --git a/kcms/style/package/metadata.desktop b/kcms/style/package/metadata.desktop --- a/kcms/style/package/metadata.desktop +++ b/kcms/style/package/metadata.desktop @@ -4,6 +4,7 @@ Name[ca]=Estil de l'aplicació Name[ca@valencia]=Estil de l'aplicació Name[cs]=Styl aplikací +Name[da]=Programstil Name[de]=Anwendungs-Stil Name[en_GB]=Application Style Name[es]=Estilo de la aplicación @@ -20,6 +21,7 @@ Name[lt]=Programų stilius Name[nl]=Stijl van toepassing Name[nn]=Program­stil +Name[pa]=ਐਪਲੀਕੇਸ਼ਨ ਸਟਾਈਲ Name[pl]=Wygląd aplikacji Name[pt]=Estilo das Aplicações Name[pt_BR]=Estilo do aplicativo @@ -36,6 +38,7 @@ Comment[ca]=Configura l'estil i el comportament de les aplicacions Comment[ca@valencia]=Configura l'estil i el comportament de les aplicacions Comment[cs]=Nastavení stylu a chování oken +Comment[da]=Indstil programmers stil og opførsel Comment[de]=Stil und Verhalten der Anwendungen einrichten Comment[en_GB]=Configure application style and behaviour Comment[es]=Configurar el estilo y el comportamiento de la aplicación @@ -51,6 +54,7 @@ Comment[lt]=Konfigūruoti programų stilių ir elgseną Comment[nl]=Toepassingstijl en gedrag configureren Comment[nn]=Set opp utsjånad og åtferd for program +Comment[pa]=ਐਪਲੀਕੇਸ਼ਨ ਸਟਾਈਲ ਅਤੇ ਰਵੱਈਏ ਦੀ ਸੰਰਚਨਾ Comment[pl]=Ustawienia wyglądu i zachowania aplikacji Comment[pt]=Configurar o estilo e comportamento das aplicações Comment[pt_BR]=Configurar o estilo e comportamento do aplicativo diff --git a/kcms/touchpad/src/kcm/kcm_touchpad.desktop b/kcms/touchpad/src/kcm/kcm_touchpad.desktop --- a/kcms/touchpad/src/kcm/kcm_touchpad.desktop +++ b/kcms/touchpad/src/kcm/kcm_touchpad.desktop @@ -82,7 +82,7 @@ Comment[lt]=Jutiklinio kilimėlio nuostatos Comment[nl]=Instellingen van touchpad Comment[nn]=Innstillingar for styreplate -Comment[pa]=ਟੱਚਪੈਡ ਸੈਟਿੰਗ +Comment[pa]=ਟੱਚਪੈਡ ਸੈਟਿੰਗਾਂ Comment[pl]=Ustawienia gładzika Comment[pt]=Configuração do rato por toque Comment[pt_BR]=Configurações do touchpad diff --git a/kcms/touchpad/src/kded/kcm_touchpad.notifyrc b/kcms/touchpad/src/kded/kcm_touchpad.notifyrc --- a/kcms/touchpad/src/kded/kcm_touchpad.notifyrc +++ b/kcms/touchpad/src/kded/kcm_touchpad.notifyrc @@ -114,7 +114,7 @@ Name[lt]=Jutiklinis kilimėlis buvo išjungtas Name[nl]=Touchpad was uitgeschakeld Name[nn]=Styreplata vart slått av -Name[pa]=ਟੱਚਪੈਡ ਬੰਦ ਸੀ +Name[pa]=ਟੱਚਪੈਡ ਅਸਮਰੱਥ ਸੀ Name[pl]=Gładzik został wyłączony Name[pt]=O rato por toque foi desactivado Name[pt_BR]=O touchpad foi desativado @@ -156,7 +156,7 @@ Comment[lt]=Jutiklinis kilimėlis buvo išjungtas, nes yra aptikta pelė Comment[nl]=Touchpad was uitgeschakeld omdat er een muis is gedetecteerd Comment[nn]=Styreplata vart slått av fordi det vart kopla til ei mus -Comment[pa]=ਟੱਚਪੈਡ ਬੰਦ ਕੀਤੀ ਸੀ ਕਿਉਂਕਿ ਮਾਊਸ ਮਿਲਿਆ ਸੀ +Comment[pa]=ਟੱਚਪੈਡ ਅਸਮਰੱਥ ਕੀਤਾ ਸੀ ਕਿਉਂਕਿ ਮਾਊਸ ਮਿਲਿਆ ਸੀ Comment[pl]=Gładzik został wyłączony, bo podłączono mysz Comment[pt]=O rato por toque foi desactivado porque foi detectado um rato Comment[pt_BR]=O touchpad foi desativado porque o mouse foi detectado @@ -244,7 +244,7 @@ Comment[lt]=Jutiklinis kilimėlis buvo įjungtas, nes buvo atjungta pelė Comment[nl]=Touchpad was ingeschakeld omdat er een muis is uitgetrokken Comment[nn]=Styreplata vart slått på fordi ei mus vart kopla frå -Comment[pa]=ਟੱਚਪੈਡ ਸਮਰੱਥ ਸੀ, ਕਿਉਂਕਿ ਮਾਊਂਸ ਨੂੰ ਜੋੜਿਆ ਨਹੀਂ ਗਿਆ ਸੀ +Comment[pa]=ਟੱਚਪੈਡ ਸਮਰੱਥ ਸੀ, ਕਿਉਂਕਿ ਮਾਊਂਸ ਦਾ ਪਲੱਗ ਨਹੀਂ ਲੱਗਾ ਸੀ Comment[pl]=Gładzik został włączony, bo odłączono mysz Comment[pt]=O rato por toque foi activado porque o rato foi desligado Comment[pt_BR]=O touchpad foi ativado porque o mouse foi desconectado diff --git a/kcms/touchpad/src/kded/kded_touchpad.desktop b/kcms/touchpad/src/kded/kded_touchpad.desktop --- a/kcms/touchpad/src/kded/kded_touchpad.desktop +++ b/kcms/touchpad/src/kded/kded_touchpad.desktop @@ -75,7 +75,7 @@ Comment[lt]=Įjungia arba išjungia jutiklinį kilimėlį Comment[nl]=Schakelt het touchpad in of uit Comment[nn]=Slå på/av styreplate -Comment[pa]=ਟੱਚਪੈਡ ਚਾਲੂ ਜਾਂ ਬੰਦ ਕਰੋ +Comment[pa]=ਟੱਚਪੈਡ ਸਮਰੱਥ ਜਾਂ ਅਸਮਰੱਥ ਕਰੋ Comment[pl]=Włącza lub wyłącza gładzik Comment[pt]=Activa ou desactiva o rato por toque Comment[pt_BR]=Ativa ou desativa o touchpad diff --git a/kcms/workspaceoptions/kcm_workspace.desktop b/kcms/workspaceoptions/kcm_workspace.desktop --- a/kcms/workspaceoptions/kcm_workspace.desktop +++ b/kcms/workspaceoptions/kcm_workspace.desktop @@ -12,6 +12,7 @@ Name[ast]=Comportamientu xeneral Name[ca]=Comportament general Name[cs]=Obecné chování +Name[da]=Generel opførsel Name[de]=Allgemeines Verhalten Name[en_GB]=General Behaviour Name[es]=Comportamiento general @@ -27,6 +28,7 @@ Name[lt]=Bendra elgsena Name[nl]=Algemeen gedrag Name[nn]=Generell åtferd +Name[pa]=ਆਮ ਰਵੱਈਆ Name[pl]=Zachowanie ogólne Name[pt]=Comportamento Geral Name[pt_BR]=Comportamento geral @@ -42,6 +44,7 @@ Comment[ast]=Configura'l comportamientu xeneral de la estaya de trabayu Comment[ca]=Configura el comportament general de l'espai de treball Comment[cs]=Nastavení obecného chování pracovního prostředí +Comment[da]=Indstil arbejdsområdets generelle opførsel Comment[de]=Allgemeines Verhalten des Arbeitsbereichs einrichten Comment[en_GB]=Configure general workspace behaviour Comment[es]=Configurar el comportamiento general del espacio de trabajo @@ -57,6 +60,7 @@ Comment[lt]=Konfigūruoti bendra darbo srities elgseną Comment[nl]=Algemeen gedrag in werkruimte configureren Comment[nn]=Set opp generelle åtferdsinnstillingar for arbeidsområdet +Comment[pa]=ਆਮ ਵਰਕਸਪੇਸ ਰਵੱਈਏ ਦੀ ਸੰਰਚਨਾ Comment[pl]=Ustawienia ogólnego zachowania przestrzeni pracy Comment[pt]=Configurar o comportamento geral da área de trabalho Comment[pt_BR]=Configurar o comportamento geral do espaço de trabalho @@ -67,35 +71,5 @@ Comment[x-test]=xxConfigure general workspace behaviorxx Comment[zh_CN]=配置工作空间的常规行为 Comment[zh_TW]=設定一般工作空間行為 -X-KDE-Keywords=plasma,workspace,shell,formfactor,dashboard,tooltips,informational tips,tooltips,click,single click,double click -X-KDE-Keywords[ca]=plasma,espai de treball,shell,factor de format,tauler,consells d'eines,consells informatius,consells d'eines,clic normal,doble clic -X-KDE-Keywords[ca@valencia]=plasma,espai de treball,shell,factor de format,tauler,consells d'eines,consells informatius,consells d'eines,clic normal,doble clic -X-KDE-Keywords[da]=plasma,arbejdsområde,skal,formfaktor,dashboard,instrumentbræt,værktøjstips,informationstip,klik,enkeltklik,dobbeltklik -X-KDE-Keywords[de]=Plasma,Arbeitsbereich,Shell,Formfaktor,Format,Dashboard,Übersichtsseite,Kurzinfo,Tipps, Klick, Einfachklick, Doppelklick -X-KDE-Keywords[el]=plasma,χώρος εργασίας,κέλυφος,formfactor,πίνακας,υποδείξεις,ενημερωτικές υποδείξεις,υποδείξεις,κλικ,μονό κλικ,διπλό κλικ -X-KDE-Keywords[en_GB]=plasma,workspace,shell,formfactor,dashboard,tooltips,informational tips,tooltips,click,single click,double click -X-KDE-Keywords[es]=plasma,espacio de trabajo,consola,factor de forma,tablero de mandos,ayudas emergentes,ayudas informativas,clic,clic sencillo,doble clic -X-KDE-Keywords[et]=plasma,töötsoon,shell,dashboard,vidinavaade,konteiner,kohtspikrid,klõps,ühekordne klõps,topeltklõps -X-KDE-Keywords[eu]=plasma,langunea,shell,formfactor,forma,dashboard,aginte-mahaia,tooltips, tresnen argibidek,informational tips,informatzeko argibideak,klik, klik bakuna,klik bikoitza -X-KDE-Keywords[fi]=plasma,työtila,ympäristö,kuori,kokoluokka,kojelauta,työkaluvihjeet,ohjevinkit,työkaluvihjeet,napsautus,yksittäisnapsautus,kaksoisnapsautus -X-KDE-Keywords[fr]=plasma, espace de travail, environnement, facteur de forme, tableau de bord, astuces d'informations, infobulles, clic, simple clic, double clic -X-KDE-Keywords[gl]=plasma,espazo de traballo,intérprete de ordes,shell,cadro de control,axudiñas,forma,consellos,clic -X-KDE-Keywords[hu]=plasma,munkaterület,formfactor,áttekintő nézet,buboréksúgók,információs súgók, buboréksúgók,kattintás,egyszeres kattintás,dupla kattintás -X-KDE-Keywords[id]=plasma,ruang kerja,shell,formfactor,dasbor,tip alat,tip penginformasian,tip alat,klik,klik tunggal,klik ganda -X-KDE-Keywords[it]=plasma,spazio di lavoro,shell,fattore di forma,cruscotto,suggerimenti,suggerimenti informativi,clic,singolo clic,doppio clic -X-KDE-Keywords[ko]=plasma,workspace,shell,formfactor,dashboard,tooltips,informational tips,작업 공간,셸,대시보드,풍선 도움말,클릭,더블 클릭,두 번 누르기,누르기 -X-KDE-Keywords[lt]=plasma,darbo sritis,darbo erdvė,darbo erdve,apvalkalas,formos faktorius,skydelis,paaiškinimai,paaiskinimai,informaciniai paaiškinimai,informaciniai paaiskinimai,patarimai,spustelėjimas,spustelejimas,spragtelėjimas,spragtelejimas,vienkartis spustelėjimas,vienkartis spustelejimas,vienkartis spragtelėjimas,vienkartis spragtelejimas,dvikartis spustelėjimas,dvikartis spustelejimas,dvikartis spragtelėjimas,dvikartis spragtelejimas -X-KDE-Keywords[nl]=plasma,werkruimte,shell,vormfactor,dashboard,tekstballonnen,informatieve tips,tekstballonnen,klik,dubbelklik -X-KDE-Keywords[nn]=plasma,arbeidsområde,skal,formfaktor,kontrollpult,hjelpebobler,verktøytips,informasjonsbobler,klikk,enkeltklikk,dobbeltklikk -X-KDE-Keywords[pa]=ਪਲਾਜ਼ਮਾ,ਵਰਕਸਪੇਸ,ਸ਼ੈੱਲ,ਫਾਰਮਫੈਕਟਰ,ਡੈਸ਼ਬੋਰਡ,ਟੂਲ-ਟਿੱਪ,ਜਾਣਕਾਰੀ ਵਾਲੇ ਟਿੱਪ,ਇਸ਼ਾਰੇ,ਗੁਰ,ਕਲਿੱਕ,ਡਬਲ ਕਲਿੱਕ,ਦੋਹਰਾ ਕਲਿੱਕ -X-KDE-Keywords[pl]=plazma,przestrzeń robocza,powłoka,współczynnik kształtu,tablica,podpowiedzi,informacyjne wskazówki,kliknięcie,jednokrotne kliknięcie,dwukrotne kliknięcie -X-KDE-Keywords[pt]=plasma,área de trabalho,consola,formato de ecrã,painel,dicas,dicas informativas,click,click simples,duplo-click -X-KDE-Keywords[pt_BR]=plasma,área de trabalho,shell,formato de tela,painel,dicas,dicas informativas,clique simples,clique duplo -X-KDE-Keywords[ru]=plasma,workspace,shell,formfactor,dashboard,tooltips,informational tips,tooltips,click,single click,double click,плазма,рабочий стол,рабочая среда,рабочее окружение,окружение рабочего стола,среда рабочего стола,приборная доска,подсказки,всплывающие подсказки,информационные подсказки,оболочка рабочего стола,щелчок,одиночный клик,одиночный щелчок,двойной клик,двойной щелчок -X-KDE-Keywords[sk]=plasma,pracovná plocha,shell,formfactor,nástenka,nástrojové tipy,informačné tipy,klik,jeden klik,dvojitý klik -X-KDE-Keywords[sv]=plasma,arbetsyta,skal,formfaktor,instrumentpanel,verktygstips,informationstips,klick,enkelklick,dubbelklick -X-KDE-Keywords[uk]=plasma,workspace,shell,formfactor,dashboard,tooltips,informational tips,tooltips,click,single click,double click,плазма,робочий простір,оболонка,форм-фактор,панель,підказки,інформація,відомості,клацання,одинарне клацання,подвійне клацання -X-KDE-Keywords[x-test]=xxplasmaxx,xxworkspacexx,xxshellxx,xxformfactorxx,xxdashboardxx,xxtooltipsxx,xxinformational tipsxx,xxtooltipsxx,xxclickxx,xxsingle clickxx,xxdouble clickxx -X-KDE-Keywords[zh_CN]=plasma,workspace,shell,formfactor,dashboard,tooltips,informational tips,tooltips,click,single click,double click,工作空间,外壳,部件版,工具提示,提示,信息提示,单击,双击 -X-KDE-Keywords[zh_TW]=plasma,workspace,shell,formfactor,dashboard,tooltips,informational tips,tooltips,click,single click,double click +X-KDE-Keywords=plasma,workspace,shell,formfactor,dashboard,tooltips,informational tips,tooltips,click,single click,double click,animation speed Categories=Qt;KDE;X-KDE-settings-system; diff --git a/kcms/workspaceoptions/package/contents/ui/main.qml b/kcms/workspaceoptions/package/contents/ui/main.qml --- a/kcms/workspaceoptions/package/contents/ui/main.qml +++ b/kcms/workspaceoptions/package/contents/ui/main.qml @@ -121,13 +121,20 @@ QQC2.RadioButton { id: doubleClick - text: i18n("Double-click to open files and folders (single click to select)") + text: i18n("Double-click to open files and folders") enabled: !kcm.globalsSettings.isImmutable("singleClick") checked: !kcm.globalsSettings.singleClick onToggled: kcm.globalsSettings.singleClick = false QQC2.ButtonGroup.group: singleClickGroup } + QQC2.Label { + Layout.fillWidth: true + text: singleClick.checked ? i18n("Select by clicking on item's selection marker") : i18n("Select by single-clicking") + elide: Text.ElideRight + font.pointSize: theme.smallestFont.pointSize + } + Item { Kirigami.FormData.isSection: false } @@ -154,5 +161,17 @@ onToggled: kcm.globalsSettings.scrollbarLeftClickNavigatesByPage = false QQC2.ButtonGroup.group: scrollHandleBehaviorGroup } + + // Don't show a label for what middle-clicking does when using the + // "click to zoom the handle" behavior because Qt doesn't invert the + // middle-click functionality when using this; see + // https://bugreports.qt.io/browse/QTBUG-80728 + QQC2.Label { + Layout.fillWidth: true + visible: scrollbarLeftClickNavigatesByPage.checked + text: i18n("Middle-click to scroll to clicked location") + elide: Text.ElideRight + font.pointSize: theme.smallestFont.pointSize + } } } diff --git a/kcms/workspaceoptions/package/metadata.desktop b/kcms/workspaceoptions/package/metadata.desktop --- a/kcms/workspaceoptions/package/metadata.desktop +++ b/kcms/workspaceoptions/package/metadata.desktop @@ -3,6 +3,7 @@ Name[ast]=Comportamientu xeneral Name[ca]=Comportament general Name[cs]=Obecné chování +Name[da]=Generel opførsel Name[de]=Allgemeines Verhalten Name[en_GB]=General Behaviour Name[es]=Comportamiento general @@ -18,6 +19,7 @@ Name[lt]=Bendra elgsena Name[nl]=Algemeen gedrag Name[nn]=Generell åtferd +Name[pa]=ਆਮ ਰਵੱਈਆ Name[pl]=Zachowanie ogólne Name[pt]=Comportamento Geral Name[pt_BR]=Comportamento geral @@ -33,6 +35,7 @@ Comment[ast]=Configura'l comportamientu xeneral de la estaya de trabayu Comment[ca]=Configura el comportament general de l'espai de treball Comment[cs]=Nastavení obecného chování pracovního prostředí +Comment[da]=Indstil arbejdsområdets generelle opførsel Comment[de]=Allgemeines Verhalten des Arbeitsbereichs einrichten Comment[en_GB]=Configure general workspace behaviour Comment[es]=Configurar el comportamiento general del espacio de trabajo @@ -48,6 +51,7 @@ Comment[lt]=Konfigūruoti bendra darbo srities elgseną Comment[nl]=Algemeen gedrag in werkruimte configureren Comment[nn]=Set opp generelle åtferdsinnstillingar for arbeidsområdet +Comment[pa]=ਆਮ ਵਰਕਸਪੇਸ ਰਵੱਈਏ ਦੀ ਸੰਰਚਨਾ Comment[pl]=Ustawienia ogólnego zachowania przestrzeni pracy Comment[pt]=Configurar o comportamento geral da área de trabalho Comment[pt_BR]=Configurar o comportamento geral do espaço de trabalho diff --git a/kcms/workspaceoptions/workspaceoptions_kdeglobalssettings.kcfg b/kcms/workspaceoptions/workspaceoptions_kdeglobalssettings.kcfg --- a/kcms/workspaceoptions/workspaceoptions_kdeglobalssettings.kcfg +++ b/kcms/workspaceoptions/workspaceoptions_kdeglobalssettings.kcfg @@ -6,7 +6,7 @@ - + true diff --git a/kcms/workspaceoptions/workspaceoptions_kdeglobalssettings.kcfgc b/kcms/workspaceoptions/workspaceoptions_kdeglobalssettings.kcfgc --- a/kcms/workspaceoptions/workspaceoptions_kdeglobalssettings.kcfgc +++ b/kcms/workspaceoptions/workspaceoptions_kdeglobalssettings.kcfgc @@ -4,4 +4,4 @@ DefaultValueGetters=true GenerateProperties=true ParentInConstructor=true -Notifiers=true +Notifiers=animationDurationFactor diff --git a/layout-templates/org.kde.plasma.desktop.defaultPanel/metadata.desktop b/layout-templates/org.kde.plasma.desktop.defaultPanel/metadata.desktop --- a/layout-templates/org.kde.plasma.desktop.defaultPanel/metadata.desktop +++ b/layout-templates/org.kde.plasma.desktop.defaultPanel/metadata.desktop @@ -3,7 +3,7 @@ Name[ar]=اللوحة الافتراضيّة Name[ast]=Panel predetermináu Name[bs]=Podrazumijevani panel -Name[ca]=Plafó per omissió +Name[ca]=Plafó predeterminat Name[ca@valencia]=Plafó per omissió Name[cs]=Výchozí panel Name[da]=Standardpanel diff --git a/org.kde.plasmashell.metainfo.xml b/org.kde.plasmashell.metainfo.xml --- a/org.kde.plasmashell.metainfo.xml +++ b/org.kde.plasmashell.metainfo.xml @@ -135,9 +135,9 @@ + + - - diff --git a/runners/plasma-desktop/plasma-runner-plasma-desktop.desktop b/runners/plasma-desktop/plasma-runner-plasma-desktop.desktop --- a/runners/plasma-desktop/plasma-runner-plasma-desktop.desktop +++ b/runners/plasma-desktop/plasma-runner-plasma-desktop.desktop @@ -3,7 +3,7 @@ Name[ar]=صدفة سطح مكتب بلازما Name[bg]=Настолна обвивка Plasma Name[bs]=Plazma školjka površi -Name[ca]=Intèrpret d'ordres de l'escriptori Plasma +Name[ca]=Àrea de treball de l'escriptori Plasma Name[ca@valencia]=Intèrpret d'ordres de l'escriptori Plasma Name[cs]=Pracovní plocha Plasma Name[da]=Plasma-skrivebordets skal @@ -67,7 +67,7 @@ Comment=Interact with the Plasma desktop shell Comment[ar]=تفاعل مع صدفة سطح مكتب بلازما Comment[bs]=Pozabavite se plazma školjkom površi -Comment[ca]=Interactua amb l'intèrpret d'ordres de l'escriptori Plasma +Comment[ca]=Interactua amb l'àrea de treball de l'escriptori Plasma Comment[ca@valencia]=Interactua amb l'intèrpret d'ordres de l'escriptori Plasma Comment[cs]=Interakce se shellem pracovní plochy plasmy Comment[da]=Interaktion med Plasma-skrivebordets skal diff --git a/solid-device-automounter/kcm/device_automounter_kcm.desktop b/solid-device-automounter/kcm/device_automounter_kcm.desktop --- a/solid-device-automounter/kcm/device_automounter_kcm.desktop +++ b/solid-device-automounter/kcm/device_automounter_kcm.desktop @@ -28,7 +28,7 @@ X-KDE-Keywords[lt]=Prijungti,Keičiamieji,Įrenginiai,Automatiškai,keiciamieji,irenginiai,automatiskai X-KDE-Keywords[nl]=Aankoppelen,verwijderbaar,apparaten,automatisch X-KDE-Keywords[nn]=montering,flyttbar,minnepinne,minnepenn,einingar,automatisk -X-KDE-Keywords[pa]=ਮਾਊਂਟ,ਹਟਾਉਣਯੋਗ,ਡਿਵਾਈਸ,ਆਟੋਮੈਟਿਕ,ਸਵੈ-ਚਾਲਤ +X-KDE-Keywords[pa]=ਮਾਊਂਟ,ਹਟਾਉਣਯੋਗ,ਡਿਵਾਈਸ,ਆਟੋਮੈਟਿਕ,ਆਪਣੇ-ਆਪ,ਆਟੋਮੈਟਿਕ X-KDE-Keywords[pl]=Montowanie,Wymienne,Urządzenia,Automatycznie X-KDE-Keywords[pt]=Montagem,Removível,Dispositivos,Automática X-KDE-Keywords[pt_BR]=Montagem,Removível,Automática,Dispositivos diff --git a/solid-device-automounter/kded/device_automounter.desktop b/solid-device-automounter/kded/device_automounter.desktop --- a/solid-device-automounter/kded/device_automounter.desktop +++ b/solid-device-automounter/kded/device_automounter.desktop @@ -30,7 +30,7 @@ Name[lt]=Automatinis keičiamųjų įrenginių prijungimas Name[nl]=Automatische aankoppelaar voor verwijderbare apparaten Name[nn]=Automontering av flyttbare einingar -Name[pa]=ਹਟਾਉਣਯੋਗ ਜੰਤਰ ਆਟੋ-ਮਾਊਂਟਰ +Name[pa]=ਹਟਾਉਣਯੋਗ ਡਿਵਾਈਸ ਆਟੋ-ਮਾਊਂਟਰ Name[pl]=Samoczynne podpinanie urządzeń wymiennych Name[pt]=Auto-Montagem de Dispositivos Removíveis Name[pt_BR]=Montagem automática de dispositivos removíveis @@ -70,7 +70,7 @@ Comment[lt]=Prireikus, automatiškai prijungia įrenginius Comment[nl]=Koppelt automatisch apparaten aan zoals nodig is Comment[nn]=Monter einingar automatisk når dei trengst -Comment[pa]=ਜਦੋਂ ਲੋੜ ਹੋਵੇ ਤਾਂ ਜੰਤਰ ਆਟੋਮੈਟਿਕ ਮਾਊਂਟ ਕਰੋ +Comment[pa]=ਜਦੋਂ ਲੋੜ ਹੋਵੇ ਤਾਂ ਡਿਵਾਈਸ ਆਪਣੇ-ਆਪ ਮਾਊਂਟ ਕਰੋ Comment[pl]=Podpina urządzenia, gdy są potrzebne Comment[pt]=Monta automaticamente os dispositivos, se necessário Comment[pt_BR]=Monta automaticamente os dispositivos quando necessário diff --git a/toolboxes/desktoptoolbox/metadata.desktop b/toolboxes/desktoptoolbox/metadata.desktop --- a/toolboxes/desktoptoolbox/metadata.desktop +++ b/toolboxes/desktoptoolbox/metadata.desktop @@ -74,7 +74,7 @@ Comment[nds]=Plasma plegen Comment[nl]=Plasma beheren Comment[nn]=Handsam Plasma -Comment[pa]=ਪਲਾਜ਼ਮਾ ਪਰਬੰਧ +Comment[pa]=ਪਲਾਜ਼ਮਾ ਇੰਤਜ਼ਾਮ Comment[pl]=Zarządzanie Plazmą Comment[pt]=Gerir o Plasma Comment[pt_BR]=Gerencia o Plasma diff --git a/toolboxes/paneltoolbox/metadata.desktop b/toolboxes/paneltoolbox/metadata.desktop --- a/toolboxes/paneltoolbox/metadata.desktop +++ b/toolboxes/paneltoolbox/metadata.desktop @@ -75,12 +75,13 @@ Comment[kk]=Plasma панелін басқару Comment[ko]=Plasma 패널 관리 Comment[lt]=Tvarkyti Plasma skydelį +Comment[ml]=പ്ലാസ്മയുടെ സഹായക്കുറിപ്പു് Comment[mr]=प्लाज्मा पटल व्यवस्थापन Comment[nb]=Håndter Plasma-panel Comment[nds]=Plasmapaneel plegen Comment[nl]=Plasmapaneel beheren Comment[nn]=Handsam Plasma-panel -Comment[pa]=ਪਲਾਜ਼ਮਾ ਪੈਨਲ ਪਰਬੰਧ +Comment[pa]=ਪਲਾਜ਼ਮਾ ਪੈਨਲ ਇੰਤਜ਼ਾਮ Comment[pl]=Zarządzanie panelem Plazmy Comment[pt]=Gerir o painel do Plasma Comment[pt_BR]=Gerencia o painel do Plasma diff --git a/toolboxes/plasma-toolbox-paneltoolbox.desktop b/toolboxes/plasma-toolbox-paneltoolbox.desktop --- a/toolboxes/plasma-toolbox-paneltoolbox.desktop +++ b/toolboxes/plasma-toolbox-paneltoolbox.desktop @@ -3,7 +3,7 @@ Comment[ar]=صندوق أدوات اللوحة الافتراضيّ لصدفة سطح مكتب بلازما Comment[bg]=Стандартен набор инструменти на панела за настолната обвивка Plasma Comment[bs]=Podrazumijevana alatnica panela za plazma školjku površi -Comment[ca]=Quadre d'eines per defecte del plafó per a l'àrea de treball de l'escriptori Plasma +Comment[ca]=Quadre d'eines del plafó predeterminat per a l'àrea de treball de l'escriptori Plasma Comment[ca@valencia]=Quadre d'eines per defecte del plafó per a l'àrea de treball de l'escriptori Plasma Comment[cs]=Výchozí nástroje panelu pro Plasma shell pracovní plochy Comment[da]=Standard panelværktøjskasse til Plasma-skrivebordets skal