diff --git a/kcms/cursortheme/kcmcursortheme.h b/kcms/cursortheme/kcmcursortheme.h --- a/kcms/cursortheme/kcmcursortheme.h +++ b/kcms/cursortheme/kcmcursortheme.h @@ -39,26 +39,27 @@ class CursorThemeConfig : public KQuickAddons::ConfigModule { Q_OBJECT + Q_PROPERTY(CursorThemeSettings *cursorThemeSettings READ cursorThemeSettings CONSTANT) Q_PROPERTY(bool canInstall READ canInstall WRITE setCanInstall NOTIFY canInstallChanged) Q_PROPERTY(bool canResize READ canResize WRITE setCanResize NOTIFY canResizeChanged) Q_PROPERTY(bool canConfigure READ canConfigure WRITE setCanConfigure NOTIFY canConfigureChanged) Q_PROPERTY(QAbstractItemModel *cursorsModel READ cursorsModel CONSTANT) Q_PROPERTY(QAbstractItemModel *sizesModel READ sizesModel CONSTANT) - Q_PROPERTY(int selectedThemeRow READ selectedThemeRow WRITE setSelectedThemeRow NOTIFY selectedThemeRowChanged) - Q_PROPERTY(int selectedSizeRow READ selectedSizeRow WRITE setSelectedSizeRow NOTIFY selectedSizeRowChanged) Q_PROPERTY(bool downloadingFile READ downloadingFile NOTIFY downloadingFileChanged) + Q_PROPERTY(int preferredSize READ preferredSize WRITE setPreferredSize NOTIFY preferredSizeChanged) public: CursorThemeConfig(QObject *parent, const QVariantList &); ~CursorThemeConfig() override; -public: void load() override; void save() override; void defaults() override; //for QML properties + CursorThemeSettings *cursorThemeSettings() const; + bool canInstall() const; void setCanInstall(bool can); @@ -68,24 +69,26 @@ bool canConfigure() const; void setCanConfigure(bool can); - int selectedThemeRow() const; - void setSelectedThemeRow(int row); - - int selectedSizeRow() const; - void setSelectedSizeRow(int row); + int preferredSize() const; + void setPreferredSize(int size); bool downloadingFile() const; QAbstractItemModel *cursorsModel(); QAbstractItemModel *sizesModel(); + Q_INVOKABLE int cursorSizeIndex(int cursorSize) const; + Q_INVOKABLE int cursorSizeFromIndex(int index); + Q_INVOKABLE int cursorThemeIndex(const QString &cursorTheme) const; + Q_INVOKABLE QString cursorThemeFromIndex(int index) const; + Q_SIGNALS: void canInstallChanged(); void canResizeChanged(); void canConfigureChanged(); - void selectedThemeRowChanged(); void selectedSizeRowChanged(); void downloadingFileChanged(); + void preferredSizeChanged(); void showSuccessMessage(const QString &message); void showInfoMessage(const QString &message); @@ -106,7 +109,7 @@ private: - QModelIndex themeSelectedIndex() const; + void updateNeedsSave(); void installThemeFile(const QString &path); /** Applies a given theme, using XFixes, XCursor and KGlobalSettings. @param theme The cursor theme to be applied. It is save to pass 0 here @@ -124,29 +127,24 @@ QStandardItemModel *m_sizesModel; CursorThemeSettings *m_settings; - int m_appliedSize; - // This index refers to the CursorThemeModel, not the proxy or the view - QPersistentModelIndex m_appliedIndex; - /** Holds the last size that was chosen by the user. Example: The user chooses theme1 which provides the sizes 24 and 36. He chooses 36. preferredSize gets set to 36. Now, he switches to theme2 which provides the sizes 30 and 40. preferredSize still is 36, so the UI will default to 40, which is next to 36. Now, he chooses theme3 which provides the sizes 34 and 44. preferredSize is still 36, so the UI defaults to 34. Now the user changes manually to 44. This will also change preferredSize. */ int m_preferredSize; - int m_originalPreferredSize; - int m_selectedThemeRow; - int m_selectedSizeRow; - int m_originalSelectedThemeRow; bool m_canInstall; bool m_canResize; bool m_canConfigure; 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 @@ -59,20 +59,22 @@ CursorThemeConfig::CursorThemeConfig(QObject *parent, const QVariantList &args) : KQuickAddons::ConfigModule(parent, args), m_settings(new CursorThemeSettings), - m_appliedSize(0), - m_preferredSize(0), - m_selectedThemeRow(-1), - m_selectedSizeRow(-1), - m_originalSelectedThemeRow(-1), 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); + connect(m_settings, &CursorThemeSettings::cursorThemeChanged, this, &CursorThemeConfig::updateSizeComboBox); qmlRegisterType("org.kde.private.kcm_cursortheme", 1, 0, "PreviewWidget"); qmlRegisterType(); - + qmlRegisterType(); KAboutData* aboutData = new KAboutData(QStringLiteral("kcm_cursortheme"), i18n("Cursors"), QStringLiteral("1.0"), QString(), KAboutLicense::GPL, i18n("(c) 2003-2007 Fredrik Höglund")); aboutData->addAuthor(i18n("Fredrik Höglund")); @@ -100,6 +102,11 @@ /* */ } +CursorThemeSettings *CursorThemeConfig::cursorThemeSettings() const +{ + return m_settings; +} + void CursorThemeConfig::setCanInstall(bool can) { if (m_canInstall == can) { @@ -140,55 +147,30 @@ emit canConfigureChanged(); } -bool CursorThemeConfig::canConfigure() const +int CursorThemeConfig::preferredSize() const { - return m_canConfigure; + return m_preferredSize; } -void CursorThemeConfig::setSelectedThemeRow(int row) +void CursorThemeConfig::setPreferredSize(int size) { - if (m_selectedThemeRow == row) { + if (m_preferredSize == size) { return; } - - m_selectedThemeRow = row; - emit selectedThemeRowChanged(); - updateSizeComboBox(); - - setNeedsSave(m_originalSelectedThemeRow != m_selectedThemeRow || m_originalPreferredSize != m_preferredSize); -} - -int CursorThemeConfig::selectedThemeRow() const -{ - return m_selectedThemeRow; -} - -void CursorThemeConfig::setSelectedSizeRow(int row) -{ - Q_ASSERT (row < m_sizesModel->rowCount() && row >= 0); - - // we don't return early if m_selectedSizeRow == row as this is called after the model is changed - m_selectedSizeRow = row; - emit selectedSizeRowChanged(); - - int size = m_sizesModel->item(row)->data().toInt(); - m_preferredSize = size; - setNeedsSave(m_originalSelectedThemeRow != m_selectedThemeRow || m_originalPreferredSize != m_preferredSize); + emit preferredSizeChanged(); } -int CursorThemeConfig::selectedSizeRow() const +bool CursorThemeConfig::canConfigure() const { - return m_selectedSizeRow; + return m_canConfigure; } bool CursorThemeConfig::downloadingFile() const { return m_tempCopyJob; } - - QAbstractItemModel *CursorThemeConfig::cursorsModel() { return m_themeProxyModel; @@ -211,12 +193,12 @@ void CursorThemeConfig::updateSizeComboBox() { - // clear the combo box m_sizesModel->clear(); // refill the combo box and adopt its icon size - QModelIndex selected = themeSelectedIndex(); + int row = cursorThemeIndex(m_settings->cursorTheme()); + QModelIndex selected = m_themeProxyModel->index(row, 0); int maxIconWidth = 0; int maxIconHeight = 0; if (selected.isValid()) { @@ -257,32 +239,36 @@ } // select an item - int selectItem = comboBoxList.indexOf(m_preferredSize); - // m_preferredSize not available for this theme + int size = m_preferredSize; + int selectItem = comboBoxList.indexOf(size); + + // cursor size not available for this theme if (selectItem < 0) { - /* Search the value next to m_preferredSize. The first entry (0) - is ignored. (If m_preferredSize would have been 0, then we - would had found it yet. As m_preferredSize is not 0, we won't + /* Search the value next to cursor size. The first entry (0) + is ignored. (If cursor size would have been 0, then we + would had found it yet. As cursor size is not 0, we won't default to "automatic size".)*/ int j; int distance; int smallestDistance; selectItem = 1; j = comboBoxList.value(selectItem); - smallestDistance = j < m_preferredSize ? m_preferredSize - j : j - m_preferredSize; + size = j; + smallestDistance = qAbs(m_preferredSize - j); for (int i = 2; i < comboBoxList.size(); ++i) { j = comboBoxList.value(i); - distance = j < m_preferredSize ? m_preferredSize - j : j - m_preferredSize; + distance = qAbs(m_preferredSize - j); if (distance < smallestDistance || (distance == smallestDistance && j > m_preferredSize)) { smallestDistance = distance; selectItem = i; + size = j; } } } if (selectItem < 0) { selectItem = 0; } - setSelectedSizeRow(selectItem); + m_settings->setCursorSize(size); } } @@ -292,7 +278,8 @@ } else { setCanResize(m_sizesModel->rowCount() > 0); } - + // We need to emit a cursorSizeChanged in all case to refresh UI + emit m_settings->cursorSizeChanged(); } bool CursorThemeConfig::applyTheme(const CursorTheme *theme, const int size) @@ -346,88 +333,95 @@ foreach (const QString &name, names) { XFixesChangeCursorByName(QX11Info::display(), theme->loadCursor(name, size), QFile::encodeName(name)); } - + updateSizeComboBox(); return true; #else Q_UNUSED(theme) return false; #endif } +int CursorThemeConfig::cursorSizeIndex(int cursorSize) const +{ + if (m_sizesModel->rowCount() > 0) { + if (cursorSize == 0) { + return 0; + } + const auto items = m_sizesModel->findItems(QString::number(cursorSize)); + if (items.count() == 1) { + return items.first()->row(); + } + } + return -1; +} -void CursorThemeConfig::save() +int CursorThemeConfig::cursorSizeFromIndex(int index) { - const CursorTheme *theme = themeSelectedIndex().isValid() ? m_themeProxyModel->theme(themeSelectedIndex()) : nullptr; + Q_ASSERT (index < m_sizesModel->rowCount() && index >= 0); - if (theme) { - m_settings->setCursorTheme(theme->name()); - } - m_settings->setCursorSize(m_preferredSize); + return m_sizesModel->item(index)->data().toInt(); +} + +int CursorThemeConfig::cursorThemeIndex(const QString &cursorTheme) const +{ + auto results = m_themeProxyModel->findIndex(cursorTheme); + return results.row(); +} + +QString CursorThemeConfig::cursorThemeFromIndex(int index) const +{ + QModelIndex idx = m_themeProxyModel->index(index, 0); + return m_themeProxyModel->theme(idx)->name(); +} +void CursorThemeConfig::save() +{ m_settings->save(); + m_currentTheme = m_settings->cursorTheme(); + m_currentSize = m_settings->cursorSize(); + setPreferredSize(m_currentSize); - if (!applyTheme(theme, m_preferredSize)) { + 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)) { emit showInfoMessage(i18n("You have to restart the Plasma session for these changes to take effect.")); } - - m_appliedIndex = themeSelectedIndex(); - m_appliedSize = m_preferredSize; - m_originalSelectedThemeRow = m_selectedThemeRow; - m_originalPreferredSize = m_preferredSize; setNeedsSave(false); } void CursorThemeConfig::load() { - // Get the name of the theme KDE is configured to use + 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 QString currentTheme = m_settings->cursorTheme(); - // Find the theme in the listview - if (!currentTheme.isEmpty()) { - m_appliedIndex = m_themeProxyModel->findIndex(currentTheme); - } else { - m_appliedIndex = m_themeProxyModel->defaultIndex(); - } - // Disable the listview and the buttons if we're in kiosk mode if (m_settings->isImmutable( QStringLiteral( "cursorTheme" ))) { setCanConfigure(false); setCanInstall(false); } - setSelectedThemeRow(m_appliedIndex.row()); - m_originalSelectedThemeRow = m_selectedThemeRow; - - // Load cursor size - int size = m_settings->cursorSize(); - if (size <= 0) { - m_preferredSize = 0; - } else { - m_preferredSize = size; - } - m_originalPreferredSize = m_preferredSize; updateSizeComboBox(); // This handles also the kiosk mode - m_appliedSize = size; - - setNeedsSave(false); } void CursorThemeConfig::defaults() { - QModelIndex defaultIndex = m_themeProxyModel->findIndex(m_settings->defaultCursorThemeValue()); - setSelectedThemeRow(defaultIndex.row()); - m_preferredSize = m_settings->defaultCursorSizeValue(); - updateSizeComboBox(); - setNeedsSave(m_originalSelectedThemeRow != m_selectedThemeRow || m_originalPreferredSize != m_preferredSize); + m_settings->setDefaults(); + m_preferredSize = m_settings->cursorSize(); } -QModelIndex CursorThemeConfig::themeSelectedIndex() const +void CursorThemeConfig::updateNeedsSave() { - return m_themeProxyModel->index(m_selectedThemeRow, 0); + setNeedsSave(m_settings->cursorTheme() != m_currentTheme || m_settings->cursorSize() != m_currentSize); } void CursorThemeConfig::getNewClicked() @@ -585,7 +579,7 @@ const CursorTheme *theme = m_themeProxyModel->theme(idx); // Don't let the user delete the currently configured theme - if (idx == m_appliedIndex) { + if (theme->name() == m_currentTheme) { 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/Delegate.qml b/kcms/cursortheme/package/contents/ui/Delegate.qml --- a/kcms/cursortheme/package/contents/ui/Delegate.qml +++ b/kcms/cursortheme/package/contents/ui/Delegate.qml @@ -48,7 +48,7 @@ scale: 1 / Screen.devicePixelRatio themeModel: kcm.cursorsModel currentIndex: index - currentSize: parseInt(sizeCombo.currentText) !== NaN ? parseInt(sizeCombo.currentText) : 0 + currentSize: kcm.cursorThemeSettings.cursorSize } actions: [ @@ -61,7 +61,7 @@ ] onClicked: { - view.currentIndex = index; view.forceActiveFocus(); + kcm.cursorThemeSettings.cursorTheme = kcm.cursorThemeFromIndex(index); } } 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 @@ -32,11 +32,17 @@ view.model: kcm.cursorsModel view.delegate: Delegate {} + view.currentIndex: kcm.cursorThemeIndex(kcm.cursorThemeSettings.cursorTheme); + view.onCurrentIndexChanged: { - kcm.selectedThemeRow = view.currentIndex; + kcm.cursorThemeSettings.cursorTheme = kcm.cursorThemeFromIndex(view.currentIndex) view.positionViewAtIndex(view.currentIndex, view.GridView.Beginning); } + Component.onCompleted: { + view.positionViewAtIndex(view.currentIndex, GridView.Beginning); + } + enabled: !kcm.downloadingFile DropArea { @@ -49,11 +55,6 @@ onDropped: kcm.installThemeFromFile(drop.urls[0]) } - Connections { - target: kcm - onSelectedThemeRowChanged: view.currentIndex = kcm.selectedThemeRow; - } - footer: ColumnLayout { id: footerLayout @@ -101,15 +102,10 @@ id: sizeCombo model: kcm.sizesModel textRole: "display" + currentIndex: kcm.cursorSizeIndex(kcm.cursorThemeSettings.cursorSize); onActivated: { - kcm.selectedSizeRow = sizeCombo.currentIndex - } - - Connections { - target: kcm - onSelectedSizeRowChanged: { - sizeCombo.currentIndex = kcm.selectedSizeRow - } + kcm.cursorThemeSettings.cursorSize = kcm.cursorSizeFromIndex(sizeCombo.currentIndex); + kcm.preferredSize = kcm.cursorSizeFromIndex(sizeCombo.currentIndex); } delegate: QtControls.ItemDelegate {