diff --git a/applets/pager/plugin/pagermodel.cpp b/applets/pager/plugin/pagermodel.cpp index e13898ef6..0b75afd82 100644 --- a/applets/pager/plugin/pagermodel.cpp +++ b/applets/pager/plugin/pagermodel.cpp @@ -1,647 +1,647 @@ /******************************************************************** Copyright 2007 Daniel Laidig Copyright 2012 Luís Gabriel Lima Copyright 2016 Eike Hein This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA . *********************************************************************/ #include "pagermodel.h" #include "windowmodel.h" #include #include #include #include #include #include #include #include #include #include #include #include using namespace TaskManager; class PagerModel::Private { public: Private(PagerModel *q); ~Private(); static int instanceCount; bool componentComplete = false; PagerType pagerType = VirtualDesktops; bool enabled = false; bool showDesktop = false; bool showOnlyCurrentScreen = false; QRect screenGeometry; WindowTasksModel *tasksModel = nullptr; static ActivityInfo *activityInfo; QMetaObject::Connection activityNumberConn; QMetaObject::Connection activityNamesConn; static VirtualDesktopInfo *virtualDesktopInfo; QMetaObject::Connection virtualDesktopNumberConn; QMetaObject::Connection virtualDesktopNamesConn; QDesktopWidget *desktopWidget = QApplication::desktop(); QList windowModels; #if HAVE_X11 QList cachedStackingOrder = KWindowSystem::stackingOrder(); #endif void refreshDataSource(); private: PagerModel *q; }; int PagerModel::Private::instanceCount = 0; ActivityInfo *PagerModel::Private::activityInfo = nullptr; VirtualDesktopInfo *PagerModel::Private::virtualDesktopInfo = nullptr; PagerModel::Private::Private(PagerModel *q) : q(q) { ++instanceCount; if (!activityInfo) { activityInfo = new ActivityInfo(); } QObject::connect(activityInfo, &ActivityInfo::numberOfRunningActivitiesChanged, q, &PagerModel::shouldShowPagerChanged); if (!virtualDesktopInfo) { virtualDesktopInfo = new VirtualDesktopInfo(); } QObject::connect(virtualDesktopInfo, &VirtualDesktopInfo::numberOfDesktopsChanged, q, &PagerModel::shouldShowPagerChanged); QObject::connect(activityInfo, &ActivityInfo::currentActivityChanged, q, [this]() { if (pagerType == VirtualDesktops && windowModels.count()) { for (auto windowModel : windowModels) { windowModel->setActivity(activityInfo->currentActivity()); } } } ); QObject::connect(virtualDesktopInfo, &VirtualDesktopInfo::desktopLayoutRowsChanged, q, &PagerModel::layoutRowsChanged); QObject::connect(desktopWidget, &QDesktopWidget::screenCountChanged, q, &PagerModel::pagerItemSizeChanged); QObject::connect(desktopWidget, &QDesktopWidget::resized, q, &PagerModel::pagerItemSizeChanged); #if HAVE_X11 QObject::connect(KWindowSystem::self(), &KWindowSystem::stackingOrderChanged, q, [this]() { cachedStackingOrder = KWindowSystem::stackingOrder(); for (auto windowModel : windowModels) { windowModel->refreshStackingOrder(); } } ); #endif } PagerModel::Private::~Private() { --instanceCount; if (!instanceCount) { delete activityInfo; activityInfo = nullptr; delete virtualDesktopInfo; virtualDesktopInfo = nullptr; } } void PagerModel::Private::refreshDataSource() { if (pagerType == VirtualDesktops) { QObject::disconnect(virtualDesktopNumberConn); virtualDesktopNumberConn = QObject::connect(virtualDesktopInfo, &VirtualDesktopInfo::numberOfDesktopsChanged, q, [this]() { q->refresh(); }); QObject::disconnect(virtualDesktopNamesConn); virtualDesktopNamesConn = QObject::connect(virtualDesktopInfo, &VirtualDesktopInfo::desktopNamesChanged, q, [this]() { if (q->rowCount()) { emit q->dataChanged(q->index(0, 0), q->index(q->rowCount() - 1, 0), QVector{Qt::DisplayRole}); } } ); QObject::disconnect(activityNumberConn); QObject::disconnect(activityNamesConn); QObject::disconnect(activityInfo, &ActivityInfo::currentActivityChanged, q, &PagerModel::currentPageChanged); QObject::connect(virtualDesktopInfo, &VirtualDesktopInfo::currentDesktopChanged, q, &PagerModel::currentPageChanged, Qt::UniqueConnection); } else { QObject::disconnect(activityNumberConn); activityNumberConn = QObject::connect(activityInfo, &ActivityInfo::numberOfRunningActivitiesChanged, q, [this]() { q->refresh(); }); QObject::disconnect(activityNamesConn); activityNamesConn = QObject::connect(activityInfo, &ActivityInfo::namesOfRunningActivitiesChanged, q, [this]() { q->refresh(); }); QObject::disconnect(virtualDesktopNumberConn); QObject::disconnect(virtualDesktopNamesConn); QObject::disconnect(virtualDesktopInfo, &VirtualDesktopInfo::currentDesktopChanged, q, &PagerModel::currentPageChanged); QObject::connect(activityInfo, &ActivityInfo::currentActivityChanged, q, &PagerModel::currentPageChanged, Qt::UniqueConnection); } emit q->currentPageChanged(); } PagerModel::PagerModel(QObject *parent) : QAbstractListModel(parent) , d(new Private(this)) { d->tasksModel = new WindowTasksModel(this); } PagerModel::~PagerModel() { } QHash PagerModel::roleNames() const { QHash roles = QAbstractItemModel::roleNames(); QMetaEnum e = metaObject()->enumerator(metaObject()->indexOfEnumerator("AdditionalRoles")); for (int i = 0; i < e.keyCount(); ++i) { roles.insert(e.value(i), e.key(i)); } return roles; } int PagerModel::rowCount(const QModelIndex &parent) const { if (parent.isValid()) { return 0; } return d->windowModels.count(); } QVariant PagerModel::data(const QModelIndex &index, int role) const { if (!index.isValid() || index.row() < 0 || index.row() >= d->windowModels.count()) { return QVariant(); } if (role == Qt::DisplayRole) { if (d->pagerType == VirtualDesktops) { return d->virtualDesktopInfo->desktopNames().at(index.row()); } else { QString activityId = d->activityInfo->runningActivities().at(index.row()); return d->activityInfo->activityName(activityId); } } else if (role == TasksModel) { return QVariant::fromValue(d->windowModels.at(index.row())); } return QVariant(); } PagerModel::PagerType PagerModel::pagerType() const { return d->pagerType; } void PagerModel::setPagerType(PagerType type) { if (d->pagerType != type) { d->pagerType = type; refresh(); emit pagerTypeChanged(); emit shouldShowPagerChanged(); } } bool PagerModel::enabled() const { return d->enabled; } void PagerModel::setEnabled(bool enabled) { if (enabled && !d->enabled) { refresh(); d->enabled = true; emit enabledChanged(); } else if (!enabled && d->enabled) { beginResetModel(); disconnect(d->activityNumberConn); disconnect(d->activityNamesConn); disconnect(d->virtualDesktopNumberConn); disconnect(d->virtualDesktopNamesConn); qDeleteAll(d->windowModels); d->windowModels.clear(); endResetModel(); d->enabled = false; emit enabledChanged(); emit countChanged(); } } bool PagerModel::shouldShowPager() const { return (d->pagerType == VirtualDesktops) ? d->virtualDesktopInfo->numberOfDesktops() > 1 : d->activityInfo->numberOfRunningActivities() > 1; } bool PagerModel::showDesktop() const { return d->showDesktop; } void PagerModel::setShowDesktop(bool show) { if (d->showDesktop != show) { d->showDesktop = show; emit showDesktopChanged(); } } bool PagerModel::showOnlyCurrentScreen() const { return d->showOnlyCurrentScreen; } void PagerModel::setShowOnlyCurrentScreen(bool show) { if (d->showOnlyCurrentScreen != show) { d->showOnlyCurrentScreen = show; if (d->screenGeometry.isValid()) { emit pagerItemSizeChanged(); refresh(); } emit showOnlyCurrentScreenChanged(); } } QRect PagerModel::screenGeometry() const { return d->screenGeometry; } void PagerModel::setScreenGeometry(const QRect &geometry) { if (d->screenGeometry != geometry) { d->screenGeometry = geometry; if (d->showOnlyCurrentScreen) { emit pagerItemSizeChanged(); refresh(); } emit showOnlyCurrentScreenChanged(); } } int PagerModel::currentPage() const { if (d->pagerType == VirtualDesktops) { return d->virtualDesktopInfo->currentDesktop() - 1; } else { return d->activityInfo->runningActivities().indexOf(d->activityInfo->currentActivity()); } } int PagerModel::layoutRows() const { return qBound(1, d->virtualDesktopInfo->desktopLayoutRows(), d->virtualDesktopInfo->numberOfDesktops()); } QSize PagerModel::pagerItemSize() const { if (d->showOnlyCurrentScreen && d->screenGeometry.isValid()) { return d->screenGeometry.size(); } QRect totalRect; for (int i = 0; i < d->desktopWidget->screenCount(); ++i) { totalRect |= d->desktopWidget->screenGeometry(i); } return totalRect.size(); } #if HAVE_X11 QList PagerModel::stackingOrder() const { return d->cachedStackingOrder; } #endif void PagerModel::refresh() { if (!d->componentComplete) { return; } beginResetModel(); d->refreshDataSource(); int modelCount = d->windowModels.count(); const int modelsNeeded = ((d->pagerType == VirtualDesktops) ? d->virtualDesktopInfo->numberOfDesktops() : d->activityInfo->numberOfRunningActivities()); if (modelCount > modelsNeeded) { while (modelCount != modelsNeeded) { delete d->windowModels.takeLast(); --modelCount; } } else if (modelsNeeded > modelCount) { while (modelCount != modelsNeeded) { WindowModel *windowModel = new WindowModel(this); windowModel->setFilterSkipPager(true); windowModel->setFilterByVirtualDesktop(true); windowModel->setFilterByActivity(true); windowModel->setDemandingAttentionSkipsFilters(false); windowModel->setSourceModel(d->tasksModel); d->windowModels.append(windowModel); ++modelCount; } } if (d->pagerType == VirtualDesktops) { int virtualDesktop = 1; for (auto windowModel : d->windowModels) { windowModel->setVirtualDesktop(virtualDesktop); ++virtualDesktop; windowModel->setActivity(d->activityInfo->currentActivity()); } } else { int activityIndex = 0; const QStringList &runningActivities = d->activityInfo->runningActivities(); for (auto windowModel : d->windowModels) { windowModel->setVirtualDesktop(0); windowModel->setActivity(runningActivities.at(activityIndex)); ++activityIndex; } } for (auto windowModel : d->windowModels) { if (d->showOnlyCurrentScreen && d->screenGeometry.isValid()) { windowModel->setScreenGeometry(d->screenGeometry); windowModel->setFilterByScreen(true); } else { windowModel->setFilterByScreen(false); } } endResetModel(); emit countChanged(); } void PagerModel::moveWindow(int window, double x, double y, int targetItemId, int sourceItemId, qreal widthScaleFactor, qreal heightScaleFactor) { #if HAVE_X11 if (!KWindowSystem::isPlatformX11()) { return; } const WId windowId = (WId)window; QPointF dest(x / widthScaleFactor, y / heightScaleFactor); // Don't move windows to negative positions. dest = QPointF(qMax(dest.x(), qreal(0.0)), qMax(dest.y(), qreal(0.0))); // Use _NET_MOVERESIZE_WINDOW rather than plain move, so that the WM knows this is a pager request. - NETRootInfo info(QX11Info::connection(), nullptr); + NETRootInfo info(QX11Info::connection(), NET::Properties()); const int flags = (0x20 << 12) | (0x03 << 8) | 1; // From tool, x/y, northwest gravity. if (!KWindowSystem::mapViewport()) { KWindowInfo windowInfo(windowId, NET::WMDesktop | NET::WMState, NET::WM2Activities); if (d->pagerType == VirtualDesktops) { if (!windowInfo.onAllDesktops()) { KWindowSystem::setOnDesktop(windowId, targetItemId + 1); } } else { const QStringList &runningActivities = d->activityInfo->runningActivities(); if (targetItemId < runningActivities.length()) { const QString &newActivity = runningActivities.at(targetItemId); QStringList activities = windowInfo.activities(); if (!activities.contains(newActivity)) { activities.removeOne(runningActivities.at(sourceItemId)); activities.append(newActivity); KWindowSystem::setOnActivities(windowId, activities); } } } // Only move the window if it is not full screen and if it is kept within the same desktop. // Moving when dropping between desktop is too annoying due to the small drop area. if (!(windowInfo.state() & NET::FullScreen) && (targetItemId == sourceItemId || windowInfo.onAllDesktops())) { const QPoint &d = dest.toPoint(); info.moveResizeWindowRequest(windowId, flags, d.x(), d.y(), 0, 0); } } else { // setOnDesktop() with viewports is also moving a window, and since it takes a moment // for the WM to do the move, there's a race condition with figuring out how much to move, // so do it only as one move. dest += KWindowSystem::desktopToViewport(targetItemId + 1, false); const QPoint &d = KWindowSystem::constrainViewportRelativePosition(dest.toPoint()); info.moveResizeWindowRequest(windowId, flags, d.x(), d.y(), 0, 0); } #else Q_UNUSED(window) Q_UNUSED(x) Q_UNUSED(y) Q_UNUSED(targetDesktop) Q_UNUSED(sourceDesktop) #endif } void PagerModel::changePage(int page) { #if HAVE_X11 if (!KWindowSystem::isPlatformX11()) { return; } if (currentPage() == page) { if (d->showDesktop) { QDBusConnection::sessionBus().asyncCall(QDBusMessage::createMethodCall(QLatin1String("org.kde.plasmashell"), QLatin1String("/PlasmaShell"), QLatin1String("org.kde.PlasmaShell"), QLatin1String("toggleDashboard"))); } } else { if (d->pagerType == VirtualDesktops) { KWindowSystem::setCurrentDesktop(page + 1); } else { const QStringList &runningActivities = d->activityInfo->runningActivities(); if (page < runningActivities.length()) { KActivities::Controller activitiesController; activitiesController.setCurrentActivity(runningActivities.at(page)); } } } #else Q_UNUSED(itemId) #endif } void PagerModel::drop(QMimeData *mimeData, int itemId) { if (!mimeData) { return; } #if HAVE_X11 if (KWindowSystem::isPlatformX11()) { bool ok; const QList &ids = TaskManager::XWindowTasksModel::winIdsFromMimeData(mimeData, &ok); if (!ok) { return; } if (d->pagerType == VirtualDesktops) { for (const auto &id : ids) { KWindowSystem::setOnDesktop(id, itemId + 1); } } else { QString newActivity; const QStringList &runningActivities = d->activityInfo->runningActivities(); if (itemId < runningActivities.length()) { newActivity = runningActivities.at(itemId); } if (newActivity.isEmpty()) { return; } for (const auto &id : ids) { - QStringList activities = KWindowInfo(id, nullptr, NET::WM2Activities).activities(); + QStringList activities = KWindowInfo(id, NET::Properties(), NET::WM2Activities).activities(); if (!activities.contains(newActivity)) { KWindowSystem::setOnActivities(id, activities << newActivity); } } } } #else Q_UNUSED(itemId) #endif } void PagerModel::addDesktop() { #if HAVE_X11 if (!KWindowSystem::isPlatformX11()) { return; } NETRootInfo info(QX11Info::connection(), NET::NumberOfDesktops); info.setNumberOfDesktops(info.numberOfDesktops() + 1); #endif } void PagerModel::removeDesktop() { #if HAVE_X11 if (!KWindowSystem::isPlatformX11()) { return; } NETRootInfo info(QX11Info::connection(), NET::NumberOfDesktops); if (info.numberOfDesktops() > 1) { info.setNumberOfDesktops(info.numberOfDesktops() - 1); } #endif } void PagerModel::classBegin() { } void PagerModel::componentComplete() { d->componentComplete = true; if (d->enabled) { refresh(); } } #include "moc_pagermodel.cpp" diff --git a/imports/activitymanager/sortedactivitiesmodel.cpp b/imports/activitymanager/sortedactivitiesmodel.cpp index 596fdc26b..c883973b2 100644 --- a/imports/activitymanager/sortedactivitiesmodel.cpp +++ b/imports/activitymanager/sortedactivitiesmodel.cpp @@ -1,491 +1,491 @@ /* * Copyright (C) 2016 Ivan Cukic * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2, * or (at your option) any later version, as published by the Free * Software Foundation * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details * * You should have received a copy of the GNU General Public * License along with this program; if not, write to the * Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ // Self #include "sortedactivitiesmodel.h" // C++ #include // Qt #include #include #include // KDE #include #include #include #include #include #define KWINDOWSYSTEM_NO_DEPRECATED #include #include #define PLASMACONFIG "plasma-org.kde.plasma.desktop-appletsrc" namespace { class BackgroundCache: public QObject { public: BackgroundCache() : initialized(false) , plasmaConfig(KSharedConfig::openConfig(PLASMACONFIG)) { using namespace std::placeholders; const QString configFile = QStandardPaths::writableLocation( QStandardPaths::GenericConfigLocation) + QLatin1Char('/') + PLASMACONFIG; KDirWatch::self()->addFile(configFile); QObject::connect(KDirWatch::self(), &KDirWatch::dirty, this, &BackgroundCache::settingsFileChanged, Qt::QueuedConnection); QObject::connect(KDirWatch::self(), &KDirWatch::created, this, &BackgroundCache::settingsFileChanged, Qt::QueuedConnection); } void settingsFileChanged(const QString &file) { if (!file.endsWith(PLASMACONFIG)) { return; } if (initialized) { plasmaConfig->reparseConfiguration(); reload(); } } void subscribe(SortedActivitiesModel *model) { if (!initialized) { reload(); } models << model; } void unsubscribe(SortedActivitiesModel *model) { models.removeAll(model); if (models.isEmpty()) { initialized = false; forActivity.clear(); } } QString backgroundFromConfig(const KConfigGroup &config) const { auto wallpaperPlugin = config.readEntry("wallpaperplugin"); auto wallpaperConfig = config.group("Wallpaper").group(wallpaperPlugin).group("General"); if (wallpaperConfig.hasKey("Image")) { // Trying for the wallpaper auto wallpaper = wallpaperConfig.readEntry("Image", QString()); if (!wallpaper.isEmpty()) { return wallpaper; } } if (wallpaperConfig.hasKey("Color")) { auto backgroundColor = wallpaperConfig.readEntry("Color", QColor(0, 0, 0)); return backgroundColor.name(); } return QString(); } void reload() { auto newForActivity = forActivity; QHash lastScreenForActivity; // contains activities for which the wallpaper // has updated QStringList changedActivities; // Contains activities not covered by any containment QStringList ghostActivities = forActivity.keys(); // Traversing through all containments in search for // containments that define activities in plasma for (const auto& containmentId: plasmaConfigContainments().groupList()) { const auto containment = plasmaConfigContainments().group(containmentId); const auto lastScreen = containment.readEntry("lastScreen", 0); const auto activity = containment.readEntry("activityId", QString()); // Ignore the containment if the activity is not defined if (activity.isEmpty()) continue; // If we have already found the same activity from another // containment, we are using the new one only if // the previous one was a color and not a proper wallpaper, // or if the screen ID is closer to zero const bool processed = !ghostActivities.contains(activity) && newForActivity.contains(activity) && (lastScreenForActivity[activity] <= lastScreen); // qDebug() << "GREPME Searching containment " << containmentId // << "for the wallpaper of the " << activity << " activity - " // << "currently, we think that the wallpaper is " << processed << (processed ? newForActivity[activity] : QString()) // << "last screen is" << lastScreen // ; if (processed && newForActivity[activity][0] != '#') continue; // Marking the current activity as processed ghostActivities.removeAll(activity); const auto background = backgroundFromConfig(containment); // qDebug() << " GREPME Found wallpaper: " << background; if (background.isEmpty()) continue; // If we got this far and we already had a new wallpaper for // this activity, it means we now have a better one bool foundBetterWallpaper = changedActivities.contains(activity); if (foundBetterWallpaper || newForActivity[activity] != background) { if (!foundBetterWallpaper) { changedActivities << activity; } // qDebug() << " GREPME Setting: " << activity << " = " << background << "," << lastScreen; newForActivity[activity] = background; lastScreenForActivity[activity] = lastScreen; } } initialized = true; // Removing the activities from the list if we haven't found them // while traversing through the containments for (const auto& activity: ghostActivities) { newForActivity.remove(activity); } // If we have detected the changes, lets notify everyone if (!changedActivities.isEmpty()) { forActivity = newForActivity; for (auto model: models) { model->onBackgroundsUpdated(changedActivities); } } } KConfigGroup plasmaConfigContainments() { return plasmaConfig->group("Containments"); } QHash forActivity; QList models; bool initialized; KSharedConfig::Ptr plasmaConfig; }; static BackgroundCache &backgrounds() { // If you convert this to a shared pointer, // fix the connections to KDirWatcher static BackgroundCache cache; return cache; } } SortedActivitiesModel::SortedActivitiesModel(const QVector &states, QObject *parent) : QSortFilterProxyModel(parent) , m_activitiesModel(new KActivities::ActivitiesModel(states, this)) , m_activities(new KActivities::Consumer(this)) { setSourceModel(m_activitiesModel); setDynamicSortFilter(true); setSortRole(LastTimeUsed); sort(0, Qt::DescendingOrder); backgrounds().subscribe(this); const QList windows = KWindowSystem::stackingOrder(); for (const auto& window: windows) { KWindowInfo info(window, NET::WMVisibleName, NET::WM2Activities); const QStringList activities = info.activities(); if (activities.isEmpty() || activities.contains("00000000-0000-0000-0000-000000000000")) continue; for (const auto& activity: activities) { m_activitiesWindows[activity] << window; } } connect(KWindowSystem::self(), &KWindowSystem::windowAdded, this, &SortedActivitiesModel::onWindowAdded); connect(KWindowSystem::self(), &KWindowSystem::windowRemoved, this, &SortedActivitiesModel::onWindowRemoved); connect(KWindowSystem::self(), SIGNAL(windowChanged(WId, NET::Properties, NET::Properties2)), this, SLOT(onWindowChanged(WId, NET::Properties, NET::Properties2))); } SortedActivitiesModel::~SortedActivitiesModel() { backgrounds().unsubscribe(this); } bool SortedActivitiesModel::inhibitUpdates() const { return m_inhibitUpdates; } void SortedActivitiesModel::setInhibitUpdates(bool inhibitUpdates) { if (m_inhibitUpdates != inhibitUpdates) { m_inhibitUpdates = inhibitUpdates; emit inhibitUpdatesChanged(m_inhibitUpdates); setDynamicSortFilter(!inhibitUpdates); } } uint SortedActivitiesModel::lastUsedTime(const QString &activity) const { if (m_activities->currentActivity() == activity) { return ~(uint)0; } else { KConfig config("kactivitymanagerd-switcher", KConfig::SimpleConfig); KConfigGroup times(&config, "LastUsed"); return times.readEntry(activity, (uint)0); } } bool SortedActivitiesModel::lessThan(const QModelIndex &sourceLeft, const QModelIndex &sourceRight) const { const auto activityLeft = sourceModel()->data(sourceLeft, KActivities::ActivitiesModel::ActivityId); const auto activityRight = sourceModel()->data(sourceRight, KActivities::ActivitiesModel::ActivityId); const auto timeLeft = lastUsedTime(activityLeft.toString()); const auto timeRight = lastUsedTime(activityRight.toString()); return (timeLeft < timeRight) || (timeLeft == timeRight && activityLeft < activityRight); } QHash SortedActivitiesModel::roleNames() const { if (!sourceModel()) return QHash(); auto roleNames = sourceModel()->roleNames(); roleNames[LastTimeUsed] = "lastTimeUsed"; roleNames[LastTimeUsedString] = "lastTimeUsedString"; roleNames[WindowCount] = "windowCount"; roleNames[HasWindows] = "hasWindows"; return roleNames; } QVariant SortedActivitiesModel::data(const QModelIndex &index, int role) const { if (role == KActivities::ActivitiesModel::ActivityBackground) { const auto activity = activityIdForIndex(index); return backgrounds().forActivity[activity]; } else if (role == LastTimeUsed || role == LastTimeUsedString) { const auto activity = activityIdForIndex(index); const auto time = lastUsedTime(activity); if (role == LastTimeUsed) { return QVariant(time); } else { const auto now = QDateTime::currentDateTime().toTime_t(); if (time == 0) return i18n("Used some time ago"); auto diff = now - time; // We do not need to be precise diff /= 60; const auto minutes = diff % 60; diff /= 60; const auto hours = diff % 24; diff /= 24; const auto days = diff % 30; diff /= 30; const auto months = diff % 12; diff /= 12; const auto years = diff; return (years > 0) ? i18n("Used more than a year ago") : (months > 0) ? i18ncp("amount in months", "Used a month ago", "Used %1 months ago", months) : (days > 0) ? i18ncp("amount in days", "Used a day ago", "Used %1 days ago", days) : (hours > 0) ? i18ncp("amount in hours", "Used an hour ago", "Used %1 hours ago", hours) : (minutes > 0) ? i18ncp("amount in minutes", "Used a minute ago", "Used %1 minutes ago", minutes) : i18n("Used a moment ago"); } } else if (role == HasWindows || role == WindowCount) { const auto activity = activityIdForIndex(index); if (role == HasWindows) { return (m_activitiesWindows[activity].size() > 0); } else { return m_activitiesWindows[activity].size(); } } else { return QSortFilterProxyModel::data(index, role); } } QString SortedActivitiesModel::activityIdForIndex(const QModelIndex &index) const { return data(index, KActivities::ActivitiesModel::ActivityId).toString(); } QString SortedActivitiesModel::activityIdForRow(int row) const { return activityIdForIndex(index(row, 0)); } int SortedActivitiesModel::rowForActivityId(const QString &activity) const { int position = -1; for (int row = 0; row < rowCount(); ++row) { if (activity == activityIdForRow(row)) { position = row; } } return position; } QString SortedActivitiesModel::relativeActivity(int relative) const { const auto currentActivity = m_activities->currentActivity(); if (!sourceModel()) return QString(); const auto currentRowCount = sourceModel()->rowCount(); //x % 0 is undefined in c++ if (currentRowCount == 0) { return QString(); } int currentActivityRow = 0; for (; currentActivityRow < currentRowCount; currentActivityRow++) { if (activityIdForRow(currentActivityRow) == currentActivity) break; } currentActivityRow = currentActivityRow + relative; //wrap to within bounds for both positive and negative currentActivityRows currentActivityRow = (currentRowCount + (currentActivityRow % currentRowCount)) % currentRowCount; return activityIdForRow(currentActivityRow); } void SortedActivitiesModel::onCurrentActivityChanged(const QString ¤tActivity) { if (m_previousActivity == currentActivity) return; const int previousActivityRow = rowForActivityId(m_previousActivity); emit rowChanged(previousActivityRow, { LastTimeUsed, LastTimeUsedString }); m_previousActivity = currentActivity; const int currentActivityRow = rowForActivityId(m_previousActivity); emit rowChanged(currentActivityRow, { LastTimeUsed, LastTimeUsedString }); } void SortedActivitiesModel::onBackgroundsUpdated(const QStringList &activities) { for (const auto &activity: activities) { const int row = rowForActivityId(activity); emit rowChanged(row, { KActivities::ActivitiesModel::ActivityBackground }); } } void SortedActivitiesModel::onWindowAdded(WId window) { - KWindowInfo info(window, nullptr, NET::WM2Activities); + KWindowInfo info(window, NET::Properties(), NET::WM2Activities); const QStringList activities = info.activities(); if (activities.isEmpty() || activities.contains("00000000-0000-0000-0000-000000000000")) return; for (const auto& activity: activities) { if (!m_activitiesWindows[activity].contains(window)) { m_activitiesWindows[activity] << window; rowChanged(rowForActivityId(activity), m_activitiesWindows.size() == 1 ? QVector{WindowCount, HasWindows} : QVector{WindowCount}); } } } void SortedActivitiesModel::onWindowRemoved(WId window) { for (const auto& activity: m_activitiesWindows.keys()) { if (m_activitiesWindows[activity].contains(window)) { m_activitiesWindows[activity].removeAll(window); rowChanged(rowForActivityId(activity), m_activitiesWindows.size() == 0 ? QVector{WindowCount, HasWindows} : QVector{WindowCount}); } } } void SortedActivitiesModel::onWindowChanged(WId window, NET::Properties properties, NET::Properties2 properties2) { Q_UNUSED(properties); if (properties2 & NET::WM2Activities) { onWindowRemoved(window); onWindowAdded(window); } } void SortedActivitiesModel::rowChanged(int row, const QVector &roles) { if (row == -1) return; emit dataChanged(index(row, 0), index(row, 0), roles); } diff --git a/kcms/baloo/folderselectionwidget.h b/kcms/baloo/folderselectionwidget.h index 3095e0638..fac5b676f 100644 --- a/kcms/baloo/folderselectionwidget.h +++ b/kcms/baloo/folderselectionwidget.h @@ -1,90 +1,90 @@ /* * This file is part of the KDE Baloo project * Copyright (C) 2014 Vishesh Handa * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * */ #ifndef FOLDERSELECTIONWIDGET_H #define FOLDERSELECTIONWIDGET_H #include #include #include #include class FolderSelectionWidget : public QWidget { Q_OBJECT public: - explicit FolderSelectionWidget(QWidget* parent = nullptr, Qt::WindowFlags f = nullptr); + explicit FolderSelectionWidget(QWidget* parent = nullptr, Qt::WindowFlags f = Qt::WindowFlags()); void setDirectoryList(QStringList includeDirs, QStringList exclude); QStringList includeFolders() const; QStringList excludeFolders() const; enum Roles { UrlRole = Qt::UserRole + 1 }; Q_SIGNALS: void changed(); private Q_SLOTS: void slotAddButtonClicked(); void slotRemoveButtonClicked(); void slotCurrentItemChanged(QListWidgetItem* current, QListWidgetItem*); private: QString folderDisplayName(const QString& url) const; bool shouldShowMountPoint(const QString& mountPoint); QString fetchMountPoint(const QString& url) const; void showMessage(const QString& message); /** * @brief Get the theme valid icon name for \p path. * * @param path Path to be analysed. * @return One of: "user-home", "drive-harddisk" or "folder" */ QString iconName(QString path) const; /** * @brief Widget with the list of directories. * */ QListWidget* m_listWidget; QStringList m_mountPoints; /** * @brief Button to add a directory to the list. * */ QPushButton* m_addButton; /** * @brief Button to remove the selected directory from the list. * */ QPushButton* m_removeButton; /** * @brief Information, warning or error message widget. * */ KMessageWidget* m_messageWidget; }; #endif // FOLDERSELECTIONWIDGET_H diff --git a/kcms/fonts/fonts.cpp b/kcms/fonts/fonts.cpp index 3ce9cdac0..3e47b5ef1 100644 --- a/kcms/fonts/fonts.cpp +++ b/kcms/fonts/fonts.cpp @@ -1,711 +1,711 @@ /* Copyright 1997 Mark Donohoe Copyright 1999 Lars Knoll Copyright 2000 Rik Hemsley Copyright 2015 Antonis Tsiapaliokas Copyright 2017 Marco Martin Ported to kcontrol2 by Geert Jansen. This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "fonts.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "../krdb/krdb.h" #include "previewimageprovider.h" /**** DLL Interface ****/ K_PLUGIN_FACTORY_WITH_JSON(KFontsFactory, "kcm_fonts.json", registerPlugin();) //from KFontRequester // Determine if the font with given properties is available on the system, // otherwise find and return the best fitting combination. static QFont nearestExistingFont(const QFont &font) { QFontDatabase dbase; // Initialize font data according to given font object. QString family = font.family(); QString style = dbase.styleString(font); qreal size = font.pointSizeF(); // Check if the family exists. const QStringList families = dbase.families(); if (!families.contains(family)) { // Chose another family. family = QFontInfo(font).family(); // the nearest match if (!families.contains(family)) { family = families.count() ? families.at(0) : QStringLiteral("fixed"); } } // Check if the family has the requested style. // Easiest by piping it through font selection in the database. QString retStyle = dbase.styleString(dbase.font(family, style, 10)); style = retStyle; // Check if the family has the requested size. // Only for bitmap fonts. if (!dbase.isSmoothlyScalable(family, style)) { QList sizes = dbase.smoothSizes(family, style); if (!sizes.contains(size)) { // Find nearest available size. int mindiff = 1000; int refsize = size; Q_FOREACH (int lsize, sizes) { int diff = qAbs(refsize - lsize); if (mindiff > diff) { mindiff = diff; size = lsize; } } } } // Select the font with confirmed properties. QFont result = dbase.font(family, style, int(size)); if (dbase.isSmoothlyScalable(family, style) && result.pointSize() == floor(size)) { result.setPointSizeF(size); } return result; } /**** FontAASettings ****/ #if defined(HAVE_FONTCONFIG) && defined (HAVE_X11) FontAASettings::FontAASettings(QObject *parent) : QObject(parent) , m_subPixelOptionsModel(new QStandardItemModel(this)) , m_hintingOptionsModel(new QStandardItemModel(this)) { for (int t = KXftConfig::SubPixel::NotSet; t <= KXftConfig::SubPixel::Vbgr; ++t) { QStandardItem *item = new QStandardItem(KXftConfig::description((KXftConfig::SubPixel::Type)t)); m_subPixelOptionsModel->appendRow(item); } for (int s = KXftConfig::Hint::NotSet; s <= KXftConfig::Hint::Full; ++s) { QStandardItem * item = new QStandardItem(KXftConfig::description((KXftConfig::Hint::Style)s)); m_hintingOptionsModel->appendRow(item); } } void FontAASettings::load() { double from, to; KXftConfig xft; if (xft.getExcludeRange(from, to)) { m_excludeFrom = from; m_excludeTo = to; setExclude(true); } else { m_excludeFrom = 8; m_excludeTo = 15; setExclude(false); } m_excludeFromOriginal = m_excludeFrom; m_excludeToOriginal = m_excludeTo; excludeToChanged(); excludeFromChanged(); KXftConfig::SubPixel::Type spType; xft.getSubPixelType(spType); setSubPixelCurrentIndex(spType); m_subPixelCurrentIndexOriginal = spType; KXftConfig::Hint::Style hStyle; if (!xft.getHintStyle(hStyle) || KXftConfig::Hint::NotSet == hStyle) { KConfig kglobals("kdeglobals", KConfig::NoGlobals); hStyle = KXftConfig::Hint::NotSet; xft.setHintStyle(hStyle); KConfigGroup(&kglobals, "General").writeEntry("XftHintStyle", KXftConfig::toStr(hStyle)); kglobals.sync(); runRdb(KRdbExportXftSettings | KRdbExportGtkTheme); } setHintingCurrentIndex(hStyle); m_hintingCurrentIndexOriginal = hStyle; KConfig _cfgfonts("kcmfonts"); KConfigGroup cfgfonts(&_cfgfonts, "General"); int dpicfg; if (KWindowSystem::isPlatformWayland()) { dpicfg = cfgfonts.readEntry("forceFontDPIWayland", 0); } else { dpicfg = cfgfonts.readEntry("forceFontDPI", 0); } if (dpicfg <= 0) { m_dpiOriginal = 0; } else { m_dpiOriginal = dpicfg; }; setDpi(dpicfg); KSharedConfig::Ptr config = KSharedConfig::openConfig("kdeglobals"); KConfigGroup cg(config, "General"); if (cfgfonts.readEntry("dontChangeAASettings", true)) { setAntiAliasing(1); //AASystem } else if (cg.readEntry("XftAntialias", true)) { setAntiAliasing(0); //AAEnabled } else { setAntiAliasing(2); //AADisabled } m_antiAliasingOriginal = m_antiAliasing; } bool FontAASettings::save(KXftConfig::AntiAliasing::State aaState) { KXftConfig xft; KConfig kglobals("kdeglobals", KConfig::NoGlobals); KConfigGroup grp(&kglobals, "General"); xft.setAntiAliasing(aaState); if (m_exclude) { xft.setExcludeRange(m_excludeFrom, m_excludeTo); } else { xft.setExcludeRange(0, 0); } KXftConfig::SubPixel::Type spType = (KXftConfig::SubPixel::Type)m_subPixelCurrentIndex; xft.setSubPixelType(spType); grp.writeEntry("XftSubPixel", KXftConfig::toStr(spType)); if (aaState == KXftConfig::AntiAliasing::NotSet) { grp.revertToDefault("XftAntialias"); } else { grp.writeEntry("XftAntialias", aaState == KXftConfig::AntiAliasing::Enabled); } bool mod = false; KXftConfig::Hint::Style hStyle = (KXftConfig::Hint::Style)m_hintingCurrentIndex; xft.setHintStyle(hStyle); QString hs(KXftConfig::toStr(hStyle)); if (hs != grp.readEntry("XftHintStyle")) { if (KXftConfig::Hint::NotSet == hStyle) { grp.revertToDefault("XftHintStyle"); } else { grp.writeEntry("XftHintStyle", hs); } } mod = true; kglobals.sync(); if (!mod) { mod = xft.changed(); } xft.apply(); KConfig _cfgfonts("kcmfonts"); KConfigGroup cfgfonts(&_cfgfonts, "General"); if (KWindowSystem::isPlatformWayland()) { cfgfonts.writeEntry("forceFontDPIWayland", m_dpi); } else { cfgfonts.writeEntry("forceFontDPI", m_dpi); } cfgfonts.sync(); #if HAVE_X11 // if the setting is reset in the module, remove the dpi value, // otherwise don't explicitly remove it and leave any possible system-wide value if (m_dpi == 0 && m_dpiOriginal != 0 && !KWindowSystem::isPlatformWayland()) { QProcess proc; proc.setProcessChannelMode(QProcess::ForwardedChannels); proc.start("xrdb", QStringList() << "-quiet" << "-remove" << "-nocpp"); if (proc.waitForStarted()) { proc.write(QByteArray("Xft.dpi\n")); proc.closeWriteChannel(); proc.waitForFinished(); } } #endif QApplication::processEvents(); // Process font change ourselves // Don't overwrite global settings unless explicitly asked for - e.g. the system // fontconfig setup may be much more complex than this module can provide. // TODO: With AASystem the changes already made by this module should be reverted somehow. #if defined(HAVE_FONTCONFIG) && defined (HAVE_X11) if (mod || (m_antiAliasing != m_antiAliasingOriginal) || m_dpi != m_dpiOriginal) { KMessageBox::information(nullptr, i18n( "

Some changes such as anti-aliasing or DPI will only affect newly started applications.

" ), i18n("Font Settings Changed"), "FontSettingsChanged"); m_antiAliasingOriginal = m_antiAliasing; m_dpiOriginal = m_dpi; } #else #if HAVE_X11 if (m_dpi != m_dpiOriginal) { KMessageBox::information(0, i18n( "

Some changes such as DPI will only affect newly started applications.

" ), i18n("Font Settings Changed"), "FontSettingsChanged"); m_dpiOriginal = m_dpi; } #endif #endif m_excludeToOriginal = m_excludeTo; m_excludeFromOriginal = m_excludeFrom; m_subPixelCurrentIndexOriginal = m_subPixelCurrentIndex; m_hintingCurrentIndexOriginal = m_hintingCurrentIndex; return mod; } void FontAASettings::defaults() { setExcludeTo(15); setExcludeFrom(8); setAntiAliasing(1); m_antiAliasingOriginal = m_antiAliasing; setDpi(0); setSubPixelCurrentIndex(KXftConfig::SubPixel::NotSet); setHintingCurrentIndex(KXftConfig::Hint::NotSet); } #endif void FontAASettings::setExclude(bool exclude) { if (exclude == m_exclude) { return; } m_exclude = exclude; emit excludeChanged(); } bool FontAASettings::exclude() const { return m_exclude; } void FontAASettings::setExcludeTo(const int &excludeTo) { if (m_excludeTo == excludeTo) { return; } m_excludeTo = excludeTo; emit excludeToChanged(); } int FontAASettings::excludeTo() const { return m_excludeTo; } void FontAASettings::setExcludeFrom(const int &excludeTo) { if (m_excludeFrom == excludeTo) { return; } m_excludeFrom = excludeTo; emit excludeToChanged(); } int FontAASettings::excludeFrom() const { return m_excludeFrom; } void FontAASettings::setAntiAliasing(const int &antiAliasing) { if (m_antiAliasing == antiAliasing) { return; } m_antiAliasing = antiAliasing; emit aliasingChanged(); } int FontAASettings::antiAliasing() const { return m_antiAliasing; } void FontAASettings::setDpi(const int &dpi) { if (m_dpi == dpi) { return; } m_dpi = dpi; emit dpiChanged(); } int FontAASettings::dpi() const { return m_dpi; } void FontAASettings::setSubPixelCurrentIndex(int idx) { if (m_subPixelCurrentIndex == idx) { return; } m_subPixelCurrentIndex = idx; emit subPixelCurrentIndexChanged(); } int FontAASettings::subPixelCurrentIndex() { return m_subPixelCurrentIndex; } void FontAASettings::setHintingCurrentIndex(int idx) { if (m_hintingCurrentIndex == idx) { return; } m_hintingCurrentIndex = idx; emit hintingCurrentIndexChanged(); } int FontAASettings::hintingCurrentIndex() { return m_hintingCurrentIndex; } bool FontAASettings::needsSave() const { return m_excludeTo != m_excludeToOriginal || m_excludeFrom != m_excludeFromOriginal || m_antiAliasing != m_antiAliasingOriginal || m_dpi != m_dpiOriginal || m_subPixelCurrentIndex != m_subPixelCurrentIndexOriginal || m_hintingCurrentIndex != m_hintingCurrentIndexOriginal; } /**** KFonts ****/ KFonts::KFonts(QObject *parent, const QVariantList &args) : KQuickAddons::ConfigModule(parent, args) , m_fontAASettings(new FontAASettings(this)) { qApp->setAttribute(Qt::AA_DontCreateNativeWidgetSiblings); KAboutData* about = new KAboutData("kcm_fonts", i18n("Configure Fonts"), "0.1", QString(), KAboutLicense::LGPL); about->addAuthor(i18n("Antonis Tsiapaliokas"), QString(), "antonis.tsiapaliokas@kde.org"); setAboutData(about); qmlRegisterType(); setButtons(Apply | Default); auto updateState = [this]() { setNeedsSave(m_fontAASettings->needsSave()); }; connect(m_fontAASettings, &FontAASettings::subPixelCurrentIndexChanged, this, updateState); connect(m_fontAASettings, &FontAASettings::hintingCurrentIndexChanged, this, updateState); connect(m_fontAASettings, &FontAASettings::excludeToChanged, this, updateState); connect(m_fontAASettings, &FontAASettings::antiAliasingChanged, this, updateState); connect(m_fontAASettings, &FontAASettings::aliasingChanged, this, updateState); connect(m_fontAASettings, &FontAASettings::dpiChanged, this, updateState); } KFonts::~KFonts() { } void KFonts::defaults() { #ifdef Q_OS_MAC setGeneralFont(QFont("Lucida Grande", 13)); setMenuFont(QFont("Lucida Grande", 13)); setFixedWidthFont(QFont("Monaco", 10)); setToolbarFont(QFont("Lucida Grande", 11)); setSmallFont(QFont("Lucida Grande", 9)); setWindowTitleFont(QFont("Lucida Grande", 14)); #else setGeneralFont(QFont("Noto Sans", 10)); setMenuFont(QFont("Noto Sans", 10)); setFixedWidthFont(QFont("Hack", 9)); setToolbarFont(QFont("Noto Sans", 10)); setSmallFont(QFont("Noto Sans", 8)); setWindowTitleFont(QFont("Noto Sans", 10)); #endif m_fontAASettings->defaults(); } void KFonts::load() { KSharedConfig::Ptr config = KSharedConfig::openConfig("kdeglobals"); KConfigGroup cg(config, "General"); m_generalFont = m_generalFontOriginal = nearestExistingFont(cg.readEntry("font", m_defaultFont)); m_fixedWidthFont = m_fixedWidthFontOriginal = nearestExistingFont(cg.readEntry("fixed", QFont("Hack", 9))); m_smallFont = m_smallFontOriginal = nearestExistingFont(cg.readEntry("smallestReadableFont", m_defaultFont)); m_toolbarFont = m_toolbarFontOriginal = nearestExistingFont(cg.readEntry("toolBarFont", m_defaultFont)); m_menuFont = m_menuFontOriginal = nearestExistingFont(cg.readEntry("menuFont", m_defaultFont)); cg = KConfigGroup(config, "WM"); m_windowTitleFont = m_windowTitleFontOriginal = nearestExistingFont(cg.readEntry("activeFont", m_defaultFont)); engine()->addImageProvider("preview", new PreviewImageProvider(generalFont())); emit generalFontChanged(); emit fixedWidthFontChanged(); emit smallFontChanged(); emit toolbarFontChanged(); emit menuFontChanged(); emit windowTitleFontChanged(); m_fontAASettings->load(); setNeedsSave(false); } void KFonts::save() { KSharedConfig::Ptr config = KSharedConfig::openConfig("kdeglobals"); KConfigGroup cg(config, "General"); cg.writeEntry("font", m_generalFont.toString()); cg.writeEntry("fixed", m_fixedWidthFont.toString()); cg.writeEntry("smallestReadableFont", m_smallFont.toString()); cg.writeEntry("toolBarFont", m_toolbarFont.toString()); cg.writeEntry("menuFont", m_menuFont.toString()); cg.sync(); cg = KConfigGroup(config, "WM"); cg.writeEntry("activeFont", m_windowTitleFont.toString()); cg.sync(); m_defaultFontOriginal = m_defaultFont; m_generalFontOriginal = m_generalFont; m_fixedWidthFontOriginal = m_fixedWidthFont; m_smallFontOriginal = m_smallFont; m_toolbarFontOriginal = m_toolbarFont; m_menuFontOriginal = m_menuFont; m_windowTitleFontOriginal = m_windowTitleFont; KConfig _cfgfonts("kcmfonts"); KConfigGroup cfgfonts(&_cfgfonts, "General"); FontAASettings::AASetting aaSetting = (FontAASettings::AASetting)m_fontAASettings->antiAliasing(); cfgfonts.writeEntry("dontChangeAASettings", aaSetting == FontAASettings::AASystem); if (aaSetting == FontAASettings::AAEnabled) { m_fontAASettings->save(KXftConfig::AntiAliasing::Enabled); } else if (aaSetting == FontAASettings::AADisabled) { m_fontAASettings->save(KXftConfig::AntiAliasing::Disabled); } else { m_fontAASettings->save(KXftConfig::AntiAliasing::NotSet); } KGlobalSettings::self()->emitChange(KGlobalSettings::FontChanged); runRdb(KRdbExportXftSettings | KRdbExportGtkTheme); emit fontsHaveChanged(); setNeedsSave(false); } void KFonts::updateNeedsSave() { setNeedsSave(m_defaultFontOriginal != m_defaultFont || m_generalFontOriginal != m_generalFont || m_fixedWidthFontOriginal != m_fixedWidthFont || m_smallFontOriginal != m_smallFont || m_toolbarFontOriginal != m_toolbarFont || m_menuFontOriginal != m_menuFont || m_windowTitleFontOriginal != m_windowTitleFont || m_fontAASettings->needsSave()); } void KFonts::setGeneralFont(const QFont &font) { if (m_generalFont == font) { return; } m_generalFont = font; emit generalFontChanged(); updateNeedsSave(); } QFont KFonts::generalFont() const { return m_generalFont; } void KFonts::setFixedWidthFont(const QFont &font) { if (m_fixedWidthFont == font) { return; } m_fixedWidthFont = font; emit fixedWidthFontChanged(); updateNeedsSave(); } QFont KFonts::fixedWidthFont() const { return m_fixedWidthFont; } void KFonts::setSmallFont(const QFont &font) { if (m_smallFont == font) { return; } m_smallFont = font; emit smallFontChanged(); updateNeedsSave(); } QFont KFonts::smallFont() const { return m_smallFont; } void KFonts::setToolbarFont(const QFont &font) { if (m_toolbarFont == font) { return; } m_toolbarFont = font; emit toolbarFontChanged(); updateNeedsSave(); } QFont KFonts::toolbarFont() const { return m_toolbarFont; } void KFonts::setMenuFont(const QFont &font) { if (m_menuFont == font) { return; } m_menuFont = font; emit menuFontChanged(); updateNeedsSave(); } QFont KFonts::menuFont() const { return m_menuFont; } void KFonts::setWindowTitleFont(const QFont &font) { if (m_windowTitleFont == font) { return; } m_windowTitleFont = font; emit windowTitleFontChanged(); updateNeedsSave(); } QFont KFonts::windowTitleFont() const { return m_windowTitleFont; } void KFonts::adjustAllFonts() { QFont font = m_generalFont; - KFontChooser::FontDiffFlags fontDiffFlags = nullptr; + KFontChooser::FontDiffFlags fontDiffFlags; int ret = KFontDialog::getFontDiff(font, fontDiffFlags, KFontChooser::NoDisplayFlags); if (ret == KDialog::Accepted && fontDiffFlags) { setGeneralFont(applyFontDiff(m_generalFont, font, fontDiffFlags)); setMenuFont(applyFontDiff(m_menuFont, font, fontDiffFlags)); { const QFont adjustedFont = applyFontDiff(m_fixedWidthFont, font, fontDiffFlags); if (QFontInfo(adjustedFont).fixedPitch()) { setFixedWidthFont(adjustedFont); } } setToolbarFont(applyFontDiff(m_toolbarFont, font, fontDiffFlags)); setSmallFont(applyFontDiff(m_smallFont, font, fontDiffFlags)); setWindowTitleFont(applyFontDiff(m_windowTitleFont, font, fontDiffFlags)); } } QFont KFonts::applyFontDiff(const QFont &fnt, const QFont &newFont, int fontDiffFlags) { QFont font(fnt); if (fontDiffFlags & KFontChooser::FontDiffSize) { font.setPointSizeF(newFont.pointSizeF()); } if ((fontDiffFlags & KFontChooser::FontDiffFamily)) { font.setFamily(newFont.family()); } if (fontDiffFlags & KFontChooser::FontDiffStyle) { font.setWeight(newFont.weight()); font.setStyle(newFont.style()); font.setUnderline(newFont.underline()); font.setStyleName(newFont.styleName()); } return font; } #include "fonts.moc" diff --git a/kcms/keyboard/kcm_view_models.cpp b/kcms/keyboard/kcm_view_models.cpp index f85039ece..931a3ede2 100644 --- a/kcms/keyboard/kcm_view_models.cpp +++ b/kcms/keyboard/kcm_view_models.cpp @@ -1,521 +1,521 @@ /* * Copyright (C) 2010 Andriy Rysin (rysin@kde.org) * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "kcm_view_models.h" #include #include #include #include #include #include #include #ifdef DRAG_ENABLED #include #endif #include "keyboard_config.h" #include "xkb_rules.h" #include "flags.h" #include "x11_helper.h" #include "bindings.h" const int LayoutsTableModel::MAP_COLUMN = 0; const int LayoutsTableModel::LAYOUT_COLUMN = 1; const int LayoutsTableModel::VARIANT_COLUMN = 2; const int LayoutsTableModel::DISPLAY_NAME_COLUMN = 3; const int LayoutsTableModel::SHORTCUT_COLUMN = 4; static const int COLUMN_COUNT = 5; LayoutsTableModel::LayoutsTableModel(Rules* rules_, Flags *flags_, KeyboardConfig* keyboardConfig_, QObject* parent): QAbstractTableModel(parent), keyboardConfig(keyboardConfig_), rules(rules_), countryFlags(flags_) { } void LayoutsTableModel::refresh() { beginResetModel(); endResetModel(); countryFlags->clearCache(); } int LayoutsTableModel::rowCount(const QModelIndex &/*parent*/) const { return keyboardConfig->layouts.count(); } int LayoutsTableModel::columnCount(const QModelIndex&) const { return COLUMN_COUNT; } Qt::ItemFlags LayoutsTableModel::flags(const QModelIndex &index) const { if (!index.isValid()) - return nullptr; + return Qt::ItemFlags(); Qt::ItemFlags flags = QAbstractTableModel::flags(index); if( index.column() == DISPLAY_NAME_COLUMN || index.column() == VARIANT_COLUMN || index.column() == SHORTCUT_COLUMN ) { flags |= Qt::ItemIsEditable; } #ifdef DRAG_ENABLED flags |= Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled; #endif return flags; } #ifdef DRAG_ENABLED QStringList LayoutsTableModel::mimeTypes() const { QStringList types; types << "application/keyboard-layout-item"; return types; } QMimeData *LayoutsTableModel::mimeData(const QModelIndexList &indexes) const { QMimeData *mimeData = new QMimeData(); QByteArray encodedData; QDataStream stream(&encodedData, QIODevice::WriteOnly); QSet rows; foreach (const QModelIndex& index, indexes) { if (index.isValid()) { rows << index.row(); } } foreach (int row, rows) { stream << row; } mimeData->setData("application/keyboard-layout-item", encodedData); return mimeData; } #endif QVariant LayoutsTableModel::data(const QModelIndex &index, int role) const { if (!index.isValid()) return QVariant(); if (index.row() >= keyboardConfig->layouts.size()) return QVariant(); const LayoutUnit& layoutUnit = keyboardConfig->layouts.at(index.row()); if (role == Qt::DecorationRole) { switch( index.column() ) { case DISPLAY_NAME_COLUMN: { // if( keyboardConfig->isFlagShown() ) { QIcon icon = countryFlags->getIconWithText(layoutUnit, *keyboardConfig); return icon.isNull() ? countryFlags->getTransparentPixmap() : icon; // } } //TODO: show the cells are editable // case VARIANT_COLUMN: { // case DISPLAY_NAME_COLUMN: { // int sz = 5; // QPixmap pm = QPixmap(sz, sz+5); // pm.fill(Qt::transparent); // QPainter p(&pm); // QPoint points[] = { QPoint(0, 0), QPoint(0, sz), QPoint(sz, 0) }; // p.drawPolygon(points, 3); // return pm; // } break; } } else if( role == Qt::BackgroundRole ) { if( keyboardConfig->layoutLoopCount != KeyboardConfig::NO_LOOPING && index.row() >= keyboardConfig->layoutLoopCount ) { return QBrush(Qt::lightGray); } } else if (role == Qt::DisplayRole) { switch( index.column() ) { case MAP_COLUMN: return layoutUnit.layout; break; case LAYOUT_COLUMN: { const LayoutInfo* layoutInfo = rules->getLayoutInfo(layoutUnit.layout); return layoutInfo != nullptr ? layoutInfo->description : layoutUnit.layout; } case VARIANT_COLUMN: { if( layoutUnit.variant.isEmpty() ) return QVariant(); const LayoutInfo* layoutInfo = rules->getLayoutInfo(layoutUnit.layout); if( layoutInfo == nullptr ) return QVariant(); const VariantInfo* variantInfo = layoutInfo->getVariantInfo(layoutUnit.variant); return variantInfo != nullptr ? variantInfo->description : layoutUnit.variant; } break; case DISPLAY_NAME_COLUMN: // if( keyboardConfig->indicatorType == KeyboardConfig::SHOW_LABEL ) { // return layoutUnit.getDisplayName(); // } break; case SHORTCUT_COLUMN: { return layoutUnit.getShortcut().toString(); } break; } } else if (role==Qt::EditRole ) { switch( index.column() ) { case DISPLAY_NAME_COLUMN: return layoutUnit.getDisplayName(); break; case VARIANT_COLUMN: return layoutUnit.variant; break; case SHORTCUT_COLUMN: return layoutUnit.getShortcut().toString(); break; default:; } } else if( role == Qt::TextAlignmentRole ) { switch( index.column() ) { case MAP_COLUMN: case DISPLAY_NAME_COLUMN: case SHORTCUT_COLUMN: return Qt::AlignCenter; break; default:; } } return QVariant(); } QVariant LayoutsTableModel::headerData(int section, Qt::Orientation orientation, int role) const { if (role != Qt::DisplayRole) return QVariant(); if (orientation == Qt::Horizontal) { const QString headers[] = {i18nc("layout map name", "Map"), i18n("Layout"), i18n("Variant"), i18n("Label"), i18n("Shortcut")}; return headers[section]; } return QVariant(); } bool LayoutsTableModel::setData(const QModelIndex &index, const QVariant &value, int role) { if (role != Qt::EditRole || (index.column() != DISPLAY_NAME_COLUMN && index.column() != VARIANT_COLUMN && index.column() != SHORTCUT_COLUMN) ) return false; if (index.row() >= keyboardConfig->layouts.size() || index.data(role) == value) return false; LayoutUnit& layoutUnit = keyboardConfig->layouts[index.row()]; switch( index.column() ) { case DISPLAY_NAME_COLUMN: { QString displayText = value.toString().left(3); layoutUnit.setDisplayName(displayText); countryFlags->clearCache(); // regenerate the label } break; case VARIANT_COLUMN: { QString variant = value.toString(); layoutUnit.variant = variant; } break; case SHORTCUT_COLUMN: { QString shortcut = value.toString(); layoutUnit.setShortcut(QKeySequence(shortcut)); } break; } emit dataChanged(index, index); return true; } // // LabelEditDelegate // LabelEditDelegate::LabelEditDelegate(const KeyboardConfig* keyboardConfig_, QObject *parent): QStyledItemDelegate(parent), keyboardConfig(keyboardConfig_) {} QWidget *LabelEditDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem & option , const QModelIndex & index ) const { if( keyboardConfig->indicatorType == KeyboardConfig::SHOW_FLAG ) return nullptr; QWidget* widget = QStyledItemDelegate::createEditor(parent, option, index); QLineEdit* lineEdit = static_cast(widget); if( lineEdit != nullptr ) { lineEdit->setMaxLength(LayoutUnit::MAX_LABEL_LENGTH); connect(lineEdit, &QLineEdit::textEdited, this, [this, lineEdit]() { Q_EMIT const_cast(this)->commitData(lineEdit); }); } return widget; } void LabelEditDelegate::updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &/* index */) const { editor->setGeometry(option.rect); } //void LabelEditDelegate::paint( QPainter * painter, const QStyleOptionViewItem & option, const QModelIndex & index ) const //{ // QStyleOptionViewItem option2(option); //// option2.decorationPosition = QStyleOptionViewItem::Right; // option2.decorationAlignment = Qt::AlignHCenter | Qt::AlignVCenter; // QStyledItemDelegate::paint(painter, option2, index); //} // // VariantComboDelegate // //TODO: reuse this function in kcm_add_layout_dialog.cpp static void populateComboWithVariants(QComboBox* combo, const QString& layout, const Rules* rules) { combo->clear(); const LayoutInfo* layoutInfo = rules->getLayoutInfo(layout); foreach(const VariantInfo* variantInfo, layoutInfo->variantInfos) { combo->addItem(variantInfo->description, variantInfo->name); } combo->model()->sort(0); combo->insertItem(0, i18nc("variant", "Default"), ""); combo->setCurrentIndex(0); } VariantComboDelegate::VariantComboDelegate(const KeyboardConfig* keyboardConfig_, const Rules* rules_, QObject *parent): QStyledItemDelegate(parent), keyboardConfig(keyboardConfig_), rules(rules_) {} QWidget *VariantComboDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem &/* option */, const QModelIndex & index ) const { QComboBox *editor = new QComboBox(parent); const LayoutUnit& layoutUnit = keyboardConfig->layouts[index.row()]; populateComboWithVariants(editor, layoutUnit.layout, rules); connect(editor, &QComboBox::currentTextChanged, this, [this, editor]() { Q_EMIT const_cast(this)->commitData(editor); }); return editor; } void VariantComboDelegate::setEditorData(QWidget *editor, const QModelIndex &index) const { QComboBox *combo = static_cast(editor); QString variant = index.model()->data(index, Qt::EditRole).toString(); int itemIndex = combo->findData(variant); if( itemIndex == -1 ) { itemIndex = 0; } combo->setCurrentIndex(itemIndex); } void VariantComboDelegate::setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const { QComboBox *combo = static_cast(editor); QString variant = combo->itemData(combo->currentIndex()).toString(); model->setData(index, variant, Qt::EditRole); } void VariantComboDelegate::updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &/* index */) const { editor->setGeometry(option.rect); } // // KKeySequenceWidgetDelegate // KKeySequenceWidgetDelegate::KKeySequenceWidgetDelegate(const KeyboardConfig* keyboardConfig_, QObject *parent): QStyledItemDelegate(parent), keyboardConfig(keyboardConfig_) {} QWidget *KKeySequenceWidgetDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem & /*option*/, const QModelIndex & index ) const { itemsBeingEdited.insert(index); KKeySequenceWidget *editor = new KKeySequenceWidget(parent); editor->setFocusPolicy(Qt::StrongFocus); editor->setModifierlessAllowed(false); const LayoutUnit& layoutUnit = keyboardConfig->layouts[index.row()]; editor->setKeySequence(layoutUnit.getShortcut()); editor->captureKeySequence(); connect(editor, &KKeySequenceWidget::keySequenceChanged, this, [this, editor]() { Q_EMIT const_cast(this)->commitData(editor); }); return editor; } //void KKeySequenceWidgetDelegate::setEditorData(QWidget *editor, const QModelIndex &index) const //{ // KKeySequenceWidget *kkeysequencewidget = static_cast(editor); // QString shortcut = index.model()->data(index, Qt::EditRole).toString(); // kkeysequencewidget->setKeySequence(QKeySequence(shortcut)); // kkeysequencewidget->captureKeySequence(); // qDebug() << "set editor data"; //} void KKeySequenceWidgetDelegate::setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const { KKeySequenceWidget *kkeysequencewidget = static_cast(editor); QString shortcut = kkeysequencewidget->keySequence().toString(); model->setData(index, shortcut, Qt::EditRole); itemsBeingEdited.remove(index); } void KKeySequenceWidgetDelegate::paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const { if (itemsBeingEdited.contains(index)) { // StyledBackgroundPainter::drawBackground(painter,option,index); } else { QStyledItemDelegate::paint(painter,option,index); } } // // Xkb Options Tree View // int XkbOptionsTreeModel::rowCount(const QModelIndex& parent) const { if( ! parent.isValid() ) return rules->optionGroupInfos.count(); if( ! parent.parent().isValid() ) return rules->optionGroupInfos[parent.row()]->optionInfos.count(); return 0; } QVariant XkbOptionsTreeModel::data(const QModelIndex& index, int role) const { if (!index.isValid()) return QVariant(); int row = index.row(); if (role == Qt::DisplayRole) { if( ! index.parent().isValid() ) { return rules->optionGroupInfos[row]->description; } else { int groupRow = index.parent().row(); const OptionGroupInfo* xkbGroup = rules->optionGroupInfos[groupRow]; return xkbGroup->optionInfos[row]->description; } } else if (role==Qt::CheckStateRole ) { if( index.parent().isValid() ) { int groupRow = index.parent().row(); const OptionGroupInfo* xkbGroup = rules->optionGroupInfos[groupRow]; const QString& xkbOptionName = xkbGroup->optionInfos[row]->name; return keyboardConfig->xkbOptions.indexOf(xkbOptionName) == -1 ? Qt::Unchecked : Qt::Checked; } else { int groupRow = index.row(); const OptionGroupInfo* xkbGroup = rules->optionGroupInfos[groupRow]; foreach(const OptionInfo* optionInfo, xkbGroup->optionInfos) { if( keyboardConfig->xkbOptions.indexOf(optionInfo->name) != -1 ) return Qt::PartiallyChecked; } return Qt::Unchecked; } } return QVariant(); } bool XkbOptionsTreeModel::setData(const QModelIndex & index, const QVariant & value, int role) { int groupRow = index.parent().row(); if( groupRow < 0 ) return false; const OptionGroupInfo* xkbGroup = rules->optionGroupInfos[groupRow]; const OptionInfo* option = xkbGroup->optionInfos[index.row()]; if( value.toInt() == Qt::Checked ) { if( xkbGroup->exclusive ) { // clear if exclusive (TODO: radiobutton) int idx = keyboardConfig->xkbOptions.indexOf(QRegExp(xkbGroup->name + ".*")); if( idx >= 0 ) { for(int i=0; ioptionInfos.count(); i++) if( xkbGroup->optionInfos[i]->name == keyboardConfig->xkbOptions[idx] ) { setData(createIndex(i, index.column(), (quint32)index.internalId()-index.row()+i), Qt::Unchecked, role); break; } // m_kxkbConfig->m_options.removeAt(idx); // idx = m_kxkbConfig->m_options.indexOf(QRegExp(xkbGroupNm+".*")); } } if( keyboardConfig->xkbOptions.indexOf(option->name) < 0 ) { keyboardConfig->xkbOptions.append(option->name); } } else { keyboardConfig->xkbOptions.removeAll(option->name); } emit dataChanged(index, index); emit dataChanged(index.parent(), index.parent()); return true; } void XkbOptionsTreeModel::gotoGroup(const QString& groupName, QTreeView* view) { const OptionGroupInfo* optionGroupInfo = rules->getOptionGroupInfo(groupName); int index = rules->optionGroupInfos.indexOf((OptionGroupInfo*)optionGroupInfo); if( index != -1 ) { QModelIndex modelIdx = createIndex(index,0); // view->selectionModel()->setCurrentIndex(createIndex(index,0), QItemSelectionModel::NoUpdate); view->setExpanded(modelIdx, true); view->scrollTo(modelIdx, QAbstractItemView::PositionAtTop); view->selectionModel()->setCurrentIndex(modelIdx, QItemSelectionModel::Current); view->setFocus(Qt::OtherFocusReason); } // else { // qDebug() << "can't scroll to group" << group; // } } diff --git a/kcms/keyboard/kcm_view_models.h b/kcms/keyboard/kcm_view_models.h index 006541943..2da79f0cb 100644 --- a/kcms/keyboard/kcm_view_models.h +++ b/kcms/keyboard/kcm_view_models.h @@ -1,175 +1,175 @@ /* * Copyright (C) 2010 Andriy Rysin (rysin@kde.org) * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef KCM_VIEW_MODELS_H_ #define KCM_VIEW_MODELS_H_ #include #include #include #include class QTreeView; class KeyboardConfig; struct Rules; class Flags; class LayoutsTableModel : public QAbstractTableModel { Q_OBJECT public: LayoutsTableModel(Rules* rules, Flags *flags, KeyboardConfig* keyboardConfig, QObject *parent = nullptr); int columnCount(const QModelIndex&) const override; Qt::ItemFlags flags(const QModelIndex &index) const override; QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override; int rowCount(const QModelIndex &parent = QModelIndex()) const override; QVariant data(const QModelIndex &index, int role) const override; bool setData(const QModelIndex &index, const QVariant &value, int role) override; #ifdef DRAG_ENABLED Qt::DropActions supportedDropActions() const { return Qt::MoveAction; } QStringList mimeTypes() const; QMimeData *mimeData(const QModelIndexList &indexes) const; #endif void refresh(); static const int MAP_COLUMN; static const int LAYOUT_COLUMN; static const int VARIANT_COLUMN; static const int DISPLAY_NAME_COLUMN; static const int SHORTCUT_COLUMN; private: KeyboardConfig* keyboardConfig; const Rules *rules; Flags *countryFlags; }; class LabelEditDelegate : public QStyledItemDelegate { Q_OBJECT public: explicit LabelEditDelegate(const KeyboardConfig* keyboardConfig, QObject *parent = nullptr); QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const override; void updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &index) const override; // void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const; private: const KeyboardConfig* keyboardConfig; }; class VariantComboDelegate : public QStyledItemDelegate { Q_OBJECT public: VariantComboDelegate(const KeyboardConfig* keyboardConfig, const Rules* rules, QObject *parent = nullptr); QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const override; void setEditorData(QWidget *editor, const QModelIndex &index) const override; void setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const override; void updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &index) const override; private: const KeyboardConfig* keyboardConfig; const Rules* rules; }; class KKeySequenceWidgetDelegate : public QStyledItemDelegate { Q_OBJECT public: KKeySequenceWidgetDelegate(const KeyboardConfig* keyboardConfig_, QObject *parent = nullptr); QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const override; // void setEditorData(QWidget *editor, const QModelIndex &index) const; void setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const override; void paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const override; private: const KeyboardConfig* keyboardConfig; mutable QSet itemsBeingEdited; }; class XkbOptionsTreeModel: public QAbstractItemModel { public: XkbOptionsTreeModel(Rules* rules_, KeyboardConfig* keyboardConfig_, QObject *parent) : QAbstractItemModel(parent), keyboardConfig(keyboardConfig_), rules(rules_) { } int columnCount(const QModelIndex& /*parent*/) const override { return 1; } int rowCount(const QModelIndex& parent) const override; QModelIndex parent(const QModelIndex& index) const override { if (!index.isValid() ) return QModelIndex(); if( index.internalId() < 100 ) return QModelIndex(); return createIndex(((index.internalId() - index.row())/100) - 1, index.column()); } QModelIndex index(int row, int column, const QModelIndex& parent) const override { if(!parent.isValid()) return createIndex(row, column); return createIndex(row, column, (100 * (parent.row()+1)) + row); } Qt::ItemFlags flags ( const QModelIndex & index ) const override { if( ! index.isValid() ) - return nullptr; + return Qt::ItemFlags(); if( !index.parent().isValid() ) return Qt::ItemIsEnabled | Qt::ItemIsSelectable; return Qt::ItemIsEnabled | Qt::ItemIsUserCheckable | Qt::ItemIsSelectable; } bool setData ( const QModelIndex & index, const QVariant & value, int role = Qt::EditRole ) override; QVariant data(const QModelIndex& index, int role) const override; void reset() { beginResetModel(); endResetModel(); } void gotoGroup(const QString& group, QTreeView* view); private: KeyboardConfig* keyboardConfig; Rules *rules; }; #endif /* KCM_VIEW_MODELS_H_ */ diff --git a/kcms/solid_actions/PredicateModel.cpp b/kcms/solid_actions/PredicateModel.cpp index 151f71c05..f77b4d1c1 100644 --- a/kcms/solid_actions/PredicateModel.cpp +++ b/kcms/solid_actions/PredicateModel.cpp @@ -1,176 +1,176 @@ /************************************************************************** * Copyright (C) 2009 Ben Cooksley * * Copyright (C) 2007 Will Stephenson * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License * * as published by the Free Software Foundation; either version 2 * * of the License, or (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the Free Software * * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * * 02110-1301, USA. * ***************************************************************************/ #include "PredicateModel.h" #include "PredicateItem.h" class PredicateModel::Private { public: Private() {} PredicateItem * rootItem; }; PredicateModel::PredicateModel( PredicateItem * menuRoot, QObject *parent ) : QAbstractItemModel( parent ) , d( new Private() ) { d->rootItem = menuRoot; } PredicateModel::~PredicateModel() { delete d; } int PredicateModel::columnCount( const QModelIndex &parent ) const { Q_UNUSED( parent ); return 1; } int PredicateModel::rowCount( const QModelIndex &parent ) const { PredicateItem * mi; if ( parent.isValid() ) { mi = static_cast( parent.internalPointer() ); } else { mi = d->rootItem; } return mi->children().count(); } QVariant PredicateModel::data( const QModelIndex &index, int role ) const { PredicateItem * mi = nullptr; QVariant theData; if ( !index.isValid() ) { return QVariant(); } mi = static_cast( index.internalPointer() ); switch ( role ) { case Qt::DisplayRole: theData.setValue( mi->prettyName() ); break; case Qt::UserRole: theData.setValue( mi ); break; default: break; } return theData; } Qt::ItemFlags PredicateModel::flags( const QModelIndex &index ) const { if ( !index.isValid() ) { - return nullptr; + return Qt::ItemFlags(); } return Qt::ItemIsEnabled | Qt::ItemIsSelectable; } QModelIndex PredicateModel::index( int row, int column, const QModelIndex &parent ) const { if ( !hasIndex(row, column, parent) ) { return QModelIndex(); } PredicateItem *parentItem; if ( !parent.isValid() ) { parentItem = d->rootItem; } else { parentItem = static_cast( parent.internalPointer() ); } PredicateItem *childItem = parentItem->children().value(row); if ( childItem ) { return createIndex( row, column, childItem ); } else { return QModelIndex(); } } QModelIndex PredicateModel::parent( const QModelIndex &index ) const { PredicateItem *childItem = static_cast( index.internalPointer() ); if( !childItem ) { return QModelIndex(); } PredicateItem * parent = childItem->parent(); PredicateItem * grandParent = parent->parent(); int childRow = 0; if( grandParent ) { childRow = grandParent->children().indexOf( parent ); } if ( parent == d->rootItem ) { return QModelIndex(); } return createIndex( childRow, 0, parent ); } PredicateItem * PredicateModel::rootItem() const { return d->rootItem; } void PredicateModel::setRootPredicate( PredicateItem * item ) { beginResetModel(); d->rootItem = item; endResetModel(); } void PredicateModel::itemUpdated( const QModelIndex& item ) { emit dataChanged( item, item ); } void PredicateModel::childrenChanging( const QModelIndex& item, Solid::Predicate::Type oldType ) { PredicateItem * currentItem = static_cast( item.internalPointer() ); Solid::Predicate::Type newType = currentItem->itemType; if( oldType == newType ) { return; } if( rowCount(item) != 0 && newType != Solid::Predicate::Conjunction && newType != Solid::Predicate::Disjunction ) { emit beginRemoveRows( item, 0, 1 ); currentItem->updateChildrenStatus(); emit endRemoveRows(); return; } bool hasChildren = (newType == Solid::Predicate::Conjunction || newType == Solid::Predicate::Disjunction); if( rowCount(item) == 0 && hasChildren ) { emit beginInsertRows( item, 0, 1 ); currentItem->updateChildrenStatus(); emit endInsertRows(); } }