diff options
author | Qt Forward Merge Bot <qt_forward_merge_bot@qt-project.org> | 2020-01-18 03:04:56 +0100 |
---|---|---|
committer | Qt Forward Merge Bot <qt_forward_merge_bot@qt-project.org> | 2020-01-18 03:04:57 +0100 |
commit | dfe72000141db04d6dd17bc37291ef208733ffb4 (patch) | |
tree | e3b2694dc1aceb7bbe9cdba147f9fdc647948eaa /src/assistant | |
parent | 5051c1e601d60707ae821c0d6836e422249c3721 (diff) | |
parent | 49809ed79cbbec7b8071660b4540d070e075d65b (diff) | |
download | qttools-dfe72000141db04d6dd17bc37291ef208733ffb4.tar.gz |
Merge remote-tracking branch 'origin/5.15' into dev
Change-Id: Iaac26eb3c356beb28f70417d63fd00bd0efb57ee
Diffstat (limited to 'src/assistant')
33 files changed, 1742 insertions, 736 deletions
diff --git a/src/assistant/assistant/assistant.pro b/src/assistant/assistant/assistant.pro index b63be28c7..5da0b0077 100644 --- a/src/assistant/assistant/assistant.pro +++ b/src/assistant/assistant/assistant.pro @@ -23,14 +23,14 @@ HEADERS += aboutdialog.h \ cmdlineparser.h \ contentwindow.h \ findwidget.h \ - filternamedialog.h \ + helpdocsettings.h \ + helpdocsettingswidget.h \ helpenginewrapper.h \ helpbrowsersupport.h \ helpviewer.h \ helpviewer_p.h \ indexwindow.h \ mainwindow.h \ - optionswidget.h \ preferencesdialog.h \ qtdocinstaller.h \ remotecontrol.h \ @@ -56,14 +56,14 @@ SOURCES += aboutdialog.cpp \ cmdlineparser.cpp \ contentwindow.cpp \ findwidget.cpp \ - filternamedialog.cpp \ + helpdocsettings.cpp \ + helpdocsettingswidget.cpp \ helpenginewrapper.cpp \ helpbrowsersupport.cpp \ helpviewer.cpp \ indexwindow.cpp \ main.cpp \ mainwindow.cpp \ - optionswidget.cpp \ preferencesdialog.cpp \ qtdocinstaller.cpp \ remotecontrol.cpp \ @@ -97,7 +97,7 @@ win32 { FORMS += bookmarkdialog.ui \ bookmarkmanagerwidget.ui \ bookmarkwidget.ui \ - filternamedialog.ui \ + helpdocsettingswidget.ui \ preferencesdialog.ui \ topicchooser.ui diff --git a/src/assistant/assistant/assistant.qch b/src/assistant/assistant/assistant.qch Binary files differindex fded08e62..b58b7ecca 100644 --- a/src/assistant/assistant/assistant.qch +++ b/src/assistant/assistant/assistant.qch diff --git a/src/assistant/assistant/assistant_images.qrc b/src/assistant/assistant/assistant_images.qrc index e55b6b27e..948de970f 100644 --- a/src/assistant/assistant/assistant_images.qrc +++ b/src/assistant/assistant/assistant_images.qrc @@ -10,9 +10,7 @@ <file>images/mac/editcopy.png</file> <file>images/mac/find.png</file> <file>images/mac/home.png</file> - <file>images/mac/minus.png</file> <file>images/mac/next.png</file> - <file>images/mac/plus.png</file> <file>images/mac/previous.png</file> <file>images/mac/print.png</file> <file>images/mac/synctoc.png</file> @@ -25,9 +23,7 @@ <file>images/win/editcopy.png</file> <file>images/win/find.png</file> <file>images/win/home.png</file> - <file>images/win/minus.png</file> <file>images/win/next.png</file> - <file>images/win/plus.png</file> <file>images/win/previous.png</file> <file>images/win/print.png</file> <file>images/win/synctoc.png</file> diff --git a/src/assistant/assistant/helpdocsettings.cpp b/src/assistant/assistant/helpdocsettings.cpp new file mode 100644 index 000000000..dc4afdb86 --- /dev/null +++ b/src/assistant/assistant/helpdocsettings.cpp @@ -0,0 +1,231 @@ +/**************************************************************************** +** +** Copyright (C) 2020 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt Assistant of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "helpdocsettings.h" + +#include <QtHelp/QCompressedHelpInfo> +#include <QtHelp/QHelpEngineCore> +#include <QtHelp/QHelpFilterEngine> + +#include <QtCore/QVersionNumber> + +#include <QtDebug> + +QT_BEGIN_NAMESPACE + +class HelpDocSettingsPrivate : public QSharedData +{ +public: + HelpDocSettingsPrivate() = default; + HelpDocSettingsPrivate(const HelpDocSettingsPrivate &other) = default; + ~HelpDocSettingsPrivate() = default; + + QMap<QString, QString> m_namespaceToComponent; + QMap<QString, QStringList> m_componentToNamespace; + + QMap<QString, QVersionNumber> m_namespaceToVersion; + QMap<QVersionNumber, QStringList> m_versionToNamespace; + + QMap<QString, QString> m_namespaceToFileName; + QMap<QString, QString> m_fileNameToNamespace; +}; + + +HelpDocSettings::HelpDocSettings() + : d(new HelpDocSettingsPrivate) +{ +} + +HelpDocSettings::HelpDocSettings(const HelpDocSettings &) = default; + +HelpDocSettings::HelpDocSettings(HelpDocSettings &&) = default; + +HelpDocSettings::~HelpDocSettings() = default; + +HelpDocSettings &HelpDocSettings::operator=(const HelpDocSettings &) = default; + +HelpDocSettings &HelpDocSettings::operator=(HelpDocSettings &&) = default; + +bool HelpDocSettings::addDocumentation(const QString &fileName) +{ + const QCompressedHelpInfo info = QCompressedHelpInfo::fromCompressedHelpFile(fileName); + + if (info.isNull()) + return false; + + const QString namespaceName = info.namespaceName(); + + if (d->m_namespaceToFileName.contains(namespaceName)) + return false; + + if (d->m_fileNameToNamespace.contains(fileName)) + return false; + + const QString component = info.component(); + const QVersionNumber version = info.version(); + + d->m_namespaceToFileName.insert(namespaceName, fileName); + d->m_fileNameToNamespace.insert(fileName, namespaceName); + + d->m_namespaceToComponent.insert(namespaceName, component); + d->m_componentToNamespace[component].append(namespaceName); + + d->m_namespaceToVersion.insert(namespaceName, version); + d->m_versionToNamespace[version].append(namespaceName); + + return true; +} + +bool HelpDocSettings::removeDocumentation(const QString &namespaceName) +{ + if (namespaceName.isEmpty()) + return false; + + const QString fileName = d->m_namespaceToFileName.value(namespaceName); + if (fileName.isEmpty()) + return false; + + const QString component = d->m_namespaceToComponent.value(namespaceName); + const QVersionNumber version = d->m_namespaceToVersion.value(namespaceName); + + d->m_namespaceToComponent.remove(namespaceName); + d->m_namespaceToVersion.remove(namespaceName); + d->m_namespaceToFileName.remove(namespaceName); + d->m_fileNameToNamespace.remove(fileName); + d->m_componentToNamespace[component].removeOne(namespaceName); + if (d->m_componentToNamespace[component].isEmpty()) + d->m_componentToNamespace.remove(component); + d->m_versionToNamespace[version].removeOne(namespaceName); + if (d->m_versionToNamespace[version].isEmpty()) + d->m_versionToNamespace.remove(version); + + return true; +} + +QString HelpDocSettings::namespaceName(const QString &fileName) const +{ + return d->m_fileNameToNamespace.value(fileName); +} + +QStringList HelpDocSettings::components() const +{ + return d->m_componentToNamespace.keys(); +} + +QList<QVersionNumber> HelpDocSettings::versions() const +{ + return d->m_versionToNamespace.keys(); +} + +QStringList HelpDocSettings::namespaces() const +{ + return d->m_namespaceToFileName.keys(); +} + +QMap<QString, QString> HelpDocSettings::namespaceToFileName() const +{ + return d->m_namespaceToFileName; +} + +HelpDocSettings HelpDocSettings::readSettings(QHelpEngineCore *helpEngine) +{ + QHelpFilterEngine *filterEngine = helpEngine->filterEngine(); + + HelpDocSettings docSettings; + docSettings.d->m_namespaceToComponent = filterEngine->namespaceToComponent(); + docSettings.d->m_namespaceToVersion = filterEngine->namespaceToVersion(); + for (auto it = docSettings.d->m_namespaceToComponent.constBegin(); + it != docSettings.d->m_namespaceToComponent.constEnd(); ++it) { + const QString namespaceName = it.key(); + const QString namespaceFileName = helpEngine->documentationFileName(namespaceName); + docSettings.d->m_namespaceToFileName.insert(namespaceName, namespaceFileName); + docSettings.d->m_fileNameToNamespace.insert(namespaceFileName, namespaceName); + docSettings.d->m_componentToNamespace[it.value()].append(namespaceName); + } + for (auto it = docSettings.d->m_namespaceToVersion.constBegin(); + it != docSettings.d->m_namespaceToVersion.constEnd(); ++it) { + docSettings.d->m_versionToNamespace[it.value()].append(it.key()); + } + + return docSettings; +} + +static QMap<QString, QString> subtract(const QMap<QString, QString> &minuend, + const QMap<QString, QString> &subtrahend) +{ + auto result = minuend; + + for (auto itSubtrahend = subtrahend.cbegin(); itSubtrahend != subtrahend.cend(); ++itSubtrahend) { + auto itResult = result.find(itSubtrahend.key()); + if (itResult != result.end() && itSubtrahend.value() == itResult.value()) + result.erase(itResult); + } + + return result; +} + +bool HelpDocSettings::applySettings(QHelpEngineCore *helpEngine, + const HelpDocSettings &settings) +{ + const HelpDocSettings oldSettings = readSettings(helpEngine); + + const QMap<QString, QString> docsToRemove = subtract( + oldSettings.namespaceToFileName(), + settings.namespaceToFileName()); + const QMap<QString, QString> docsToAdd = subtract( + settings.namespaceToFileName(), + oldSettings.namespaceToFileName()); + + bool changed = false; + for (const QString &namespaceName : docsToRemove.keys()) { + if (!helpEngine->unregisterDocumentation(namespaceName)) + qWarning() << "Cannot unregister documentation:" << namespaceName; + changed = true; + } + + for (const QString &fileName : docsToAdd.values()) { + if (!helpEngine->registerDocumentation(fileName)) + qWarning() << "Cannot register documentation file:" << fileName; + changed = true; + } + + return changed; +} + +QT_END_NAMESPACE diff --git a/src/assistant/assistant/helpdocsettings.h b/src/assistant/assistant/helpdocsettings.h new file mode 100644 index 000000000..7476eb63a --- /dev/null +++ b/src/assistant/assistant/helpdocsettings.h @@ -0,0 +1,82 @@ +/**************************************************************************** +** +** Copyright (C) 2020 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt Assistant of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef HELPDOCSETTINGS_H +#define HELPDOCSETTINGS_H + +#include <QtCore/QSharedDataPointer> + +QT_BEGIN_NAMESPACE + +class QVersionNumber; +class QHelpEngineCore; +class HelpDocSettingsPrivate; + +class HelpDocSettings final +{ +public: + HelpDocSettings(); + HelpDocSettings(const HelpDocSettings &other); + HelpDocSettings(HelpDocSettings &&other); + ~HelpDocSettings(); + + HelpDocSettings &operator=(const HelpDocSettings &other); + HelpDocSettings &operator=(HelpDocSettings &&other); + + void swap(HelpDocSettings &other) noexcept + { d.swap(other.d); } + + bool addDocumentation(const QString &fileName); + bool removeDocumentation(const QString &namespaceName); + QString namespaceName(const QString &fileName) const; + QStringList components() const; + QList<QVersionNumber> versions() const; + QStringList namespaces() const; + QMap<QString, QString> namespaceToFileName() const; + + static HelpDocSettings readSettings(QHelpEngineCore *helpEngine); + static bool applySettings(QHelpEngineCore *helpEngine, const HelpDocSettings &settings); + +private: + QSharedDataPointer<HelpDocSettingsPrivate> d; +}; + +QT_END_NAMESPACE + +#endif // HELPDOCSETTINGS_H diff --git a/src/assistant/assistant/helpdocsettingswidget.cpp b/src/assistant/assistant/helpdocsettingswidget.cpp new file mode 100644 index 000000000..94ca2b25a --- /dev/null +++ b/src/assistant/assistant/helpdocsettingswidget.cpp @@ -0,0 +1,194 @@ +/**************************************************************************** +** +** Copyright (C) 2020 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt Assistant of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "helpdocsettings.h" +#include "helpdocsettingswidget.h" +#include "ui_helpdocsettingswidget.h" + +#include <QtWidgets/QFileDialog> +#include <QtWidgets/QPushButton> + +QT_BEGIN_NAMESPACE + +class HelpDocSettingsWidgetPrivate +{ + HelpDocSettingsWidget *q_ptr; + Q_DECLARE_PUBLIC(HelpDocSettingsWidget) +public: + HelpDocSettingsWidgetPrivate() = default; + + void addDocumentation(); + void removeDocumentation(); + void applyDocListFilter(QListWidgetItem *item); + + QMap<QString, QListWidgetItem *> m_namespaceToItem; + QHash<QListWidgetItem *, QString> m_itemToNamespace; + + Ui::HelpDocSettingsWidget m_ui; + HelpDocSettings m_settings; +}; + +void HelpDocSettingsWidgetPrivate::addDocumentation() +{ + Q_Q(HelpDocSettingsWidget); + + const QStringList &fileNames = QFileDialog::getOpenFileNames(q, + q->tr("Add Documentation"), QString(), q->tr("Qt Compressed Help Files (*.qch)")); + if (fileNames.isEmpty()) + return; + + bool added = false; + + for (const QString &fileName : fileNames) { + if (!m_settings.addDocumentation(fileName)) + continue; + + if (!added) { + added = true; + m_ui.registeredDocsListWidget->clearSelection(); + } + + const QString namespaceName = m_settings.namespaceName(fileName); + QListWidgetItem *item = new QListWidgetItem(namespaceName); + m_namespaceToItem.insert(namespaceName, item); + m_itemToNamespace.insert(item, namespaceName); + m_ui.registeredDocsListWidget->insertItem(m_namespaceToItem.keys().indexOf(namespaceName), item); + + item->setSelected(true); + applyDocListFilter(item); + } + + if (added) + emit q->docSettingsChanged(m_settings); +} + +void HelpDocSettingsWidgetPrivate::removeDocumentation() +{ + Q_Q(HelpDocSettingsWidget); + + const QList<QListWidgetItem *> selectedItems = m_ui.registeredDocsListWidget->selectedItems(); + if (selectedItems.isEmpty()) + return; + + for (QListWidgetItem *item : selectedItems) { + const QString namespaceName = m_itemToNamespace.value(item); + m_itemToNamespace.remove(item); + m_namespaceToItem.remove(namespaceName); + delete item; + + m_settings.removeDocumentation(namespaceName); + } + + emit q->docSettingsChanged(m_settings); +} + +void HelpDocSettingsWidgetPrivate::applyDocListFilter(QListWidgetItem *item) +{ + const QString namespaceName = m_itemToNamespace.value(item); + const QString nameFilter = m_ui.registeredDocsFilterLineEdit->text(); + + const bool matches = nameFilter.isEmpty() || namespaceName.contains(nameFilter); + + if (!matches) + item->setSelected(false); + item->setHidden(!matches); +} + +HelpDocSettingsWidget::HelpDocSettingsWidget(QWidget *parent) + : QWidget(parent) + , d_ptr(new HelpDocSettingsWidgetPrivate()) +{ + Q_D(HelpDocSettingsWidget); + d->q_ptr = this; + d->m_ui.setupUi(this); + + connect(d->m_ui.docAddButton, &QAbstractButton::clicked, + [this]() { + Q_D(HelpDocSettingsWidget); + d->addDocumentation(); + }); + connect(d->m_ui.docRemoveButton, &QAbstractButton::clicked, + [this]() { + Q_D(HelpDocSettingsWidget); + d->removeDocumentation(); + }); + connect(d->m_ui.registeredDocsFilterLineEdit, &QLineEdit::textChanged, + [this](const QString &) { + Q_D(HelpDocSettingsWidget); + for (const auto item : d->m_namespaceToItem) + d->applyDocListFilter(item); + }); + connect(d->m_ui.registeredDocsListWidget, &QListWidget::itemSelectionChanged, + [this]() { + Q_D(HelpDocSettingsWidget); + d->m_ui.docRemoveButton->setEnabled( + !d->m_ui.registeredDocsListWidget->selectedItems().isEmpty()); + }); +} + +HelpDocSettingsWidget::~HelpDocSettingsWidget() = default; + +void HelpDocSettingsWidget::setDocSettings(const HelpDocSettings &settings) +{ + Q_D(HelpDocSettingsWidget); + d->m_settings = settings; + + d->m_ui.registeredDocsListWidget->clear(); + d->m_namespaceToItem.clear(); + d->m_itemToNamespace.clear(); + + for (const QString &namespaceName : d->m_settings.namespaces()) { + QListWidgetItem *item = new QListWidgetItem(namespaceName); + d->m_namespaceToItem.insert(namespaceName, item); + d->m_itemToNamespace.insert(item, namespaceName); + d->m_ui.registeredDocsListWidget->addItem(item); + d->applyDocListFilter(item); + } + + d->m_ui.docRemoveButton->setEnabled( + !d->m_ui.registeredDocsListWidget->selectedItems().isEmpty()); +} + +HelpDocSettings HelpDocSettingsWidget::docSettings() const +{ + Q_D(const HelpDocSettingsWidget); + return d->m_settings; +} + +QT_END_NAMESPACE diff --git a/src/assistant/assistant/helpdocsettingswidget.h b/src/assistant/assistant/helpdocsettingswidget.h new file mode 100644 index 000000000..3ed089353 --- /dev/null +++ b/src/assistant/assistant/helpdocsettingswidget.h @@ -0,0 +1,73 @@ +/**************************************************************************** +** +** Copyright (C) 2020 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt Assistant of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef HELPDOCSETTINGSWIDGET_H +#define HELPDOCSETTINGSWIDGET_H + +#include <QtWidgets/QWidget> + +QT_BEGIN_NAMESPACE + +class HelpDocSettings; +class HelpDocSettingsWidgetPrivate; + +class HelpDocSettingsWidget : public QWidget +{ + Q_OBJECT +public: + HelpDocSettingsWidget(QWidget *parent = nullptr); + + ~HelpDocSettingsWidget(); + + void setDocSettings(const HelpDocSettings &settings); + HelpDocSettings docSettings() const; + +Q_SIGNALS: + void docSettingsChanged(const HelpDocSettings &settings); + +private: + QScopedPointer<class HelpDocSettingsWidgetPrivate> d_ptr; + Q_DECLARE_PRIVATE(HelpDocSettingsWidget) + Q_DISABLE_COPY_MOVE(HelpDocSettingsWidget) +}; + +QT_END_NAMESPACE + +#endif + diff --git a/src/assistant/assistant/helpdocsettingswidget.ui b/src/assistant/assistant/helpdocsettingswidget.ui new file mode 100644 index 000000000..4897dfe86 --- /dev/null +++ b/src/assistant/assistant/helpdocsettingswidget.ui @@ -0,0 +1,76 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>HelpDocSettingsWidget</class> + <widget class="QWidget" name="HelpDocSettingsWidget"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>268</width> + <height>128</height> + </rect> + </property> + <property name="windowTitle"> + <string>Form</string> + </property> + <layout class="QGridLayout" name="gridLayout"> + <item row="0" column="0"> + <widget class="QLabel" name="docLabel"> + <property name="text"> + <string>Registered Documentation</string> + </property> + </widget> + </item> + <item row="1" column="0"> + <widget class="QLineEdit" name="registeredDocsFilterLineEdit"> + <property name="placeholderText"> + <string><Filter></string> + </property> + <property name="clearButtonEnabled"> + <bool>true</bool> + </property> + </widget> + </item> + <item row="1" column="1" rowspan="2"> + <layout class="QVBoxLayout" name="buttonLayout"> + <item> + <widget class="QPushButton" name="docAddButton"> + <property name="text"> + <string>Add...</string> + </property> + </widget> + </item> + <item> + <widget class="QPushButton" name="docRemoveButton"> + <property name="text"> + <string>Remove</string> + </property> + </widget> + </item> + <item> + <spacer name="buttonSpacer"> + <property name="orientation"> + <enum>Qt::Vertical</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>20</width> + <height>40</height> + </size> + </property> + </spacer> + </item> + </layout> + </item> + <item row="2" column="0"> + <widget class="QListWidget" name="registeredDocsListWidget"> + <property name="selectionMode"> + <enum>QAbstractItemView::ExtendedSelection</enum> + </property> + </widget> + </item> + </layout> + </widget> + <resources/> + <connections/> +</ui> diff --git a/src/assistant/assistant/helpenginewrapper.cpp b/src/assistant/assistant/helpenginewrapper.cpp index 17e4bde8c..d69138ff8 100644 --- a/src/assistant/assistant/helpenginewrapper.cpp +++ b/src/assistant/assistant/helpenginewrapper.cpp @@ -670,6 +670,12 @@ void HelpEngineWrapper::setTopicChooserGeometry(const QByteArray &geometry) d->m_helpEngine->setCustomValue(TopicChooserGeometryKey, geometry); } +QHelpEngineCore *HelpEngineWrapper::helpEngine() const +{ + return d->m_helpEngine; +} + + // -- TimeoutForwarder TimeoutForwarder::TimeoutForwarder(const QString &fileName) diff --git a/src/assistant/assistant/helpenginewrapper.h b/src/assistant/assistant/helpenginewrapper.h index 6026a0473..81d8ffa1f 100644 --- a/src/assistant/assistant/helpenginewrapper.h +++ b/src/assistant/assistant/helpenginewrapper.h @@ -46,6 +46,7 @@ class QHelpIndexModel; class QHelpIndexWidget; class QHelpSearchEngine; class QHelpFilterEngine; +class QHelpEngineCore; enum { ShowHomePage = 0, @@ -175,6 +176,8 @@ public: const QByteArray topicChooserGeometry() const; void setTopicChooserGeometry(const QByteArray &geometry); + QHelpEngineCore *helpEngine() const; + signals: // For asynchronous doc updates triggered by external actions. diff --git a/src/assistant/assistant/main.cpp b/src/assistant/assistant/main.cpp index 3ddbdbc29..cd6487751 100644 --- a/src/assistant/assistant/main.cpp +++ b/src/assistant/assistant/main.cpp @@ -265,69 +265,49 @@ void setupTranslations() } // Anonymous namespace. -int main(int argc, char *argv[]) -{ - QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling); - QCoreApplication::setAttribute(Qt::AA_UseHighDpiPixmaps); - QCoreApplication::setAttribute(Qt::AA_DisableWindowContextHelpButton); - TRACE_OBJ - QScopedPointer<QCoreApplication> a(createApplication(argc, argv)); -#if QT_CONFIG(library) - a->addLibraryPath(a->applicationDirPath() + QLatin1String("/plugins")); -#endif - setupTranslations(); - -#if defined(BROWSER_QTWEBKIT) - if (qobject_cast<QApplication *>(a.data())) { - QFont f; - f.setStyleHint(QFont::SansSerif); - QWebSettings::globalSettings()->setFontFamily(QWebSettings::StandardFont, f.defaultFamily()); - } -#endif // BROWSER_QTWEBKIT - - // Parse arguments. - CmdLineParser cmd(a->arguments()); - CmdLineParser::Result res = cmd.parse(); - if (res == CmdLineParser::Help) - return 0; - else if (res == CmdLineParser::Error) - return -1; +enum ExitStatus { + ExitSuccess = 0, + ExitFailure, + NoExit +}; +static ExitStatus preliminarySetup(CmdLineParser *cmd) +{ /* * Create the collection objects that we need. We always have the * cached collection file. Depending on whether the user specified * one, we also may have an input collection file. */ - const QString collectionFile = cmd.collectionFile(); + const QString collectionFile = cmd->collectionFile(); const bool collectionFileGiven = !collectionFile.isEmpty(); QScopedPointer<QHelpEngineCore> collection; if (collectionFileGiven) { collection.reset(new QHelpEngineCore(collectionFile)); collection->setProperty("_q_readonly", QVariant::fromValue<bool>(true)); if (!collection->setupData()) { - cmd.showMessage(QCoreApplication::translate("Assistant", - "Error reading collection file '%1': %2."). - arg(collectionFile).arg(collection->error()), true); - return EXIT_FAILURE; + cmd->showMessage(QCoreApplication::translate("Assistant", + "Error reading collection file '%1': %2.") + .arg(collectionFile).arg(collection->error()), true); + return ExitFailure; } } const QString &cachedCollectionFile = collectionFileGiven - ? constructCachedCollectionFilePath(*collection) - : MainWindow::defaultHelpCollectionFileName(); + ? constructCachedCollectionFilePath(*collection) + : MainWindow::defaultHelpCollectionFileName(); if (collectionFileGiven && !QFileInfo(cachedCollectionFile).exists() - && !collection->copyCollectionFile(cachedCollectionFile)) { - cmd.showMessage(QCoreApplication::translate("Assistant", - "Error creating collection file '%1': %2."). - arg(cachedCollectionFile).arg(collection->error()), true); - return EXIT_FAILURE; + && !collection->copyCollectionFile(cachedCollectionFile)) { + cmd->showMessage(QCoreApplication::translate("Assistant", + "Error creating collection file '%1': %2.") + .arg(cachedCollectionFile).arg(collection->error()), true); + return ExitFailure; } QHelpEngineCore cachedCollection(cachedCollectionFile); if (!cachedCollection.setupData()) { - cmd.showMessage(QCoreApplication::translate("Assistant", - "Error reading collection file '%1': %2."). - arg(cachedCollectionFile). - arg(cachedCollection.error()), true); - return EXIT_FAILURE; + cmd->showMessage(QCoreApplication::translate("Assistant", + "Error reading collection file '%1': %2.") + .arg(cachedCollectionFile) + .arg(cachedCollection.error()), true); + return ExitFailure; } stripNonexistingDocs(cachedCollection); @@ -335,56 +315,94 @@ int main(int argc, char *argv[]) if (CollectionConfiguration::isNewer(*collection, cachedCollection)) CollectionConfiguration::copyConfiguration(*collection, cachedCollection); - if (!synchronizeDocs(*collection, cachedCollection, cmd)) - return EXIT_FAILURE; + if (!synchronizeDocs(*collection, cachedCollection, *cmd)) + return ExitFailure; } - if (cmd.registerRequest() != CmdLineParser::None) { + if (cmd->registerRequest() != CmdLineParser::None) { const QStringList &cachedDocs = - cachedCollection.registeredDocumentations(); + cachedCollection.registeredDocumentations(); const QString &namespaceName = - QHelpEngineCore::namespaceName(cmd.helpFile()); - if (cmd.registerRequest() == CmdLineParser::Register) { + QHelpEngineCore::namespaceName(cmd->helpFile()); + if (cmd->registerRequest() == CmdLineParser::Register) { if (collectionFileGiven - && !registerDocumentation(*collection, cmd, true)) - return EXIT_FAILURE; + && !registerDocumentation(*collection, *cmd, true)) + return ExitFailure; if (!cachedDocs.contains(namespaceName) - && !registerDocumentation(cachedCollection, cmd, !collectionFileGiven)) - return EXIT_FAILURE; - return EXIT_SUCCESS; + && !registerDocumentation(cachedCollection, *cmd, !collectionFileGiven)) + return ExitFailure; + return ExitSuccess; } - if (cmd.registerRequest() == CmdLineParser::Unregister) { + if (cmd->registerRequest() == CmdLineParser::Unregister) { if (collectionFileGiven - && !unregisterDocumentation(*collection, namespaceName, cmd, true)) - return EXIT_FAILURE; + && !unregisterDocumentation(*collection, namespaceName, *cmd, true)) + return ExitFailure; if (cachedDocs.contains(namespaceName) - && !unregisterDocumentation(cachedCollection, namespaceName, - cmd, !collectionFileGiven)) - return EXIT_FAILURE; - return EXIT_SUCCESS; + && !unregisterDocumentation(cachedCollection, namespaceName, + *cmd, !collectionFileGiven)) + return ExitFailure; + return ExitSuccess; } } - if (cmd.removeSearchIndex()) { + if (cmd->removeSearchIndex()) { return removeSearchIndex(cachedCollectionFile) - ? EXIT_SUCCESS : EXIT_FAILURE; + ? ExitSuccess : ExitFailure; } if (!QSqlDatabase::isDriverAvailable(QLatin1String("QSQLITE"))) { - cmd.showMessage(QCoreApplication::translate("Assistant", - "Cannot load sqlite database driver!"), - true); - return EXIT_FAILURE; + cmd->showMessage(QCoreApplication::translate("Assistant", + "Cannot load sqlite database driver!"), + true); + return ExitFailure; } - if (!cmd.currentFilter().isEmpty()) { + if (!cmd->currentFilter().isEmpty()) { if (collectionFileGiven) - collection->setCurrentFilter(cmd.currentFilter()); - cachedCollection.setCurrentFilter(cmd.currentFilter()); + collection->setCurrentFilter(cmd->currentFilter()); + cachedCollection.setCurrentFilter(cmd->currentFilter()); } if (collectionFileGiven) - cmd.setCollectionFile(cachedCollectionFile); + cmd->setCollectionFile(cachedCollectionFile); + + return NoExit; +} + +int main(int argc, char *argv[]) +{ + QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling); + QCoreApplication::setAttribute(Qt::AA_UseHighDpiPixmaps); + QCoreApplication::setAttribute(Qt::AA_DisableWindowContextHelpButton); + TRACE_OBJ + QScopedPointer<QCoreApplication> a(createApplication(argc, argv)); +#if QT_CONFIG(library) + a->addLibraryPath(a->applicationDirPath() + QLatin1String("/plugins")); +#endif + setupTranslations(); + +#if defined(BROWSER_QTWEBKIT) + if (qobject_cast<QApplication *>(a.data())) { + QFont f; + f.setStyleHint(QFont::SansSerif); + QWebSettings::globalSettings()->setFontFamily(QWebSettings::StandardFont, f.defaultFamily()); + } +#endif // BROWSER_QTWEBKIT + + // Parse arguments. + CmdLineParser cmd(a->arguments()); + CmdLineParser::Result res = cmd.parse(); + if (res == CmdLineParser::Help) + return 0; + else if (res == CmdLineParser::Error) + return -1; + + const ExitStatus status = preliminarySetup(&cmd); + switch (status) { + case ExitFailure: return EXIT_FAILURE; + case ExitSuccess: return EXIT_SUCCESS; + default: break; + } MainWindow *w = new MainWindow(&cmd); w->show(); diff --git a/src/assistant/assistant/mainwindow.cpp b/src/assistant/assistant/mainwindow.cpp index a6b257eb7..0273129ca 100644 --- a/src/assistant/assistant/mainwindow.cpp +++ b/src/assistant/assistant/mainwindow.cpp @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2016 The Qt Company Ltd. +** Copyright (C) 2020 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the Qt Assistant of the Qt Toolkit. @@ -906,7 +906,7 @@ void MainWindow::showAboutDialog() "<p>Version %2</p>" "<p>Browser: %3</p></center>" "<p>Copyright (C) %4 The Qt Company Ltd.</p>") - .arg(tr("Qt Assistant"), QLatin1String(QT_VERSION_STR), browser, QStringLiteral("2019")), + .arg(tr("Qt Assistant"), QLatin1String(QT_VERSION_STR), browser, QStringLiteral("2020")), resources); QLatin1String path(":/qt-project.org/assistant/images/assistant-128.png"); aboutDia.setPixmap(QString(path)); diff --git a/src/assistant/assistant/preferencesdialog.cpp b/src/assistant/assistant/preferencesdialog.cpp index 66d6381d3..ebd2a96e8 100644 --- a/src/assistant/assistant/preferencesdialog.cpp +++ b/src/assistant/assistant/preferencesdialog.cpp @@ -28,42 +28,24 @@ #include "preferencesdialog.h" #include "centralwidget.h" -#include "filternamedialog.h" #include "fontpanel.h" #include "helpenginewrapper.h" #include "openpagesmanager.h" +#include "helpdocsettingswidget.h" #include <QtCore/QVersionNumber> + #include <QtGui/QFontDatabase> -#include <QtWidgets/QMessageBox> -#include <QtHelp/QCompressedHelpInfo> #include <QtHelp/QHelpEngineCore> #include <QtHelp/QHelpFilterData> #include <QtHelp/QHelpFilterEngine> - -#include <QtWidgets/QFileDialog> +#include <QtHelp/QHelpFilterSettingsWidget> #include <QtDebug> QT_BEGIN_NAMESPACE -static QStringList versionsToStringList(const QList<QVersionNumber> &versions) -{ - QStringList versionList; - for (const QVersionNumber &version : versions) - versionList.append(version.isNull() ? QString() : version.toString()); - return versionList; -} - -static QList<QVersionNumber> stringListToVersions(const QStringList &versionList) -{ - QList<QVersionNumber> versions; - for (const QString &versionString : versionList) - versions.append(QVersionNumber::fromString(versionString)); - return versions; -} - PreferencesDialog::PreferencesDialog(QWidget *parent) : QDialog(parent) , m_appFontChanged(false) @@ -74,18 +56,6 @@ PreferencesDialog::PreferencesDialog(QWidget *parent) { m_ui.setupUi(this); - QString resourcePath = QLatin1String(":/qt-project.org/assistant/images/"); -#ifdef Q_OS_MACOS - resourcePath.append(QLatin1String("mac")); -#else - resourcePath.append(QLatin1String("win")); -#endif - - m_ui.filterAddButton->setIcon(QIcon(resourcePath + QLatin1String("/plus.png"))); - m_ui.filterRemoveButton->setIcon(QIcon(resourcePath + QLatin1String("/minus.png"))); - - // TODO: filter docs via lineedit - connect(m_ui.buttonBox->button(QDialogButtonBox::Ok), &QAbstractButton::clicked, this, &PreferencesDialog::okClicked); connect(m_ui.buttonBox->button(QDialogButtonBox::Apply), &QAbstractButton::clicked, @@ -93,56 +63,30 @@ PreferencesDialog::PreferencesDialog(QWidget *parent) connect(m_ui.buttonBox->button(QDialogButtonBox::Cancel), &QAbstractButton::clicked, this, &QDialog::reject); - m_originalSetup = readOriginalSetup(); - m_currentSetup = m_originalSetup; + m_docSettings = HelpDocSettings::readSettings(helpEngine.helpEngine()); if (m_hideDocsTab) { m_ui.tabWidget->removeTab(m_ui.tabWidget->indexOf(m_ui.docsTab)); } else { - connect(m_ui.docAddButton, &QAbstractButton::clicked, - this, &PreferencesDialog::addDocumentation); - connect(m_ui.docRemoveButton, &QAbstractButton::clicked, - this, &PreferencesDialog::removeDocumentation); - connect(m_ui.registeredDocsFilterLineEdit, &QLineEdit::textChanged, - this, [this](const QString &) { - for (const auto item : m_namespaceToItem) - applyDocListFilter(item); - }); - connect(m_ui.registeredDocsListWidget, &QListWidget::itemSelectionChanged, - this, [this](){ - m_ui.docRemoveButton->setEnabled( - !m_ui.registeredDocsListWidget->selectedItems().isEmpty()); + connect(m_ui.docSettingsWidget, &HelpDocSettingsWidget::docSettingsChanged, + [this](const HelpDocSettings &settings) { + m_docSettings = settings; + if (m_hideFiltersTab) + return; + + m_ui.filterSettingsWidget->setAvailableComponents(m_docSettings.components()); + m_ui.filterSettingsWidget->setAvailableVersions(m_docSettings.versions()); }); - updateDocumentationPage(); + m_ui.docSettingsWidget->setDocSettings(m_docSettings); } if (m_hideFiltersTab) { m_ui.tabWidget->removeTab(m_ui.tabWidget->indexOf(m_ui.filtersTab)); } else { - connect(m_ui.componentWidget, &OptionsWidget::optionSelectionChanged, - this, &PreferencesDialog::componentsChanged); - connect(m_ui.versionWidget, &OptionsWidget::optionSelectionChanged, - this, &PreferencesDialog::versionsChanged); - connect(m_ui.filterWidget, &QListWidget::currentItemChanged, - this, &PreferencesDialog::filterSelected); - connect(m_ui.filterWidget, &QListWidget::itemDoubleClicked, - this, &PreferencesDialog::renameFilterClicked); - - // TODO: repeat these actions on context menu - connect(m_ui.filterAddButton, &QAbstractButton::clicked, - this, &PreferencesDialog::addFilterClicked); - connect(m_ui.filterRenameButton, &QAbstractButton::clicked, - this, &PreferencesDialog::renameFilterClicked); - connect(m_ui.filterRemoveButton, &QAbstractButton::clicked, - this, &PreferencesDialog::removeFilterClicked); - - m_ui.componentWidget->setNoOptionText(tr("No Component")); - m_ui.componentWidget->setInvalidOptionText(tr("Invalid Component")); - m_ui.versionWidget->setNoOptionText(tr("No Version")); - m_ui.versionWidget->setInvalidOptionText(tr("Invalid Version")); - - updateFilterPage(); + m_ui.filterSettingsWidget->setAvailableComponents(m_docSettings.components()); + m_ui.filterSettingsWidget->setAvailableVersions(m_docSettings.versions()); + m_ui.filterSettingsWidget->readSettings(helpEngine.filterEngine()); } updateFontSettingsPage(); @@ -152,331 +96,6 @@ PreferencesDialog::PreferencesDialog(QWidget *parent) setFont(helpEngine.appFont()); } -FilterSetup PreferencesDialog::readOriginalSetup() const -{ - FilterSetup filterSetup; - - filterSetup.m_namespaceToComponent = helpEngine.filterEngine()->namespaceToComponent(); - filterSetup.m_namespaceToVersion = helpEngine.filterEngine()->namespaceToVersion(); - for (auto it = filterSetup.m_namespaceToComponent.constBegin(); - it != filterSetup.m_namespaceToComponent.constEnd(); ++it) { - const QString namespaceName = it.key(); - const QString namespaceFileName = helpEngine.documentationFileName(namespaceName); - filterSetup.m_namespaceToFileName.insert(namespaceName, namespaceFileName); - filterSetup.m_fileNameToNamespace.insert(namespaceFileName, namespaceName); - filterSetup.m_componentToNamespace[it.value()].append(namespaceName); - } - for (auto it = filterSetup.m_namespaceToVersion.constBegin(); - it != filterSetup.m_namespaceToVersion.constEnd(); ++it) { - filterSetup.m_versionToNamespace[it.value()].append(it.key()); - } - - const QStringList allFilters = helpEngine.filterEngine()->filters(); - for (const QString &filter : allFilters) - filterSetup.m_filterToData.insert(filter, helpEngine.filterEngine()->filterData(filter)); - - filterSetup.m_currentFilter = helpEngine.filterEngine()->activeFilter(); - - return filterSetup; -} - -void PreferencesDialog::updateFilterPage() -{ - if (m_hideFiltersTab) - return; - - QString currentFilter = m_itemToFilter.value(m_ui.filterWidget->currentItem()); - if (currentFilter.isEmpty()) - currentFilter = m_currentSetup.m_currentFilter; - - m_currentSetup = m_originalSetup; - - m_ui.filterWidget->clear(); - m_ui.componentWidget->clear(); - m_ui.versionWidget->clear(); - m_itemToFilter.clear(); - m_filterToItem.clear(); - - for (const QString &filterName : m_currentSetup.m_filterToData.keys()) { - QListWidgetItem *item = new QListWidgetItem(filterName); - m_ui.filterWidget->addItem(item); - m_itemToFilter.insert(item, filterName); - m_filterToItem.insert(filterName, item); - if (filterName == currentFilter) - m_ui.filterWidget->setCurrentItem(item); - } - - if (!m_ui.filterWidget->currentItem() && !m_filterToItem.isEmpty()) - m_ui.filterWidget->setCurrentItem(m_filterToItem.first()); - - updateCurrentFilter(); -} - -void PreferencesDialog::updateCurrentFilter() -{ - if (m_hideFiltersTab) - return; - - const QString ¤tFilter = m_itemToFilter.value(m_ui.filterWidget->currentItem()); - - const bool filterSelected = !currentFilter.isEmpty(); - m_ui.componentWidget->setEnabled(filterSelected); - m_ui.versionWidget->setEnabled(filterSelected); - m_ui.filterRenameButton->setEnabled(filterSelected); - m_ui.filterRemoveButton->setEnabled(filterSelected); - - m_ui.componentWidget->setOptions(m_currentSetup.m_componentToNamespace.keys(), - m_currentSetup.m_filterToData.value(currentFilter).components()); - m_ui.versionWidget->setOptions(versionsToStringList(m_currentSetup.m_versionToNamespace.keys()), - versionsToStringList(m_currentSetup.m_filterToData.value(currentFilter).versions())); -} - -void PreferencesDialog::updateDocumentationPage() -{ - if (m_hideDocsTab) - return; - - m_ui.registeredDocsListWidget->clear(); - m_namespaceToItem.clear(); - m_itemToNamespace.clear(); - - for (const QString &namespaceName : m_currentSetup.m_namespaceToFileName.keys()) { - QListWidgetItem *item = new QListWidgetItem(namespaceName); - m_namespaceToItem.insert(namespaceName, item); - m_itemToNamespace.insert(item, namespaceName); - applyDocListFilter(item); - m_ui.registeredDocsListWidget->addItem(item); - } - m_ui.docRemoveButton->setEnabled( - !m_ui.registeredDocsListWidget->selectedItems().isEmpty()); -} - -void PreferencesDialog::applyDocListFilter(QListWidgetItem *item) -{ - const QString namespaceName = m_itemToNamespace.value(item); - const QString nameFilter = m_ui.registeredDocsFilterLineEdit->text(); - - const bool matches = nameFilter.isEmpty() || namespaceName.contains(nameFilter); - - if (!matches) - item->setSelected(false); - item->setHidden(!matches); -} - -void PreferencesDialog::filterSelected(QListWidgetItem *item) -{ - Q_UNUSED(item) - - updateCurrentFilter(); -} - -void PreferencesDialog::componentsChanged(const QStringList &components) -{ - const QString ¤tFilter = m_itemToFilter.value(m_ui.filterWidget->currentItem()); - if (currentFilter.isEmpty()) - return; - - m_currentSetup.m_filterToData[currentFilter].setComponents(components); -} - -void PreferencesDialog::versionsChanged(const QStringList &versions) -{ - const QString ¤tFilter = m_itemToFilter.value(m_ui.filterWidget->currentItem()); - if (currentFilter.isEmpty()) - return; - - m_currentSetup.m_filterToData[currentFilter].setVersions(stringListToVersions(versions)); -} - -QString PreferencesDialog::suggestedNewFilterName(const QString &initialFilterName) const -{ - QString newFilterName = initialFilterName; - - int counter = 1; - while (m_filterToItem.contains(newFilterName)) { - newFilterName = initialFilterName + QLatin1Char(' ') - + QString::number(++counter); - } - - return newFilterName; -} - -QString PreferencesDialog::getUniqueFilterName(const QString &windowTitle, - const QString &initialFilterName) -{ - QString newFilterName = initialFilterName; - while (1) { - FilterNameDialog dialog(this); - dialog.setWindowTitle(windowTitle); - dialog.setFilterName(newFilterName); - if (dialog.exec() == QDialog::Rejected) - return QString(); - - newFilterName = dialog.filterName(); - if (!m_filterToItem.contains(newFilterName)) - break; - - if (QMessageBox::warning(this, tr("Filter Exists"), - tr("The filter \"%1\" already exists.") - .arg(newFilterName), - QMessageBox::Retry | QMessageBox::Cancel) - == QMessageBox::Cancel) { - return QString(); - } - } - - return newFilterName; -} - -void PreferencesDialog::addFilterClicked() -{ - const QString newFilterName = getUniqueFilterName(tr("Add Filter"), - suggestedNewFilterName(tr("New Filter"))); - if (newFilterName.isEmpty()) - return; - - addFilter(newFilterName); -} - -void PreferencesDialog::renameFilterClicked() -{ - const QString ¤tFilter = m_itemToFilter.value(m_ui.filterWidget->currentItem()); - if (currentFilter.isEmpty()) - return; - - const QString newFilterName = getUniqueFilterName(tr("Rename Filter"), currentFilter); - if (newFilterName.isEmpty()) - return; - - const QHelpFilterData oldFilterData = m_currentSetup.m_filterToData.value(currentFilter); - removeFilter(currentFilter); - addFilter(newFilterName, oldFilterData); - - if (m_currentSetup.m_currentFilter == currentFilter) - m_currentSetup.m_currentFilter = newFilterName; -} - -void PreferencesDialog::removeFilterClicked() -{ - const QString ¤tFilter = m_itemToFilter.value(m_ui.filterWidget->currentItem()); - if (currentFilter.isEmpty()) - return; - - if (QMessageBox::question(this, tr("Remove Filter"), - tr("Are you sure you want to remove the \"%1\" filter?") - .arg(currentFilter), - QMessageBox::Yes | QMessageBox::No) - != QMessageBox::Yes) { - return; - } - - removeFilter(currentFilter); - - if (m_currentSetup.m_currentFilter == currentFilter) - m_currentSetup.m_currentFilter.clear(); -} - -void PreferencesDialog::addFilter(const QString &filterName, - const QHelpFilterData &filterData) -{ - QListWidgetItem *item = new QListWidgetItem(filterName); - m_currentSetup.m_filterToData.insert(filterName, filterData); - m_filterToItem.insert(filterName, item); - m_itemToFilter.insert(item, filterName); - m_ui.filterWidget->insertItem(m_filterToItem.keys().indexOf(filterName), item); - - m_ui.filterWidget->setCurrentItem(item); - updateCurrentFilter(); -} - -void PreferencesDialog::removeFilter(const QString &filterName) -{ - QListWidgetItem *item = m_filterToItem.value(filterName); - m_itemToFilter.remove(item); - m_filterToItem.remove(filterName); - delete item; - - m_currentSetup.m_filterToData.remove(filterName); -} - -void PreferencesDialog::addDocumentation() -{ - const QStringList &fileNames = QFileDialog::getOpenFileNames(this, - tr("Add Documentation"), QString(), tr("Qt Compressed Help Files (*.qch)")); - if (fileNames.isEmpty()) - return; - - bool added = false; - - for (const QString &fileName : fileNames) { - const QCompressedHelpInfo info = QCompressedHelpInfo::fromCompressedHelpFile(fileName); - const QString namespaceName = info.namespaceName(); - - if (m_currentSetup.m_namespaceToFileName.contains(namespaceName)) - continue; - - if (m_currentSetup.m_fileNameToNamespace.contains(fileName)) - continue; - - const QString component = info.component(); - const QVersionNumber version = info.version(); - - m_currentSetup.m_namespaceToFileName.insert(namespaceName, fileName); - m_currentSetup.m_fileNameToNamespace.insert(fileName, namespaceName); - - m_currentSetup.m_namespaceToComponent.insert(namespaceName, component); - m_currentSetup.m_componentToNamespace[component].append(namespaceName); - - m_currentSetup.m_namespaceToVersion.insert(namespaceName, version); - m_currentSetup.m_versionToNamespace[version].append(namespaceName); - - if (!added) { - added = true; - m_ui.registeredDocsListWidget->clearSelection(); - } - - QListWidgetItem *item = new QListWidgetItem(namespaceName); - m_namespaceToItem.insert(namespaceName, item); - m_itemToNamespace.insert(item, namespaceName); - m_ui.registeredDocsListWidget->insertItem(m_namespaceToItem.keys().indexOf(namespaceName), item); - item->setSelected(true); - applyDocListFilter(item); - } - - if (added) - updateCurrentFilter(); -} - -void PreferencesDialog::removeDocumentation() -{ - const QList<QListWidgetItem *> selectedItems = m_ui.registeredDocsListWidget->selectedItems(); - if (selectedItems.isEmpty()) - return; - - for (QListWidgetItem *item : selectedItems) { - const QString namespaceName = m_itemToNamespace.value(item); - m_itemToNamespace.remove(item); - m_namespaceToItem.remove(namespaceName); - delete item; - - const QString fileName = m_currentSetup.m_namespaceToFileName.value(namespaceName); - const QString component = m_currentSetup.m_namespaceToComponent.value(namespaceName); - const QVersionNumber version = m_currentSetup.m_namespaceToVersion.value(namespaceName); - m_currentSetup.m_namespaceToComponent.remove(namespaceName); - m_currentSetup.m_namespaceToVersion.remove(namespaceName); - m_currentSetup.m_namespaceToFileName.remove(namespaceName); - m_currentSetup.m_fileNameToNamespace.remove(fileName); - m_currentSetup.m_componentToNamespace[component].removeOne(namespaceName); - if (m_currentSetup.m_componentToNamespace[component].isEmpty()) - m_currentSetup.m_componentToNamespace.remove(component); - m_currentSetup.m_versionToNamespace[version].removeOne(namespaceName); - if (m_currentSetup.m_versionToNamespace[version].isEmpty()) - m_currentSetup.m_versionToNamespace.remove(version); - } - - updateCurrentFilter(); -} - void PreferencesDialog::okClicked() { applyChanges(); @@ -486,74 +105,27 @@ void PreferencesDialog::okClicked() void PreferencesDialog::applyClicked() { applyChanges(); - m_originalSetup = readOriginalSetup(); - m_currentSetup = m_originalSetup; - updateDocumentationPage(); - updateFilterPage(); -} -template <class T> -static QMap<QString, T> subtract(const QMap<QString, T> &minuend, - const QMap<QString, T> &subtrahend) -{ - QMap<QString, T> result = minuend; + m_docSettings = HelpDocSettings::readSettings(helpEngine.helpEngine()); - for (auto itSubtrahend = subtrahend.cbegin(); itSubtrahend != subtrahend.cend(); ++itSubtrahend) { - auto itResult = result.find(itSubtrahend.key()); - if (itResult != result.end() && itSubtrahend.value() == itResult.value()) - result.erase(itResult); + if (!m_hideDocsTab) + m_ui.docSettingsWidget->setDocSettings(m_docSettings); + if (!m_hideFiltersTab) { + m_ui.filterSettingsWidget->setAvailableComponents(m_docSettings.components()); + m_ui.filterSettingsWidget->setAvailableVersions(m_docSettings.versions()); + m_ui.filterSettingsWidget->readSettings(helpEngine.filterEngine()); } - - return result; } void PreferencesDialog::applyChanges() { bool changed = false; - - const QMap<QString, QString> docsToRemove = subtract( - m_originalSetup.m_namespaceToFileName, - m_currentSetup.m_namespaceToFileName); - const QMap<QString, QString> docsToAdd = subtract( - m_currentSetup.m_namespaceToFileName, - m_originalSetup.m_namespaceToFileName); - - for (const QString &namespaceName : docsToRemove.keys()) { - if (!helpEngine.unregisterDocumentation(namespaceName)) - qWarning() << "Cannot unregister documentation:" << namespaceName; - changed = true; - } - - for (const QString &fileName : docsToAdd.values()) { - if (!helpEngine.registerDocumentation(fileName)) - qWarning() << "Cannot register documentation file:" << fileName; - changed = true; - } - - const QMap<QString, QHelpFilterData> filtersToRemove = subtract( - m_originalSetup.m_filterToData, - m_currentSetup.m_filterToData); - const QMap<QString, QHelpFilterData> filtersToAdd = subtract( - m_currentSetup.m_filterToData, - m_originalSetup.m_filterToData); - - const QString ¤tFilter = helpEngine.filterEngine()->activeFilter(); - - for (const QString &filter : filtersToRemove.keys()) { - helpEngine.filterEngine()->removeFilter(filter); - if (currentFilter == filter && !filtersToAdd.contains(filter)) - helpEngine.filterEngine()->setActiveFilter(QString()); - changed = true; - } - - for (auto it = filtersToAdd.cbegin(); it != filtersToAdd.cend(); ++it) { - helpEngine.filterEngine()->setFilterData(it.key(), it.value()); - changed = true; - } + if (!m_hideDocsTab) + changed = HelpDocSettings::applySettings(helpEngine.helpEngine(), m_docSettings); + if (!m_hideFiltersTab) + changed = changed || m_ui.filterSettingsWidget->applySettings(helpEngine.filterEngine()); if (changed) { - helpEngine.filterEngine()->setActiveFilter(m_currentSetup.m_currentFilter); - // In order to update the filtercombobox and indexwidget // according to the new filter configuration. helpEngine.setupData(); diff --git a/src/assistant/assistant/preferencesdialog.h b/src/assistant/assistant/preferencesdialog.h index b0601e280..a65066fde 100644 --- a/src/assistant/assistant/preferencesdialog.h +++ b/src/assistant/assistant/preferencesdialog.h @@ -29,31 +29,17 @@ #ifndef PREFERENCESDIALOG_H #define PREFERENCESDIALOG_H -#include <QtCore/QVersionNumber> +#include <QtCore/QMap> #include <QtWidgets/QDialog> #include <QtHelp/QHelpFilterData> #include "ui_preferencesdialog.h" +#include "helpdocsettings.h" QT_BEGIN_NAMESPACE class FontPanel; class HelpEngineWrapper; class QFileSystemWatcher; -class QVersionNumber; - -struct FilterSetup { - QMap<QString, QString> m_namespaceToComponent; - QMap<QString, QStringList> m_componentToNamespace; - - QMap<QString, QVersionNumber> m_namespaceToVersion; - QMap<QVersionNumber, QStringList> m_versionToNamespace; - - QMap<QString, QString> m_namespaceToFileName; - QMap<QString, QString> m_fileNameToNamespace; - - QMap<QString, QHelpFilterData> m_filterToData; - QString m_currentFilter; -}; class PreferencesDialog : public QDialog { @@ -63,17 +49,6 @@ public: PreferencesDialog(QWidget *parent = nullptr); private slots: - void filterSelected(QListWidgetItem *item); - void componentsChanged(const QStringList &components); - void versionsChanged(const QStringList &versions); - void addFilterClicked(); - void renameFilterClicked(); - void removeFilterClicked(); - void addFilter(const QString &filterName, - const QHelpFilterData &filterData = QHelpFilterData()); - void removeFilter(const QString &filterName); - void addDocumentation(); - void removeDocumentation(); void okClicked(); void applyClicked(); void applyChanges(); @@ -92,28 +67,12 @@ signals: void updateUserInterface(); private: - QString suggestedNewFilterName(const QString &initialFilterName) const; - QString getUniqueFilterName(const QString &windowTitle, - const QString &initialFilterName = QString()); - void applyDocListFilter(QListWidgetItem *item); - - void updateFilterPage(); - void updateCurrentFilter(); - void updateDocumentationPage(); void updateFontSettingsPage(); void updateOptionsPage(); - FilterSetup readOriginalSetup() const; Ui::PreferencesDialogClass m_ui; - FilterSetup m_originalSetup; - FilterSetup m_currentSetup; - - QMap<QString, QListWidgetItem *> m_namespaceToItem; - QHash<QListWidgetItem *, QString> m_itemToNamespace; - - QMap<QString, QListWidgetItem *> m_filterToItem; - QHash<QListWidgetItem *, QString> m_itemToFilter; + HelpDocSettings m_docSettings; FontPanel *m_appFontPanel; FontPanel *m_browserFontPanel; diff --git a/src/assistant/assistant/preferencesdialog.ui b/src/assistant/assistant/preferencesdialog.ui index 68dbf68e2..2d1c480a6 100644 --- a/src/assistant/assistant/preferencesdialog.ui +++ b/src/assistant/assistant/preferencesdialog.ui @@ -7,7 +7,7 @@ <x>0</x> <y>0</y> <width>395</width> - <height>341</height> + <height>376</height> </rect> </property> <property name="windowTitle"> @@ -17,7 +17,7 @@ <item> <widget class="QTabWidget" name="tabWidget"> <property name="currentIndex"> - <number>1</number> + <number>2</number> </property> <widget class="QWidget" name="fontsTab"> <attribute name="title"> @@ -69,60 +69,21 @@ <attribute name="title"> <string>Filters</string> </attribute> - <layout class="QGridLayout" name="gridLayout_2"> - <item row="0" column="3"> - <widget class="QLabel" name="componentsLabel"> - <property name="frameShape"> - <enum>QFrame::NoFrame</enum> - </property> - <property name="text"> - <string>Components:</string> - </property> - </widget> - </item> - <item row="0" column="4"> - <widget class="QLabel" name="versionsLabel"> - <property name="text"> - <string>Versions:</string> - </property> - </widget> - </item> - <item row="1" column="0" colspan="3"> - <widget class="QListWidget" name="filterWidget"/> - </item> - <item row="1" column="3" rowspan="2"> - <widget class="OptionsWidget" name="componentWidget" native="true"/> - </item> - <item row="1" column="4" rowspan="2"> - <widget class="OptionsWidget" name="versionWidget" native="true"/> - </item> - <item row="2" column="0"> - <widget class="QToolButton" name="filterAddButton"> - <property name="text"> - <string>Add...</string> - </property> - </widget> - </item> - <item row="2" column="1"> - <widget class="QToolButton" name="filterRenameButton"> - <property name="text"> - <string>Rename...</string> - </property> - </widget> - </item> - <item row="2" column="2"> - <widget class="QToolButton" name="filterRemoveButton"> - <property name="text"> - <string>Remove</string> - </property> - </widget> - </item> - <item row="0" column="0" colspan="3"> - <widget class="QLabel" name="filterLabel"> - <property name="text"> - <string>Filter:</string> - </property> - </widget> + <layout class="QVBoxLayout" name="verticalLayout_5"> + <property name="leftMargin"> + <number>0</number> + </property> + <property name="topMargin"> + <number>0</number> + </property> + <property name="rightMargin"> + <number>0</number> + </property> + <property name="bottomMargin"> + <number>0</number> + </property> + <item> + <widget class="QHelpFilterSettingsWidget" name="filterSettingsWidget" native="true"/> </item> </layout> </widget> @@ -130,61 +91,21 @@ <attribute name="title"> <string>Documentation</string> </attribute> - <layout class="QGridLayout" name="gridLayout_3"> - <item row="0" column="0"> - <widget class="QLabel" name="label_3"> - <property name="text"> - <string>Registered Documentation:</string> - </property> - </widget> - </item> - <item row="1" column="0"> - <widget class="QLineEdit" name="registeredDocsFilterLineEdit"> - <property name="placeholderText"> - <string><Filter></string> - </property> - <property name="clearButtonEnabled"> - <bool>true</bool> - </property> - </widget> - </item> - <item row="1" column="1" rowspan="2"> - <layout class="QVBoxLayout" name="verticalLayout_4"> - <item> - <widget class="QPushButton" name="docAddButton"> - <property name="text"> - <string>Add...</string> - </property> - </widget> - </item> - <item> - <widget class="QPushButton" name="docRemoveButton"> - <property name="text"> - <string>Remove</string> - </property> - </widget> - </item> - <item> - <spacer> - <property name="orientation"> - <enum>Qt::Vertical</enum> - </property> - <property name="sizeHint" stdset="0"> - <size> - <width>20</width> - <height>40</height> - </size> - </property> - </spacer> - </item> - </layout> - </item> - <item row="2" column="0"> - <widget class="QListWidget" name="registeredDocsListWidget"> - <property name="selectionMode"> - <enum>QAbstractItemView::ExtendedSelection</enum> - </property> - </widget> + <layout class="QVBoxLayout" name="verticalLayout_4"> + <property name="leftMargin"> + <number>0</number> + </property> + <property name="topMargin"> + <number>0</number> + </property> + <property name="rightMargin"> + <number>0</number> + </property> + <property name="bottomMargin"> + <number>0</number> + </property> + <item> + <widget class="HelpDocSettingsWidget" name="docSettingsWidget" native="true"/> </item> </layout> </widget> @@ -359,9 +280,15 @@ <layoutdefault spacing="6" margin="11"/> <customwidgets> <customwidget> - <class>OptionsWidget</class> + <class>HelpDocSettingsWidget</class> + <extends>QWidget</extends> + <header>helpdocsettingswidget.h</header> + <container>1</container> + </customwidget> + <customwidget> + <class>QHelpFilterSettingsWidget</class> <extends>QWidget</extends> - <header>optionswidget.h</header> + <header>qhelpfiltersettingswidget.h</header> <container>1</container> </customwidget> </customwidgets> diff --git a/src/assistant/help/help.pro b/src/assistant/help/help.pro index cd7781dde..ff7a81374 100644 --- a/src/assistant/help/help.pro +++ b/src/assistant/help/help.pro @@ -12,10 +12,13 @@ DEFINES -= QT_ASCII_CAST_WARNINGS RESOURCES += helpsystem.qrc SOURCES += \ qcompressedhelpinfo.cpp \ + qfilternamedialog.cpp \ qhelpenginecore.cpp \ qhelpengine.cpp \ qhelpfilterdata.cpp \ qhelpfilterengine.cpp \ + qhelpfiltersettings.cpp \ + qhelpfiltersettingswidget.cpp \ qhelpdbreader.cpp \ qhelpcontentwidget.cpp \ qhelpindexwidget.cpp \ @@ -26,15 +29,19 @@ SOURCES += \ qhelpsearchindexwriter_default.cpp \ qhelpsearchindexreader_default.cpp \ qhelpsearchindexreader.cpp \ - qhelp_global.cpp + qhelp_global.cpp \ + qoptionswidget.cpp HEADERS += \ qcompressedhelpinfo.h \ + qfilternamedialog_p.h \ qhelpenginecore.h \ qhelpengine.h \ qhelpengine_p.h \ qhelpfilterdata.h \ qhelpfilterengine.h \ + qhelpfiltersettings_p.h \ + qhelpfiltersettingswidget.h \ qhelp_global.h \ qhelpdbreader_p.h \ qhelpcontentwidget.h \ @@ -45,6 +52,12 @@ HEADERS += \ qhelpsearchresultwidget.h \ qhelpsearchindexwriter_default_p.h \ qhelpsearchindexreader_default_p.h \ - qhelpsearchindexreader_p.h + qhelpsearchindexreader_p.h \ + qoptionswidget_p.h + +FORMS += \ + qhelpfiltersettingswidget.ui \ + qfilternamedialog.ui + load(qt_module) diff --git a/src/assistant/help/helpsystem.qrc b/src/assistant/help/helpsystem.qrc index 785923aad..611008639 100644 --- a/src/assistant/help/helpsystem.qrc +++ b/src/assistant/help/helpsystem.qrc @@ -4,5 +4,9 @@ <file>images/1rightarrow.png</file> <file>images/3leftarrow.png</file> <file>images/3rightarrow.png</file> + <file>images/mac/minus.png</file> + <file>images/mac/plus.png</file> + <file>images/win/minus.png</file> + <file>images/win/plus.png</file> </qresource> </RCC> diff --git a/src/assistant/assistant/images/mac/minus.png b/src/assistant/help/images/mac/minus.png Binary files differindex 8d2eaed52..8d2eaed52 100644 --- a/src/assistant/assistant/images/mac/minus.png +++ b/src/assistant/help/images/mac/minus.png diff --git a/src/assistant/assistant/images/mac/plus.png b/src/assistant/help/images/mac/plus.png Binary files differindex 1ee45423e..1ee45423e 100644 --- a/src/assistant/assistant/images/mac/plus.png +++ b/src/assistant/help/images/mac/plus.png diff --git a/src/assistant/assistant/images/win/minus.png b/src/assistant/help/images/win/minus.png Binary files differindex c0dc274bb..c0dc274bb 100644 --- a/src/assistant/assistant/images/win/minus.png +++ b/src/assistant/help/images/win/minus.png diff --git a/src/assistant/assistant/images/win/plus.png b/src/assistant/help/images/win/plus.png Binary files differindex ecf058941..ecf058941 100644 --- a/src/assistant/assistant/images/win/plus.png +++ b/src/assistant/help/images/win/plus.png diff --git a/src/assistant/help/qcompressedhelpinfo.cpp b/src/assistant/help/qcompressedhelpinfo.cpp index bbdc64157..a3c5b75d5 100644 --- a/src/assistant/help/qcompressedhelpinfo.cpp +++ b/src/assistant/help/qcompressedhelpinfo.cpp @@ -55,12 +55,14 @@ public: , m_namespaceName(other.m_namespaceName) , m_component(other.m_component) , m_version(other.m_version) + , m_isNull(other.m_isNull) { } ~QCompressedHelpInfoPrivate() = default; QString m_namespaceName; QString m_component; QVersionNumber m_version; + bool m_isNull = true; }; /*! @@ -151,6 +153,15 @@ QVersionNumber QCompressedHelpInfo::version() const } /*! + Returns \c true if the info is invalid, otherwise returns + \c false. +*/ +bool QCompressedHelpInfo::isNull() const +{ + return d->m_isNull; +} + +/*! Returns the QCompressedHelpInfo instance for the \a documentationFileName of the existing qch file. */ @@ -164,6 +175,7 @@ QCompressedHelpInfo QCompressedHelpInfo::fromCompressedHelpFile(const QString &d info.d->m_namespaceName = reader.namespaceName(); info.d->m_component = reader.virtualFolder(); info.d->m_version = QVersionNumber::fromString(reader.version()); + info.d->m_isNull = false; return info; } return QCompressedHelpInfo(); diff --git a/src/assistant/help/qcompressedhelpinfo.h b/src/assistant/help/qcompressedhelpinfo.h index c392bb74c..7b3c78c12 100644 --- a/src/assistant/help/qcompressedhelpinfo.h +++ b/src/assistant/help/qcompressedhelpinfo.h @@ -66,6 +66,7 @@ public: QString namespaceName() const; QString component() const; QVersionNumber version() const; + bool isNull() const; static QCompressedHelpInfo fromCompressedHelpFile(const QString &documentationFileName); diff --git a/src/assistant/assistant/filternamedialog.cpp b/src/assistant/help/qfilternamedialog.cpp index 4c17d3332..8563a3355 100644 --- a/src/assistant/assistant/filternamedialog.cpp +++ b/src/assistant/help/qfilternamedialog.cpp @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2016 The Qt Company Ltd. +** Copyright (C) 2020 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the Qt Assistant of the Qt Toolkit. @@ -28,11 +28,11 @@ #include <QtWidgets/QPushButton> -#include "filternamedialog.h" +#include "qfilternamedialog_p.h" QT_BEGIN_NAMESPACE -FilterNameDialog::FilterNameDialog(QWidget *parent) +QFilterNameDialog::QFilterNameDialog(QWidget *parent) : QDialog(parent) { m_ui.setupUi(this); @@ -41,22 +41,22 @@ FilterNameDialog::FilterNameDialog(QWidget *parent) connect(m_ui.buttonBox->button(QDialogButtonBox::Cancel), &QAbstractButton::clicked, this, &QDialog::reject); connect(m_ui.lineEdit, &QLineEdit::textChanged, - this, &FilterNameDialog::updateOkButton); + this, &QFilterNameDialog::updateOkButton); m_ui.buttonBox->button(QDialogButtonBox::Ok)->setDisabled(true); } -void FilterNameDialog::setFilterName(const QString &filter) +void QFilterNameDialog::setFilterName(const QString &filter) { m_ui.lineEdit->setText(filter); m_ui.lineEdit->selectAll(); } -QString FilterNameDialog::filterName() const +QString QFilterNameDialog::filterName() const { return m_ui.lineEdit->text(); } -void FilterNameDialog::updateOkButton() +void QFilterNameDialog::updateOkButton() { m_ui.buttonBox->button(QDialogButtonBox::Ok) ->setDisabled(m_ui.lineEdit->text().isEmpty()); diff --git a/src/assistant/assistant/filternamedialog.ui b/src/assistant/help/qfilternamedialog.ui index 1da584a80..1da584a80 100644 --- a/src/assistant/assistant/filternamedialog.ui +++ b/src/assistant/help/qfilternamedialog.ui diff --git a/src/assistant/assistant/filternamedialog.h b/src/assistant/help/qfilternamedialog_p.h index 522b611af..f805e9308 100644 --- a/src/assistant/assistant/filternamedialog.h +++ b/src/assistant/help/qfilternamedialog_p.h @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2016 The Qt Company Ltd. +** Copyright (C) 2020 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the Qt Assistant of the Qt Toolkit. @@ -26,20 +26,20 @@ ** ****************************************************************************/ -#ifndef FILTERNAMEDIALOG_H -#define FILTERNAMEDIALOG_H +#ifndef QFILTERNAMEDIALOG_H +#define QFILTERNAMEDIALOG_H #include <QtWidgets/QDialog> -#include "ui_filternamedialog.h" +#include "ui_qfilternamedialog.h" QT_BEGIN_NAMESPACE -class FilterNameDialog : public QDialog +class QFilterNameDialog : public QDialog { Q_OBJECT public: - FilterNameDialog(QWidget *parent = nullptr); + QFilterNameDialog(QWidget *parent = nullptr); void setFilterName(const QString &filter); QString filterName() const; @@ -53,4 +53,4 @@ private: QT_END_NAMESPACE -#endif // FILTERNAMEDIALOG_H +#endif // QFILTERNAMEDIALOG_H diff --git a/src/assistant/help/qhelpfiltersettings.cpp b/src/assistant/help/qhelpfiltersettings.cpp new file mode 100644 index 000000000..e9a1c3f4e --- /dev/null +++ b/src/assistant/help/qhelpfiltersettings.cpp @@ -0,0 +1,170 @@ +/**************************************************************************** +** +** Copyright (C) 2020 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt Assistant of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qhelpfiltersettings_p.h" +#include "qhelpfilterdata.h" + +#include <QtCore/QMap> +#include <QtHelp/QHelpFilterEngine> + +QT_BEGIN_NAMESPACE + +class QHelpFilterSettingsPrivate : public QSharedData +{ +public: + QHelpFilterSettingsPrivate() = default; + QHelpFilterSettingsPrivate(const QHelpFilterSettingsPrivate &other) = default; + ~QHelpFilterSettingsPrivate() = default; + + QMap<QString, QHelpFilterData> m_filterToData; + QString m_currentFilter; +}; + +QHelpFilterSettings::QHelpFilterSettings() + : d(new QHelpFilterSettingsPrivate) +{ +} + +QHelpFilterSettings::QHelpFilterSettings(const QHelpFilterSettings &) = default; + +QHelpFilterSettings::QHelpFilterSettings(QHelpFilterSettings &&) = default; + +QHelpFilterSettings::~QHelpFilterSettings() = default; + +QHelpFilterSettings &QHelpFilterSettings::operator=(const QHelpFilterSettings &) = default; + +QHelpFilterSettings &QHelpFilterSettings::operator=(QHelpFilterSettings &&) = default; + +void QHelpFilterSettings::setFilter(const QString &filterName, + const QHelpFilterData &filterData) +{ + d->m_filterToData.insert(filterName, filterData); +} + +void QHelpFilterSettings::removeFilter(const QString &filterName) +{ + d->m_filterToData.remove(filterName); +} + +QStringList QHelpFilterSettings::filterNames() const +{ + return d->m_filterToData.keys(); +} + +QHelpFilterData QHelpFilterSettings::filterData(const QString &filterName) const +{ + return d->m_filterToData.value(filterName); +} + +QMap<QString, QHelpFilterData> QHelpFilterSettings::filters() const +{ + return d->m_filterToData; +} + +void QHelpFilterSettings::setCurrentFilter(const QString &filterName) +{ + d->m_currentFilter = filterName; +} + +QString QHelpFilterSettings::currentFilter() const +{ + return d->m_currentFilter; +} + +QHelpFilterSettings QHelpFilterSettings::readSettings(QHelpFilterEngine *filterEngine) +{ + QHelpFilterSettings filterSettings; + + const QStringList allFilters = filterEngine->filters(); + for (const QString &filter : allFilters) + filterSettings.setFilter(filter, filterEngine->filterData(filter)); + + filterSettings.setCurrentFilter(filterEngine->activeFilter()); + + return filterSettings; +} + +static QMap<QString, QHelpFilterData> subtract(const QMap<QString, QHelpFilterData> &minuend, + const QMap<QString, QHelpFilterData> &subtrahend) +{ + QMap<QString, QHelpFilterData> result = minuend; + + for (auto itSubtrahend = subtrahend.cbegin(); itSubtrahend != subtrahend.cend(); ++itSubtrahend) { + auto itResult = result.find(itSubtrahend.key()); + if (itResult != result.end() && itSubtrahend.value() == itResult.value()) + result.erase(itResult); + } + + return result; +} + +bool QHelpFilterSettings::applySettings(QHelpFilterEngine *filterEngine, + const QHelpFilterSettings &settings) +{ + bool changed = false; + const QHelpFilterSettings oldSettings = readSettings(filterEngine); + + const QMap<QString, QHelpFilterData> filtersToRemove = subtract( + oldSettings.filters(), + settings.filters()); + const QMap<QString, QHelpFilterData> filtersToAdd = subtract( + settings.filters(), + oldSettings.filters()); + + const QString ¤tFilter = filterEngine->activeFilter(); + + for (const QString &filter : filtersToRemove.keys()) { + filterEngine->removeFilter(filter); + if (currentFilter == filter && !filtersToAdd.contains(filter)) + filterEngine->setActiveFilter(QString()); + changed = true; + } + + for (auto it = filtersToAdd.cbegin(); it != filtersToAdd.cend(); ++it) { + filterEngine->setFilterData(it.key(), it.value()); + changed = true; + } + + if (changed) + filterEngine->setActiveFilter(settings.currentFilter()); + + return changed; +} + +QT_END_NAMESPACE diff --git a/src/assistant/help/qhelpfiltersettings_p.h b/src/assistant/help/qhelpfiltersettings_p.h new file mode 100644 index 000000000..50e30e492 --- /dev/null +++ b/src/assistant/help/qhelpfiltersettings_p.h @@ -0,0 +1,85 @@ +/**************************************************************************** +** +** Copyright (C) 2020 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt Assistant of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QHELPFILTERSETTINGS_H +#define QHELPFILTERSETTINGS_H + +#include <QtCore/QSharedDataPointer> + +QT_BEGIN_NAMESPACE + +template <class K, class T> +class QMap; +class QHelpFilterData; +class QHelpFilterEngine; +class QHelpFilterSettingsPrivate; + +class QHelpFilterSettings final +{ +public: + QHelpFilterSettings(); + QHelpFilterSettings(const QHelpFilterSettings &other); + QHelpFilterSettings(QHelpFilterSettings &&other); + ~QHelpFilterSettings(); + + QHelpFilterSettings &operator=(const QHelpFilterSettings &other); + QHelpFilterSettings &operator=(QHelpFilterSettings &&other); + + void swap(QHelpFilterSettings &other) noexcept + { d.swap(other.d); } + + void setFilter(const QString &filterName, const QHelpFilterData &filterData); + void removeFilter(const QString &filterName); + QStringList filterNames() const; + QHelpFilterData filterData(const QString &filterName) const; + QMap<QString, QHelpFilterData> filters() const; + + void setCurrentFilter(const QString &filterName); + QString currentFilter() const; + + static QHelpFilterSettings readSettings(QHelpFilterEngine *filterEngine); + static bool applySettings(QHelpFilterEngine *filterEngine, const QHelpFilterSettings &settings); + +private: + QSharedDataPointer<QHelpFilterSettingsPrivate> d; +}; + +QT_END_NAMESPACE + +#endif // QHELPFILTERSETTINGS_H diff --git a/src/assistant/help/qhelpfiltersettingswidget.cpp b/src/assistant/help/qhelpfiltersettingswidget.cpp new file mode 100644 index 000000000..15cc4f475 --- /dev/null +++ b/src/assistant/help/qhelpfiltersettingswidget.cpp @@ -0,0 +1,428 @@ +/**************************************************************************** +** +** Copyright (C) 2020 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt Assistant of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qhelpfilterdata.h" +#include "qhelpfiltersettings_p.h" +#include "qhelpfiltersettingswidget.h" +#include "ui_qhelpfiltersettingswidget.h" +#include "qfilternamedialog_p.h" + +#include <QtWidgets/QMessageBox> +#include <QtCore/QVersionNumber> + +QT_BEGIN_NAMESPACE + +static QStringList versionsToStringList(const QList<QVersionNumber> &versions) +{ + QStringList versionList; + for (const QVersionNumber &version : versions) + versionList.append(version.isNull() ? QString() : version.toString()); + return versionList; +} + +static QList<QVersionNumber> stringListToVersions(const QStringList &versionList) +{ + QList<QVersionNumber> versions; + for (const QString &versionString : versionList) + versions.append(QVersionNumber::fromString(versionString)); + return versions; +} + +class QHelpFilterSettingsWidgetPrivate +{ + QHelpFilterSettingsWidget *q_ptr; + Q_DECLARE_PUBLIC(QHelpFilterSettingsWidget) +public: + QHelpFilterSettingsWidgetPrivate() = default; + + QHelpFilterSettings filterSettings() const; + void setFilterSettings(const QHelpFilterSettings &settings); + + void updateCurrentFilter(); + void componentsChanged(const QStringList &components); + void versionsChanged(const QStringList &versions); + void addFilterClicked(); + void renameFilterClicked(); + void removeFilterClicked(); + void addFilter(const QString &filterName, + const QHelpFilterData &filterData = QHelpFilterData()); + void removeFilter(const QString &filterName); + QString getUniqueFilterName(const QString &windowTitle, + const QString &initialFilterName); + QString suggestedNewFilterName(const QString &initialFilterName) const; + + QMap<QString, QListWidgetItem *> m_filterToItem; + QHash<QListWidgetItem *, QString> m_itemToFilter; + + Ui::QHelpFilterSettingsWidget m_ui; + QStringList m_components; + QList<QVersionNumber> m_versions; + QHelpFilterSettings m_filterSettings; +}; + +void QHelpFilterSettingsWidgetPrivate::setFilterSettings(const QHelpFilterSettings &settings) +{ + QString currentFilter = m_itemToFilter.value(m_ui.filterWidget->currentItem()); + if (currentFilter.isEmpty()) { + if (!m_filterSettings.currentFilter().isEmpty()) + currentFilter = m_filterSettings.currentFilter(); + else + currentFilter = settings.currentFilter(); + } + + m_filterSettings = settings; + + m_ui.filterWidget->clear(); + m_ui.componentWidget->clear(); + m_ui.versionWidget->clear(); + m_itemToFilter.clear(); + m_filterToItem.clear(); + + for (const QString &filterName : m_filterSettings.filterNames()) { + QListWidgetItem *item = new QListWidgetItem(filterName); + m_ui.filterWidget->addItem(item); + m_itemToFilter.insert(item, filterName); + m_filterToItem.insert(filterName, item); + if (filterName == currentFilter) + m_ui.filterWidget->setCurrentItem(item); + } + + if (!m_ui.filterWidget->currentItem() && !m_filterToItem.isEmpty()) + m_ui.filterWidget->setCurrentItem(m_filterToItem.first()); + + updateCurrentFilter(); +} + +QHelpFilterSettings QHelpFilterSettingsWidgetPrivate::filterSettings() const +{ + return m_filterSettings; +} + +void QHelpFilterSettingsWidgetPrivate::updateCurrentFilter() +{ + const QString ¤tFilter = m_itemToFilter.value(m_ui.filterWidget->currentItem()); + + const bool filterSelected = !currentFilter.isEmpty(); + m_ui.componentWidget->setEnabled(filterSelected); + m_ui.versionWidget->setEnabled(filterSelected); + m_ui.renameButton->setEnabled(filterSelected); + m_ui.removeButton->setEnabled(filterSelected); + + m_ui.componentWidget->setOptions(m_components, + m_filterSettings.filterData(currentFilter).components()); + m_ui.versionWidget->setOptions(versionsToStringList(m_versions), + versionsToStringList(m_filterSettings.filterData(currentFilter).versions())); +} + +void QHelpFilterSettingsWidgetPrivate::componentsChanged(const QStringList &components) +{ + const QString ¤tFilter = m_itemToFilter.value(m_ui.filterWidget->currentItem()); + if (currentFilter.isEmpty()) + return; + + QHelpFilterData filterData = m_filterSettings.filterData(currentFilter); + filterData.setComponents(components); + m_filterSettings.setFilter(currentFilter, filterData); +} + +void QHelpFilterSettingsWidgetPrivate::versionsChanged(const QStringList &versions) +{ + const QString ¤tFilter = m_itemToFilter.value(m_ui.filterWidget->currentItem()); + if (currentFilter.isEmpty()) + return; + + QHelpFilterData filterData = m_filterSettings.filterData(currentFilter); + filterData.setVersions(stringListToVersions(versions)); + m_filterSettings.setFilter(currentFilter, filterData); +} + +void QHelpFilterSettingsWidgetPrivate::addFilterClicked() +{ + Q_Q(QHelpFilterSettingsWidget); + + const QString newFilterName = getUniqueFilterName(q->tr("Add Filter"), + suggestedNewFilterName(q->tr("New Filter"))); + if (newFilterName.isEmpty()) + return; + + addFilter(newFilterName); +} + +void QHelpFilterSettingsWidgetPrivate::renameFilterClicked() +{ + Q_Q(QHelpFilterSettingsWidget); + + const QString ¤tFilter = m_itemToFilter.value(m_ui.filterWidget->currentItem()); + if (currentFilter.isEmpty()) + return; + + const QString newFilterName = getUniqueFilterName(q->tr("Rename Filter"), currentFilter); + if (newFilterName.isEmpty()) + return; + + const QHelpFilterData oldFilterData = m_filterSettings.filterData(currentFilter); + removeFilter(currentFilter); + addFilter(newFilterName, oldFilterData); + + if (m_filterSettings.currentFilter() == currentFilter) + m_filterSettings.setCurrentFilter(newFilterName); +} + +void QHelpFilterSettingsWidgetPrivate::removeFilterClicked() +{ + Q_Q(QHelpFilterSettingsWidget); + + const QString ¤tFilter = m_itemToFilter.value(m_ui.filterWidget->currentItem()); + if (currentFilter.isEmpty()) + return; + + if (QMessageBox::question(q, q->tr("Remove Filter"), + q->tr("Are you sure you want to remove the \"%1\" filter?") + .arg(currentFilter), + QMessageBox::Yes | QMessageBox::No) + != QMessageBox::Yes) { + return; + } + + removeFilter(currentFilter); + + if (m_filterSettings.currentFilter() == currentFilter) + m_filterSettings.setCurrentFilter(QString()); +} + +void QHelpFilterSettingsWidgetPrivate::addFilter(const QString &filterName, + const QHelpFilterData &filterData) +{ + QListWidgetItem *item = new QListWidgetItem(filterName); + m_filterSettings.setFilter(filterName, filterData); + m_filterToItem.insert(filterName, item); + m_itemToFilter.insert(item, filterName); + m_ui.filterWidget->insertItem(m_filterToItem.keys().indexOf(filterName), item); + + m_ui.filterWidget->setCurrentItem(item); + updateCurrentFilter(); +} + +void QHelpFilterSettingsWidgetPrivate::removeFilter(const QString &filterName) +{ + QListWidgetItem *item = m_filterToItem.value(filterName); + m_itemToFilter.remove(item); + m_filterToItem.remove(filterName); + delete item; + + m_filterSettings.removeFilter(filterName); +} + +QString QHelpFilterSettingsWidgetPrivate::getUniqueFilterName(const QString &windowTitle, + const QString &initialFilterName) +{ + Q_Q(QHelpFilterSettingsWidget); + + QString newFilterName = initialFilterName; + while (1) { + QFilterNameDialog dialog(q); + dialog.setWindowTitle(windowTitle); + dialog.setFilterName(newFilterName); + if (dialog.exec() == QDialog::Rejected) + return QString(); + + newFilterName = dialog.filterName(); + if (!m_filterToItem.contains(newFilterName)) + break; + + if (QMessageBox::warning(q, q->tr("Filter Exists"), + q->tr("The filter \"%1\" already exists.") + .arg(newFilterName), + QMessageBox::Retry | QMessageBox::Cancel) + == QMessageBox::Cancel) { + return QString(); + } + } + + return newFilterName; +} + +QString QHelpFilterSettingsWidgetPrivate::suggestedNewFilterName(const QString &initialFilterName) const +{ + QString newFilterName = initialFilterName; + + int counter = 1; + while (m_filterToItem.contains(newFilterName)) { + newFilterName = initialFilterName + QLatin1Char(' ') + + QString::number(++counter); + } + + return newFilterName; +} + +/*! + \class QHelpFilterSettingsWidget + \inmodule QtHelp + \since 5.15 + \brief The QHelpFilterSettingsWidget class provides a widget that allows + for creating, editing and removing filters. + + The instance of QHelpFilterSettingsWidget may be a part of + a preferences dialog. Before showing the dialog, \l setAvailableComponents() + and \l setAvailableVersions() should be called, otherwise the filter + settings widget will only offer a creation of empty filters, + which wouldn't be useful. In addition, \l readSettings should also + be called to fill up the filter settings widget with the list of filters + already stored in the filter engine. The creation of new filters, + modifications to existing filters and removal of unneeded filters are + handled by the widget automatically. If you want to store the current + state of the widget and apply it to the filter engine e.g. after + the user clicked the apply button - call \l applySettings(). +*/ + +/*! + Constructs a filter settings widget with \a parent as parent widget. +*/ +QHelpFilterSettingsWidget::QHelpFilterSettingsWidget(QWidget *parent) + : QWidget(parent) + , d_ptr(new QHelpFilterSettingsWidgetPrivate()) +{ + Q_D(QHelpFilterSettingsWidget); + d->q_ptr = this; + d->m_ui.setupUi(this); + + // TODO: make resources configurable + QString resourcePath = QLatin1String(":/qt-project.org/assistant/images/"); +#ifdef Q_OS_MACOS + resourcePath.append(QLatin1String("mac")); +#else + resourcePath.append(QLatin1String("win")); +#endif + d->m_ui.addButton->setIcon(QIcon(resourcePath + QLatin1String("/plus.png"))); + d->m_ui.removeButton->setIcon(QIcon(resourcePath + QLatin1String("/minus.png"))); + + connect(d->m_ui.componentWidget, &QOptionsWidget::optionSelectionChanged, + [this](const QStringList &options) { + Q_D(QHelpFilterSettingsWidget); + d->componentsChanged(options); + }); + connect(d->m_ui.versionWidget, &QOptionsWidget::optionSelectionChanged, + [this](const QStringList &options) { + Q_D(QHelpFilterSettingsWidget); + d->versionsChanged(options); + }); + connect(d->m_ui.filterWidget, &QListWidget::currentItemChanged, + this, [this](QListWidgetItem *) { + Q_D(QHelpFilterSettingsWidget); + d->updateCurrentFilter(); + }); + connect(d->m_ui.filterWidget, &QListWidget::itemDoubleClicked, + [this](QListWidgetItem *) { + Q_D(QHelpFilterSettingsWidget); + d->renameFilterClicked(); + }); + + // TODO: repeat these actions on context menu + connect(d->m_ui.addButton, &QAbstractButton::clicked, + [this]() { + Q_D(QHelpFilterSettingsWidget); + d->addFilterClicked(); + }); + connect(d->m_ui.renameButton, &QAbstractButton::clicked, + [this]() { + Q_D(QHelpFilterSettingsWidget); + d->renameFilterClicked(); + }); + connect(d->m_ui.removeButton, &QAbstractButton::clicked, + [this]() { + Q_D(QHelpFilterSettingsWidget); + d->removeFilterClicked(); + }); + + d->m_ui.componentWidget->setNoOptionText(tr("No Component")); + d->m_ui.componentWidget->setInvalidOptionText(tr("Invalid Component")); + d->m_ui.versionWidget->setNoOptionText(tr("No Version")); + d->m_ui.versionWidget->setInvalidOptionText(tr("Invalid Version")); +} + +/*! + Destroys the filter settings widget. +*/ +QHelpFilterSettingsWidget::~QHelpFilterSettingsWidget() = default; + +/*! + Sets the list of all available components to \a components. + \sa QHelpFilterEngine::availableComponents() +*/ +void QHelpFilterSettingsWidget::setAvailableComponents(const QStringList &components) +{ + Q_D(QHelpFilterSettingsWidget); + d->m_components = components; + d->updateCurrentFilter(); +} + +/*! + Sets the list of all available version numbers to \a versions. + \sa QHelpFilterEngine::availableVersions() +*/ +void QHelpFilterSettingsWidget::setAvailableVersions(const QList<QVersionNumber> &versions) +{ + Q_D(QHelpFilterSettingsWidget); + d->m_versions = versions; + d->updateCurrentFilter(); +} + +/*! + Reads the filter settings stored inside \a filterEngine and sets up + this filter settings widget accordingly. +*/ +void QHelpFilterSettingsWidget::readSettings(QHelpFilterEngine *filterEngine) +{ + Q_D(QHelpFilterSettingsWidget); + const QHelpFilterSettings settings = QHelpFilterSettings::readSettings(filterEngine); + d->setFilterSettings(settings); +} + +/*! + Writes the filter settings, currently presented in this filter settings + widget, to the \a filterEngine. The old settings stored in the filter + engine will be overwritten. +*/ +bool QHelpFilterSettingsWidget::applySettings(QHelpFilterEngine *filterEngine) +{ + Q_D(QHelpFilterSettingsWidget); + return QHelpFilterSettings::applySettings(filterEngine, d->filterSettings()); +} + +QT_END_NAMESPACE diff --git a/src/assistant/help/qhelpfiltersettingswidget.h b/src/assistant/help/qhelpfiltersettingswidget.h new file mode 100644 index 000000000..1b6606054 --- /dev/null +++ b/src/assistant/help/qhelpfiltersettingswidget.h @@ -0,0 +1,78 @@ +/**************************************************************************** +** +** Copyright (C) 2020 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt Assistant of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QHELPFILTERSETTINGSWIDGET_H +#define QHELPFILTERSETTINGSWIDGET_H + +#include <QtHelp/qhelp_global.h> + +#include <QtWidgets/QWidget> + +QT_BEGIN_NAMESPACE + +class QVersionNumber; + +class QHelpFilterEngine; +class QHelpFilterSettingsWidgetPrivate; + +class QHELP_EXPORT QHelpFilterSettingsWidget : public QWidget +{ + Q_OBJECT +public: + QHelpFilterSettingsWidget(QWidget *parent); + + ~QHelpFilterSettingsWidget(); + + void setAvailableComponents(const QStringList &components); + void setAvailableVersions(const QList<QVersionNumber> &versions); + + // TODO: filterEngine may be moved to c'tor or to setFilterEngine() setter + void readSettings(QHelpFilterEngine *filterEngine); + bool applySettings(QHelpFilterEngine *filterEngine); + +private: + QScopedPointer<class QHelpFilterSettingsWidgetPrivate> d_ptr; + Q_DECLARE_PRIVATE(QHelpFilterSettingsWidget) + Q_DISABLE_COPY_MOVE(QHelpFilterSettingsWidget) +}; + +QT_END_NAMESPACE + +#endif + diff --git a/src/assistant/help/qhelpfiltersettingswidget.ui b/src/assistant/help/qhelpfiltersettingswidget.ui new file mode 100644 index 000000000..7e16e3f7b --- /dev/null +++ b/src/assistant/help/qhelpfiltersettingswidget.ui @@ -0,0 +1,83 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>QHelpFilterSettingsWidget</class> + <widget class="QWidget" name="QHelpFilterSettingsWidget"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>347</width> + <height>127</height> + </rect> + </property> + <property name="windowTitle"> + <string>Form</string> + </property> + <layout class="QGridLayout" name="gridLayout"> + <item row="0" column="0" colspan="3"> + <widget class="QLabel" name="filterLabel"> + <property name="text"> + <string>Filter</string> + </property> + </widget> + </item> + <item row="0" column="3"> + <widget class="QLabel" name="componentsLabel"> + <property name="frameShape"> + <enum>QFrame::NoFrame</enum> + </property> + <property name="text"> + <string>Components</string> + </property> + </widget> + </item> + <item row="0" column="4"> + <widget class="QLabel" name="versionsLabel"> + <property name="text"> + <string>Versions</string> + </property> + </widget> + </item> + <item row="1" column="0" colspan="3"> + <widget class="QListWidget" name="filterWidget"/> + </item> + <item row="1" column="3" rowspan="2"> + <widget class="QOptionsWidget" name="componentWidget" native="true"/> + </item> + <item row="1" column="4" rowspan="2"> + <widget class="QOptionsWidget" name="versionWidget" native="true"/> + </item> + <item row="2" column="0"> + <widget class="QToolButton" name="addButton"> + <property name="text"> + <string>Add...</string> + </property> + </widget> + </item> + <item row="2" column="1"> + <widget class="QToolButton" name="renameButton"> + <property name="text"> + <string>Rename...</string> + </property> + </widget> + </item> + <item row="2" column="2"> + <widget class="QToolButton" name="removeButton"> + <property name="text"> + <string>Remove</string> + </property> + </widget> + </item> + </layout> + </widget> + <customwidgets> + <customwidget> + <class>QOptionsWidget</class> + <extends>QWidget</extends> + <header>qoptionswidget_p.h</header> + <container>1</container> + </customwidget> + </customwidgets> + <resources/> + <connections/> +</ui> diff --git a/src/assistant/assistant/optionswidget.cpp b/src/assistant/help/qoptionswidget.cpp index bc089c5bf..21fdfe07a 100644 --- a/src/assistant/assistant/optionswidget.cpp +++ b/src/assistant/help/qoptionswidget.cpp @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2018 The Qt Company Ltd. +** Copyright (C) 2020 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the Qt Assistant of the Qt Toolkit. @@ -26,20 +26,17 @@ ** ****************************************************************************/ -#include "optionswidget.h" +#include "qoptionswidget_p.h" #include <QtWidgets/QComboBox> #include <QtWidgets/QItemDelegate> #include <QtWidgets/QListWidget> #include <QtWidgets/QVBoxLayout> -#include <algorithm> - QT_BEGIN_NAMESPACE class ListWidgetDelegate : public QItemDelegate { -// Q_OBJECT not needed public: ListWidgetDelegate(QWidget *w) : QItemDelegate(w), m_widget(w) {} @@ -87,9 +84,7 @@ static QStringList subtract(const QStringList &minuend, const QStringList &subtr return result; } -///////////////// - -OptionsWidget::OptionsWidget(QWidget *parent) +QOptionsWidget::QOptionsWidget(QWidget *parent) : QWidget(parent) , m_noOptionText(tr("No Option")) , m_invalidOptionText(tr("Invalid Option")) @@ -100,16 +95,16 @@ OptionsWidget::OptionsWidget(QWidget *parent) layout->addWidget(m_listWidget); layout->setContentsMargins(QMargins()); - connect(m_listWidget, &QListWidget::itemChanged, this, &OptionsWidget::itemChanged); + connect(m_listWidget, &QListWidget::itemChanged, this, &QOptionsWidget::itemChanged); } -void OptionsWidget::clear() +void QOptionsWidget::clear() { setOptions(QStringList(), QStringList()); } -void OptionsWidget::setOptions(const QStringList &validOptions, - const QStringList &selectedOptions) +void QOptionsWidget::setOptions(const QStringList &validOptions, + const QStringList &selectedOptions) { m_listWidget->clear(); m_optionToItem.clear(); @@ -145,17 +140,17 @@ void OptionsWidget::setOptions(const QStringList &validOptions, } } -QStringList OptionsWidget::validOptions() const +QStringList QOptionsWidget::validOptions() const { return m_validOptions; } -QStringList OptionsWidget::selectedOptions() const +QStringList QOptionsWidget::selectedOptions() const { return m_selectedOptions; } -void OptionsWidget::setNoOptionText(const QString &text) +void QOptionsWidget::setNoOptionText(const QString &text) { if (m_noOptionText == text) return; @@ -171,7 +166,7 @@ void OptionsWidget::setNoOptionText(const QString &text) } } -void OptionsWidget::setInvalidOptionText(const QString &text) +void QOptionsWidget::setInvalidOptionText(const QString &text) { if (m_invalidOptionText == text) return; @@ -183,7 +178,7 @@ void OptionsWidget::setInvalidOptionText(const QString &text) m_optionToItem.value(option)->setText(optionText(option, false)); } -QString OptionsWidget::optionText(const QString &optionName, bool valid) const +QString QOptionsWidget::optionText(const QString &optionName, bool valid) const { QString text = optionName; if (optionName.isEmpty()) @@ -193,7 +188,7 @@ QString OptionsWidget::optionText(const QString &optionName, bool valid) const return text; } -QListWidgetItem *OptionsWidget::appendItem(const QString &optionName, bool valid, bool selected) +QListWidgetItem *QOptionsWidget::appendItem(const QString &optionName, bool valid, bool selected) { QListWidgetItem *optionItem = new QListWidgetItem(optionText(optionName, valid), m_listWidget); optionItem->setCheckState(selected ? Qt::Checked : Qt::Unchecked); @@ -203,14 +198,14 @@ QListWidgetItem *OptionsWidget::appendItem(const QString &optionName, bool valid return optionItem; } -void OptionsWidget::appendSeparator() +void QOptionsWidget::appendSeparator() { QListWidgetItem *separatorItem = new QListWidgetItem(m_listWidget); ListWidgetDelegate::setSeparator(separatorItem); m_listWidget->insertItem(m_listWidget->count(), separatorItem); } -void OptionsWidget::itemChanged(QListWidgetItem *item) +void QOptionsWidget::itemChanged(QListWidgetItem *item) { const auto it = m_itemToOption.constFind(item); if (it == m_itemToOption.constEnd()) diff --git a/src/assistant/assistant/optionswidget.h b/src/assistant/help/qoptionswidget_p.h index 52c876bad..ff075e464 100644 --- a/src/assistant/assistant/optionswidget.h +++ b/src/assistant/help/qoptionswidget_p.h @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2018 The Qt Company Ltd. +** Copyright (C) 2020 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the Qt Assistant of the Qt Toolkit. @@ -26,8 +26,8 @@ ** ****************************************************************************/ -#ifndef OPTIONSWIDGET_H -#define OPTIONSWIDGET_H +#ifndef QOPTIONSWIDGET_H +#define QOPTIONSWIDGET_H #include <QtWidgets/QWidget> #include <QtCore/QMap> @@ -37,11 +37,11 @@ QT_BEGIN_NAMESPACE class QListWidget; class QListWidgetItem; -class OptionsWidget : public QWidget +class QOptionsWidget : public QWidget { Q_OBJECT public: - OptionsWidget(QWidget *parent = nullptr); + QOptionsWidget(QWidget *parent = nullptr); void clear(); void setOptions(const QStringList &validOptions, |