diff --git a/applets/kicker/plugin/runnermodel.cpp b/applets/kicker/plugin/runnermodel.cpp index a3c193a09..732d04764 100644 --- a/applets/kicker/plugin/runnermodel.cpp +++ b/applets/kicker/plugin/runnermodel.cpp @@ -1,330 +1,330 @@ /*************************************************************************** * Copyright (C) 2012 by Aurélien Gâteau * * Copyright (C) 2014 by 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 "runnermodel.h" #include "runnermatchesmodel.h" #include #include #include #include RunnerModel::RunnerModel(QObject *parent) : QAbstractListModel(parent) , m_favoritesModel(0) , m_appletInterface(nullptr) , m_runnerManager(0) , m_mergeResults(false) , m_deleteWhenEmpty(false) { - QHash roles; - roles.insert(Qt::DisplayRole, "display"); - - setRoleNames(roles); - m_queryTimer.setSingleShot(true); m_queryTimer.setInterval(10); connect(&m_queryTimer, SIGNAL(timeout()), this, SLOT(startQuery())); } RunnerModel::~RunnerModel() { } +QHash RunnerModel::roleNames() const +{ + return {{ Qt::DisplayRole, "display" }}; +} + AbstractModel *RunnerModel::favoritesModel() const { return m_favoritesModel; } void RunnerModel::setFavoritesModel(AbstractModel *model) { if (m_favoritesModel != model) { m_favoritesModel = model; clear(); if (!m_query.isEmpty()) { m_queryTimer.start(); } emit favoritesModelChanged(); } } QObject *RunnerModel::appletInterface() const { return m_appletInterface; } void RunnerModel::setAppletInterface(QObject *appletInterface) { if (m_appletInterface != appletInterface) { m_appletInterface = appletInterface; clear(); if (!m_query.isEmpty()) { m_queryTimer.start(); } emit appletInterfaceChanged(); } } bool RunnerModel::deleteWhenEmpty() const { return m_deleteWhenEmpty; } void RunnerModel::setDeleteWhenEmpty(bool deleteWhenEmpty) { if (m_deleteWhenEmpty != deleteWhenEmpty) { m_deleteWhenEmpty = deleteWhenEmpty; clear(); if (!m_query.isEmpty()) { m_queryTimer.start(); } emit deleteWhenEmptyChanged(); } } bool RunnerModel::mergeResults() const { return m_mergeResults; } void RunnerModel::setMergeResults(bool merge) { if (m_mergeResults != merge) { m_mergeResults = merge; clear(); if (!m_query.isEmpty()) { m_queryTimer.start(); } emit mergeResultsChanged(); } } QVariant RunnerModel::data(const QModelIndex &index, int role) const { if (!index.isValid() || index.row() >= m_models.count()) { return QVariant(); } if (role == Qt::DisplayRole) { return m_models.at(index.row())->name(); } return QVariant(); } int RunnerModel::rowCount(const QModelIndex &parent) const { return parent.isValid() ? 0 : m_models.count(); } int RunnerModel::count() const { return rowCount(); } QObject *RunnerModel::modelForRow(int row) { if (row < 0 || row >= m_models.count()) { return 0; } return m_models.at(row); } QStringList RunnerModel::runners() const { return m_runners; } void RunnerModel::setRunners(const QStringList &runners) { if (m_runners.toSet() != runners.toSet()) { m_runners = runners; if (m_runnerManager) { m_runnerManager->setAllowedRunners(runners); } emit runnersChanged(); } } QString RunnerModel::query() const { return m_query; } void RunnerModel::setQuery(const QString &query) { if (m_query != query) { m_query = query; m_queryTimer.start(); emit queryChanged(); } } void RunnerModel::startQuery() { if (m_query.isEmpty()) { clear(); } if (m_query.isEmpty() && m_runnerManager) { return; } createManager(); m_runnerManager->launchQuery(m_query); } void RunnerModel::matchesChanged(const QList &matches) { // Group matches by runner. // We do not use a QMultiHash here because it keeps values in LIFO order, while we want FIFO. QHash > matchesForRunner; foreach (const Plasma::QueryMatch &match, matches) { auto it = matchesForRunner.find(match.runner()->id()); if (it == matchesForRunner.end()) { it = matchesForRunner.insert(match.runner()->id(), QList()); } it.value().append(match); } if (m_mergeResults) { RunnerMatchesModel *matchesModel = nullptr; if (m_models.isEmpty()) { matchesModel = new RunnerMatchesModel(QString(), i18n("Search results"), m_runnerManager, this); beginInsertRows(QModelIndex(), 0, 0); m_models.append(matchesModel); endInsertRows(); emit countChanged(); } else { matchesModel = m_models.at(0); } QList matches; foreach (const QString &runnerId, m_runners) { matches.append(matchesForRunner.take(runnerId)); } matchesModel->setMatches(matches); return; } // Assign matches to existing models. If there is no match for a model, delete it. for (int row = m_models.count() - 1; row >= 0; --row) { RunnerMatchesModel *matchesModel = m_models.at(row); QList matches = matchesForRunner.take(matchesModel->runnerId()); if (m_deleteWhenEmpty && matches.isEmpty()) { beginRemoveRows(QModelIndex(), row, row); m_models.removeAt(row); delete matchesModel; endRemoveRows(); } else { matchesModel->setMatches(matches); } } // At this point, matchesForRunner contains only matches for runners which // do not have a model yet. Create new models for them. if (!matchesForRunner.isEmpty()) { auto it = matchesForRunner.constBegin(); auto end = matchesForRunner.constEnd(); int appendCount = 0; for (; it != end; ++it) { QList matches = it.value(); Q_ASSERT(!matches.isEmpty()); RunnerMatchesModel *matchesModel = new RunnerMatchesModel(it.key(), matches.first().runner()->name(), m_runnerManager, this); matchesModel->setMatches(matches); if (it.key() == "services") { beginInsertRows(QModelIndex(), 0, 0); m_models.prepend(matchesModel); endInsertRows(); emit countChanged(); } else { m_models.append(matchesModel); ++appendCount; } } if (appendCount > 0) { beginInsertRows(QModelIndex(), rowCount() - appendCount, rowCount() - 1); endInsertRows(); emit countChanged(); } } } void RunnerModel::createManager() { if (!m_runnerManager) { m_runnerManager = new Plasma::RunnerManager(this); // FIXME: Which KConfigGroup is this using now? m_runnerManager->setAllowedRunners(m_runners); connect(m_runnerManager, SIGNAL(matchesChanged(QList)), this, SLOT(matchesChanged(QList))); } } void RunnerModel::clear() { if (m_runnerManager) { m_runnerManager->reset(); } if (m_models.isEmpty()) { return; } beginResetModel(); qDeleteAll(m_models); m_models.clear(); endResetModel(); emit countChanged(); } diff --git a/applets/kicker/plugin/runnermodel.h b/applets/kicker/plugin/runnermodel.h index d447efc3c..5437a9839 100644 --- a/applets/kicker/plugin/runnermodel.h +++ b/applets/kicker/plugin/runnermodel.h @@ -1,107 +1,108 @@ /*************************************************************************** * Copyright (C) 2012 by Aurélien Gâteau * * Copyright (C) 2014 by 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 . * ***************************************************************************/ #ifndef RUNNERMODEL_H #define RUNNERMODEL_H #include "abstractmodel.h" #include #include #include namespace Plasma { class RunnerManager; } class AbstractModel; class RunnerMatchesModel; class RunnerModel : public QAbstractListModel { Q_OBJECT Q_PROPERTY(int count READ count NOTIFY countChanged) Q_PROPERTY(AbstractModel* favoritesModel READ favoritesModel WRITE setFavoritesModel NOTIFY favoritesModelChanged) Q_PROPERTY(QObject* appletInterface READ appletInterface WRITE setAppletInterface NOTIFY appletInterfaceChanged) Q_PROPERTY(QStringList runners READ runners WRITE setRunners NOTIFY runnersChanged); Q_PROPERTY(QString query READ query WRITE setQuery NOTIFY queryChanged); Q_PROPERTY(bool mergeResults READ mergeResults WRITE setMergeResults NOTIFY mergeResultsChanged) Q_PROPERTY(bool deleteWhenEmpty READ deleteWhenEmpty WRITE setDeleteWhenEmpty NOTIFY deleteWhenEmptyChanged) public: explicit RunnerModel(QObject *parent = 0); ~RunnerModel(); QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const; + QHash roleNames() const override; int rowCount(const QModelIndex &parent = QModelIndex()) const; int count() const; Q_INVOKABLE QObject *modelForRow(int row); QStringList runners() const; void setRunners(const QStringList &runners); QString query() const; void setQuery(const QString &query); AbstractModel *favoritesModel() const; void setFavoritesModel(AbstractModel *model); QObject *appletInterface() const; void setAppletInterface(QObject *appletInterface); bool mergeResults() const; void setMergeResults(bool merge); bool deleteWhenEmpty() const; void setDeleteWhenEmpty(bool deleteWhenEmpty); Q_SIGNALS: void countChanged() const; void favoritesModelChanged() const; void appletInterfaceChanged() const; void runnersChanged() const; void queryChanged() const; void mergeResultsChanged() const; void deleteWhenEmptyChanged(); private Q_SLOTS: void startQuery(); void matchesChanged(const QList &matches); private: void createManager(); void clear(); AbstractModel *m_favoritesModel; QObject *m_appletInterface; Plasma::RunnerManager *m_runnerManager; QStringList m_runners; QList m_models; QString m_query; QTimer m_queryTimer; bool m_mergeResults; bool m_deleteWhenEmpty; }; #endif diff --git a/applets/pager/plugin/model.cpp b/applets/pager/plugin/model.cpp index 1b80baa0e..595e3c65a 100644 --- a/applets/pager/plugin/model.cpp +++ b/applets/pager/plugin/model.cpp @@ -1,250 +1,247 @@ /* * Copyright 2012 Luís Gabriel Lima * * 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 . */ #include "model.h" RectangleModel::RectangleModel(QObject *parent) : QAbstractListModel(parent) { - setRoleNames(roles()); } -QHash RectangleModel::roles() const +QHash RectangleModel::roleNames() const { QHash rectRoles; rectRoles[WidthRole] = "width"; rectRoles[HeightRole] = "height"; rectRoles[XRole] = "x"; rectRoles[YRole] = "y"; return rectRoles; } void RectangleModel::clear() { m_rects.clear(); } void RectangleModel::append(const QRectF &rect) { m_rects.append(rect); } QRectF &RectangleModel::rectAt(int index) { return m_rects[index]; } int RectangleModel::rowCount(const QModelIndex &parent) const { Q_UNUSED(parent); return m_rects.count(); } QVariant RectangleModel::data(const QModelIndex &index, int role) const { if (index.row() < 0 || index.row() > m_rects.count()) return QVariant(); const QRectF &rect = m_rects[index.row()]; switch(role) { case WidthRole: return rect.width(); case HeightRole: return rect.height(); case XRole: return rect.x(); case YRole: return rect.y(); default: return QVariant(); } } WindowModel::WindowModel(QObject *parent) : RectangleModel(parent) { - setRoleNames(roles()); } -QHash WindowModel::roles() const +QHash WindowModel::roleNames() const { - QHash rectRoles = RectangleModel::roles(); + QHash rectRoles = RectangleModel::roleNames(); rectRoles[IdRole] = "windowId"; rectRoles[ActiveRole] = "active"; rectRoles[IconRole] = "icon"; rectRoles[VisibleNameRole] = "visibleName"; return rectRoles; } void WindowModel::clear() { beginResetModel(); RectangleModel::clear(); m_ids.clear(); m_active.clear(); m_icons.clear(); m_visibleNames.clear(); endResetModel(); } void WindowModel::append(WId windowId, const QRectF &rect, bool active, const QPixmap &icon, const QString &name) { beginInsertRows(QModelIndex(), rowCount(), rowCount()); m_ids.append(windowId); RectangleModel::append(rect); m_active.append(active); m_icons.append(icon); m_visibleNames.append(name); endInsertRows(); } WId WindowModel::idAt(int index) const { return m_ids[index]; } QString WindowModel::visibleNameAt(int index) const { return m_visibleNames[index]; } QVariant WindowModel::data(const QModelIndex &index, int role) const { if (index.row() < 0 || index.row() >= rowCount()) return QVariant(); if (role >= RectangleModel::WidthRole && role < IdRole) return RectangleModel::data(index, role); switch (role) { case IdRole: return int(m_ids[index.row()]); case ActiveRole: return m_active[index.row()]; case IconRole: return m_icons[index.row()]; case VisibleNameRole: return m_visibleNames[index.row()]; default: return QVariant(); } } PagerModel::PagerModel(QObject *parent) : QAbstractListModel(parent) { - setRoleNames(roles()); } WindowModel *PagerModel::windowsAt(int index) const { if (index < 0 || index >= m_windows.count()) return 0; return qobject_cast(m_windows[index]); } -QHash PagerModel::roles() const +QHash PagerModel::roleNames() const { - QHash rectRoles = m_desktops.roles(); + QHash rectRoles = m_desktops.roleNames(); rectRoles[WindowsRole] = "windows"; rectRoles[DesktopNameRole] = "desktopName"; return rectRoles; } void PagerModel::clearDesktopRects() { beginResetModel(); m_desktops.clear(); m_names.clear(); endResetModel(); } void PagerModel::appendDesktopRect(const QRectF &rect, const QString &name) { beginInsertRows(QModelIndex(), rowCount(), rowCount()); m_desktops.append(rect); m_names.append(name); endInsertRows(); } QRectF& PagerModel::desktopRectAt(int index) { return m_desktops.rectAt(index); } void PagerModel::clearWindowRects() { int removeIndex = -1; for (int i = 0; i < m_windows.count(); i++) { windowsAt(i)->clear(); if (i >= rowCount()) removeIndex = (removeIndex == -1) ? i : -1; } if (removeIndex != -1) { // remove the windows model if the number of desktop has decreased for (int i = m_windows.count()-1; i >= removeIndex; i--) { windowsAt(i)->deleteLater(); m_windows.removeAt(i); } } // append more windows model if the number of desktop has increased for (int i = m_windows.count(); i < rowCount(); i++) m_windows.append(new WindowModel(this)); } void PagerModel::appendWindowRect(int desktopId, WId windowId, const QRectF &rect, bool active, const QPixmap &icon, const QString &name) { WindowModel *windows = windowsAt(desktopId); if (!windows) return; windows->append(windowId, rect, active, icon, name); QModelIndex i = index(desktopId); emit dataChanged(i, i); } QVariant PagerModel::data(const QModelIndex &index, int role) const { if (role >= RectangleModel::WidthRole && role < WindowsRole) return m_desktops.data(index, role); if (index.row() < 0 || index.row() >= m_windows.count()) return QVariant(); switch (role) { case WindowsRole: return QVariant::fromValue(m_windows[index.row()]); case DesktopNameRole: return m_names[index.row()]; default: return QVariant(); } } int PagerModel::rowCount(const QModelIndex &index) const { return m_desktops.rowCount(index); } diff --git a/applets/pager/plugin/model.h b/applets/pager/plugin/model.h index 938224730..91dabc2e9 100644 --- a/applets/pager/plugin/model.h +++ b/applets/pager/plugin/model.h @@ -1,112 +1,112 @@ /* * Copyright 2012 Luís Gabriel Lima * * 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 . */ #ifndef MODEL_H #define MODEL_H #include #include #include // For WId #include class RectangleModel : public QAbstractListModel { Q_OBJECT public: enum RectangleRoles { WidthRole = Qt::UserRole + 1, HeightRole, XRole, YRole }; RectangleModel(QObject *parent = 0); - virtual QHash roles() const; + virtual QHash roleNames() const; virtual void clear(); void append(const QRectF &rect); QRectF &rectAt(int index); int rowCount(const QModelIndex &parent = QModelIndex()) const; virtual QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const; private: QList m_rects; }; class WindowModel : public RectangleModel { Q_OBJECT public: enum WindowRole { IdRole = RectangleModel::YRole + 1, ActiveRole, IconRole, VisibleNameRole }; WindowModel(QObject *parent = 0); - QHash roles() const; + QHash roleNames() const; void clear(); void append(WId, const QRectF &, bool active, const QPixmap &icon, const QString &name); WId idAt(int index) const; QString visibleNameAt(int index) const; QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const; private: QList m_ids; QList m_active; QList m_icons; QStringList m_visibleNames; }; class PagerModel : public QAbstractListModel { Q_OBJECT public: enum PagerRoles { WindowsRole = RectangleModel::YRole + 1, DesktopNameRole }; PagerModel(QObject *parent = 0); - QHash roles() const; + QHash roleNames() const; void clearDesktopRects(); void appendDesktopRect(const QRectF &rect, const QString &name); QRectF &desktopRectAt(int index); void clearWindowRects(); void appendWindowRect(int desktopId, WId, const QRectF &, bool active, const QPixmap &icon, const QString &name); WindowModel *windowsAt(int index) const; QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const; int rowCount(const QModelIndex &parent = QModelIndex()) const; private: RectangleModel m_desktops; QList m_windows; QStringList m_names; }; #endif // MODEL_H diff --git a/applets/trash/plugin/dirmodel.cpp b/applets/trash/plugin/dirmodel.cpp index cc36e1a29..19169669f 100644 --- a/applets/trash/plugin/dirmodel.cpp +++ b/applets/trash/plugin/dirmodel.cpp @@ -1,211 +1,214 @@ /* * Copyright 2012 by Marco Martin * This program 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, 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 Library General Public License for more details * * You should have received a copy of the GNU Library 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 "dirmodel.h" #include #include #include #include #include #include #include #include #include #include DirModel::DirModel(QObject *parent) : KDirModel(parent), m_screenshotSize(180, 120) { #if 0 // unused here in trash QMimeDatabase db; QList mimeList = db.allMimeTypes(); m_mimeTypes << "inode/directory"; foreach (const QMimeType &mime, mimeList) { if (mime.name().startsWith(QStringLiteral("image/"))) { m_mimeTypes << mime.name(); } } //TODO: configurable mime filter //dirLister()->setMimeFilter(m_mimeTypes); #endif - QHashroleNames; - roleNames[Qt::DisplayRole] = "display"; - roleNames[Qt::DecorationRole] = "decoration"; - roleNames[UrlRole] = "url"; - roleNames[MimeTypeRole] = "mimeType"; - roleNames[Thumbnail] = "thumbnail"; - setRoleNames(roleNames); - m_previewTimer = new QTimer(this); m_previewTimer->setSingleShot(true); connect(m_previewTimer, &QTimer::timeout, this, &DirModel::delayedPreview); //using the same cache of the engine, they index both by url m_imageCache = new KImageCache(QStringLiteral("org.kde.dirmodel-qml"), 10485760); connect(this, &QAbstractItemModel::rowsInserted, this, &DirModel::countChanged); connect(this, &QAbstractItemModel::rowsRemoved, this, &DirModel::countChanged); connect(this, &QAbstractItemModel::modelReset, this, &DirModel::countChanged); } DirModel::~DirModel() { delete m_imageCache; } +QHash DirModel::roleNames() const +{ + return { + { Qt::DisplayRole, "display" }, + { Qt::DecorationRole, "decoration" }, + { UrlRole, "url" }, + { MimeTypeRole, "mimeType" }, + { Thumbnail, "thumbnail" } + }; +} + QString DirModel::url() const { return dirLister()->url().toString(); } void DirModel::setUrl(const QString& url) { if (url.isEmpty()) { return; } if (dirLister()->url().path() == url) { dirLister()->updateDirectory(QUrl(url)); return; } beginResetModel(); dirLister()->openUrl(QUrl(url)); endResetModel(); emit urlChanged(); } int DirModel::indexForUrl(const QString &url) const { QModelIndex index = KDirModel::indexForUrl(QUrl(url)); return index.row(); } QVariantMap DirModel::get(int i) const { QModelIndex modelIndex = index(i, 0); KFileItem item = itemForIndex(modelIndex); QString url = item.url().toString(); QString mimeType = item.mimetype(); QVariantMap ret; ret.insert(QStringLiteral("url"), QVariant(url)); ret.insert(QStringLiteral("mimeType"), QVariant(mimeType)); return ret; } void DirModel::emptyTrash() { KIO::emptyTrash(); } QVariant DirModel::data(const QModelIndex &index, int role) const { if (!index.isValid()) { return QVariant(); } switch (role) { case UrlRole: { KFileItem item = itemForIndex(index); return item.url().toString(); } case MimeTypeRole: { KFileItem item = itemForIndex(index); return item.mimetype(); } case Thumbnail: { KFileItem item = itemForIndex(index); QImage preview = QImage(m_screenshotSize, QImage::Format_ARGB32_Premultiplied); if (m_imageCache->findImage(item.url().toString(), &preview)) { return preview; } m_previewTimer->start(100); const_cast(this)->m_filesToPreview[item.url()] = QPersistentModelIndex(index); } default: return KDirModel::data(index, role); } } void DirModel::delayedPreview() { QHash::const_iterator i = m_filesToPreview.constBegin(); KFileItemList list; while (i != m_filesToPreview.constEnd()) { QUrl file = i.key(); QPersistentModelIndex index = i.value(); if (!m_previewJobs.contains(file) && file.isValid()) { list.append(KFileItem(file, QString(), 0)); m_previewJobs.insert(file, QPersistentModelIndex(index)); } ++i; } if (list.size() > 0) { KIO::PreviewJob* job = KIO::filePreview(list, m_screenshotSize); job->setIgnoreMaximumSize(true); // qDebug() << "Created job" << job; connect(job, &KIO::PreviewJob::gotPreview, this, &DirModel::showPreview); connect(job, &KIO::PreviewJob::failed, this, &DirModel::previewFailed); } m_filesToPreview.clear(); } void DirModel::showPreview(const KFileItem &item, const QPixmap &preview) { QPersistentModelIndex index = m_previewJobs.value(item.url()); m_previewJobs.remove(item.url()); if (!index.isValid()) { return; } m_imageCache->insertImage(item.url().toString(), preview.toImage()); //qDebug() << "preview size:" << preview.size(); emit dataChanged(index, index); } void DirModel::previewFailed(const KFileItem &item) { m_previewJobs.remove(item.url()); } #include "moc_dirmodel.cpp" diff --git a/applets/trash/plugin/dirmodel.h b/applets/trash/plugin/dirmodel.h index 9e7ad1214..49683015d 100644 --- a/applets/trash/plugin/dirmodel.h +++ b/applets/trash/plugin/dirmodel.h @@ -1,96 +1,98 @@ /* * Copyright 2012 by Marco Martin * This program 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, 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 Library General Public License for more details * * You should have received a copy of the GNU Library 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 DIRMODEL_H #define DIRMODEL_H #include #include #include #include #include class QTimer; /** * This class provides a QML binding to KDirModel * Provides an easy way to navigate a filesystem from within QML * * @author Marco Martin */ class DirModel : public KDirModel { Q_OBJECT /** * @property string The url we want to browse. it may be an absolute path or a correct url of any protocol KIO supports */ Q_PROPERTY(QString url READ url WRITE setUrl NOTIFY urlChanged) /** * @property count Total number of rows */ Q_PROPERTY(int count READ count NOTIFY countChanged) public: enum Roles { UrlRole = Qt::UserRole + 1, MimeTypeRole = Qt::UserRole + 2, Thumbnail = Qt::UserRole + 3 }; DirModel(QObject* parent=0); virtual ~DirModel(); + QHash roleNames() const override; + void setUrl(const QString& url); QString url() const; QVariant data(const QModelIndex &index, int role) const; int count() const {return rowCount();} Q_INVOKABLE int indexForUrl(const QString &url) const; Q_INVOKABLE QVariantMap get(int index) const; /** * Helper method to empty the trash */ Q_INVOKABLE void emptyTrash(); protected Q_SLOTS: void showPreview(const KFileItem &item, const QPixmap &preview); void previewFailed(const KFileItem &item); void delayedPreview(); Q_SIGNALS: void countChanged(); void urlChanged(); private: QStringList m_mimeTypes; //previews QTimer *m_previewTimer; QHash m_filesToPreview; QSize m_screenshotSize; QHash m_previewJobs; KImageCache* m_imageCache; }; #endif // DIRMODEL_H diff --git a/containments/desktop/plugins/folder/mimetypesmodel.cpp b/containments/desktop/plugins/folder/mimetypesmodel.cpp index 731414a6c..8000b0ff5 100644 --- a/containments/desktop/plugins/folder/mimetypesmodel.cpp +++ b/containments/desktop/plugins/folder/mimetypesmodel.cpp @@ -1,190 +1,193 @@ /*************************************************************************** * Copyright (C) 2014 by 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 "mimetypesmodel.h" #include static bool lessThan(const QMimeType &a, const QMimeType &b) { return QString::localeAwareCompare(a.name(), b.name()) < 0; } MimeTypesModel::MimeTypesModel(QObject *parent) : QAbstractListModel(parent) { - QHash roleNames; - roleNames[Qt::DisplayRole] = "display"; - roleNames[Qt::DecorationRole] = "decoration"; - roleNames[Qt::CheckStateRole] = "checked"; - setRoleNames(roleNames); - QMimeDatabase db; m_mimeTypesList = db.allMimeTypes(); qStableSort(m_mimeTypesList.begin(), m_mimeTypesList.end(), lessThan); checkedRows = QVector(m_mimeTypesList.size(), false); } MimeTypesModel::~MimeTypesModel() { } +QHash MimeTypesModel::roleNames() const +{ + return { + { Qt::DisplayRole, "display" }, + { Qt::DecorationRole, "decoration" }, + { Qt::CheckStateRole, "checked" } + }; +} + QVariant MimeTypesModel::data(const QModelIndex &index, int role) const { if (index.row() < 0 || index.row() >= m_mimeTypesList.size()) { return QVariant(); } switch (role) { case Qt::DisplayRole: return m_mimeTypesList.at(index.row()).name(); case Qt::DecorationRole: { QString icon = m_mimeTypesList.at(index.row()).iconName(); if (icon.isEmpty()) { icon = m_mimeTypesList.at(index.row()).genericIconName(); } return icon; } case Qt::CheckStateRole: return checkedRows.at(index.row()) ? Qt::Checked : Qt::Unchecked; } return QVariant(); } void MimeTypesModel::setRowChecked(int row, bool checked) { checkedRows[row] = checked; QModelIndex idx = index(row, 0); emit dataChanged(idx, idx); emit checkedTypesChanged(); } void MimeTypesModel::checkAll() { checkedRows = QVector(m_mimeTypesList.size(), true); emit dataChanged(index(0, 0), index(m_mimeTypesList.size() - 1, 0)); emit checkedTypesChanged(); } int MimeTypesModel::indexOfType(const QString &name) const { for (int i = 0; i < m_mimeTypesList.size(); i++) { if (m_mimeTypesList.at(i).name() == name) { return i; } } return -1; } QStringList MimeTypesModel::checkedTypes() const { QStringList list; for (int i =0; i < checkedRows.size(); ++i) { if (checkedRows.at(i)) { list.append(m_mimeTypesList.at(i).name()); } } if (!list.isEmpty()) { return list; } return QStringList(QLatin1String("")); } void MimeTypesModel::setCheckedTypes(const QStringList &list) { checkedRows = QVector(m_mimeTypesList.size(), false); foreach (const QString &name, list) { const int row = indexOfType(name); if (row != -1) { checkedRows[row] = true; } } emit dataChanged(index(0, 0), index(m_mimeTypesList.size() - 1, 0)); emit checkedTypesChanged(); } FilterableMimeTypesModel::FilterableMimeTypesModel(QObject *parent) : QSortFilterProxyModel(parent), m_sourceModel(new MimeTypesModel(this)) { setSourceModel(m_sourceModel); setDynamicSortFilter(true); connect(m_sourceModel, &MimeTypesModel::checkedTypesChanged, this, &FilterableMimeTypesModel::checkedTypesChanged); } FilterableMimeTypesModel::~FilterableMimeTypesModel() { } void FilterableMimeTypesModel::setRowChecked(int row, bool checked) { QModelIndex idx = index(row, 0); m_sourceModel->setRowChecked(mapToSource(idx).row(), checked); } void FilterableMimeTypesModel::checkAll() { m_sourceModel->checkAll(); } QStringList FilterableMimeTypesModel::checkedTypes() const { return m_sourceModel->checkedTypes(); } void FilterableMimeTypesModel::setCheckedTypes(const QStringList &list) { m_sourceModel->setCheckedTypes(list); } QString FilterableMimeTypesModel::filter() const { return m_filter; } void FilterableMimeTypesModel::setFilter(const QString &filter) { if (m_filter != filter) { m_filter = filter; setFilterFixedString(m_filter); emit filterChanged(); } } diff --git a/containments/desktop/plugins/folder/mimetypesmodel.h b/containments/desktop/plugins/folder/mimetypesmodel.h index f3d701caa..4bf55a0bd 100644 --- a/containments/desktop/plugins/folder/mimetypesmodel.h +++ b/containments/desktop/plugins/folder/mimetypesmodel.h @@ -1,88 +1,89 @@ /*************************************************************************** * Copyright (C) 2014 by 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 . * ***************************************************************************/ #ifndef MIMETYPESMODEL_H #define MIMETYPESMODEL_H #include #include #include class QStringList; class MimeTypesModel : public QAbstractListModel { Q_OBJECT Q_PROPERTY(QStringList checkedTypes READ checkedTypes WRITE setCheckedTypes NOTIFY checkedTypesChanged) public: MimeTypesModel(QObject *parent = 0); ~MimeTypesModel(); + QHash roleNames() const override; QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const; Q_INVOKABLE void checkAll(); Q_INVOKABLE void setRowChecked(int row, bool checked); int rowCount(const QModelIndex &parent = QModelIndex()) const { Q_UNUSED(parent) return m_mimeTypesList.size(); } QStringList checkedTypes() const; void setCheckedTypes(const QStringList &list); Q_SIGNALS: void checkedTypesChanged() const; private: int indexOfType(const QString &name) const; QList m_mimeTypesList; QVector checkedRows; }; class FilterableMimeTypesModel : public QSortFilterProxyModel { Q_OBJECT Q_PROPERTY(QStringList checkedTypes READ checkedTypes WRITE setCheckedTypes NOTIFY checkedTypesChanged) Q_PROPERTY(QString filter READ filter WRITE setFilter NOTIFY filterChanged) public: FilterableMimeTypesModel(QObject *parent = 0); ~FilterableMimeTypesModel(); Q_INVOKABLE void setRowChecked(int row, bool checked); Q_INVOKABLE void checkAll(); QStringList checkedTypes() const; void setCheckedTypes(const QStringList &list); QString filter() const; void setFilter(const QString &filter); Q_SIGNALS: void checkedTypesChanged() const; void filterChanged() const; private: MimeTypesModel *m_sourceModel; QString m_filter; }; #endif diff --git a/containments/desktop/plugins/folder/placesmodel.cpp b/containments/desktop/plugins/folder/placesmodel.cpp index 9ca3becf9..af37478c5 100644 --- a/containments/desktop/plugins/folder/placesmodel.cpp +++ b/containments/desktop/plugins/folder/placesmodel.cpp @@ -1,89 +1,92 @@ /*************************************************************************** * Copyright (C) 2014 by 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 "placesmodel.h" #include #include #include PlacesModel::PlacesModel(QObject *parent) : QSortFilterProxyModel(parent) { m_sourceModel = new KFilePlacesModel(this); connect(m_sourceModel, &KFilePlacesModel::rowsInserted, this, &PlacesModel::placesChanged); connect(m_sourceModel, &KFilePlacesModel::rowsRemoved, this, &PlacesModel::placesChanged); setSourceModel(m_sourceModel); - QHash roleNames = m_sourceModel->roleNames(); - roleNames[Qt::DisplayRole] = "display"; - roleNames[Qt::DecorationRole] = "decoration"; - setRoleNames(roleNames); - setDynamicSortFilter(true); } PlacesModel::~PlacesModel() { } +QHash PlacesModel::roleNames() const +{ + QHash roleNames = QSortFilterProxyModel::roleNames(); + roleNames[Qt::DisplayRole] = "display"; + roleNames[Qt::DecorationRole] = "decoration"; + return roleNames; +} + bool PlacesModel::activityLinkingEnabled() { const KService::List services = KServiceTypeTrader::self()->query(QStringLiteral("KFileItemAction/Plugin"), QStringLiteral("Library == 'kactivitymanagerd_fileitem_linking_plugin'")); if (services.isEmpty()) { return false; } return !services.at(0).data()->noDisplay(); } QString PlacesModel::urlForIndex(int idx) const { return m_sourceModel->url(mapToSource(index(idx, 0))).toString(); } int PlacesModel::indexForUrl(const QString& url) const { QUrl _url(url); QModelIndex idx; for (int i = 0; i < rowCount(); i++) { if (_url == m_sourceModel->url(mapToSource(index(i, 0)))) { idx = index(i, 0); break; } } if (idx.isValid()) { return idx.row(); } return -1; } bool PlacesModel::filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const { const QModelIndex index = m_sourceModel->index(sourceRow, 0, sourceParent); return !m_sourceModel->isHidden(index); } diff --git a/containments/desktop/plugins/folder/placesmodel.h b/containments/desktop/plugins/folder/placesmodel.h index b7f9f7049..9fcbc4801 100644 --- a/containments/desktop/plugins/folder/placesmodel.h +++ b/containments/desktop/plugins/folder/placesmodel.h @@ -1,52 +1,53 @@ /*************************************************************************** * Copyright (C) 2014 by 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 . * ***************************************************************************/ #ifndef PLACESMODEL_H #define PLACESMODEL_H #include class KFilePlacesModel; class PlacesModel : public QSortFilterProxyModel { Q_OBJECT Q_PROPERTY(bool activityLinkingEnabled READ activityLinkingEnabled CONSTANT) public: PlacesModel(QObject *parent = 0); ~PlacesModel(); bool activityLinkingEnabled(); + QHash roleNames() const override; Q_INVOKABLE QString urlForIndex(int idx) const; Q_INVOKABLE int indexForUrl(const QString &url) const; Q_SIGNALS: void placesChanged() const; protected: bool filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const; private: KFilePlacesModel *m_sourceModel; }; #endif diff --git a/containments/desktop/plugins/folder/previewpluginsmodel.cpp b/containments/desktop/plugins/folder/previewpluginsmodel.cpp index 2b14551d7..6ce309b0b 100644 --- a/containments/desktop/plugins/folder/previewpluginsmodel.cpp +++ b/containments/desktop/plugins/folder/previewpluginsmodel.cpp @@ -1,109 +1,112 @@ /*************************************************************************** * Copyright (C) 2008 Fredrik Höglund * * Copyright (C) 2014 by 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 "previewpluginsmodel.h" #include static bool lessThan(const KService::Ptr &a, const KService::Ptr &b) { return QString::localeAwareCompare(a->name(), b->name()) < 0; } PreviewPluginsModel::PreviewPluginsModel(QObject *parent) : QAbstractListModel(parent) { - QHash roleNames; - roleNames[Qt::DisplayRole] = "display"; - roleNames[Qt::CheckStateRole] = "checked"; - setRoleNames(roleNames); - m_plugins = KServiceTypeTrader::self()->query(QStringLiteral("ThumbCreator")); qStableSort(m_plugins.begin(), m_plugins.end(), lessThan); m_checkedRows = QVector(m_plugins.size(), false); } PreviewPluginsModel::~PreviewPluginsModel() { } +QHash PreviewPluginsModel::roleNames() const +{ + return { + { Qt::DisplayRole, "display" }, + { Qt::CheckStateRole, "checked" } + }; +} + QVariant PreviewPluginsModel::data(const QModelIndex &index, int role) const { if (index.row() < 0 || index.row() >= m_plugins.size()) { return QVariant(); } switch (role) { case Qt::DisplayRole: return m_plugins.at(index.row())->name(); case Qt::CheckStateRole: return m_checkedRows.at(index.row()) ? Qt::Checked : Qt::Unchecked; } return QVariant(); } void PreviewPluginsModel::setRowChecked(int row, bool checked) { m_checkedRows[row] = checked; QModelIndex idx = index(row, 0); emit dataChanged(idx, idx); } int PreviewPluginsModel::indexOfPlugin(const QString &name) const { for (int i = 0; i < m_plugins.size(); i++) { if (m_plugins.at(i)->desktopEntryName() == name) { return i; } } return -1; } void PreviewPluginsModel::setCheckedPlugins(const QStringList &list) { m_checkedRows = QVector(m_plugins.size(), false); foreach (const QString &name, list) { const int row = indexOfPlugin(name); if (row != -1) { m_checkedRows[row] = true; } } emit dataChanged(index(0, 0), index(m_plugins.size() - 1, 0)); emit checkedPluginsChanged(); } QStringList PreviewPluginsModel::checkedPlugins() const { QStringList list; for (int i =0; i < m_checkedRows.size(); ++i) { if (m_checkedRows.at(i)) { list.append(m_plugins.at(i)->desktopEntryName()); } } return list; } diff --git a/containments/desktop/plugins/folder/previewpluginsmodel.h b/containments/desktop/plugins/folder/previewpluginsmodel.h index d340eb52b..2af732b6b 100644 --- a/containments/desktop/plugins/folder/previewpluginsmodel.h +++ b/containments/desktop/plugins/folder/previewpluginsmodel.h @@ -1,57 +1,58 @@ /*************************************************************************** * Copyright (C) 2008 Fredrik Höglund * * Copyright (C) 2014 by 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 . * ***************************************************************************/ #ifndef PREVIEWPLUGINSMODEL_H #define PREVIEWPLUGINSMODEL_H #include #include class QStringList; class PreviewPluginsModel : public QAbstractListModel { Q_OBJECT Q_PROPERTY(QStringList checkedPlugins READ checkedPlugins WRITE setCheckedPlugins NOTIFY checkedPluginsChanged) public: PreviewPluginsModel(QObject *parent = 0); ~PreviewPluginsModel(); + QHash roleNames() const override; QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const; Q_INVOKABLE void setRowChecked(int row, bool checked); int rowCount(const QModelIndex &parent = QModelIndex()) const { Q_UNUSED(parent) return m_plugins.size(); } QStringList checkedPlugins() const; void setCheckedPlugins(const QStringList &list); Q_SIGNALS: void checkedPluginsChanged() const; private: int indexOfPlugin(const QString &name) const; KService::List m_plugins; QVector m_checkedRows; }; #endif diff --git a/imports/activitymanager/switcherbackend.cpp b/imports/activitymanager/switcherbackend.cpp index 939575f4c..89b09b125 100644 --- a/imports/activitymanager/switcherbackend.cpp +++ b/imports/activitymanager/switcherbackend.cpp @@ -1,434 +1,434 @@ /* * Copyright (C) 2014. 2015 Ivan Cukic * Copyright (C) 2009 Martin Gräßlin * Copyright (C) 2003 Lubos Lunak * Copyright (C) 1999, 2000 Matthias Ettrich * * 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 "switcherbackend.h" // Qt #include // #include #include #include #include // KDE #include #include #include #include #include // X11 #include #include #include #define ACTION_NAME_NEXT_ACTIVITY "next activity" #define ACTION_NAME_PREVIOUS_ACTIVITY "previous activity" namespace { // Taken from kwin/tabbox/tabbox.cpp Display* display() { static Display *s_display = nullptr; if (!s_display) { s_display = QX11Info::display(); } return s_display; } bool areKeySymXsDepressed(bool bAll, const uint keySyms[], int nKeySyms) { char keymap[32]; XQueryKeymap(display(), keymap); for (int iKeySym = 0; iKeySym < nKeySyms; iKeySym++) { uint keySymX = keySyms[ iKeySym ]; uchar keyCodeX = XKeysymToKeycode(display(), keySymX); int i = keyCodeX / 8; char mask = 1 << (keyCodeX - (i * 8)); // Abort if bad index value, if (i < 0 || i >= 32) return false; // If ALL keys passed need to be depressed, if (bAll) { if ((keymap[i] & mask) == 0) return false; } else { // If we are looking for ANY key press, and this key is depressed, if (keymap[i] & mask) return true; } } // If we were looking for ANY key press, then none was found, return false, // If we were looking for ALL key presses, then all were found, return true. return bAll; } bool areModKeysDepressed(const QKeySequence& seq) { uint rgKeySyms[10]; int nKeySyms = 0; if (seq.isEmpty()) { return false; } int mod = seq[seq.count()-1] & Qt::KeyboardModifierMask; if (mod & Qt::SHIFT) { rgKeySyms[nKeySyms++] = XK_Shift_L; rgKeySyms[nKeySyms++] = XK_Shift_R; } if (mod & Qt::CTRL) { rgKeySyms[nKeySyms++] = XK_Control_L; rgKeySyms[nKeySyms++] = XK_Control_R; } if (mod & Qt::ALT) { rgKeySyms[nKeySyms++] = XK_Alt_L; rgKeySyms[nKeySyms++] = XK_Alt_R; } if (mod & Qt::META) { // It would take some code to determine whether the Win key // is associated with Super or Meta, so check for both. // See bug #140023 for details. rgKeySyms[nKeySyms++] = XK_Super_L; rgKeySyms[nKeySyms++] = XK_Super_R; rgKeySyms[nKeySyms++] = XK_Meta_L; rgKeySyms[nKeySyms++] = XK_Meta_R; } return areKeySymXsDepressed(false, rgKeySyms, nKeySyms); } bool isReverseTab(const QKeySequence &prevAction) { - if (Qt::SHIFT & prevAction && Qt::Key_Tab & prevAction) { + if (prevAction == QKeySequence(Qt::ShiftModifier | Qt::Key_Tab)) { return areModKeysDepressed(Qt::SHIFT); } else { return false; } } } // local namespace template inline void SwitcherBackend::registerShortcut(const QString &actionName, const QString &text, const QKeySequence &shortcut, Handler &&handler) { auto action = new QAction(this); m_actionShortcut[actionName] = shortcut; action->setObjectName(actionName); action->setText(text); KGlobalAccel::self()->setShortcut(action, { shortcut }); using KActivities::Controller; connect(action, &QAction::triggered, this, std::forward(handler)); } SwitcherBackend::SwitcherBackend(QObject *parent) : QObject(parent) , m_lastInvokedAction(Q_NULLPTR) , m_shouldShowSwitcher(false) { m_wallpaperCache = new KImageCache("activityswitcher_wallpaper_preview", 10485760); registerShortcut(ACTION_NAME_NEXT_ACTIVITY, i18n("Walk through activities"), Qt::META + Qt::Key_Tab, &SwitcherBackend::keybdSwitchToNextActivity); registerShortcut(ACTION_NAME_PREVIOUS_ACTIVITY, i18n("Walk through activities (Reverse)"), Qt::META + Qt::SHIFT + Qt::Key_Tab, &SwitcherBackend::keybdSwitchToPreviousActivity); connect(&m_modKeyPollingTimer, &QTimer::timeout, this, &SwitcherBackend::showActivitySwitcherIfNeeded); connect(&m_activities, &KActivities::Controller::currentActivityChanged, this, &SwitcherBackend::currentActivityChangedSlot); m_previousActivity = m_activities.currentActivity(); } SwitcherBackend::~SwitcherBackend() { delete m_wallpaperCache; } QObject *SwitcherBackend::instance(QQmlEngine *engine, QJSEngine *scriptEngine) { Q_UNUSED(engine) Q_UNUSED(scriptEngine) return new SwitcherBackend(); } void SwitcherBackend::keybdSwitchToNextActivity() { if (isReverseTab(m_actionShortcut[ACTION_NAME_PREVIOUS_ACTIVITY])) { switchToActivity(Previous); } else { switchToActivity(Next); } } void SwitcherBackend::keybdSwitchToPreviousActivity() { switchToActivity(Previous); } void SwitcherBackend::switchToActivity(Direction direction) { auto runningActivities = m_activities.activities(KActivities::Info::Running); if (runningActivities.count() == 0) { return; } // Sorting this every time is not really (or at all) efficient, // but at least we do not need to connect to too many Info objects std::sort(runningActivities.begin(), runningActivities.end(), [] (const QString &left, const QString &right) { using KActivities::Info; const QString &leftName = Info(left).name().toLower(); const QString &rightName = Info(right).name().toLower(); return (leftName < rightName) || (leftName == rightName && left < right); }); auto index = std::max( 0, runningActivities.indexOf(m_activities.currentActivity())); index += direction == Next ? 1 : -1; if (index < 0) { index = runningActivities.count() - 1; } else if (index >= runningActivities.count()) { index = 0; } // TODO: This is evil, but plasmashell goes into a dead-lock if // the activity is changed while one tries to open the switcher O.o // m_activities.setCurrentActivity(runningActivities[index]); const auto activityToSet = runningActivities[index]; QTimer::singleShot(150, this, [this,activityToSet] () { m_activities.setCurrentActivity(activityToSet); }); keybdSwitchedToAnotherActivity(); } void SwitcherBackend::keybdSwitchedToAnotherActivity() { m_lastInvokedAction = dynamic_cast(sender()); QTimer::singleShot(0, this, &SwitcherBackend::showActivitySwitcherIfNeeded); } void SwitcherBackend::showActivitySwitcherIfNeeded() { if (!m_lastInvokedAction) { return; } auto actionName = m_lastInvokedAction->objectName(); if (!m_actionShortcut.contains(actionName)) { return; } if (!areModKeysDepressed(m_actionShortcut[actionName])) { m_lastInvokedAction = Q_NULLPTR; setShouldShowSwitcher(false); return; } setShouldShowSwitcher(true); } void SwitcherBackend::init() { // nothing } void SwitcherBackend::currentActivityChangedSlot(const QString &id) { // Safe, we have a long-lived Consumer object KActivities::Info activity(id); emit showSwitchNotification(id, activity.name(), activity.icon()); KConfig config("kactivitymanagerd-switcher"); KConfigGroup times(&config, "LastUsed"); const auto now = QDateTime::currentDateTime().toTime_t(); // Updating the time for the activity we just switched to // in the case we do not power off properly, and on the next // start, kamd switches to another activity for some reason times.writeEntry(id, now); if (!m_previousActivity.isEmpty()) { // When leaving an activity, say goodbye and fondly remember // the time we saw it times.writeEntry(m_previousActivity, now); } times.sync(); m_previousActivity = id; } bool SwitcherBackend::shouldShowSwitcher() const { return m_shouldShowSwitcher; } void SwitcherBackend::setShouldShowSwitcher(const bool &shouldShowSwitcher) { if (m_shouldShowSwitcher == shouldShowSwitcher) return; m_shouldShowSwitcher = shouldShowSwitcher; if (m_shouldShowSwitcher) { // TODO: We really should NOT do this by polling m_modKeyPollingTimer.start(100); } else { m_modKeyPollingTimer.stop(); } emit shouldShowSwitcherChanged(m_shouldShowSwitcher); } QPixmap SwitcherBackend::wallpaperThumbnail(const QString &path, int width, int height, const QJSValue &_callback) { QPixmap preview = QPixmap(QSize(1, 1)); QJSValue callback(_callback); if (path.isEmpty()) { callback.call({false}); return preview; } // qDebug() << "SwitcherBackend: Requesting wallpaper: " << path << width << height; if (width == 0) { width = 320; } if (height == 0) { height = 240; } const auto pixmapKey = path + "/" + QString::number(width) + "x" + QString::number(height); // qDebug() << "SwitcherBackend: Wallpaper cache id is: " << pixmapKey; if (m_wallpaperCache->findPixmap(pixmapKey, &preview)) { return preview; } QUrl file(path); // qDebug() << "SwitcherBackend: Cache miss. We need to generate the thumbnail: " << file; if (!m_previewJobs.contains(file) && file.isValid()) { m_previewJobs.insert(file); KFileItemList list; list.append(KFileItem(file, QString(), 0)); KIO::PreviewJob* job = KIO::filePreview(list, QSize(width, height)); job->setScaleType(KIO::PreviewJob::Scaled); job->setIgnoreMaximumSize(true); connect(job, &KIO::PreviewJob::gotPreview, this, [=] (const KFileItem& item, const QPixmap& pixmap) mutable { Q_UNUSED(item); m_wallpaperCache->insertPixmap(pixmapKey, pixmap); m_previewJobs.remove(path); // qDebug() << "SwitcherBackend: Got the thumbnail for " << path << "saving under" << pixmapKey; callback.call({true}); }); connect(job, &KIO::PreviewJob::failed, this, [=] (const KFileItem& item) mutable { Q_UNUSED(item); m_previewJobs.remove(path); qWarning() << "SwitcherBackend: FAILED to get the thumbnail for " << path << job->detailedErrorStrings(&file); callback.call({false}); }); } return preview; } QString SwitcherBackend::lastTimeUsedString(const QString &activity) { KConfig config("kactivitymanagerd-switcher"); KConfigGroup times(&config, "LastUsed"); const auto now = QDateTime::currentDateTime().toTime_t(); const auto time = times.readEntry(activity, 0); if (time == 0) return i18n("Used some time ago"); auto diff = now - time; // We do not need to be precise const auto seconds = diff % 60; 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 a long time 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"); } #include "switcherbackend.moc" diff --git a/kcms/desktoptheme/thememodel.cpp b/kcms/desktoptheme/thememodel.cpp index 8274b7253..8db5fb220 100644 --- a/kcms/desktoptheme/thememodel.cpp +++ b/kcms/desktoptheme/thememodel.cpp @@ -1,220 +1,218 @@ /* * ThemeModel * Copyright (C) 2002 Karol Szwed * Copyright (C) 2002 Daniel Molkentin * Copyright (C) 2007 Urs Wolfer * Copyright (C) 2009 by Davide Bettio * Portions Copyright (C) 2007 Paolo Capriotti * Portions Copyright (C) 2007 Ivan Cukic * Portions Copyright (C) 2008 by Petri Damsten * Portions Copyright (C) 2000 TrollTech AS. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public * License version 2 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; see the file COPYING. If not, write to * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ #include "thememodel.h" #include #include #include #include #include #include #include #include #include #include ThemeModel::ThemeModel( QObject *parent ) : QAbstractListModel( parent ) { reload(); } ThemeModel::~ThemeModel() { clearThemeList(); } void ThemeModel::clearThemeList() { foreach (const ThemeInfo& themeInfo, m_themes) { delete themeInfo.svg; } m_themes.clear(); } void ThemeModel::reload() { - reset(); + beginResetModel(); clearThemeList(); // get all desktop themes QStringList themes; const QStringList &packs = QStandardPaths::locateAll(QStandardPaths::GenericDataLocation, QStringLiteral("plasma/desktoptheme"), QStandardPaths::LocateDirectory); foreach (const QString &ppath, packs) { const QDir cd(ppath); const QStringList &entries = cd.entryList(QDir::Dirs | QDir::Hidden); foreach (const QString pack, entries) { const QString _metadata = ppath+QLatin1Char('/')+pack+QStringLiteral("/metadata.desktop"); if ((pack != QLatin1String(".") && pack != QLatin1String("..")) && (QFile::exists(_metadata))) { themes << _metadata; } } } foreach (const QString &theme, themes) { int themeSepIndex = theme.lastIndexOf('/', -1); QString themeRoot = theme.left(themeSepIndex); int themeNameSepIndex = themeRoot.lastIndexOf('/', -1); 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 QString comment = df.readComment(); const QString author = df.desktopGroup().readEntry("X-KDE-PluginInfo-Author",QString()); const QString version = df.desktopGroup().readEntry("X-KDE-PluginInfo-Version",QString()); Plasma::FrameSvg *svg = new Plasma::FrameSvg(this); Plasma::Theme *t = new Plasma::Theme(packageName, svg); svg->setTheme(t); svg->setImagePath(QStringLiteral("widgets/background")); svg->setEnabledBorders(Plasma::FrameSvg::AllBorders); ThemeInfo info; info.package = packageName; info.description = comment; info.author = author; info.version = version; info.svg = svg; info.themeRoot = themeRoot; m_themes[name] = info; } - - beginInsertRows(QModelIndex(), 0, m_themes.size()); - endInsertRows(); + endResetModel(); } int ThemeModel::rowCount(const QModelIndex &) const { return m_themes.size(); } QVariant ThemeModel::data(const QModelIndex &index, int role) const { if (!index.isValid()) { return QVariant(); } if (index.row() >= m_themes.size()) { return QVariant(); } QMap::const_iterator it = m_themes.constBegin(); for (int i = 0; i < index.row(); ++i) { ++it; } switch (role) { case Qt::DisplayRole: return it.key(); case PackageNameRole: return (*it).package; case SvgRole: return qVariantFromValue((void*)(*it).svg); case PackageDescriptionRole: return (*it).description; case PackageAuthorRole: return (*it).author; case PackageVersionRole: return (*it).version; default: return QVariant(); } } QModelIndex ThemeModel::indexOf(const QString &name) const { QMapIterator it(m_themes); int i = -1; while (it.hasNext()) { ++i; if (it.next().value().package == name) { return index(i, 0); } } return QModelIndex(); } ThemeDelegate::ThemeDelegate(QObject* parent) : QAbstractItemDelegate(parent) { } void ThemeDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const { QString title = index.model()->data(index, Qt::DisplayRole).toString(); QString package = index.model()->data(index, ThemeModel::PackageNameRole).toString(); QStyleOptionViewItemV4 opt(option); QStyle *style = opt.widget ? opt.widget->style() : QApplication::style(); style->drawPrimitive(QStyle::PE_PanelItemViewItem, &opt, painter, opt.widget); // draw image Plasma::FrameSvg *svg = static_cast( index.model()->data(index, ThemeModel::SvgRole).value()); svg->resizeFrame(QSize(option.rect.width() - (2 * MARGIN), 100 - (2 * MARGIN))); QRect imgRect = QRect(option.rect.topLeft(), QSize(option.rect.width() - (2 * MARGIN), 100 - (2 * MARGIN))) .translated(MARGIN, MARGIN); svg->paintFrame(painter, QPoint(option.rect.left() + MARGIN, option.rect.top() + MARGIN)); // draw text painter->save(); QFont font = painter->font(); //font.setWeight(QFont::Bold); const QString colorFile = QStandardPaths::locate(QStandardPaths::GenericDataLocation, "plasma/desktoptheme/" + package + "/colors"); if (!colorFile.isEmpty()) { KSharedConfigPtr colors = KSharedConfig::openConfig(colorFile); KColorScheme colorScheme(QPalette::Active, KColorScheme::Window, colors); painter->setPen(colorScheme.foreground(KColorScheme::NormalText).color()); } painter->setFont(font); painter->drawText(option.rect, Qt::AlignCenter | Qt::TextWordWrap, title); painter->restore(); } QSize ThemeDelegate::sizeHint(const QStyleOptionViewItem &, const QModelIndex &) const { return QSize(152, 100); } diff --git a/kcms/keyboard/kcm_view_models.h b/kcms/keyboard/kcm_view_models.h index 434bbe9a2..ff6924e5a 100644 --- a/kcms/keyboard/kcm_view_models.h +++ b/kcms/keyboard/kcm_view_models.h @@ -1,172 +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; class Rules; class Flags; class LayoutsTableModel : public QAbstractTableModel { Q_OBJECT public: LayoutsTableModel(Rules* rules, Flags *flags, KeyboardConfig* keyboardConfig, QObject *parent = 0); int columnCount(const QModelIndex&) const; Qt::ItemFlags flags(const QModelIndex &index) const; QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const; int rowCount(const QModelIndex &parent = QModelIndex()) const; QVariant data(const QModelIndex &index, int role) const; bool setData(const QModelIndex &index, const QVariant &value, int role); #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 = 0); QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const; void updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &index) const; // 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 = 0); QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const; void setEditorData(QWidget *editor, const QModelIndex &index) const; void setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const; void updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &index) const; private: const KeyboardConfig* keyboardConfig; const Rules* rules; }; class KKeySequenceWidgetDelegate : public QStyledItemDelegate { Q_OBJECT public: KKeySequenceWidgetDelegate(const KeyboardConfig* keyboardConfig_, QObject *parent = 0); QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const; // void setEditorData(QWidget *editor, const QModelIndex &index) const; void setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const; void paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const; 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 { return 1; } int rowCount(const QModelIndex& parent) const; QModelIndex parent(const QModelIndex& index) const { 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 { if(!parent.isValid()) return createIndex(row, column); return createIndex(row, column, (100 * (parent.row()+1)) + row); } Qt::ItemFlags flags ( const QModelIndex & index ) const { if( ! index.isValid() ) return 0; 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 ); QVariant data(const QModelIndex& index, int role) const; - void reset() { QAbstractItemModel::reset(); } + 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/keyboard/preview/keysymhelper.cpp b/kcms/keyboard/preview/keysymhelper.cpp index 1479fb0d8..d5d138662 100644 --- a/kcms/keyboard/preview/keysymhelper.cpp +++ b/kcms/keyboard/preview/keysymhelper.cpp @@ -1,83 +1,83 @@ /* * Copyright (C) 2012 Shivam Makkar (amourphious1992@gmail.com) * * 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 "keysymhelper.h" #include "keysym2ucs.h" #include #include #include #include KeySymHelper::KeySymHelper() { nill = 0; } QString KeySymHelper::getKeySymbol(const QString &opton) { if (keySymbolMap.contains(opton)) { return keySymbolMap[opton]; } - const char *str = opton.toAscii().data(); + const char *str = opton.toLatin1().data(); #if 0 //TODO: figure out how to use this so we don't need our own symkey2ucs mapping int res = Xutf8LookupString(XIC ic, XKeyPressedEvent * event, char *buffer_return, int bytes_buffer, KeySym * keysym_return, Status * status_return); #else KeySym keysym = XStringToKeysym(str); //TODO: make it more generic // if( keysym == 0xfe03 ) // return "L3"; long ucs = keysym2ucs(keysym); // if( ucs == -1 && (keysym >= 0xFE50 && keysym <= 0xFE5F) ) { // ucs = 0x0300 + (keysym & 0x000F); // qWarning() << "Got dead symbol" << QString("0x%1").arg(keysym, 0, 16) << "named" << opton << "will use" << QString("0x%1").arg(ucs, 0, 16) << "as UCS"; // } if (ucs == -1) { nill++; qWarning() << "No mapping from keysym:" << QStringLiteral("0x%1").arg(keysym, 0, 16) << "named:" << opton << "to UCS"; } QString ucsStr = QString(QChar((int)ucs)); // Combining Diacritical Marks if (ucs >= 0x0300 && ucs <= 0x036F) { ucsStr = " " + ucsStr + " "; } // qWarning() << "--" << opton << "keysym: " << keysym << QString("0x%1").arg(keysym, 0, 16) << "keysym2string" << XKeysymToString(keysym) // << "---" << QString("0x%1").arg(ucs, 0, 16) << ucsStr; keySymbolMap[opton] = ucsStr; return ucsStr; #endif } diff --git a/kcms/keyboard/tests/keyboard_daemon_test.cpp b/kcms/keyboard/tests/keyboard_daemon_test.cpp index 885f070cf..8067aa52e 100644 --- a/kcms/keyboard/tests/keyboard_daemon_test.cpp +++ b/kcms/keyboard/tests/keyboard_daemon_test.cpp @@ -1,100 +1,100 @@ /* * Copyright (C) 2011 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 #include #include #include "../flags.h" #include "../xkb_rules.h" #include "../keyboard_config.h" #include "../keyboard_daemon.h" class KeyboardDaemonTest : public QObject { Q_OBJECT KeyboardDaemon* keyboardDaemon; // KApplication* kapplication; private Q_SLOTS: void initTestCase() { // kapplication = new KApplication(); -// const KAboutData* kAboutData = new KAboutData(i18n("a").toAscii(), i18n("a").toAscii(), KLocalizedString(), i18n("a").toAscii()); +// const KAboutData* kAboutData = new KAboutData(i18n("a").toLatin1(), i18n("a").toLatin1(), KLocalizedString(), i18n("a").toLatin1()); // KCmdLineArgs::init(kAboutData); keyboardDaemon = new KeyboardDaemon(this, QList()); } void cleanupTestCase() { delete keyboardDaemon; // delete kapplication; } void testDaemon() { QVERIFY( keyboardDaemon != NULL ); // QVERIFY( ! flags->getTransparentPixmap().isNull() ); // // const QIcon iconUs(flags->getIcon("us")); // QVERIFY( ! iconUs.isNull() ); // QVERIFY( flags->getIcon("--").isNull() ); // // KeyboardConfig keyboardConfig; // LayoutUnit layoutUnit("us"); // LayoutUnit layoutUnit1("us", "intl"); // layoutUnit1.setDisplayName("usi"); // LayoutUnit layoutUnit2("us", "other"); // // keyboardConfig.showFlag = true; // const QIcon iconUsFlag = flags->getIconWithText(layoutUnit, keyboardConfig); // QVERIFY( ! iconUsFlag.isNull() ); // QCOMPARE( image(iconUsFlag), image(iconUs) ); // // keyboardConfig.showFlag = false; // const QIcon iconUsText = flags->getIconWithText(layoutUnit, keyboardConfig); // QVERIFY( ! iconUsText.isNull() ); // QVERIFY( image(iconUsText) != image(iconUs) ); // // keyboardConfig.layouts.append(layoutUnit1); // QCOMPARE( flags->getShortText(layoutUnit, keyboardConfig), QString("us") ); // QCOMPARE( flags->getShortText(layoutUnit1, keyboardConfig), QString("usi") ); // QCOMPARE( flags->getShortText(layoutUnit2, keyboardConfig), QString("us") ); // // const Rules* rules = Rules::readRules(); // QCOMPARE( flags->getLongText(layoutUnit, rules), QString("USA") ); // QVERIFY( flags->getLongText(layoutUnit1, rules).startsWith("USA - International") ); // QCOMPARE( flags->getLongText(layoutUnit2, rules), QString("USA - other") ); // // flags->clearCache(); } // void loadRulesBenchmark() { // QBENCHMARK { // Flags* flags = new Flags(); // delete flags; // } // } }; // need GUI for xkb protocol in xkb_rules.cpp QTEST_MAIN(KeyboardDaemonTest) #include "keyboard_daemon_test.moc" diff --git a/kcms/phonon/audiosetup.cpp b/kcms/phonon/audiosetup.cpp index bd6fcb00a..2f0bd7ea2 100644 --- a/kcms/phonon/audiosetup.cpp +++ b/kcms/phonon/audiosetup.cpp @@ -1,884 +1,884 @@ /* This file is part of the KDE project Copyright (C) 2010 Colin Guthrie Copyright (C) 2011 Harald Sitter This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License version 2 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. */ #include "audiosetup.h" #include #include #include #include #include #include #include #include #include "testspeakerwidget.h" #define SS_DEFAULT_ICON "audio-card" #define THAT(userdata) Q_ASSERT(userdata); AudioSetup *ss = static_cast(userdata) static pa_glib_mainloop *s_mainloop = NULL; static pa_context *s_context = NULL; QMap s_Cards; QMap s_Sinks; QMap s_Sources; static void card_cb(pa_context *c, const pa_card_info *i, int eol, void *userdata) { Q_ASSERT(c); THAT(userdata); if (eol < 0) { if (pa_context_errno(c) == PA_ERR_NOENTITY) return; qDebug() << "Card callback failure"; return; } if (eol > 0) { ss->updateFromPulse(); return; } Q_ASSERT(i); ss->updateCard(i); } static void sink_cb(pa_context *c, const pa_sink_info *i, int eol, void *userdata) { Q_ASSERT(c); THAT(userdata); if (eol < 0) { if (pa_context_errno(c) == PA_ERR_NOENTITY) return; qDebug() << "Sink callback failure"; return; } if (eol > 0) { ss->updateIndependantDevices(); ss->updateFromPulse(); return; } Q_ASSERT(i); ss->updateSink(i); } static void source_cb(pa_context *c, const pa_source_info *i, int eol, void *userdata) { Q_ASSERT(c); THAT(userdata); if (eol < 0) { if (pa_context_errno(c) == PA_ERR_NOENTITY) return; qDebug() << "Source callback failure"; return; } if (eol > 0) { ss->updateIndependantDevices(); ss->updateFromPulse(); return; } Q_ASSERT(i); ss->updateSource(i); } static void subscribe_cb(pa_context *c, pa_subscription_event_type_t t, uint32_t index, void *userdata) { Q_ASSERT(c); THAT(userdata); switch (t & PA_SUBSCRIPTION_EVENT_FACILITY_MASK) { case PA_SUBSCRIPTION_EVENT_CARD: if ((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) == PA_SUBSCRIPTION_EVENT_REMOVE) { ss->removeCard(index); } else { pa_operation *operation = pa_context_get_card_info_by_index(c, index, card_cb, ss); if (!operation) { qDebug() << "pa_context_get_card_info_by_index() failed"; return; } pa_operation_unref(operation); } break; case PA_SUBSCRIPTION_EVENT_SINK: if ((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) == PA_SUBSCRIPTION_EVENT_REMOVE) { ss->removeSink(index); } else { pa_operation *operation = pa_context_get_sink_info_by_index(c, index, sink_cb, ss); if (!operation) { qDebug() << "pa_context_get_sink_info_by_index() failed"; return; } pa_operation_unref(operation); } break; case PA_SUBSCRIPTION_EVENT_SOURCE: if ((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) == PA_SUBSCRIPTION_EVENT_REMOVE) { ss->removeSource(index); } else { pa_operation *o; if (!(o = pa_context_get_source_info_by_index(c, index, source_cb, ss))) { qDebug() << "pa_context_get_source_info_by_index() failed"; return; } pa_operation_unref(o); } break; } } static void context_state_callback(pa_context *c, void *userdata) { Q_ASSERT(c); THAT(userdata); qDebug() << "context_state_callback" << pa_context_get_state(c); pa_context_state_t state = pa_context_get_state(c); if (state == PA_CONTEXT_READY) { // Attempt to load things up pa_operation *o; pa_context_set_subscribe_callback(c, subscribe_cb, ss); if (!(o = pa_context_subscribe(c, (pa_subscription_mask_t) (PA_SUBSCRIPTION_MASK_CARD| PA_SUBSCRIPTION_MASK_SINK| PA_SUBSCRIPTION_MASK_SOURCE), NULL, NULL))) { qDebug() << "pa_context_subscribe() failed"; return; } pa_operation_unref(o); if (!(o = pa_context_get_card_info_list(c, card_cb, ss))) { qDebug() << "pa_context_get_card_info_list() failed"; return; } pa_operation_unref(o); if (!(o = pa_context_get_sink_info_list(c, sink_cb, ss))) { qDebug() << "pa_context_get_sink_info_list() failed"; return; } pa_operation_unref(o); if (!(o = pa_context_get_source_info_list(c, source_cb, ss))) { qDebug() << "pa_context_get_source_info_list() failed"; return; } pa_operation_unref(o); ss->load(); } else if (!PA_CONTEXT_IS_GOOD(state)) { // If this is our probe phase, exit our context immediately if (s_context != c) pa_context_disconnect(c); else { qWarning() << "PulseAudio context lost. Scheduling reconnect in eventloop."; pa_context_unref(s_context); s_context = 0; QMetaObject::invokeMethod(ss, "connectToDaemon", Qt::QueuedConnection); } } } static void suspended_callback(pa_stream *s, void *userdata) { THAT(userdata); if (pa_stream_is_suspended(s)) ss->updateVUMeter(-1); } static void read_callback(pa_stream *s, size_t length, void *userdata) { THAT(userdata); const void *data; int v; if (pa_stream_peek(s, &data, &length) < 0) { qDebug() << "Failed to read data from stream"; return; } Q_ASSERT(length > 0); Q_ASSERT(length % sizeof(float) == 0); v = ((const float*) data)[length / sizeof(float) -1] * 100; pa_stream_drop(s); if (v < 0) v = 0; if (v > 100) v = 100; ss->updateVUMeter(v); } AudioSetup::AudioSetup(QWidget *parent) : QWidget(parent) , m_OutstandingRequests(3) , m_Canberra(0) , m_VUStream(0) , m_VURealValue(0) { setupUi(this); cardLabel->setEnabled(false); cardBox->setEnabled(false); profileLabel->setVisible(false); profileBox->setVisible(false); deviceLabel->setEnabled(false); deviceBox->setEnabled(false); portLabel->setVisible(false); portBox->setVisible(false); for (int i = 0; i < 5; ++i) placementGrid->setColumnStretch(i, 1); for (int i = 0; i < 3; ++i) placementGrid->setRowStretch(i, 1); m_icon = new QLabel(this); m_icon->setPixmap(QPixmap(KUser().faceIconPath())); if (m_icon->pixmap()->isNull()) m_icon->setPixmap(QIcon::fromTheme("system-users").pixmap(KIconLoader::SizeHuge, KIconLoader::SizeHuge)); m_icon->setMaximumSize(KIconLoader::SizeHuge, KIconLoader::SizeHuge); m_icon->setScaledContents(true); placementGrid->addWidget(m_icon, 1, 2, Qt::AlignCenter); update(); connect(cardBox, static_cast(&KComboBox::currentIndexChanged), this, &AudioSetup::cardChanged); connect(profileBox, static_cast(&KComboBox::currentIndexChanged), this, &AudioSetup::profileChanged); connect(deviceBox, static_cast(&KComboBox::currentIndexChanged), this, &AudioSetup::deviceChanged); connect(portBox, static_cast(&KComboBox::currentIndexChanged), this, &AudioSetup::portChanged); m_VUTimer = new QTimer(this); m_VUTimer->setInterval(10); connect(m_VUTimer, &QTimer::timeout, this, &AudioSetup::reallyUpdateVUMeter); // We require a glib event loop const QByteArray eventDispatcher( QAbstractEventDispatcher::instance()->metaObject()->className()); if (!eventDispatcher.contains("EventDispatcherGlib")) { qDebug() << "Disabling PulseAudio integration for lack of GLib event loop."; return; } int ret = ca_context_create(&m_Canberra); if (ret < 0) { qDebug() << "Disabling PulseAudio integration. Canberra context failed."; return; } s_mainloop = pa_glib_mainloop_new(NULL); if (!s_mainloop) { qDebug() << "Disabling PulseAudio integration for lack of working GLib event loop."; ca_context_destroy(m_Canberra); m_Canberra = 0; return; } connectToDaemon(); } AudioSetup::~AudioSetup() { if (m_Canberra) ca_context_destroy(m_Canberra); if (s_context) { pa_context_unref(s_context); s_context = 0; } if (s_mainloop) { pa_glib_mainloop_free(s_mainloop); s_mainloop = 0; } s_Cards.clear(); s_Sinks.clear(); s_Sources.clear(); } void AudioSetup::load() { } void AudioSetup::save() { } void AudioSetup::defaults() { } void AudioSetup::updateCard(const pa_card_info *pInfo) { cardInfo info; info.index = pInfo->index; const char *description = pa_proplist_gets(pInfo->proplist, PA_PROP_DEVICE_DESCRIPTION); if(description) info.name = QString::fromUtf8(description); else info.name = QString::fromUtf8(pInfo->name); const char *icon = pa_proplist_gets(pInfo->proplist, PA_PROP_DEVICE_ICON_NAME); if (icon) info.icon = QString::fromUtf8(icon); else info.icon = QString::fromUtf8(SS_DEFAULT_ICON); for (quint32 i = 0; i < pInfo->n_profiles; ++i) { const pa_card_profile_info *profile = &(pInfo->profiles[i]); const quint32 priority = profile->priority; const QPair name(profile->name ? QString::fromUtf8(profile->name) : QString(), profile->description ? QString::fromUtf8(profile->description) : QString()); info.profiles.insert(priority, name); } if (pInfo->active_profile) info.activeProfile = pInfo->active_profile->name; cardBox->blockSignals(true); if (s_Cards.contains(pInfo->index)) { int idx = cardBox->findData(pInfo->index); if (idx >= 0) { cardBox->setItemIcon(idx, QIcon::fromTheme(info.icon)); cardBox->setItemText(idx, info.name); } } else { cardBox->addItem(QIcon::fromTheme(info.icon), info.name, pInfo->index); } cardBox->blockSignals(false); s_Cards[pInfo->index] = info; cardChanged(); qDebug() << "Got info about card" << info.name; } void AudioSetup::removeCard(uint32_t index) { s_Cards.remove(index); updateFromPulse(); const int idx = cardBox->findData(index); if (idx >= 0) cardBox->removeItem(idx); } void AudioSetup::updateSink(const pa_sink_info* i) { deviceInfo info; info.index = i->index; info.cardIndex = i->card; info.name = QString::fromUtf8(i->description); const char *icon = pa_proplist_gets(i->proplist, PA_PROP_DEVICE_ICON_NAME); info.icon = icon ? icon : SS_DEFAULT_ICON; info.channelMap = i->channel_map; for (uint32_t j = 0; j < i->n_ports; ++j) info.ports[i->ports[j]->priority] = QPair(i->ports[j]->name, QString::fromUtf8(i->ports[j]->description)); if (i->active_port) info.activePort = i->active_port->name; s_Sinks[i->index] = info; // Need to update the currently displayed port if this sink is the currently displayed one. if (info.ports.size()) { int idx = deviceBox->currentIndex(); if (idx >= 0) { qint64 index = deviceBox->itemData(idx).toInt(); if (index >= 0 && index == i->index) { portBox->blockSignals(true); portBox->setCurrentIndex(portBox->findData(info.activePort)); portBox->blockSignals(false); } } } qDebug() << "Got info about sink" << info.name; } void AudioSetup::removeSink(uint32_t index) { s_Sinks.remove(index); updateIndependantDevices(); updateFromPulse(); int idx = deviceBox->findData(index); if (idx >= 0) deviceBox->removeItem(idx); } void AudioSetup::updateSource(const pa_source_info* i) { if (i->monitor_of_sink != PA_INVALID_INDEX) return; deviceInfo info; info.index = i->index; info.cardIndex = i->card; info.name = QString::fromUtf8(i->description); const char* icon = pa_proplist_gets(i->proplist, PA_PROP_DEVICE_ICON_NAME); info.icon = icon ? icon : SS_DEFAULT_ICON; info.channelMap = i->channel_map; for (uint32_t j = 0; j < i->n_ports; ++j) info.ports[i->ports[j]->priority] = QPair(i->ports[j]->name, QString::fromUtf8(i->ports[j]->description)); if (i->active_port) info.activePort = i->active_port->name; s_Sources[i->index] = info; // Need to update the currently displayed port if this source is the currently displayed one. if (false && info.ports.size()) { int idx = deviceBox->currentIndex(); if (idx >= 0) { qint64 index = deviceBox->itemData(idx).toInt(); if (index < 0 && ((-1*index) - 1) == i->index) { portBox->blockSignals(true); portBox->setCurrentIndex(portBox->findData(info.activePort)); portBox->blockSignals(false); } } } qDebug() << "Got info about source" << info.name; } void AudioSetup::removeSource(uint32_t index) { s_Sources.remove(index); updateIndependantDevices(); updateFromPulse(); int idx = deviceBox->findData(index); if (false && idx >= 0) deviceBox->removeItem(idx); } void AudioSetup::updateFromPulse() { bool setupReady = false; if (m_OutstandingRequests > 0) { if (0 == --m_OutstandingRequests) { // Work out which seclector to pick by default (we want to choose a real Card if possible) if (s_Cards.size() != cardBox->count()) cardBox->setCurrentIndex(1); setupReady = true; } } if (!m_OutstandingRequests) { if (!s_Cards.size() && !s_Sinks.size()) { cardLabel->setEnabled(false); cardBox->setEnabled(false); profileLabel->setVisible(false); profileBox->setVisible(false); deviceLabel->setEnabled(false); deviceBox->setEnabled(false); portLabel->setVisible(false); portBox->setVisible(false); } if (s_Cards.size() && !cardBox->isEnabled()) { cardLabel->setEnabled(true); cardBox->setEnabled(true); cardChanged(); } if (s_Sinks.size() && !deviceBox->isEnabled()) { deviceLabel->setEnabled(true); deviceBox->setEnabled(true); deviceChanged(); } if (setupReady) { emit ready(); } } } void AudioSetup::cardChanged() { int idx = cardBox->currentIndex(); if (idx < 0) { profileLabel->setVisible(false); profileBox->setVisible(false); return; } uint32_t card_index = cardBox->itemData(idx).toUInt(); Q_ASSERT(PA_INVALID_INDEX == card_index || s_Cards.contains(card_index)); bool show_profiles = (PA_INVALID_INDEX != card_index && s_Cards[card_index].profiles.size()); if (show_profiles) { cardInfo &card_info = s_Cards[card_index]; profileBox->blockSignals(true); profileBox->clear(); QMap >::const_iterator it; for (it = card_info.profiles.constBegin(); it != card_info.profiles.constEnd(); ++it) profileBox->insertItem(0, it.value().second, it.value().first); profileBox->setCurrentIndex(profileBox->findData(card_info.activeProfile)); profileBox->blockSignals(false); } profileLabel->setVisible(show_profiles); profileBox->setVisible(show_profiles); deviceBox->blockSignals(true); deviceBox->clear(); QMap::const_iterator it; for (it = s_Sinks.constBegin(); it != s_Sinks.constEnd(); ++it) { if (it->cardIndex == card_index) deviceBox->addItem(QIcon::fromTheme(it->icon), i18n("Playback (%1)", it->name), it->index); } for (it = s_Sources.constBegin(); it != s_Sources.constEnd(); ++it) { if (it->cardIndex == card_index) deviceBox->addItem(QIcon::fromTheme(it->icon), i18n("Recording (%1)", it->name), ((-1*it->index) - 1)); } deviceBox->blockSignals(false); deviceGroupBox->setEnabled(!!deviceBox->count()); deviceChanged(); qDebug() << "Doing update" << cardBox->currentIndex(); emit changed(); } void AudioSetup::profileChanged() { quint32 card_index = cardBox->itemData(cardBox->currentIndex()).toUInt(); Q_ASSERT(PA_INVALID_INDEX != card_index); QString profile = profileBox->itemData(profileBox->currentIndex()).toString(); qDebug() << "Changing profile to" << profile; Q_ASSERT(s_Cards[card_index].profiles.size()); pa_operation *operation = pa_context_set_card_profile_by_index(s_context, card_index, qPrintable(profile), NULL, NULL); if (!operation) qDebug() << "pa_context_set_card_profile_by_name() failed"; else pa_operation_unref(operation); emit changed(); } void AudioSetup::updateIndependantDevices() { // Should we display the "Independent Devices" drop down? // Count all the sinks without cards bool showID = false; QMap::const_iterator it; for (it = s_Sinks.constBegin(); it != s_Sinks.constEnd(); ++it) { if (PA_INVALID_INDEX == it->cardIndex) { showID = true; break; } } bool haveID = (PA_INVALID_INDEX == cardBox->itemData(0).toUInt()); qDebug() << QString("Want ID: %1; Have ID: %2").arg(showID?"Yes":"No").arg(haveID?"Yes":"No"); cardBox->blockSignals(true); if (haveID && !showID) cardBox->removeItem(0); else if (!haveID && showID) cardBox->insertItem(0, QIcon::fromTheme(SS_DEFAULT_ICON), i18n("Independent Devices"), PA_INVALID_INDEX); cardBox->blockSignals(false); } void AudioSetup::updateVUMeter(int vol) { if (vol < 0) { inputLevels->setEnabled(false); inputLevels->setValue(0); m_VURealValue = 0; } else { inputLevels->setEnabled(true); if (vol > inputLevels->value()) inputLevels->setValue(vol); m_VURealValue = vol; } } void AudioSetup::reallyUpdateVUMeter() { int val = inputLevels->value(); if (val > m_VURealValue) inputLevels->setValue(val-1); } bool AudioSetup::connectToDaemon() { pa_mainloop_api *api = pa_glib_mainloop_get_api(s_mainloop); s_context = pa_context_new(api, i18n("KDE Audio Hardware Setup").toUtf8().constData()); if (pa_context_connect(s_context, NULL, PA_CONTEXT_NOFAIL, 0) < 0) { qDebug() << "Disabling PulseAudio integration. Context connection failed: " << pa_strerror(pa_context_errno(s_context)); pa_context_unref(s_context); s_context = 0; pa_glib_mainloop_free(s_mainloop); s_mainloop = 0; ca_context_destroy(m_Canberra); m_Canberra = 0; setEnabled(false); return false; } pa_context_set_state_callback(s_context, &context_state_callback, this); setEnabled(true); return true; } static deviceInfo &getDeviceInfo(qint64 index) { if (index >= 0) { Q_ASSERT(s_Sinks.contains(index)); return s_Sinks[index]; } index = (-1 * index) - 1; Q_ASSERT(s_Sources.contains(index)); return s_Sources[index]; } void AudioSetup::deviceChanged() { int idx = deviceBox->currentIndex(); if (idx < 0) { portLabel->setVisible(false); portBox->setVisible(false); _updatePlacementTester(); return; } qint64 index = deviceBox->itemData(idx).toInt(); deviceInfo &device_info = getDeviceInfo(index); qDebug() << QString("Updating ports for device '%1' (%2 ports available)") .arg(device_info.name) .arg(device_info.ports.size()); bool showPorts = !!device_info.ports.size(); if (showPorts) { portBox->blockSignals(true); portBox->clear(); QMap >::const_iterator it; for (it = device_info.ports.constBegin(); it != device_info.ports.constEnd(); ++it) portBox->insertItem(0, it.value().second, it.value().first); portBox->setCurrentIndex(portBox->findData(device_info.activePort)); portBox->blockSignals(false); } portLabel->setVisible(showPorts); portBox->setVisible(showPorts); if (deviceBox->currentIndex() >= 0) { if (index < 0) _createMonitorStreamForSource((-1*index) - 1); else if (m_VUStream) { pa_stream_disconnect(m_VUStream); m_VUStream = NULL; } _updatePlacementTester(); } emit changed(); } void AudioSetup::portChanged() { qint64 index = deviceBox->itemData(deviceBox->currentIndex()).toInt(); QString port = portBox->itemData(portBox->currentIndex()).toString(); qDebug() << "Changing port to" << port; #ifndef QT_NO_DEBUG deviceInfo &device_info = getDeviceInfo(index); Q_ASSERT(device_info.ports.size()); #endif /* QT_NO_DEBUG */ pa_operation *o; if (index >= 0) { - if (!(o = pa_context_set_sink_port_by_index(s_context, (uint32_t)index, port.toAscii().constData(), NULL, NULL))) + if (!(o = pa_context_set_sink_port_by_index(s_context, (uint32_t)index, port.toLatin1().constData(), NULL, NULL))) qDebug() << "pa_context_set_sink_port_by_index() failed"; else pa_operation_unref(o); } else { - if (!(o = pa_context_set_source_port_by_index(s_context, (uint32_t)((-1*index) - 1), port.toAscii().constData(), NULL, NULL))) + if (!(o = pa_context_set_source_port_by_index(s_context, (uint32_t)((-1*index) - 1), port.toLatin1().constData(), NULL, NULL))) qDebug() << "pa_context_set_source_port_by_index() failed"; else pa_operation_unref(o); } emit changed(); } void AudioSetup::_updatePlacementTester() { static const int position_table[] = { /* Position, X, Y */ PA_CHANNEL_POSITION_FRONT_LEFT, 0, 0, PA_CHANNEL_POSITION_FRONT_LEFT_OF_CENTER, 1, 0, PA_CHANNEL_POSITION_FRONT_CENTER, 2, 0, PA_CHANNEL_POSITION_MONO, 2, 0, PA_CHANNEL_POSITION_FRONT_RIGHT_OF_CENTER, 3, 0, PA_CHANNEL_POSITION_FRONT_RIGHT, 4, 0, PA_CHANNEL_POSITION_SIDE_LEFT, 0, 1, PA_CHANNEL_POSITION_SIDE_RIGHT, 4, 1, PA_CHANNEL_POSITION_REAR_LEFT, 0, 2, PA_CHANNEL_POSITION_REAR_CENTER, 2, 2, PA_CHANNEL_POSITION_REAR_RIGHT, 4, 2, PA_CHANNEL_POSITION_LFE, 3, 2 }; QLayoutItem* w; while ((w = placementGrid->takeAt(0))) { if (w->widget() != m_icon) { if (w->widget()) delete w->widget(); delete w; } } placementGrid->addWidget(m_icon, 1, 2, Qt::AlignCenter); int idx = deviceBox->currentIndex(); if (idx < 0) return; qint64 index = deviceBox->itemData(idx).toInt(); deviceInfo& sink_info = getDeviceInfo(index); if (index < 0) { playbackOrCaptureStack->setCurrentIndex(1); m_VUTimer->start(); return; } playbackOrCaptureStack->setCurrentIndex(0); m_VUTimer->stop(); for (int i = 0; i < 36; i += 3) { pa_channel_position_t pos = (pa_channel_position_t)position_table[i]; // Check to see if we have this item in our current channel map. bool have = false; for (uint32_t j = 0; j < sink_info.channelMap.channels; ++j) { if (sink_info.channelMap.map[j] == pos) { have = true; break; } } if (!have) { continue; } QPushButton *btn = new TestSpeakerWidget(pos, m_Canberra, this); placementGrid->addWidget(btn, position_table[i+2], position_table[i+1], Qt::AlignCenter); } } void AudioSetup::_createMonitorStreamForSource(uint32_t source_idx) { if (m_VUStream) { pa_stream_disconnect(m_VUStream); m_VUStream = NULL; } char t[16]; pa_buffer_attr attr; pa_sample_spec ss; ss.channels = 1; ss.format = PA_SAMPLE_FLOAT32; ss.rate = 25; memset(&attr, 0, sizeof(attr)); attr.fragsize = sizeof(float); attr.maxlength = static_cast(-1); snprintf(t, sizeof(t), "%u", source_idx); m_VUStream = pa_stream_new(s_context, "Peak detect", &ss, NULL); if (!m_VUStream) { qDebug() << "Failed to create monitoring stream"; return; } pa_stream_set_read_callback(m_VUStream, read_callback, this); pa_stream_set_suspended_callback(m_VUStream, suspended_callback, this); if (pa_stream_connect_record(m_VUStream, t, &attr, (pa_stream_flags_t) (PA_STREAM_DONT_MOVE|PA_STREAM_PEAK_DETECT|PA_STREAM_ADJUST_LATENCY)) < 0) { qDebug() << "Failed to connect monitoring stream"; pa_stream_unref(m_VUStream); m_VUStream = NULL; } } quint32 AudioSetup::getCurrentSinkIndex() { int idx = deviceBox->currentIndex(); if (idx < 0) return PA_INVALID_INDEX; qint64 index = deviceBox->itemData(idx).toInt(); if (index >= 0) return static_cast(index); return PA_INVALID_INDEX; } QDebug operator<<(QDebug dbg, const pa_context_state_t &state) { QString name; switch (state) { case PA_CONTEXT_UNCONNECTED: name = QLatin1Literal("Unconnected"); case PA_CONTEXT_CONNECTING: name = QLatin1Literal("Connecting"); case PA_CONTEXT_AUTHORIZING: name = QLatin1Literal("Authorizing"); case PA_CONTEXT_SETTING_NAME: name = QLatin1Literal("Setting Name"); case PA_CONTEXT_READY: name = QLatin1Literal("Ready"); case PA_CONTEXT_FAILED: name = QLatin1Literal("Failed"); case PA_CONTEXT_TERMINATED: name = QLatin1Literal("Terminated"); } if (name.isEmpty()) name = QString("Unknown state(%0)").arg(state); dbg.nospace() << name; return dbg; } diff --git a/kcms/phonon/testspeakerwidget.cpp b/kcms/phonon/testspeakerwidget.cpp index 45572be59..f9e1832f8 100644 --- a/kcms/phonon/testspeakerwidget.cpp +++ b/kcms/phonon/testspeakerwidget.cpp @@ -1,203 +1,203 @@ /* This file is part of the KDE project Copyright (C) 2010 Colin Guthrie This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License version 2 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. */ #include "testspeakerwidget.h" #include #include "audiosetup.h" static uint32_t s_CurrentIndex = PA_INVALID_INDEX; static TestSpeakerWidget *s_CurrentWidget = NULL; static void finish_cb(ca_context *, uint32_t id, int, void *) { Q_ASSERT(id == 0); Q_UNUSED(id); // Suppress compiler warning if QT_NO_DEBUG // Mustn't access QWidgets from a foreign thread, so queue a slot call. QMetaObject::invokeMethod(s_CurrentWidget, "onFinish", Qt::QueuedConnection); } TestSpeakerWidget::TestSpeakerWidget(const pa_channel_position_t pos, ca_context *canberra, AudioSetup* ss) : QPushButton(QIcon::fromTheme("preferences-desktop-sound"), "Test", ss) , m_Ss(ss) , m_Pos(pos) , m_Canberra(canberra) { setCheckable(true); setText(_positionName()); connect(this, &TestSpeakerWidget::toggled, this, &TestSpeakerWidget::onToggle); } TestSpeakerWidget::~TestSpeakerWidget() { if (this == s_CurrentWidget) s_CurrentWidget = NULL; } void TestSpeakerWidget::onToggle(bool state) { if (s_CurrentIndex != PA_INVALID_INDEX) { ca_context_cancel(m_Canberra, s_CurrentIndex); s_CurrentIndex = PA_INVALID_INDEX; } if (s_CurrentWidget) { if (this != s_CurrentWidget && state) s_CurrentWidget->setChecked(false); s_CurrentWidget = NULL; } if (!state) return; uint32_t sink_index = m_Ss->getCurrentSinkIndex(); char dev[64]; snprintf(dev, sizeof(dev), "%lu", (unsigned long) sink_index); ca_context_change_device(m_Canberra, dev); const char* sound_name = _positionSoundName(); ca_proplist* proplist; ca_proplist_create(&proplist); ca_proplist_sets(proplist, CA_PROP_MEDIA_ROLE, "test"); - ca_proplist_sets(proplist, CA_PROP_MEDIA_NAME, _positionName().toAscii().constData()); + ca_proplist_sets(proplist, CA_PROP_MEDIA_NAME, _positionName().toLatin1().constData()); ca_proplist_sets(proplist, CA_PROP_CANBERRA_FORCE_CHANNEL, _positionAsString()); ca_proplist_sets(proplist, CA_PROP_CANBERRA_ENABLE, "1"); ca_proplist_sets(proplist, CA_PROP_EVENT_ID, sound_name); s_CurrentIndex = 0; s_CurrentWidget = this; if (ca_context_play_full(m_Canberra, s_CurrentIndex, proplist, finish_cb, NULL) < 0) { // Try a different sound name. ca_proplist_sets(proplist, CA_PROP_EVENT_ID, "audio-test-signal"); if (ca_context_play_full(m_Canberra, s_CurrentIndex, proplist, finish_cb, NULL) < 0) { // Finaly try this... if this doesn't work, then stuff it. ca_proplist_sets(proplist, CA_PROP_EVENT_ID, "bell-window-system"); if (ca_context_play_full(m_Canberra, s_CurrentIndex, proplist, finish_cb, NULL) < 0) { s_CurrentIndex = PA_INVALID_INDEX; s_CurrentWidget = NULL; setChecked(false); } } } ca_context_change_device(m_Canberra, NULL); ca_proplist_destroy(proplist); } void TestSpeakerWidget::onFinish() { if (s_CurrentWidget && s_CurrentWidget->isChecked()) { s_CurrentIndex = PA_INVALID_INDEX; s_CurrentWidget->setChecked(false); s_CurrentWidget = NULL; } } const char* TestSpeakerWidget::_positionAsString() { switch (m_Pos) { case PA_CHANNEL_POSITION_FRONT_LEFT: return "front-left"; case PA_CHANNEL_POSITION_FRONT_LEFT_OF_CENTER: return "front-left-of-center"; case PA_CHANNEL_POSITION_FRONT_CENTER: return "front-center"; case PA_CHANNEL_POSITION_MONO: return "mono"; case PA_CHANNEL_POSITION_FRONT_RIGHT_OF_CENTER: return "front-right-of-center"; case PA_CHANNEL_POSITION_FRONT_RIGHT: return "front-right"; case PA_CHANNEL_POSITION_SIDE_LEFT: return "side-left"; case PA_CHANNEL_POSITION_SIDE_RIGHT: return "side-right"; case PA_CHANNEL_POSITION_REAR_LEFT: return "rear-left"; case PA_CHANNEL_POSITION_REAR_CENTER: return "rear-center"; case PA_CHANNEL_POSITION_REAR_RIGHT: return "rear-right"; case PA_CHANNEL_POSITION_LFE: return "lfe"; default: break; } return "invalid"; } QString TestSpeakerWidget::_positionName() { switch (m_Pos) { case PA_CHANNEL_POSITION_FRONT_LEFT: return i18n("Front Left"); case PA_CHANNEL_POSITION_FRONT_LEFT_OF_CENTER: return i18n("Front Left of Center"); case PA_CHANNEL_POSITION_FRONT_CENTER: return i18n("Front Center"); case PA_CHANNEL_POSITION_MONO: return i18n("Mono"); case PA_CHANNEL_POSITION_FRONT_RIGHT_OF_CENTER: return i18n("Front Right of Center"); case PA_CHANNEL_POSITION_FRONT_RIGHT: return i18n("Front Right"); case PA_CHANNEL_POSITION_SIDE_LEFT: return i18n("Side Left"); case PA_CHANNEL_POSITION_SIDE_RIGHT: return i18n("Side Right"); case PA_CHANNEL_POSITION_REAR_LEFT: return i18n("Rear Left"); case PA_CHANNEL_POSITION_REAR_CENTER: return i18n("Rear Center"); case PA_CHANNEL_POSITION_REAR_RIGHT: return i18n("Rear Right"); case PA_CHANNEL_POSITION_LFE: return i18n("Subwoofer"); default: break; } return i18n("Unknown Channel"); } const char* TestSpeakerWidget::_positionSoundName() { switch (m_Pos) { case PA_CHANNEL_POSITION_FRONT_LEFT: return "audio-channel-front-left"; case PA_CHANNEL_POSITION_FRONT_RIGHT: return "audio-channel-front-right"; case PA_CHANNEL_POSITION_FRONT_CENTER: return "audio-channel-front-center"; case PA_CHANNEL_POSITION_REAR_LEFT: return "audio-channel-rear-left"; case PA_CHANNEL_POSITION_REAR_RIGHT: return "audio-channel-rear-right"; case PA_CHANNEL_POSITION_REAR_CENTER: return "audio-channel-rear-center"; case PA_CHANNEL_POSITION_LFE: return "audio-channel-lfe"; case PA_CHANNEL_POSITION_SIDE_LEFT: return "audio-channel-side-left"; case PA_CHANNEL_POSITION_SIDE_RIGHT: return "audio-channel-side-right"; default: break; } return NULL; } diff --git a/kcms/solid_actions/ActionModel.cpp b/kcms/solid_actions/ActionModel.cpp index 36a55cf32..dbff6f3a1 100644 --- a/kcms/solid_actions/ActionModel.cpp +++ b/kcms/solid_actions/ActionModel.cpp @@ -1,128 +1,129 @@ /************************************************************************** * 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 "ActionModel.h" #include "ActionItem.h" #include #include #include #include class ActionModel::Private { public: Private() {} QList actions; }; static bool sortAction( ActionItem * left, ActionItem * right ) { return left->name().localeAwareCompare(right->name()) < 0; } ActionModel::ActionModel( QObject *parent ) : QAbstractTableModel( parent ) , d( new Private() ) { } ActionModel::~ActionModel() { qDeleteAll( d->actions ); d->actions.clear(); delete d; } int ActionModel::columnCount( const QModelIndex &parent ) const { Q_UNUSED( parent ); return 2; } int ActionModel::rowCount( const QModelIndex &parent ) const { if( !parent.isValid() ) { return d->actions.count(); } return 0; } QVariant ActionModel::data( const QModelIndex &index, int role ) const { QVariant theData; if ( !index.isValid() ) { return QVariant(); } ActionItem * mi = d->actions.at( index.row() ); switch ( role ) { case Qt::DisplayRole: if( index.column() == 0 ) { theData.setValue( mi->name() ); } else if( index.column() == 1 ) { theData.setValue( mi->involvedTypes() ); } break; case Qt::DecorationRole: if( index.column() == 0 ) { theData = QIcon::fromTheme(mi->icon()); } break; case Qt::UserRole: theData.setValue( mi ); break; default: break; } return theData; } void ActionModel::buildActionList() { + beginResetModel(); qDeleteAll( d->actions ); d->actions.clear(); // Prepare to search for possible actions -> we only want solid types const QStringList actionDirs = QStandardPaths::locateAll(QStandardPaths::GenericDataLocation, QStringLiteral("solid/actions"), QStandardPaths::LocateDirectory); // Get service objects for those actions and add them to the display foreach (const QString & actionDir, actionDirs) { QDirIterator it(actionDir, QStringList() << QStringLiteral("*.desktop")); while (it.hasNext()) { it.next(); const QString desktop = it.filePath(); // Get contained services list QList services = KDesktopFileActions::userDefinedServices(desktop, true); foreach( const KServiceAction &deviceAction, services ) { ActionItem * actionItem = new ActionItem( desktop, deviceAction.name(), this ); // Create an action d->actions.append( actionItem ); } } } qSort( d->actions.begin(), d->actions.end(), sortAction ); - reset(); + endResetModel(); } QList ActionModel::actionList() const { return d->actions; } diff --git a/kcms/solid_actions/PredicateModel.cpp b/kcms/solid_actions/PredicateModel.cpp index 7d3a9dac9..9c59e763d 100644 --- a/kcms/solid_actions/PredicateModel.cpp +++ b/kcms/solid_actions/PredicateModel.cpp @@ -1,175 +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 = 0; 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 0; } 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; - reset(); + 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(); } } diff --git a/kcms/solid_actions/SolidActions.cpp b/kcms/solid_actions/SolidActions.cpp index 9b607d966..38bf8e1a8 100644 --- a/kcms/solid_actions/SolidActions.cpp +++ b/kcms/solid_actions/SolidActions.cpp @@ -1,235 +1,235 @@ /*************************************************************************** * Copyright (C) 2009 by Ben Cooksley * * * * 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 "SolidActions.h" #include "ActionItem.h" #include #include #include #include #include #include #include #include #include #include #include #include K_PLUGIN_FACTORY( SolidActionsFactory, registerPlugin(); ) SolidActions::SolidActions(QWidget* parent, const QVariantList&) : KCModule(parent) { KAboutData * about = new KAboutData(QStringLiteral("Device Actions"), i18n("Solid Device Actions Editor"), QStringLiteral("1.2"), i18n("Solid Device Actions Control Panel Module"), KAboutLicense::GPL, i18n("(c) 2009, 2014 Solid Device Actions team")); about->addAuthor(i18n("Ben Cooksley"), i18n("Maintainer"), QStringLiteral("ben@eclipse.endoftheinternet.org")); about->addCredit(QStringLiteral("Lukáš Tinkl"), i18n("Port to Plasma 5"), QStringLiteral("ltinkl@redhat.com")); setAboutData(about); setButtons(KCModule::Help); // Prepare main display dialog actionModel = new ActionModel( this ); mainUi.setupUi( this ); mainUi.TvActions->setModel( actionModel ); mainUi.TvActions->setHeaderHidden( true ); mainUi.TvActions->setRootIsDecorated( false ); mainUi.TvActions->setSelectionMode( QAbstractItemView::SingleSelection ); KStandardGuiItem::assign(mainUi.PbAddAction, KStandardGuiItem::Add); mainUi.PbEditAction->setIcon( QIcon::fromTheme(QStringLiteral("document-edit")) ); connect(mainUi.PbAddAction, &QPushButton::clicked, this, &SolidActions::slotShowAddDialog); connect(mainUi.PbEditAction, &QPushButton::clicked, this, &SolidActions::editAction); connect(mainUi.PbDeleteAction, &QPushButton::clicked, this, &SolidActions::deleteAction); connect( mainUi.TvActions->selectionModel(), &QItemSelectionModel::currentChanged, this, &SolidActions::toggleEditDelete ); connect(mainUi.TvActions, &QTreeView::doubleClicked, this, &SolidActions::editAction); // Prepare + connect up with Edit dialog editUi = new ActionEditor(this); connect(editUi, &ActionEditor::accepted, this, &SolidActions::acceptActionChanges); // Prepare + connect up add action dialog addDialog = new QDialog(this); addUi.setupUi( addDialog ); addDialog->resize(QSize(300, 100)); // Set a sensible default size slotTextChanged( addUi.LeActionName->text() ); connect(addUi.LeActionName, &QLineEdit::textChanged, this, &SolidActions::slotTextChanged); connect(addUi.buttonBox, &QDialogButtonBox::accepted, this, &SolidActions::addAction); connect(addUi.buttonBox, &QDialogButtonBox::rejected, addDialog, &QDialog::reject); } SolidActions::~SolidActions() { delete editUi; delete actionModel; } void SolidActions::slotShowAddDialog() { addDialog->show(); addUi.LeActionName->setFocus(); addUi.LeActionName->clear(); } void SolidActions::slotTextChanged( const QString & text ) { addUi.buttonBox->button(QDialogButtonBox::Ok)->setEnabled(!text.isEmpty()); } void SolidActions::load() { fillActionsList(); } void SolidActions::defaults() { } void SolidActions::save() { } void SolidActions::addAction() { const QString enteredName = addUi.LeActionName->text(); KDesktopFile templateDesktop(QStandardPaths::GenericDataLocation, QStringLiteral("kcmsolidactions/solid-action-template.desktop")); // Lets get the template // Lets get a desktop file QString internalName = enteredName; // copy the name the user entered -> we will be making mods internalName.replace(QChar(' '), QChar('-'), Qt::CaseSensitive); // replace spaces with dashes QString filePath = QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation) + "/solid/actions/"; // Get the location on disk for "data" if (!QDir().exists(filePath)) { QDir().mkpath(filePath); } filePath += internalName + ".desktop"; // Fill in an initial template KDesktopFile * newDesktop = templateDesktop.copyTo(filePath); newDesktop->actionGroup(QStringLiteral("open")).writeEntry("Name", enteredName); // ditto delete newDesktop; // Force file to be written // Prepare to open the editDialog fillActionsList(); QList actionList = actionModel->actionList(); QModelIndex newAction; foreach( ActionItem * newItem, actionList ) { // Lets find our new action if( newItem->desktopMasterPath == filePath ) { const int position = actionList.indexOf( newItem ); newAction = actionModel->index( position, 0 ); // Grab it break; } } mainUi.TvActions->setCurrentIndex( newAction ); // Set it as currently active addDialog->hide(); editAction(); // Open the edit dialog } void SolidActions::editAction() { ActionItem * selectedItem = selectedAction(); if( !selectedItem ) { return; } // We should error out here if we have to if( !selectedItem->predicate().isValid() ) { KMessageBox::error(this, i18n("It appears that the predicate for this action is not valid."), i18n("Error Parsing Device Conditions")); return; } // Display us! editUi->setActionToEdit( selectedItem ); editUi->setWindowIcon( windowIcon() ); editUi->show(); } void SolidActions::deleteAction() { ActionItem * action = selectedAction(); if( action->isUserSupplied() ) { // Is the action user supplied? QFile::remove(action->desktopMasterPath); // Remove the main desktop file then } QFile::remove(action->desktopWritePath); // Remove the modified desktop file now fillActionsList(); // Update the list of actions } ActionItem * SolidActions::selectedAction() const { QModelIndex action = mainUi.TvActions->currentIndex(); ActionItem * actionItem = actionModel->data( action, Qt::UserRole ).value(); return actionItem; } void SolidActions::fillActionsList() { mainUi.TvActions->clearSelection(); actionModel->buildActionList(); - mainUi.TvActions->header()->setResizeMode( 0, QHeaderView::Stretch ); - mainUi.TvActions->header()->setResizeMode( 1, QHeaderView::ResizeToContents ); + mainUi.TvActions->header()->setSectionResizeMode( 0, QHeaderView::Stretch ); + mainUi.TvActions->header()->setSectionResizeMode( 1, QHeaderView::ResizeToContents ); toggleEditDelete(); } void SolidActions::acceptActionChanges() { // Re-read the actions list to ensure changes are reflected KBuildSycocaProgressDialog::rebuildKSycoca(this); fillActionsList(); } void SolidActions::toggleEditDelete() { bool toggle = true; if( !mainUi.TvActions->currentIndex().isValid() ) { // Is an action selected? mainUi.PbDeleteAction->setText( i18n("No Action Selected") ); // Set a friendly disabled text mainUi.PbDeleteAction->setIcon( QIcon() ); toggle = false; } mainUi.PbEditAction->setEnabled(toggle); // Change them to the new state mainUi.PbDeleteAction->setEnabled(toggle); // Ditto if( !toggle ) { return; } // What functionality do we need to change? if( selectedAction()->isUserSupplied() ) { // We are able to directly delete it, enable full delete functionality KStandardGuiItem::assign(mainUi.PbDeleteAction, KStandardGuiItem::Remove); } else if( QFile::exists(selectedAction()->desktopWritePath) ) { // Does the write file exist? // We are able to revert, lets show it KStandardGuiItem::assign(mainUi.PbDeleteAction, KStandardGuiItem::Discard); } else { // We cannot do anything then, disable delete functionality mainUi.PbDeleteAction->setText( i18n("Cannot be deleted") ); mainUi.PbDeleteAction->setIcon( QIcon() ); mainUi.PbDeleteAction->setEnabled( false ); } } #include "SolidActions.moc"