diff --git a/containments/desktop/package/contents/ui/ConfigFilter.qml b/containments/desktop/package/contents/ui/ConfigFilter.qml index ce753cc3a..c9b08a5d2 100644 --- a/containments/desktop/package/contents/ui/ConfigFilter.qml +++ b/containments/desktop/package/contents/ui/ConfigFilter.qml @@ -1,238 +1,255 @@ /*************************************************************************** * 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 . * ***************************************************************************/ import QtQuick 2.0 import QtQuick.Controls 1.0 import QtQuick.Layouts 1.0 import org.kde.plasma.core 2.0 as PlasmaCore import org.kde.private.desktopcontainment.folder 0.1 as Folder Item { id: configIcons width: childrenRect.width height: childrenRect.height property alias cfg_filterMode: filterMode.currentIndex property alias cfg_filterPattern: filterPattern.text property alias cfg_filterMimeTypes: mimeTypesModel.checkedTypes PlasmaCore.SortFilterModel { - id: filderedMimeTypesModel + id: filteredMimeTypesModel sourceModel: Folder.MimeTypesModel { id: mimeTypesModel } // SortFilterModel doesn't have a case-sensitivity option // but filterRegExp always causes case-insensitive sorting. filterRegExp: mimeFilter.text filterRole: "name" sortRole: mimeTypesView.getColumn(mimeTypesView.sortIndicatorColumn).role sortOrder: mimeTypesView.sortIndicatorOrder + + function checkFiltered() { + var types = []; + + for (var i = 0; i < count; ++i) { + types.push(get(i).name); + } + + mimeTypesModel.checkedTypes = types; + } + + function uncheckFiltered() { + var types = []; + + for (var i = 0; i < count; ++i) { + types.push(get(i).name); + } + + mimeTypesModel.checkedTypes = mimeTypesModel.checkedTypes.filter(function(x) { + return types.indexOf(x) < 0; }); + } } ColumnLayout { width: parent.width height: parent.height ComboBox { id: filterMode Layout.fillWidth: true model: [i18n("Show All Files"), i18n("Show Files Matching"), i18n("Hide Files Matching")] } Label { Layout.fillWidth: true text: i18n("File name pattern:") } TextField { id: filterPattern Layout.fillWidth: true enabled: (filterMode.currentIndex > 0) } Label { Layout.fillWidth: true text: i18n("File types:") } TextField { id: mimeFilter Layout.fillWidth: true enabled: (filterMode.currentIndex > 0) placeholderText: i18n("Search file type...") } RowLayout { Layout.fillWidth: true Layout.fillHeight: true CheckBox { // Purely for metrics. id: metricsCheckBox visible: false } TableView { id: mimeTypesView // Signal the delegates listen to when user presses space to toggle current row. signal toggleCurrent Layout.fillWidth: true Layout.fillHeight: true enabled: (filterMode.currentIndex > 0) - model: filderedMimeTypesModel + model: filteredMimeTypesModel sortIndicatorVisible: true sortIndicatorColumn: 2 // Default to sort by "File type". onSortIndicatorColumnChanged: { // Disallow sorting by icon. if (sortIndicatorColumn === 1) { sortIndicatorColumn = 2; } } Keys.onSpacePressed: toggleCurrent() function adjustColumns() { // Resize description column to take whatever space is left. var width = viewport.width; for (var i = 0; i < columnCount - 1; ++i) { width -= getColumn(i).width; } descriptionColumn.width = width; } onWidthChanged: adjustColumns() // Component.onCompleted is too early to do this... onRowCountChanged: adjustColumns() TableViewColumn { role: "checked" width: metricsCheckBox.width resizable: false movable: false delegate: CheckBox { id: checkBox checked: styleData.value activeFocusOnTab: false // only let the TableView as a whole get focus onClicked: { model.checked = checked // Clicking it breaks the binding to the model value which becomes // an issue during sorting as TableView re-uses delegates. checked = Qt.binding(function() { return styleData.value; }); } Connections { target: mimeTypesView onToggleCurrent: { if (styleData.row === mimeTypesView.currentRow) { model.checked = !checkBox.checked } } } } } TableViewColumn { role: "decoration" width: units.iconSizes.small resizable: false movable: false delegate: PlasmaCore.IconItem { width: units.iconSizes.small height: units.iconSizes.small animated: false // TableView re-uses delegates, avoid animation when sorting/filtering. source: styleData.value } } TableViewColumn { id: nameColumn role: "name" title: i18n("File type") width: units.gridUnit * 10 // Assume somewhat reasonable default for mime type name. onWidthChanged: mimeTypesView.adjustColumns() movable: false } TableViewColumn { id: descriptionColumn role: "comment" title: i18n("Description") movable: false resizable: false } } ColumnLayout { Layout.alignment: Qt.AlignTop // Need to explicitly base the size off the button's implicitWidth // to avoid the column from growing way too wide due to fillWidth... Layout.maximumWidth: Math.max(selectAllButton.implicitWidth, deselectAllButton.implicitWidth) Button { id: selectAllButton Layout.fillWidth: true enabled: (filterMode.currentIndex > 0) text: i18n("Select All") - onClicked: { - mimeTypesModel.checkAll(); - } + onClicked: filteredMimeTypesModel.checkFiltered() } Button { id: deselectAllButton Layout.fillWidth: true enabled: (filterMode.currentIndex > 0) text: i18n("Deselect All") - onClicked: { - mimeTypesModel.checkedTypes = ""; - } + onClicked: filteredMimeTypesModel.uncheckFiltered() } } } } } diff --git a/containments/desktop/plugins/folder/mimetypesmodel.cpp b/containments/desktop/plugins/folder/mimetypesmodel.cpp index 6701e1f0a..96670c492 100644 --- a/containments/desktop/plugins/folder/mimetypesmodel.cpp +++ b/containments/desktop/plugins/folder/mimetypesmodel.cpp @@ -1,152 +1,143 @@ /*************************************************************************** * 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) { QMimeDatabase db; m_mimeTypesList = db.allMimeTypes(); qStableSort(m_mimeTypesList.begin(), m_mimeTypesList.end(), lessThan); m_checkedRows = QVector(m_mimeTypesList.size(), false); } MimeTypesModel::~MimeTypesModel() { } QHash MimeTypesModel::roleNames() const { return { { Qt::DisplayRole, "comment" }, { Qt::UserRole, "name" }, { 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()).comment(); case Qt::UserRole: 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 m_checkedRows.at(index.row()) ? Qt::Checked : Qt::Unchecked; } return QVariant(); } bool MimeTypesModel::setData(const QModelIndex &index, const QVariant &value, int role) { if (index.row() < 0 || index.row() >= m_mimeTypesList.size()) { return false; } if (role == Qt::CheckStateRole) { const bool newChecked = value.toBool(); if (m_checkedRows.at(index.row()) != newChecked) { m_checkedRows[index.row()] = newChecked; emit dataChanged(index, index, {role}); emit checkedTypesChanged(); return true; } } return false; } -void MimeTypesModel::checkAll() -{ - m_checkedRows = QVector(m_mimeTypesList.size(), true); - - emit dataChanged(index(0, 0), index(m_mimeTypesList.size() - 1, 0), {Qt::CheckStateRole}); - - 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 < m_checkedRows.size(); ++i) { if (m_checkedRows.at(i)) { list.append(m_mimeTypesList.at(i).name()); } } if (!list.isEmpty()) { return list; } return QStringList(QLatin1String("")); } void MimeTypesModel::setCheckedTypes(const QStringList &list) { m_checkedRows = QVector(m_mimeTypesList.size(), false); foreach (const QString &name, list) { const int row = indexOfType(name); if (row != -1) { m_checkedRows[row] = true; } } emit dataChanged(index(0, 0), index(m_mimeTypesList.size() - 1, 0), {Qt::CheckStateRole}); emit checkedTypesChanged(); } diff --git a/containments/desktop/plugins/folder/mimetypesmodel.h b/containments/desktop/plugins/folder/mimetypesmodel.h index cc4ec46cf..a9eede44d 100644 --- a/containments/desktop/plugins/folder/mimetypesmodel.h +++ b/containments/desktop/plugins/folder/mimetypesmodel.h @@ -1,59 +1,57 @@ /*************************************************************************** * 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 class QStringList; class MimeTypesModel : public QAbstractListModel { Q_OBJECT Q_PROPERTY(QStringList checkedTypes READ checkedTypes WRITE setCheckedTypes NOTIFY checkedTypesChanged) public: explicit MimeTypesModel(QObject *parent = nullptr); ~MimeTypesModel(); QHash roleNames() const override; QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override; bool setData(const QModelIndex &index, const QVariant &value, int role) override; - Q_INVOKABLE void checkAll(); - int rowCount(const QModelIndex &parent = QModelIndex()) const override { 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 m_checkedRows; }; #endif