diff --git a/kcms/baloo/CMakeLists.txt b/kcms/baloo/CMakeLists.txt --- a/kcms/baloo/CMakeLists.txt +++ b/kcms/baloo/CMakeLists.txt @@ -3,27 +3,25 @@ set(kcm_file_SRCS kcm.cpp fileexcludefilters.cpp - folderselectionwidget.cpp -) - -ki18n_wrap_ui(kcm_file_SRCS - configwidget.ui + filteredfoldermodel.cpp ) add_library(kcm_baloofile MODULE ${kcm_file_SRCS}) target_link_libraries(kcm_baloofile - KF5::KIOWidgets KF5::CoreAddons KF5::KCMUtils KF5::I18n KF5::Solid KF5::Baloo - + KF5::QuickAddons Qt5::DBus Qt5::Widgets ) +kcoreaddons_desktop_to_json(kcm_baloofile "kcm_baloofile.desktop") install(FILES kcm_baloofile.desktop DESTINATION ${KDE_INSTALL_KSERVICES5DIR}) -install(TARGETS kcm_baloofile DESTINATION ${KDE_INSTALL_PLUGINDIR}) +install(TARGETS kcm_baloofile DESTINATION ${KDE_INSTALL_PLUGINDIR}/kcms) + +kpackage_install_package(package kcm_baloofile kcms) diff --git a/kcms/baloo/configwidget.ui b/kcms/baloo/configwidget.ui deleted file mode 100644 --- a/kcms/baloo/configwidget.ui +++ /dev/null @@ -1,104 +0,0 @@ - - - Vishesh Handa - ConfigWidget - - - - 0 - 0 - 669 - 671 - - - - - - - - - - 0 - 0 - - - - File Search helps you quickly locate all your files based on their content - - - true - - - - - - - - - Enable File Search - - - - - - - Also index file content - - - - - - - Qt::Vertical - - - QSizePolicy::Fixed - - - - 1 - 20 - - - - - - - - - - - 0 - 0 - - - - Do not search in these locations: - - - true - - - - - - - - - - - - - - - - - FolderSelectionWidget - QWidget -
folderselectionwidget.h
- 1 -
-
- - -
diff --git a/kcms/baloo/folderselectionwidget.h b/kcms/baloo/filteredfoldermodel.h rename from kcms/baloo/folderselectionwidget.h rename to kcms/baloo/filteredfoldermodel.h --- a/kcms/baloo/folderselectionwidget.h +++ b/kcms/baloo/filteredfoldermodel.h @@ -21,33 +21,29 @@ #ifndef FOLDERSELECTIONWIDGET_H #define FOLDERSELECTIONWIDGET_H -#include -#include -#include -#include +#include -class FolderSelectionWidget : public QWidget +class FilteredFolderModel : public QAbstractListModel { Q_OBJECT public: - explicit FolderSelectionWidget(QWidget* parent = nullptr, Qt::WindowFlags f = Qt::WindowFlags()); + explicit FilteredFolderModel(QObject* parent); - void setDirectoryList(QStringList includeDirs, QStringList exclude); + void setDirectoryList(const QStringList& includeDirs, const QStringList& exclude); QStringList includeFolders() const; QStringList excludeFolders() const; enum Roles { - UrlRole = Qt::UserRole + 1 + Folder = Qt::UserRole + 1, + Url }; -Q_SIGNALS: - void changed(); - -private Q_SLOTS: - void slotAddButtonClicked(); - void slotRemoveButtonClicked(); - void slotCurrentItemChanged(QListWidgetItem* current, QListWidgetItem*); + QVariant data(const QModelIndex& idx, int role) const override; + int rowCount(const QModelIndex& parent) const override; + Q_INVOKABLE void addFolder(const QString& folder); + Q_INVOKABLE void removeFolder(int row); + QHash roleNames() const override; private: QString folderDisplayName(const QString& url) const; bool shouldShowMountPoint(const QString& mountPoint); @@ -66,25 +62,8 @@ * @brief Widget with the list of directories. * */ - QListWidget* m_listWidget; QStringList m_mountPoints; - - /** - * @brief Button to add a directory to the list. - * - */ - QPushButton* m_addButton; - /** - * @brief Button to remove the selected directory from the list. - * - */ - QPushButton* m_removeButton; - - /** - * @brief Information, warning or error message widget. - * - */ - KMessageWidget* m_messageWidget; + QStringList m_excludeList; }; #endif // FOLDERSELECTIONWIDGET_H diff --git a/kcms/baloo/filteredfoldermodel.cpp b/kcms/baloo/filteredfoldermodel.cpp new file mode 100644 --- /dev/null +++ b/kcms/baloo/filteredfoldermodel.cpp @@ -0,0 +1,246 @@ +/* + * This file is part of the KDE Baloo Project + * Copyright (C) 2014 Vishesh Handa + * Copyright (C) 2019 Tomaz Canabrava + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#include "filteredfoldermodel.h" + +#include +#include +#include + +#include + +#include +#include +#include +#include +#include + +FilteredFolderModel::FilteredFolderModel(QObject* parent) + : QAbstractListModel(parent) +{ +} + +namespace { + QStringList addTrailingSlashes(const QStringList& input) { + QStringList output = input; + + for (QString& str : output) { + if (!str.endsWith(QDir::separator())) + str.append(QDir::separator()); + } + + return output; + } + + QString makeHomePretty(const QString& url) { + if (url.startsWith(QDir::homePath())) + return QString(url).replace(0, QDir::homePath().length(), QStringLiteral("~")); + return url; + } +} + +void FilteredFolderModel::setDirectoryList(const QStringList& include, const QStringList& exclude) +{ + beginResetModel(); + + m_mountPoints.clear(); + + QList devices = Solid::Device::listFromType(Solid::DeviceInterface::StorageAccess); + + for (const Solid::Device& dev : devices) { + const Solid::StorageAccess* sa = dev.as(); + if (!sa->isAccessible()) + continue; + + const QString mountPath = sa->filePath(); + if (!shouldShowMountPoint(mountPath)) + continue; + + m_mountPoints.append(mountPath); + } + m_mountPoints.append(QDir::homePath()); + m_mountPoints = addTrailingSlashes(m_mountPoints); + + QStringList includeList = addTrailingSlashes(include); + + m_excludeList = addTrailingSlashes(exclude); + + // This algorithm seems bogus. verify later. + for (const QString& mountPath : m_mountPoints) { + if (includeList.contains(mountPath)) + continue; + + if (exclude.contains(mountPath)) + continue; + + if (!m_excludeList.contains(mountPath)) { + m_excludeList.append(mountPath); + } + } + + endResetModel(); +} + +QVariant FilteredFolderModel::data(const QModelIndex& idx, int role) const +{ + if (!idx.isValid() || idx.row() >= m_excludeList.size()) { + return {}; + } + + const auto currentUrl = m_excludeList.at(idx.row()); + switch (role) { + case Qt::DisplayRole: return folderDisplayName(currentUrl); + case Qt::WhatsThisRole: return currentUrl; + case Qt::DecorationRole: return QIcon::fromTheme(iconName(currentUrl)); + case Qt::ToolTipRole: return makeHomePretty(currentUrl); + case Url: return currentUrl; + case Folder: return folderDisplayName(currentUrl); + default: + return {}; + } + + return {}; + } + +int FilteredFolderModel::rowCount(const QModelIndex& parent) const +{ + Q_UNUSED(parent); + return m_excludeList.count(); +} + +QStringList FilteredFolderModel::includeFolders() const +{ + const QSet mountPointSet = + QSet::fromList(m_excludeList) + - QSet::fromList(m_mountPoints); + + return mountPointSet.toList(); +} + +QStringList FilteredFolderModel::excludeFolders() const +{ + return m_excludeList; +} + +QString FilteredFolderModel::fetchMountPoint(const QString& url) const +{ + QString mountPoint; + + Q_FOREACH (const QString& mount, m_mountPoints) { + if (url.startsWith(mount) && mount.size() > mountPoint.size()) + mountPoint = mount; + } + + return mountPoint; +} + + +void FilteredFolderModel::addFolder(const QString& url) +{ + if (m_excludeList.contains(url)) { + return; + } + beginResetModel(); + m_excludeList.append(url); + std::sort(std::begin(m_excludeList), std::end(m_excludeList)); + endResetModel(); +} + +void FilteredFolderModel::removeFolder(int row) +{ + beginRemoveRows(QModelIndex(), row, row); + m_excludeList.removeAt(row); + endResetModel(); +} + + +QString FilteredFolderModel::folderDisplayName(const QString& url) const +{ + QString name = url; + + // Check Home Dir + QString homePath = QDir::homePath() + QLatin1Char('/'); + if (url == homePath) { + return QDir(homePath).dirName(); + } + + if (url.startsWith(homePath)) { + name = url.mid(homePath.size()); + } + else { + // Check Mount allMountPointsExcluded + for (QString mountPoint : m_mountPoints) { + if (url.startsWith(mountPoint)) { + name = QLatin1Char('[') + QDir(mountPoint).dirName() + QLatin1String("]/") + url.mid(mountPoint.length()); + break; + } + } + } + + if (name.endsWith(QLatin1Char('/'))) { + name = name.mid(0, name.size() - 1); + } + return name; +} + +bool FilteredFolderModel::shouldShowMountPoint(const QString& mountPoint) +{ + if (mountPoint == QLatin1String("/")) + return false; + + if (mountPoint.startsWith(QLatin1String("/boot"))) + return false; + + if (mountPoint.startsWith(QLatin1String("/tmp"))) + return false; + + // The user's home directory is forcibly added so we can ignore /home + // if /home actually contains the home directory + return !(mountPoint.startsWith(QLatin1String("/home")) || !QDir::homePath().startsWith(QLatin1String("/home"))); +} + +QHash FilteredFolderModel::roleNames() const +{ + return { + {Url, "Url"}, + {Folder, "Folder"} + }; +} + +QString FilteredFolderModel::iconName(QString path) const +{ + // Ensure paths end with / + if (!path.endsWith(QDir::separator())) + path.append(QDir::separator()); + + QString homePath = QDir::homePath(); + if (!homePath.endsWith(QDir::separator())) + homePath.append(QDir::separator()); + + if (path == homePath) + return QStringLiteral("user-home"); + + if (m_mountPoints.contains(path)) + return QStringLiteral("drive-harddisk"); + + return QStringLiteral("folder"); +} + diff --git a/kcms/baloo/folderselectionwidget.cpp b/kcms/baloo/folderselectionwidget.cpp deleted file mode 100644 --- a/kcms/baloo/folderselectionwidget.cpp +++ /dev/null @@ -1,357 +0,0 @@ -/* - * This file is part of the KDE Baloo Project - * Copyright (C) 2014 Vishesh Handa - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - */ - -#include "folderselectionwidget.h" - -#include -#include -#include - -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include - -FolderSelectionWidget::FolderSelectionWidget(QWidget* parent, Qt::WindowFlags f) - : QWidget(parent, f) -{ - m_listWidget = new QListWidget(this); - m_listWidget->setAlternatingRowColors(true); - - m_messageWidget = new KMessageWidget(this); - m_messageWidget->hide(); - - QVBoxLayout* layout = new QVBoxLayout(this); - layout->addWidget(m_messageWidget); - layout->addWidget(m_listWidget); - - QHBoxLayout* hLayout = new QHBoxLayout; - - m_addButton = new QPushButton(this); - m_addButton->setIcon(QIcon::fromTheme(QStringLiteral("list-add"))); - connect(m_addButton, &QPushButton::clicked, this, &FolderSelectionWidget::slotAddButtonClicked); - - m_removeButton = new QPushButton(this); - m_removeButton->setIcon(QIcon::fromTheme(QStringLiteral("list-remove"))); - m_removeButton->setEnabled(false); - connect(m_removeButton, &QPushButton::clicked, this, &FolderSelectionWidget::slotRemoveButtonClicked); - - connect(m_listWidget, &QListWidget::currentItemChanged, this, &FolderSelectionWidget::slotCurrentItemChanged); - - hLayout->addWidget(m_addButton); - hLayout->addWidget(m_removeButton); - - QSpacerItem* spacer = new QSpacerItem(0, 0, QSizePolicy::Expanding, QSizePolicy::Minimum); - hLayout->addItem(spacer); - - layout->addItem(hLayout); -} - -namespace { - QStringList addTrailingSlashes(const QStringList& input) { - QStringList output; - Q_FOREACH (QString str, input) { - if (!str.endsWith(QDir::separator())) - str.append(QDir::separator()); - - output << str; - } - - return output; - } - - QString makeHomePretty(const QString& url) { - if (url.startsWith(QDir::homePath())) - return QString(url).replace(0, QDir::homePath().length(), QStringLiteral("~")); - return url; - } -} -void FolderSelectionWidget::setDirectoryList(QStringList includeDirs, QStringList exclude) -{ - m_listWidget->clear(); - m_mountPoints.clear(); - - QList devices - = Solid::Device::listFromType(Solid::DeviceInterface::StorageAccess); - - Q_FOREACH (const Solid::Device& dev, devices) { - const Solid::StorageAccess* sa = dev.as(); - if (!sa->isAccessible()) - continue; - - QString mountPath = sa->filePath(); - if (!shouldShowMountPoint(mountPath)) - continue; - - m_mountPoints << mountPath; - } - m_mountPoints << QDir::homePath(); - - m_mountPoints = addTrailingSlashes(m_mountPoints); - includeDirs = addTrailingSlashes(includeDirs); - exclude = addTrailingSlashes(exclude); - - QStringList excludeList = exclude; - Q_FOREACH (const QString& mountPath, m_mountPoints) { - if (includeDirs.contains(mountPath)) - continue; - - if (exclude.contains(mountPath)) - continue; - - if (!excludeList.contains(mountPath)) { - excludeList << mountPath; - } - } - - Q_FOREACH (QString url, excludeList) { - QListWidgetItem* item = new QListWidgetItem(m_listWidget); - QString display = folderDisplayName(url); - - item->setData(Qt::DisplayRole, display); - item->setData(Qt::WhatsThisRole, url); - item->setData(UrlRole, url); - item->setData(Qt::DecorationRole, QIcon::fromTheme(iconName(url))); - item->setToolTip(makeHomePretty(url)); - - m_listWidget->addItem(item); - } - - if (m_listWidget->count() == 0) { - m_removeButton->setEnabled(false); - } -} - -QStringList FolderSelectionWidget::includeFolders() const -{ - QStringList folders; - Q_FOREACH (const QString& mountPath, m_mountPoints) { - bool inExclude = false; - for (int i=0; icount(); ++i) { - QListWidgetItem* item = m_listWidget->item(i); - QString url = item->data(UrlRole).toString(); - - if (mountPath == url) { - inExclude = true; - break; - } - } - - if (!inExclude && !folders.contains(mountPath)) { - folders << mountPath; - } - } - - return folders; -} - -QStringList FolderSelectionWidget::excludeFolders() const -{ - QStringList folders; - for (int i=0; icount(); ++i) { - QListWidgetItem* item = m_listWidget->item(i); - QString url = item->data(UrlRole).toString(); - - if (!folders.contains(url)) { - folders << url; - } - } - - return folders; -} - -QString FolderSelectionWidget::fetchMountPoint(const QString& url) const -{ - QString mountPoint; - - Q_FOREACH (const QString& mount, m_mountPoints) { - if (url.startsWith(mount) && mount.size() > mountPoint.size()) - mountPoint = mount; - } - - return mountPoint; -} - - -void FolderSelectionWidget::slotAddButtonClicked() -{ - QString url = QFileDialog::getExistingDirectory(this, i18n("Select the folder which should be excluded")); - if (url.isEmpty()) { - return; - } - - if (!url.endsWith(QDir::separator())) - url.append(QDir::separator()); - - // We don't care about the root dir - if (url == QLatin1String("/")) { - showMessage(i18n("Not allowed to exclude root folder, please disable File Search if you do not want it")); - return; - } - - // Remove any existing folder with that name - // Remove any folder which is a sub-folder - QVector deleteList; - - for (int i=0; icount(); ++i) { - QListWidgetItem* item = m_listWidget->item(i); - QString existingUrl = item->data(UrlRole).toString(); - - if (existingUrl == url) { - QString name = QUrl::fromLocalFile(url).fileName(); - showMessage(i18n("Folder %1 is already excluded", name)); - - deleteList << item; - continue; - } - - QString existingMountPoint = fetchMountPoint(existingUrl); - QString mountPoint = fetchMountPoint(url); - - if (existingMountPoint == mountPoint) { - // existingUrl is not required since it comes under url - if (existingUrl.startsWith(url)) { - deleteList << item; - } - else if (url.startsWith(existingUrl)) { - // No point adding ourselves since our parents exists - // we just move the parent to the bottom - url = existingUrl; - deleteList << item; - - QString name = QUrl::fromLocalFile(url).adjusted(QUrl::StripTrailingSlash).fileName(); - showMessage(i18n("Folder's parent %1 is already excluded", name)); - } - } - } - qDeleteAll(deleteList); - - QListWidgetItem* item = new QListWidgetItem(m_listWidget); - QString displayName = folderDisplayName(url); - - item->setData(Qt::DisplayRole, displayName); - item->setData(Qt::WhatsThisRole, url); - item->setData(UrlRole, url); - item->setData(Qt::DecorationRole, QIcon::fromTheme(iconName(url))); - item->setToolTip(makeHomePretty(url)); - - m_listWidget->addItem(item); - m_listWidget->setCurrentItem(item); - - Q_EMIT changed(); -} - -void FolderSelectionWidget::slotRemoveButtonClicked() -{ - QListWidgetItem* item = m_listWidget->currentItem(); - delete item; - - Q_EMIT changed(); -} - -void FolderSelectionWidget::slotCurrentItemChanged(QListWidgetItem* current, QListWidgetItem*) -{ - m_removeButton->setEnabled(current != nullptr); -} - -void FolderSelectionWidget::showMessage(const QString& message) -{ - m_messageWidget->setText(message); - m_messageWidget->setMessageType(KMessageWidget::Warning); - m_messageWidget->animatedShow(); - - QTimer::singleShot(3000, m_messageWidget, &KMessageWidget::animatedHide); -} - - -QString FolderSelectionWidget::folderDisplayName(const QString& url) const -{ - QString name = url; - - // Check Home Dir - QString homePath = QDir::homePath() + QLatin1Char('/'); - if (url == homePath) { - return QDir(homePath).dirName(); - } - - if (url.startsWith(homePath)) { - name = url.mid(homePath.size()); - } - else { - // Check Mount allMountPointsExcluded - Q_FOREACH (QString mountPoint, m_mountPoints) { - if (url.startsWith(mountPoint)) { - name = QLatin1Char('[') + QDir(mountPoint).dirName() + QLatin1String("]/") + url.mid(mountPoint.length()); - break; - } - } - } - - if (name.endsWith(QLatin1Char('/'))) { - name = name.mid(0, name.size() - 1); - } - return name; -} - -bool FolderSelectionWidget::shouldShowMountPoint(const QString& mountPoint) -{ - if (mountPoint == QLatin1String("/")) - return false; - - if (mountPoint.startsWith(QLatin1String("/boot"))) - return false; - - if (mountPoint.startsWith(QLatin1String("/tmp"))) - return false; - - // The user's home directory is forcibly added so we can ignore /home - // if /home actually contains the home directory - if (mountPoint.startsWith(QLatin1String("/home")) && QDir::homePath().startsWith(QLatin1String("/home"))) - return false; - - return true; -} - -QString FolderSelectionWidget::iconName(QString path) const -{ - // Ensure paths end with / - if (!path.endsWith(QDir::separator())) - path.append(QDir::separator()); - - QString homePath = QDir::homePath(); - if (!homePath.endsWith(QDir::separator())) - homePath.append(QDir::separator()); - - if (path == homePath) - return QStringLiteral("user-home"); - - if (m_mountPoints.contains(path)) - return QStringLiteral("drive-harddisk"); - - return QStringLiteral("folder"); -} - diff --git a/kcms/baloo/kcm.h b/kcms/baloo/kcm.h --- a/kcms/baloo/kcm.h +++ b/kcms/baloo/kcm.h @@ -20,35 +20,51 @@ #ifndef _BALOO_FILE_KCM_H_ #define _BALOO_FILE_KCM_H_ -#include -#include "ui_configwidget.h" +#include + +#include "filteredfoldermodel.h" namespace Baloo { -class ServerConfigModule : public KCModule, private Ui::ConfigWidget +class ServerConfigModule : public KQuickAddons::ConfigModule { Q_OBJECT + Q_PROPERTY(FilteredFolderModel *filteredModel READ filteredModel CONSTANT) + Q_PROPERTY(bool indexing READ indexing WRITE setIndexing NOTIFY indexingChanged) + Q_PROPERTY(bool fileContents READ fileContents WRITE setFileContents NOTIFY fileContentsChanged) public: - ServerConfigModule(QWidget* parent, const QVariantList& args); - ~ServerConfigModule() override; + ServerConfigModule(QObject* parent, const QVariantList& args); + virtual ~ServerConfigModule() override; + + bool indexing() const; + void setIndexing(bool indexing); + Q_SIGNAL void indexingChanged(bool indexing); + + bool fileContents() const; + void setFileContents(bool fileContents); + Q_SIGNAL void fileContentsChanged(bool fileContents); + + FilteredFolderModel *filteredModel() const; public Q_SLOTS: void load() override; void save() override; void defaults() override; - void indexingEnabledChanged(); - void onDirectoryListChanged(); private: bool m_previouslyEnabled; /** * @brief Check if all mount points are in the excluded from indexing list. * * @return True if all mount points are excluded. False otherwise. */ bool allMountPointsExcluded(); + FilteredFolderModel *m_filteredFolderModel; + + bool m_indexing; + bool m_fileContents; }; } diff --git a/kcms/baloo/kcm.cpp b/kcms/baloo/kcm.cpp --- a/kcms/baloo/kcm.cpp +++ b/kcms/baloo/kcm.cpp @@ -19,7 +19,6 @@ #include "kcm.h" #include "fileexcludefilters.h" -#include "folderselectionwidget.h" #include #include @@ -38,88 +37,62 @@ #include -K_PLUGIN_FACTORY(BalooConfigModuleFactory, registerPlugin();) -K_EXPORT_PLUGIN(BalooConfigModuleFactory("kcm_baloofile")) - +K_PLUGIN_FACTORY_WITH_JSON(KCMColorsFactory, "kcm_baloofile.json", registerPlugin();) namespace { -QStringList defaultFolders() -{ - return QStringList() << QDir::homePath(); -} - -} + QStringList defaultFolders() + { + return { QDir::homePath() }; + } +} // namespace using namespace Baloo; -ServerConfigModule::ServerConfigModule(QWidget* parent, const QVariantList& args) - : KCModule(parent, args) +ServerConfigModule::ServerConfigModule(QObject* parent, const QVariantList& args) + : KQuickAddons::ConfigModule(parent, args) + , m_filteredFolderModel(new FilteredFolderModel(this)) { + qmlRegisterType(); + KAboutData* about = new KAboutData( QStringLiteral("kcm_baloofile"), i18n("Configure File Search"), QStringLiteral("0.1"), QString(), KAboutLicense::GPL, i18n("Copyright 2007-2010 Sebastian Trüg")); + about->addAuthor(i18n("Sebastian Trüg"), QString(), QStringLiteral("trueg@kde.org")); about->addAuthor(i18n("Vishesh Handa"), QString(), QStringLiteral("vhanda@kde.org")); + about->addAuthor(i18n("Tomaz Canabrava"), QString(), QStringLiteral("tcnaabrava@kde.org")); + setAboutData(about); setButtons(Help | Apply | Default); - setupUi(this); - - connect(m_excludeFolders_FSW, SIGNAL(changed()), - this, SLOT(changed())); - connect(m_excludeFolders_FSW, &FolderSelectionWidget::changed, - this, &ServerConfigModule::onDirectoryListChanged); - connect(m_enableCheckbox, SIGNAL(stateChanged(int)), - this, SLOT(changed())); - connect(m_enableContentIndexing, SIGNAL(stateChanged(int)), - this, SLOT(changed())); - connect(m_enableCheckbox, SIGNAL(stateChanged(int)), - this, SLOT(indexingEnabledChanged())); + connect(m_filteredFolderModel, &QAbstractListModel::rowsRemoved, this, [this]{ setNeedsSave(true); }); + connect(m_filteredFolderModel, &QAbstractListModel::rowsInserted, this, [this]{ setNeedsSave(true); }); } - ServerConfigModule::~ServerConfigModule() { } - void ServerConfigModule::load() { Baloo::IndexerConfig config; - - m_previouslyEnabled = config.fileIndexingEnabled(); - m_enableCheckbox->setChecked(m_previouslyEnabled); - - m_enableContentIndexing->setChecked(!config.onlyBasicIndexing()); - m_enableContentIndexing->setEnabled(m_enableCheckbox->isChecked()); - - QStringList includeFolders = config.includeFolders(); - QStringList excludeFolders = config.excludeFolders(); - m_excludeFolders_FSW->setDirectoryList(includeFolders, excludeFolders); - - // All values loaded -> no changes - Q_EMIT changed(false); + setIndexing(config.fileIndexingEnabled()); + setFileContents(!config.onlyBasicIndexing()); + m_filteredFolderModel->setDirectoryList(config.includeFolders(), config.excludeFolders()); } - void ServerConfigModule::save() { - QStringList includeFolders = m_excludeFolders_FSW->includeFolders(); - QStringList excludeFolders = m_excludeFolders_FSW->excludeFolders(); - - bool mountPointsEx = allMountPointsExcluded(); - - bool enabled = m_enableCheckbox->isChecked(); - if (mountPointsEx) - enabled = false; + qDebug() << "Saving!"; + bool enabled = m_indexing && !allMountPointsExcluded(); Baloo::IndexerConfig config; config.setFileIndexingEnabled(enabled); - config.setIncludeFolders(includeFolders); - config.setExcludeFolders(excludeFolders); - config.setOnlyBasicIndexing(!m_enableContentIndexing->isChecked()); + config.setIncludeFolders(m_filteredFolderModel->includeFolders()); + config.setExcludeFolders(m_filteredFolderModel->excludeFolders()); + config.setOnlyBasicIndexing(!m_fileContents); if (m_previouslyEnabled != enabled) { config.setFirstRun(true); @@ -131,10 +104,12 @@ QProcess::startDetached(exe, QStringList()); } else { - QDBusMessage message = QDBusMessage::createMethodCall(QStringLiteral("org.kde.baloo"), - QStringLiteral("/"), - QStringLiteral("org.kde.baloo.main"), - QStringLiteral("quit")); + QDBusMessage message = QDBusMessage::createMethodCall( + QStringLiteral("org.kde.baloo"), + QStringLiteral("/"), + QStringLiteral("org.kde.baloo.main"), + QStringLiteral("quit") + ); QDBusConnection::sessionBus().asyncCall(message); } @@ -145,41 +120,53 @@ // Update the baloo_file's config cache config.refresh(); - - // all values saved -> no changes - Q_EMIT changed(false); } - void ServerConfigModule::defaults() { - m_excludeFolders_FSW->setDirectoryList(defaultFolders(), QStringList()); + m_filteredFolderModel->setDirectoryList(defaultFolders(), QStringList()); } -void ServerConfigModule::indexingEnabledChanged() +bool ServerConfigModule::indexing() const { - m_enableContentIndexing->setEnabled(m_enableCheckbox->isChecked()); + return m_indexing; } -void ServerConfigModule::onDirectoryListChanged() +bool ServerConfigModule::fileContents() const { - m_enableCheckbox->setChecked(!allMountPointsExcluded()); + return m_fileContents; } -bool ServerConfigModule::allMountPointsExcluded() +FilteredFolderModel *ServerConfigModule::filteredModel() const { + return m_filteredFolderModel; +} + +void ServerConfigModule::setIndexing(bool indexing) { - QStringList mountPoints; - Q_FOREACH (const QStorageInfo &si, QStorageInfo::mountedVolumes()) { - mountPoints << si.rootPath(); + if (m_indexing != indexing) { + m_indexing = indexing; + Q_EMIT indexingChanged(indexing); + setNeedsSave(true); } +} - const QStringList excluded = m_excludeFolders_FSW->excludeFolders(); +void ServerConfigModule::setFileContents(bool fileContents) +{ + if (m_fileContents != fileContents) { + m_fileContents = fileContents; + Q_EMIT fileContentsChanged(fileContents); + setNeedsSave(true); + } +} - if (excluded.toSet() == mountPoints.toSet()) { - return true; +bool ServerConfigModule::allMountPointsExcluded() +{ + QStringList mountPoints; + for (const QStorageInfo &si : QStorageInfo::mountedVolumes()) { + mountPoints.append(si.rootPath()); } - return false; + return m_filteredFolderModel->excludeFolders().toSet() == mountPoints.toSet(); } #include "kcm.moc" diff --git a/kcms/baloo/package/contents/ui/main.qml b/kcms/baloo/package/contents/ui/main.qml new file mode 100644 --- /dev/null +++ b/kcms/baloo/package/contents/ui/main.qml @@ -0,0 +1,141 @@ +/* + * Copyright 2018 Kai Uwe Broulik + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License or (at your option) version 3 or any later version + * accepted by the membership of KDE e.V. (or its successor approved + * by the membership of KDE e.V.), which shall act as a proxy + * defined in Section 14 of version 3 of the license. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +import QtQuick 2.1 +import QtQuick.Layouts 1.1 +import QtQuick.Controls 2.12 as QQC2 +import QtQuick.Dialogs 1.2 as QtDialogs +import org.kde.kirigami 2.4 as Kirigami +import org.kde.kcm 1.1 as KCM +import Qt.labs.platform 1.1 + +KCM.SimpleKCM { + id: root + + KCM.ConfigModule.quickHelp: i18n("This module lets you configure the search in the system.") + ColumnLayout { + anchors.fill: parent + + QQC2.Label { + text: i18n("File Search helps you quickly locate all your files based on their content") + } + + QQC2.CheckBox { + id: fileSearchEnabled + text: i18n("Enable File Search") + + onCheckStateChanged: { + if (!checkState === Qt.Unchecked) { + indexFileContents.checked = false; + } + kcm.indexing = fileSearchEnabled.checked + } + + Component.onCompleted : { + fileSearchEnabled.checked = kcm.indexing ? Qt.Checked : Qt.Unchecked + } + } + + QQC2.CheckBox { + id: indexFileContents + text: i18n("Also index file content") + enabled: fileSearchEnabled.checked + + onCheckStateChanged: { + kcm.fileContents = indexFileContents.checkState === Qt.Checked + } + + Component.onCompleted : { + indexFileContents.checked = kcm.fileContents ? Qt.Checked : Qt.Unchecked + } + } + + QQC2.Label { + text: "Do not search in these locations:" + } + + ListView { + id: fileExcludeList + Layout.fillWidth: true + Layout.fillHeight: true + + model: kcm.filteredModel + highlight: Rectangle { color: "lightsteelblue" } + focus: true + + delegate: MouseArea { + width: fileExcludeList.width + height: childrenRect.height + + Image { + source: model.DecorationRole ? model.DecorationRole : "" + } + QQC2.Label { + text: model.Folder + } + onClicked: { + fileExcludeList.currentIndex = index + } + } + + Component.onCompleted : { + fileExcludeList.currentIndex = -1 + } + } + + RowLayout { + QQC2.Button { + id: addFolder + icon.name: "list-add" + onClicked: fileDialogLoader.active = true + } + + QQC2.Button{ + id: removeFolder + icon.name: "list-remove" + enabled: fileExcludeList.currentIndex !== -1 + onClicked: { + kcm.filteredModel.removeFolder(fileExcludeList.currentIndex) + } + } + } + } + + Loader { + id: fileDialogLoader + active: false + sourceComponent: QtDialogs.FileDialog { + title: i18n("Select a folder to filter") + folder: shortcuts.home + selectFolder: true + + onAccepted: { + kcm.filteredModel.addFolder(fileUrls[0]) + fileDialogLoader.active = false + } + + onRejected: { + fileDialogLoader.active = false + } + + Component.onCompleted: open() + } + } +} diff --git a/kcms/baloo/package/metadata.desktop b/kcms/baloo/package/metadata.desktop new file mode 100644 --- /dev/null +++ b/kcms/baloo/package/metadata.desktop @@ -0,0 +1,16 @@ +[Desktop Entry] +Name=Search +Comment=Choose color scheme + +Icon=baloo +Type=Service +X-KDE-PluginInfo-Author=Tomaz Canabrava +X-KDE-PluginInfo-Email=tcanabrava@kde.org +X-KDE-PluginInfo-License=GPL +X-KDE-PluginInfo-Name=kcm_baloofile +X-KDE-PluginInfo-Version= +X-KDE-PluginInfo-Website= +X-KDE-ServiceTypes=Plasma/Generic +X-Plasma-API=declarativeappletscript + +X-Plasma-MainScript=ui/main.qml