diff --git a/applets/icontasks/metadata.desktop b/applets/icontasks/metadata.desktop
--- a/applets/icontasks/metadata.desktop
+++ b/applets/icontasks/metadata.desktop
@@ -18,12 +18,13 @@
Name[gl]=Xestor de tarefas de só iconas
Name[he]=מנהל משימות של סמלים בלבד
Name[hu]=Ikonos feladatkezelő
-Name[id]=Pengelola Tugas Hanya Ikon
+Name[id]=Task Manager Hanya Ikon
Name[is]=Verkefnastjóri einungis með táknmyndum
Name[it]=Gestore dei processi solo icone
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/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/kickoff/package/contents/config/main.xml b/applets/kickoff/package/contents/config/main.xml
--- a/applets/kickoff/package/contents/config/main.xml
+++ b/applets/kickoff/package/contents/config/main.xml
@@ -12,7 +12,7 @@
- false
+ true
diff --git a/applets/kickoff/package/contents/ui/Header.qml b/applets/kickoff/package/contents/ui/Header.qml
--- a/applets/kickoff/package/contents/ui/Header.qml
+++ b/applets/kickoff/package/contents/ui/Header.qml
@@ -16,7 +16,7 @@
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
-import QtQuick 2.0
+import QtQuick 2.12
import org.kde.plasma.core 2.0 as PlasmaCore
import org.kde.plasma.components 2.0 as PlasmaComponents
import org.kde.plasma.extras 2.0 as PlasmaExtras
diff --git a/applets/kimpanel/backend/ibus/CMakeLists.txt b/applets/kimpanel/backend/ibus/CMakeLists.txt
--- a/applets/kimpanel/backend/ibus/CMakeLists.txt
+++ b/applets/kimpanel/backend/ibus/CMakeLists.txt
@@ -4,41 +4,37 @@
find_package(GObject)
if(IBUS_FOUND AND GLIB2_FOUND AND GIO_FOUND AND GOBJECT_FOUND)
- configure_file(config-kimpanel.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/config-kimpanel.h)
- include_directories(${IBUS_INCLUDE_DIR})
- include_directories(${GIO_INCLUDE_DIR})
- include_directories(${GOBJECT_INCLUDE_DIR})
- set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=c99")
+ include_directories(${IBUS_INCLUDE_DIR} ${GLIB2_INCLUDE_DIR})
+ add_subdirectory(emojier)
+ configure_file(config-kimpanel.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/config-kimpanel.h)
find_package(Qt5X11Extras)
find_package(XCB COMPONENTS XCB KEYSYMS)
- add_subdirectory(emojier)
-
if (Qt5X11Extras_FOUND AND XCB_XCB_FOUND AND XCB_KEYSYMS_FOUND)
+ include_directories(${GIO_INCLUDE_DIR})
+ include_directories(${GOBJECT_INCLUDE_DIR})
include_directories(${XCB_XCB_INCLUDE_DIRS})
include_directories(${XCB_KEYSYMS_INCLUDE_DIRS})
- set(kimpanel_ibus_panel_SRCS
+ set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=c99")
+ add_executable(kimpanel-ibus-panel
ibus15/xkblayoutmanager.cpp
ibus15/gtkaccelparse_p.c
ibus15/gdkkeynames_p.c
ibus15/app.cpp
ibus15/enginemanager.cpp
ibus15/main.cpp
ibus15/panel.cpp
ibus15/propertymanager.cpp)
- add_definitions(-DQT_NO_KEYWORDS)
- add_executable(kimpanel-ibus-panel ${kimpanel_ibus_panel_SRCS})
+ target_compile_definitions(kimpanel-ibus-panel PRIVATE -DQT_NO_KEYWORDS)
target_link_libraries(kimpanel-ibus-panel ${IBUS_LIBRARIES} GLIB2::GLIB2 ${GIO_LIBRARIES} ${GOBJECT_LIBRARIES} Qt5::Core Qt5::DBus Qt5::Gui Qt5::X11Extras XCB::KEYSYMS)
# configure_file(${CMAKE_CURRENT_SOURCE_DIR}/kimpanel.xml.in ${CMAKE_CURRENT_BINARY_DIR}/kimpanel.xml @ONLY)
# install(FILES ${CMAKE_CURRENT_BINARY_DIR}/kimpanel.xml DESTINATION ${CMAKE_INSTALL_PREFIX}/share/ibus/component)
target_include_directories(kimpanel-ibus-panel PRIVATE ${CMAKE_CURRENT_BINARY_DIR})
add_executable(kimpanel-ibus-panel-launcher launcher.cpp)
- set_target_properties(kimpanel-ibus-panel-launcher PROPERTIES AUTOMOC TRUE)
target_link_libraries(kimpanel-ibus-panel-launcher Qt5::Core Qt5::DBus)
- target_include_directories(kimpanel-ibus-panel-launcher PRIVATE ${CMAKE_CURRENT_BINARY_DIR})
install(TARGETS kimpanel-ibus-panel kimpanel-ibus-panel-launcher DESTINATION ${KDE_INSTALL_LIBEXECDIR})
endif()
endif()
diff --git a/applets/kimpanel/backend/ibus/README b/applets/kimpanel/backend/ibus/README
--- a/applets/kimpanel/backend/ibus/README
+++ b/applets/kimpanel/backend/ibus/README
@@ -2,4 +2,4 @@
ibus>=1.1.0 is needed, not 0.1.1 version
START:
-ibus-daemon --panel=//panel.py
+ibus-daemon --panel=/...prefix.../lib/libexec/kimpanel-ibus-panel
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
@@ -43,6 +43,7 @@
#include
#include
#include
+#include
#include "emojiersettings.h"
#include "config-workspace.h"
@@ -129,35 +130,56 @@
EmojiModel() {
QLocale locale;
- const QString dictName = "ibus/dicts/emoji-" + locale.bcp47Name().replace(QLatin1Char('-'), QLatin1Char('_')) + ".dict";
+ const auto bcp = locale.bcp47Name();
+ const QString dictName = "ibus/dicts/emoji-" + QString(bcp).replace(QLatin1Char('-'), QLatin1Char('_')) + ".dict";
const QString path = QStandardPaths::locate(QStandardPaths::GenericDataLocation, dictName);
if (path.isEmpty()) {
qWarning() << "could not find" << dictName;
return;
}
- GSList *list = ibus_emoji_data_load (path.toUtf8().constData());
- m_emoji.reserve(g_slist_length(list));
+ 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;
+ }
+
QSet categories;
- for (GSList *l = list; l; l = l->next) {
- IBusEmojiData *data = (IBusEmojiData *) l->data;
- if (!IBUS_IS_EMOJI_DATA (data)) {
- qWarning() << "Your dict format is no longer supported.\n"
- "Need to create the dictionaries again.";
- g_slist_free (list);
- return;
+ QSet processedEmoji;
+ for (const auto &dictPath : qAsConst(dicts)) {
+ GSList *list = ibus_emoji_data_load (dictPath.toUtf8().constData());
+ m_emoji.reserve(g_slist_length(list));
+ for (GSList *l = list; l; l = l->next) {
+ IBusEmojiData *data = (IBusEmojiData *) l->data;
+ if (!IBUS_IS_EMOJI_DATA (data)) {
+ qWarning() << "Your dict format is no longer supported.\n"
+ "Need to create the dictionaries again.";
+ g_slist_free (list);
+ return;
+ }
+
+ 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;
+ }
+
+ const QString category = QString::fromUtf8(ibus_emoji_data_get_category(data));
+ categories.insert(category);
+ m_emoji += { emoji, description, category };
+ processedEmoji << emoji;
}
-
- const QString category = QString::fromUtf8(ibus_emoji_data_get_category(data));
- categories.insert(category);
- m_emoji += { QString::fromUtf8(ibus_emoji_data_get_emoji(data)), ibus_emoji_data_get_description(data), category };
+ g_slist_free (list);
}
+
categories.remove({});
m_categories = categories.values();
m_categories.sort();
m_categories.prepend({});
m_categories.prepend(QStringLiteral(":recent:"));
- g_slist_free (list);
}
Q_SCRIPTABLE QString findFirstEmojiForCategory(const QString &category) {
@@ -306,6 +328,7 @@
int main(int argc, char** argv)
{
+ QGuiApplication::setFallbackSessionManagementEnabled(false);
QApplication app(argc, argv);
app.setAttribute(Qt::AA_UseHighDpiPixmaps, true);
app.setWindowIcon(QIcon::fromTheme(QStringLiteral("preferences-desktop-emoticons")));
@@ -322,6 +345,12 @@
about.setProgramLogo(app.windowIcon());
KAboutData::setApplicationData(about);
+ auto disableSessionManagement = [](QSessionManager &sm) {
+ sm.setRestartHint(QSessionManager::RestartNever);
+ };
+ QObject::connect(&app, &QGuiApplication::commitDataRequest, disableSessionManagement);
+ QObject::connect(&app, &QGuiApplication::saveStateRequest, disableSessionManagement);
+
KDBusService::StartupOptions startup = nullptr;
{
QCommandLineParser parser;
diff --git a/applets/kimpanel/backend/ibus/ibus15/README b/applets/kimpanel/backend/ibus/ibus15/README
deleted file mode 100644
--- a/applets/kimpanel/backend/ibus/ibus15/README
+++ /dev/null
@@ -1,5 +0,0 @@
-WARINGING:
-ibus>=1.1.0 is needed, not 0.1.1 version
-
-START:
-ibus-daemon --panel=//panel.py
diff --git a/applets/kimpanel/backend/ibus/ibus15/panel.cpp b/applets/kimpanel/backend/ibus/ibus15/panel.cpp
--- a/applets/kimpanel/backend/ibus/ibus15/panel.cpp
+++ b/applets/kimpanel/backend/ibus/ibus15/panel.cpp
@@ -535,8 +535,7 @@
IBusEngineDesc** engines = ibus_bus_get_engines_by_names(impanel->bus, engine_names);
impanel->engineManager->setEngines(engines);
-
- if (engines && engines[0] && !contains(engine_names, ibus_engine_desc_get_name(ibus_bus_get_global_engine(impanel->bus)))) {
+ if (engines && engines[0] && (!ibus_bus_get_global_engine(impanel->bus) || !contains(engine_names, ibus_engine_desc_get_name(ibus_bus_get_global_engine(impanel->bus))))) {
ibus_bus_set_global_engine(impanel->bus, ibus_engine_desc_get_name(engines[0]));
}
g_strfreev(engine_names);
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
@@ -16,6 +16,7 @@
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[pl]=Minimalizacja wszystkich okien
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
@@ -16,6 +16,7 @@
Name[it]=Mostra il desktop
Name[ko]=바탕 화면 표시
Name[lt]=Rodyti darbalaukį
+Name[ml]=പണിയിടം കാണിക്കുക
Name[nl]=Bureaublad tonen
Name[nn]=Vis skrivebord
Name[pl]=Pokaż pulpit
@@ -47,6 +48,7 @@
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[pl]=Pokaż pulpit Plazmy
diff --git a/applets/taskmanager/package/contents/ui/ConfigBehavior.qml b/applets/taskmanager/package/contents/ui/ConfigBehavior.qml
--- a/applets/taskmanager/package/contents/ui/ConfigBehavior.qml
+++ b/applets/taskmanager/package/contents/ui/ConfigBehavior.qml
@@ -48,7 +48,6 @@
// TODO: port to QQC2 version once we've fixed https://bugs.kde.org/show_bug.cgi?id=403153
QQC1.ComboBox {
id: groupingStrategy
- visible: (plasmoid.pluginName !== "org.kde.plasma.icontasks")
Kirigami.FormData.label: i18n("Group:")
Layout.fillWidth: true
model: [i18n("Do not group"), i18n("By program name")]
@@ -144,7 +143,6 @@
CheckBox {
id: showOnlyMinimized
- visible: (plasmoid.pluginName !== "org.kde.plasma.icontasks")
text: i18n("Show only tasks that are minimized")
}
}
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
@@ -132,15 +132,22 @@
}
// Count badge.
- Badge {
+ Item {
Layout.alignment: Qt.AlignRight | Qt.AlignTop
- height: units.iconSizes.smallMedium
- visible: flatIndex === 0 && smartLauncherCountVisible
- number: smartLauncherCount
+ Layout.preferredHeight: closeButton.height
+ Layout.preferredWidth: closeButton.width
+
+ Badge {
+ anchors.centerIn: parent
+ height: units.iconSizes.smallMedium
+ visible: flatIndex === 0 && smartLauncherCountVisible
+ number: smartLauncherCount
+ }
}
// close button
PlasmaComponents.ToolButton {
+ id: closeButton
Layout.alignment: Qt.AlignRight | Qt.AlignTop
visible: isWin
iconSource: "window-close"
@@ -171,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
@@ -220,6 +234,7 @@
}
ToolTipWindowMouseArea {
+ id: hoverHandler
anchors.fill: parent
rootTask: parentTask
modelIndex: submodelIndex
diff --git a/applets/taskmanager/package/contents/ui/ToolTipWindowMouseArea.qml b/applets/taskmanager/package/contents/ui/ToolTipWindowMouseArea.qml
--- a/applets/taskmanager/package/contents/ui/ToolTipWindowMouseArea.qml
+++ b/applets/taskmanager/package/contents/ui/ToolTipWindowMouseArea.qml
@@ -29,6 +29,7 @@
property Item rootTask
acceptedButtons: Qt.LeftButton | Qt.MiddleButton | Qt.RightButton
+ cursorShape: Qt.PointingHandCursor
hoverEnabled: true
enabled: winId != 0
diff --git a/applets/taskmanager/package/contents/ui/main.qml b/applets/taskmanager/package/contents/ui/main.qml
--- a/applets/taskmanager/package/contents/ui/main.qml
+++ b/applets/taskmanager/package/contents/ui/main.qml
@@ -138,8 +138,7 @@
return true;
}
- groupMode: iconsOnly ? TaskManager.TasksModel.GroupApplications
- : groupModeEnumValue(plasmoid.configuration.groupingStrategy)
+ groupMode: groupModeEnumValue(plasmoid.configuration.groupingStrategy)
groupInline: !plasmoid.configuration.groupPopups
groupingWindowTasksThreshold: (plasmoid.configuration.onlyGroupWhenFull && !iconsOnly
? LayoutManager.optimumCapacity(width, height) + 1 : -1)
diff --git a/applets/taskmanager/package/metadata.desktop b/applets/taskmanager/package/metadata.desktop
--- a/applets/taskmanager/package/metadata.desktop
+++ b/applets/taskmanager/package/metadata.desktop
@@ -33,7 +33,7 @@
Name[hsb]=Rjadowar nadawkow
Name[hu]=Feladatkezelő
Name[ia]=Gerente de carga
-Name[id]=Pengelola Tugas
+Name[id]=Task Manager
Name[is]=Verkefnastjóri
Name[it]=Gestore dei processi
Name[ja]=タスクマネージャ
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/ActionButton.qml b/containments/desktop/package/contents/ui/ActionButton.qml
--- a/containments/desktop/package/contents/ui/ActionButton.qml
+++ b/containments/desktop/package/contents/ui/ActionButton.qml
@@ -52,7 +52,7 @@
id: toolTip
text: button.qAction ? button.qAction.text : ""
delay: 0
- visible: button.hovered
+ visible: button.hovered && text.length > 0
x: button.width
y: button.height/2 - height/2
}
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
@@ -98,7 +98,7 @@
id: rotateButton
svg: configIconsSvg
elementId: "rotate"
- toolTip: i18n("Rotate")
+ toolTip: !rotateHandle.pressed ? i18n("Rotate") : ""
iconSize: overlay.iconSize
action: (applet) ? applet.action("rotate") : null
down: !rotateHandle.pressed
@@ -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/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/kaccess/kaccess.notifyrc b/kaccess/kaccess.notifyrc
--- a/kaccess/kaccess.notifyrc
+++ b/kaccess/kaccess.notifyrc
@@ -63,7 +63,7 @@
Comment[oc]=Accessibilitat
Comment[or]=ଅଭିଗମ୍ୟତା
Comment[pa]=ਸਹੂਲਤਾਂ
-Comment[pl]=Ułatwienia dostępu
+Comment[pl]=Ułatwienia
Comment[pt]=Acessibilidade
Comment[pt_BR]=Acessibilidade
Comment[ro]=Accesibilitate
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
@@ -78,7 +78,7 @@
Name[oc]=Accessibilitat
Name[or]=ଅଭିଗମ୍ୟତା
Name[pa]=ਸਹੂਲਤਾਂ
-Name[pl]=Ułatwienia dostępu
+Name[pl]=Ułatwienia
Name[pt]=Acessibilidade
Name[pt_BR]=Acessibilidade
Name[ro]=Accesibilitate
@@ -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/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,6 +52,8 @@
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/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/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
@@ -13,6 +13,7 @@
Name[id]=Pencarian
Name[it]=Ricerca
Name[lt]=Paieška
+Name[ml]=തിരയുക
Name[nl]=Zoeken
Name[nn]=Søk
Name[pl]=Szukaj
@@ -39,6 +40,7 @@
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[pl]=Ustawienia indeksera plików
diff --git a/kcms/componentchooser/EXAMPLE.desktop b/kcms/componentchooser/EXAMPLE.desktop
--- a/kcms/componentchooser/EXAMPLE.desktop
+++ b/kcms/componentchooser/EXAMPLE.desktop
@@ -133,7 +133,7 @@
Comment[lv]=Noderīgs saskarnes apraksts augšējai labajai informācijas rūtij
Comment[mai]=ऊपरका दहिन्ना कोना केर सूचना बाक्स केर इंटरफेस क' उपयोगी वर्णन.
Comment[mk]=Опис со објаснување за интерфејсот за горното десно поле за инфо.
-Comment[ml]=വലത്തു് മുകളിലായുള്ള വിവരം നല്കുന്ന കളത്തില് കാണിയ്ക്കാനായി നിങ്ങളുടെ വിനിമയതലത്തിനുള്ള സഹായകരമായ ഒരു വിവരണം.
+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
diff --git a/kcms/componentchooser/componentchooser.desktop b/kcms/componentchooser/componentchooser.desktop
--- a/kcms/componentchooser/componentchooser.desktop
+++ b/kcms/componentchooser/componentchooser.desktop
@@ -14,7 +14,7 @@
Name=Default Applications
Name[af]=Verstektoepassings
Name[ar]=التّطبيقات الافتراضيّة
-Name[ast]=Aplicaicones predeterminaes
+Name[ast]=Aplicaciones predeterminaes
Name[be]=Праграмы па змаўчанні
Name[be@latin]=Zmoŭčanyja aplikacyi
Name[bg]=Стандартни програми
@@ -98,7 +98,7 @@
Name[zh_TW]=預設應用程式
Comment=Default Applications
Comment[ar]=التّطبيقات الافتراضيّة
-Comment[ast]=Aplicaicones predeterminaes
+Comment[ast]=Aplicaciones predeterminaes
Comment[bs]=Podrazumijevani programi
Comment[ca]=Aplicacions per omissió
Comment[ca@valencia]=Aplicacions per omissió
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)
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,76 @@
+/*
+ * 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 source_row, const QModelIndex &source_parent) const override;
+
+Q_SIGNALS:
+ void filterChanged();
+ void queryChanged();
+
+ void selectedThemeChanged();
+ void selectedThemeIndexChanged();
+
+private:
+ void emitSelectedThemeIndexChange();
+
+ QString m_selectedTheme;
+ QString m_query;
+ ThemeFilter m_filter = AllThemes;
+};
diff --git a/kcms/desktoptheme/filterproxymodel.cpp b/kcms/desktoptheme/filterproxymodel.cpp
new file mode 100644
--- /dev/null
+++ b/kcms/desktoptheme/filterproxymodel.cpp
@@ -0,0 +1,134 @@
+/*
+ * 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 "filterproxymodel.h"
+
+#include "themesmodel.h"
+
+FilterProxyModel::FilterProxyModel(QObject *parent) : QSortFilterProxyModel(parent)
+{
+
+}
+
+FilterProxyModel::~FilterProxyModel() = default;
+
+QString FilterProxyModel::selectedTheme() const
+{
+ return m_selectedTheme;
+}
+
+void FilterProxyModel::setSelectedTheme(const QString &pluginName)
+{
+ if (m_selectedTheme == pluginName) {
+ return;
+ }
+
+ const bool firstTime = m_selectedTheme.isNull();
+ m_selectedTheme = pluginName;
+
+ if (!firstTime) {
+ emit selectedThemeChanged();
+ }
+ emit selectedThemeIndexChanged();
+}
+
+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), ThemesModel::PluginNameRole, m_selectedTheme);
+
+ if (results.count() == 1) {
+ const QModelIndex result = mapFromSource(results.first());
+ if (result.isValid()) {
+ return result.row();
+ }
+ }
+
+ return -1;
+}
+
+QString FilterProxyModel::query() const
+{
+ return m_query;
+}
+
+void FilterProxyModel::setQuery(const QString &query)
+{
+ if (m_query != query) {
+ const int oldIndex = selectedThemeIndex();
+
+ m_query = query;
+ invalidateFilter();
+
+ emit queryChanged();
+
+ if (selectedThemeIndex() != oldIndex) {
+ emit selectedThemeIndexChanged();
+ }
+ }
+}
+
+FilterProxyModel::ThemeFilter FilterProxyModel::filter() const
+{
+ return m_filter;
+}
+
+void FilterProxyModel::setFilter(ThemeFilter filter)
+{
+ if (m_filter != filter) {
+ const int oldIndex = selectedThemeIndex();
+
+ m_filter = filter;
+ invalidateFilter();
+
+ emit filterChanged();
+
+ if (selectedThemeIndex() != oldIndex) {
+ emit selectedThemeIndexChanged();
+ }
+ }
+}
+
+bool FilterProxyModel::filterAcceptsRow(int source_row, const QModelIndex &source_parent) const
+{
+ const QModelIndex idx = sourceModel()->index(source_row, 0, source_parent);
+
+ if (!m_query.isEmpty()) {
+ if (!idx.data(Qt::DisplayRole).toString().contains(m_query, Qt::CaseInsensitive)
+ && !idx.data(ThemesModel::PluginNameRole).toString().contains(m_query, Qt::CaseInsensitive)) {
+ return false;
+ }
+ }
+
+ 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
@@ -39,44 +39,36 @@
}
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,8 +93,8 @@
DesktopThemeSettings *m_settings;
- QStandardItemModel *m_model;
- QStringList m_pendingRemoval;
+ ThemesModel *m_model;
+ FilterProxyModel *m_filteredModel;
QHash m_themes;
bool m_haveThemeExplorerInstalled;
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
@@ -44,35 +43,45 @@
#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,41 +93,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) {
@@ -222,58 +211,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*/);
-
+ m_model->load();
+ m_model->setSelectedTheme(m_settings->name());
// Model has been cleared so pretend the theme name changed to force view update
emit m_settings->nameChanged();
}
@@ -290,9 +229,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 +247,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 +279,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/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
@@ -26,12 +26,26 @@
import org.kde.kirigami 2.4 as Kirigami
import org.kde.kconfig 1.0 // for KAuthorized
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,80 @@
}
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("Themes following color scheme"), 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 +158,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;
}
]
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) const override;
+ QVariant data(const QModelIndex &index, int role) const override;
+ bool setData(const QModelIndex &index, const QVariant &value, int role) 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,249 @@
+/*
+ * 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});
+
+ // 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);
+ Q_FOREACH (const QString &pack, entries) {
+ const QString _metadata = ppath + QLatin1Char('/') + pack + QStringLiteral("/metadata.desktop");
+ if (QFile::exists(_metadata)) {
+ themes << _metadata;
+ }
+ }
+ }
+
+ for (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();
+ 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 : 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/icons/main.cpp b/kcms/icons/main.cpp
--- a/kcms/icons/main.cpp
+++ b/kcms/icons/main.cpp
@@ -474,7 +474,7 @@
{QStringLiteral("folder")},
{QStringLiteral("document"), QStringLiteral("text-x-generic")},
{QStringLiteral("user-trash"), QStringLiteral("user-trash-empty")},
- {QStringLiteral("system-help"), QStringLiteral("help-about"), QStringLiteral("help-contents")},
+ {QStringLiteral("help-browser"), QStringLiteral("system-help"), QStringLiteral("help-about"), QStringLiteral("help-contents")},
{QStringLiteral("preferences-system"), QStringLiteral("systemsettings"), QStringLiteral("configure")},
{QStringLiteral("text-html")},
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,7 +130,7 @@
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
diff --git a/kcms/launch/launchfeedback.h b/kcms/launch/launchfeedback.h
--- a/kcms/launch/launchfeedback.h
+++ b/kcms/launch/launchfeedback.h
@@ -44,9 +44,6 @@
LaunchFeedbackSettings *launchFeedbackSettings() const;
-public Q_SLOTS:
- void save() override;
-
private:
LaunchFeedbackSettings *m_settings;
};
diff --git a/kcms/launch/launchfeedback.cpp b/kcms/launch/launchfeedback.cpp
--- a/kcms/launch/launchfeedback.cpp
+++ b/kcms/launch/launchfeedback.cpp
@@ -53,14 +53,4 @@
return m_settings;
}
-void LaunchFeedback::save()
-{
- ManagedConfigModule::save();
-
- org::kde::kwin::Effects kwin(QStringLiteral("org.kde.KWin"),
- QStringLiteral("/Effects"),
- QDBusConnection::sessionBus());
- kwin.reconfigureEffect(QStringLiteral("startupfeedback"));
-}
-
#include "launchfeedback.moc"
diff --git a/kcms/launch/launchfeedbacksettings.kcfgc b/kcms/launch/launchfeedbacksettings.kcfgc
--- a/kcms/launch/launchfeedbacksettings.kcfgc
+++ b/kcms/launch/launchfeedbacksettings.kcfgc
@@ -4,3 +4,4 @@
DefaultValueGetters=true
GenerateProperties=true
ParentInConstructor=true
+Notifiers=true
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
@@ -61,7 +61,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[pl]=Wybierz globalny wygląd oraz wrażenia wzrokowe i dotykowe
+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
Comment[ru]=Выбор оформления рабочей среды Plasma
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
@@ -49,7 +49,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[pl]=Wybierz globalny wygląd oraz wrażenia wzrokowe i dotykowe
+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
Comment[ru]=Выбор оформления рабочей среды Plasma
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
@@ -14,6 +14,7 @@
X-KDE-Weight=120
Name=Night Color
+Name[ast]=Color nocherniegu
Name[ca]=Color de nit
Name[ca@valencia]=Color de nit
Name[cs]=Noční barva
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,12 +15,12 @@
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
@@ -32,37 +32,40 @@
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: "edit-paste-in-place"
- 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
@@ -108,13 +109,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 +142,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 +187,128 @@
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
@@ -1,5 +1,6 @@
[Desktop Entry]
Name=Night Color
+Name[ast]=Color nocherniegu
Name[ca]=Color de nit
Name[ca@valencia]=Color de nit
Name[cs]=Noční barva
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
@@ -33,6 +33,14 @@
// Sidebar on SourcesPage is 1/3 of the width at a minimum of 12, so assume 3 * 12 = 36 as preferred
implicitWidth: Kirigami.Units.gridUnit * 36
+ readonly property string ourServerVendor: "KDE"
+ readonly property string ourServerName: "Plasma"
+
+ readonly property NotificationManager.ServerInfo currentOwnerInfo: NotificationManager.Server.currentOwner
+
+ readonly property bool notificationsAvailable: currentOwnerInfo.status === NotificationManager.ServerInfo.Running
+ && currentOwnerInfo.vendor === ourServerVendor && currentOwnerInfo.name === ourServerName
+
function openSourcesSettings() {
// TODO would be nice to re-use the current SourcesPage instead of pushing a new one that lost all state
// but there's no pageAt(index) method in KConfigModuleQml
@@ -46,37 +54,67 @@
}
Kirigami.FormLayout {
+ Kirigami.InlineMessage {
+ Kirigami.FormData.isSection: true
+ Layout.fillWidth: true
+ type: Kirigami.MessageType.Error
+ text: i18n("Could not find a 'Notifications' widget which is required for displaying notifications.");
+ visible: currentOwnerInfo.status === NotificationManager.ServerInfo.NotRunning
+ }
+
+ Kirigami.InlineMessage {
+ Kirigami.FormData.isSection: true
+ Layout.fillWidth: true
+ type: Kirigami.MessageType.Information
+ text: {
+ if (currentOwnerInfo.vendor && currentOwnerInfo.name) {
+ return i18nc("Vendor and product name",
+ "Notifications are currently provided by '%1 %2' instead of Plasma.",
+ currentOwnerInfo.vendor, currentOwnerInfo.name);
+ }
+
+ return i18n("Notifications are currently not provided by Plasma.");
+ }
+ visible: root.currentOwnerInfo.status === NotificationManager.ServerInfo.Running
+ && (currentOwnerInfo.vendor !== root.ourServerVendor || currentOwnerInfo.name !== root.ourServerName)
+ }
+
QtControls.CheckBox {
Kirigami.FormData.label: i18n("Do not disturb:")
text: i18nc("Do not disturb when screens are mirrored", "When screens are mirrored")
checked: kcm.settings.inhibitNotificationsWhenScreensMirrored
onClicked: kcm.settings.inhibitNotificationsWhenScreensMirrored = checked
+ enabled: root.notificationsAvailable
}
QtControls.CheckBox {
text: i18n("Show critical notifications")
checked: kcm.settings.criticalPopupsInDoNotDisturbMode
onClicked: kcm.settings.criticalPopupsInDoNotDisturbMode = checked
+ enabled: root.notificationsAvailable
}
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
}
QtControls.CheckBox {
Kirigami.FormData.label: i18n("Low priority notifications:")
text: i18n("Show popup")
checked: kcm.settings.lowPriorityPopups
onClicked: kcm.settings.lowPriorityPopups = checked
+ enabled: root.notificationsAvailable
}
QtControls.CheckBox {
text: i18n("Show in history")
checked: kcm.settings.lowPriorityHistory
onClicked: kcm.settings.lowPriorityHistory = checked
+ enabled: root.notificationsAvailable
}
QtControls.ButtonGroup {
@@ -90,10 +128,13 @@
text: i18nc("Popup position near notification plasmoid", "Near the notification icon") // "widget"
checked: kcm.settings.popupPosition === NotificationManager.Settings.CloseToWidget
onClicked: kcm.settings.popupPosition = NotificationManager.Settings.CloseToWidget
+ enabled: root.notificationsAvailable
}
RowLayout {
spacing: 0
+ enabled: root.notificationsAvailable
+
QtControls.RadioButton {
id: positionCustomPosition
checked: kcm.settings.popupPosition !== NotificationManager.Settings.CloseToWidget
@@ -126,6 +167,7 @@
to: 120000 // 2 minutes
stepSize: 1000
value: kcm.settings.popupTimeout
+ enabled: root.notificationsAvailable
editable: true
valueFromText: function(text, locale) {
return parseInt(text) * 1000;
@@ -180,6 +222,7 @@
Kirigami.FormData.label: i18n("Applications:")
text: i18n("Configure...")
icon.name: "configure"
+ enabled: root.notificationsAvailable
onClicked: root.openSourcesSettings()
}
}
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,7 +39,7 @@
Name[lv]=Uzlādes procenti
Name[mai]=चार्ज प्रतिशत
Name[mk]=Процент на полнеж
-Name[ml]=ചാര്ജ്ജ് ശതമാനം
+Name[ml]=ചാര്ജ്ജ് ശതമാനം
Name[mr]=चार्ज टक्केवारी
Name[nb]=Prosent lading
Name[nds]=Oplaadperzent
diff --git a/kcms/spellchecking/spellchecking.desktop b/kcms/spellchecking/spellchecking.desktop
--- a/kcms/spellchecking/spellchecking.desktop
+++ b/kcms/spellchecking/spellchecking.desktop
@@ -36,6 +36,7 @@
Name[ja]=スペルチェック
Name[ko]=맞춤법 검사
Name[lt]=Rašybos tikrinimas
+Name[ml]=അക്ഷരത്തെറ്റു് പരിശോധക
Name[mr]=शब्द तपासक
Name[nb]=Stavekontroll
Name[nds]=Klookschriever
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
@@ -68,10 +68,24 @@
toolTip: model.description
thumbnailAvailable: thumbnailItem.valid
- thumbnail: Private.PreviewItem {
- id: thumbnailItem
+ thumbnail: Item {
anchors.fill: parent
- styleName: model.styleName
+ clip: thumbnailItem.implicitWidth * thumbnailItem.scale > width
+
+ Private.PreviewItem {
+ id: thumbnailItem
+ anchors.centerIn: parent
+ // Fit the widget's width in the grid view
+ // Round up to the nearest 0.05, so that 0.95 gets scaled up to 1.0
+ // to avoid blurriness in case the widget is only slightly bigger
+ scale: (Math.ceil(Math.min(1, parent.width / implicitWidth) * 20) / 20).toFixed(2)
+ width: Math.max(parent.width, implicitWidth)
+ // Scale the height back up as the background color comes from the style
+ // and we don't want to leave an ugly gap above/below it
+ height: parent.height / scale
+ smooth: true
+ styleName: model.styleName
+ }
Connections {
target: kcm
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,3 +4,4 @@
DefaultValueGetters=true
GenerateProperties=true
ParentInConstructor=true
+Notifiers=true
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/toolboxes/desktoptoolbox/metadata.desktop b/toolboxes/desktoptoolbox/metadata.desktop
--- a/toolboxes/desktoptoolbox/metadata.desktop
+++ b/toolboxes/desktoptoolbox/metadata.desktop
@@ -16,7 +16,7 @@
Name[gl]=Caixa de ferramentas declarativa
Name[hu]=Deklaratív eszközdoboz
Name[ia]=Instrumentario declarative
-Name[id]=Kotak-Alat Deklaratif
+Name[id]=Perkakas Deklaratif
Name[is]=Skilgreininga-verkfærasafn
Name[it]=Strumento dichiarativo
Name[kk]=Мәлімдеме құралдары
diff --git a/toolboxes/paneltoolbox/metadata.desktop b/toolboxes/paneltoolbox/metadata.desktop
--- a/toolboxes/paneltoolbox/metadata.desktop
+++ b/toolboxes/paneltoolbox/metadata.desktop
@@ -18,7 +18,7 @@
Name[he]=ארגז־הכלים של הלוח
Name[hu]=Panel eszköztár
Name[ia]=Instrumentario de pannello
-Name[id]=Kotak-Alat Panel
+Name[id]=Perkakas Panel
Name[is]=Verkfærasafn fyrir spjöld
Name[it]=Strumento per pannelli
Name[ja]=パネルツールボックス
@@ -75,6 +75,7 @@
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
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
@@ -20,7 +20,7 @@
Comment[hr]=Zadana panelna alatna kutija za Plasma ljusku radne površine
Comment[hu]=Alapértelmezett panel eszközkészlet a Plasma asztali héjhoz
Comment[ia]=Instrumentario de pannello pro le shell de scriptorio de Plasma
-Comment[id]=Toolbar panel baku untuk shell desktop Plasma
+Comment[id]=Perkakas panel baku untuk shell desktop Plasma
Comment[is]=Sjálfgefið verkfærasafn með Plasma skjáborðsskelinni
Comment[it]=Strumento predefinito del pannello per la shell del desktop di Plasma
Comment[ja]=Plasma デスクトップシェルの標準パネルツールボックス
@@ -78,7 +78,7 @@
Name[hr]=Alatna kutija panela
Name[hu]=Panel eszköztár
Name[ia]=Instrumentario de pannello
-Name[id]=Kotak-alat panel
+Name[id]=Perkakas panel
Name[is]=Verkfærasafn fyrir spjöld
Name[it]=Strumento per pannelli
Name[ja]=パネルツールボックス