diff options
Diffstat (limited to 'src/assistant/help')
60 files changed, 3321 insertions, 5536 deletions
diff --git a/src/assistant/help/CMakeLists.txt b/src/assistant/help/CMakeLists.txt index f2673fb04..a9bfc9b53 100644 --- a/src/assistant/help/CMakeLists.txt +++ b/src/assistant/help/CMakeLists.txt @@ -1,47 +1,48 @@ -# Generated from help.pro. +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: BSD-3-Clause ##################################################################### ## Help Module: ##################################################################### qt_internal_add_module(Help + PLUGIN_TYPES help SOURCES + # QtHelpCore qcompressedhelpinfo.cpp qcompressedhelpinfo.h - qfilternamedialog.cpp qfilternamedialog.ui qfilternamedialog_p.h qhelp_global.cpp qhelp_global.h qhelpcollectionhandler.cpp qhelpcollectionhandler_p.h - qhelpcontentwidget.cpp qhelpcontentwidget.h + qhelpcontentitem.cpp qhelpcontentitem.h qhelpdbreader.cpp qhelpdbreader_p.h - qhelpengine.cpp qhelpengine.h qhelpengine_p.h qhelpenginecore.cpp qhelpenginecore.h qhelpfilterdata.cpp qhelpfilterdata.h qhelpfilterengine.cpp qhelpfilterengine.h - qhelpfiltersettings.cpp qhelpfiltersettings_p.h + qhelplink.cpp qhelplink.h + qhelpsearchenginecore.cpp qhelpsearchenginecore.h + qhelpsearchindexreader.cpp qhelpsearchindexreader_p.h + qhelpsearchindexwriter.cpp qhelpsearchindexwriter_p.h + qhelpsearchresult.cpp qhelpsearchresult.h + # QtHelp + qfilternamedialog.cpp qfilternamedialog.ui qfilternamedialog_p.h + qhelpcontentwidget.cpp qhelpcontentwidget.h + qhelpengine.cpp qhelpengine.h qhelpfiltersettingswidget.cpp qhelpfiltersettingswidget.h qhelpfiltersettingswidget.ui qhelpindexwidget.cpp qhelpindexwidget.h - qhelplink.cpp qhelplink.h qhelpsearchengine.cpp qhelpsearchengine.h - qhelpsearchindexreader.cpp qhelpsearchindexreader_p.h - qhelpsearchindexreader_default.cpp qhelpsearchindexreader_default_p.h - qhelpsearchindexwriter_default.cpp qhelpsearchindexwriter_default_p.h qhelpsearchquerywidget.cpp qhelpsearchquerywidget.h qhelpsearchresultwidget.cpp qhelpsearchresultwidget.h qoptionswidget.cpp qoptionswidget_p.h DEFINES # -QT_ASCII_CAST_WARNINGS # special case remove QHELP_LIB - LIBRARIES - Qt::CorePrivate - Qt::Network PUBLIC_LIBRARIES Qt::Core Qt::Gui Qt::Sql Qt::Widgets - PRIVATE_MODULE_INTERFACE - Qt::CorePrivate ENABLE_AUTOGEN_TOOLS uic + NO_GENERATE_CPP_EXPORTS ) # Resources: diff --git a/src/assistant/help/doc/qthelp.qdocconf b/src/assistant/help/doc/qthelp.qdocconf index 9471222b0..95a80b6b4 100644 --- a/src/assistant/help/doc/qthelp.qdocconf +++ b/src/assistant/help/doc/qthelp.qdocconf @@ -23,7 +23,7 @@ qhp.QtHelp.subprojects.classes.sortPages = true language = Cpp -depends += qtdoc qtcore qtwidgets qmake +depends += qtdoc qtcore qtwidgets qmake qtgui headerdirs += .. @@ -37,4 +37,5 @@ imagedirs = images navigation.landingpage = "Qt Help" navigation.cppclassespage = "Qt Help C++ Classes" +# Enforce zero documentation warnings warninglimit = 0 diff --git a/src/assistant/help/doc/snippets/doc_src_qthelp.cpp b/src/assistant/help/doc/snippets/doc_src_qthelp.cpp index 04d0b7377..7498c22f3 100644 --- a/src/assistant/help/doc/snippets/doc_src_qthelp.cpp +++ b/src/assistant/help/doc/snippets/doc_src_qthelp.cpp @@ -1,56 +1,5 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the documentation of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:BSD$ -** 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. -** -** BSD License Usage -** Alternatively, you may use this file under the terms of the BSD license -** as follows: -** -** "Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions are -** met: -** * Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** * Redistributions in binary form must reproduce the above copyright -** notice, this list of conditions and the following disclaimer in -** the documentation and/or other materials provided with the -** distribution. -** * Neither the name of The Qt Company Ltd nor the names of its -** contributors may be used to endorse or promote products derived -** from this software without specific prior written permission. -** -** -** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -//! [0] -#include <QtHelp> -//! [0] +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause //! [6] QHelpEngineCore helpEngine("mycollection.qhc"); diff --git a/src/assistant/help/doc/snippets/doc_src_qthelp.qdoc b/src/assistant/help/doc/snippets/doc_src_qthelp.qdoc index 648598079..1d027a88e 100644 --- a/src/assistant/help/doc/snippets/doc_src_qthelp.qdoc +++ b/src/assistant/help/doc/snippets/doc_src_qthelp.qdoc @@ -1,52 +1,5 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the documentation of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:BSD$ -** 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. -** -** BSD License Usage -** Alternatively, you may use this file under the terms of the BSD license -** as follows: -** -** "Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions are -** met: -** * Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** * Redistributions in binary form must reproduce the above copyright -** notice, this list of conditions and the following disclaimer in -** the documentation and/or other materials provided with the -** distribution. -** * Neither the name of The Qt Company Ltd nor the names of its -** contributors may be used to endorse or promote products derived -** from this software without specific prior written permission. -** -** -** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only //! [1] QT += help diff --git a/src/assistant/help/doc/src/qthelp-examples.qdoc b/src/assistant/help/doc/src/qthelp-examples.qdoc index 051454a5b..e2191bb03 100644 --- a/src/assistant/help/doc/src/qthelp-examples.qdoc +++ b/src/assistant/help/doc/src/qthelp-examples.qdoc @@ -1,29 +1,5 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the documentation of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:FDL$ -** 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 Free Documentation License Usage -** Alternatively, this file may be used under the terms of the GNU Free -** Documentation License version 1.3 as published by the Free Software -** Foundation and appearing in the file included in the packaging of -** this file. Please review the following information to ensure -** the GNU Free Documentation License version 1.3 requirements -** will be met: https://www.gnu.org/licenses/fdl-1.3.html. -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only /*! \group examples-qthelp diff --git a/src/assistant/help/doc/src/qthelp-index.qdoc b/src/assistant/help/doc/src/qthelp-index.qdoc index abe20b81f..f97ed415a 100644 --- a/src/assistant/help/doc/src/qthelp-index.qdoc +++ b/src/assistant/help/doc/src/qthelp-index.qdoc @@ -1,29 +1,5 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the documentation of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:FDL$ -** 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 Free Documentation License Usage -** Alternatively, this file may be used under the terms of the GNU Free -** Documentation License version 1.3 as published by the Free Software -** Foundation and appearing in the file included in the packaging of -** this file. Please review the following information to ensure -** the GNU Free Documentation License version 1.3 requirements -** will be met: https://www.gnu.org/licenses/fdl-1.3.html. -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only /*! \page qthelp-index.html @@ -34,10 +10,6 @@ \section1 Getting Started - To use Qt Help classes, add this directive into the C++ files: - - \snippet doc_src_qthelp.cpp 0 - To link against the Qt Help module, add this line to the project file: \snippet doc_src_qthelp.qdoc 1 diff --git a/src/assistant/help/doc/src/qthelp-module.qdoc b/src/assistant/help/doc/src/qthelp-module.qdoc index 9cd8ab332..3308b95b8 100644 --- a/src/assistant/help/doc/src/qthelp-module.qdoc +++ b/src/assistant/help/doc/src/qthelp-module.qdoc @@ -1,29 +1,5 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the documentation of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:FDL$ -** 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 Free Documentation License Usage -** Alternatively, this file may be used under the terms of the GNU Free -** Documentation License version 1.3 as published by the Free Software -** Foundation and appearing in the file included in the packaging of -** this file. Please review the following information to ensure -** the GNU Free Documentation License version 1.3 requirements -** will be met: https://www.gnu.org/licenses/fdl-1.3.html. -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only /*! \module QtHelp @@ -39,11 +15,6 @@ online help and documentation in their applications are described in more detail in \l{The Qt Help Framework} overview document. - To include the definitions of the module's classes, use the - following directive: - - \snippet doc_src_qthelp.cpp 0 - To link against the module, add this line to your \l qmake \c .pro file: diff --git a/src/assistant/help/doc/src/qthelp.qdoc b/src/assistant/help/doc/src/qthelp.qdoc index 8db90f0ea..2c010b87b 100644 --- a/src/assistant/help/doc/src/qthelp.qdoc +++ b/src/assistant/help/doc/src/qthelp.qdoc @@ -1,29 +1,5 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the documentation of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:FDL$ -** 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 Free Documentation License Usage -** Alternatively, this file may be used under the terms of the GNU Free -** Documentation License version 1.3 as published by the Free Software -** Foundation and appearing in the file included in the packaging of -** this file. Please review the following information to ensure -** the GNU Free Documentation License version 1.3 requirements -** will be met: https://www.gnu.org/licenses/fdl-1.3.html. -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only /*! \group helpsystem diff --git a/src/assistant/help/helpsystem.qrc b/src/assistant/help/helpsystem.qrc deleted file mode 100644 index 611008639..000000000 --- a/src/assistant/help/helpsystem.qrc +++ /dev/null @@ -1,12 +0,0 @@ -<RCC> - <qresource prefix="/qt-project.org/assistant" > - <file>images/1leftarrow.png</file> - <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/help/qcompressedhelpinfo.cpp b/src/assistant/help/qcompressedhelpinfo.cpp index a3c5b75d5..8051fdddc 100644 --- a/src/assistant/help/qcompressedhelpinfo.cpp +++ b/src/assistant/help/qcompressedhelpinfo.cpp @@ -1,51 +1,16 @@ -/**************************************************************************** -** -** Copyright (C) 2019 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$ -** -****************************************************************************/ +// Copyright (C) 2019 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only #include "qcompressedhelpinfo.h" #include "qhelpdbreader_p.h" -#include <QtCore/QThread> -#include <QtCore/QVersionNumber> +#include <QtCore/qversionnumber.h> QT_BEGIN_NAMESPACE +using namespace Qt::StringLiterals; + class QCompressedHelpInfoPrivate : public QSharedData { public: @@ -57,7 +22,6 @@ public: , m_version(other.m_version) , m_isNull(other.m_isNull) { } - ~QCompressedHelpInfoPrivate() = default; QString m_namespaceName; QString m_component; @@ -90,8 +54,7 @@ public: */ QCompressedHelpInfo::QCompressedHelpInfo() : d(new QCompressedHelpInfoPrivate) -{ -} +{} /*! Constructs a copy of \a other. @@ -167,9 +130,9 @@ bool QCompressedHelpInfo::isNull() const */ QCompressedHelpInfo QCompressedHelpInfo::fromCompressedHelpFile(const QString &documentationFileName) { - QHelpDBReader reader(documentationFileName, - QHelpGlobal::uniquifyConnectionName(QLatin1String("GetCompressedHelpInfo"), - QThread::currentThread()), nullptr); + void *pointer = const_cast<QString *>(&documentationFileName); + QHelpDBReader reader(documentationFileName, QHelpGlobal::uniquifyConnectionName( + "GetCompressedHelpInfo"_L1, pointer), nullptr); if (reader.init()) { QCompressedHelpInfo info; info.d->m_namespaceName = reader.namespaceName(); @@ -178,7 +141,7 @@ QCompressedHelpInfo QCompressedHelpInfo::fromCompressedHelpFile(const QString &d info.d->m_isNull = false; return info; } - return QCompressedHelpInfo(); + return {}; } QT_END_NAMESPACE diff --git a/src/assistant/help/qcompressedhelpinfo.h b/src/assistant/help/qcompressedhelpinfo.h index 7b3c78c12..a68c03c11 100644 --- a/src/assistant/help/qcompressedhelpinfo.h +++ b/src/assistant/help/qcompressedhelpinfo.h @@ -1,53 +1,17 @@ -/**************************************************************************** -** -** Copyright (C) 2019 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$ -** -****************************************************************************/ +// Copyright (C) 2019 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only #ifndef QCOMPRESSEDHELPINFO_H #define QCOMPRESSEDHELPINFO_H #include <QtHelp/qhelp_global.h> -#include <QtCore/QSharedDataPointer> +#include <QtCore/qshareddata.h> QT_BEGIN_NAMESPACE -class QVersionNumber; class QCompressedHelpInfoPrivate; +class QVersionNumber; class QHELP_EXPORT QCompressedHelpInfo final { @@ -76,4 +40,4 @@ private: QT_END_NAMESPACE -#endif // QHELPCOLLECTIONDETAILS_H +#endif // QCOMPRESSEDHELPINFO_H diff --git a/src/assistant/help/qfilternamedialog.cpp b/src/assistant/help/qfilternamedialog.cpp index 8563a3355..11e71bc9a 100644 --- a/src/assistant/help/qfilternamedialog.cpp +++ b/src/assistant/help/qfilternamedialog.cpp @@ -1,35 +1,10 @@ -/**************************************************************************** -** -** 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:GPL-EXCEPT$ -** 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 General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** 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-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include <QtWidgets/QPushButton> +// Copyright (C) 2020 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only #include "qfilternamedialog_p.h" +#include <QtWidgets/qpushbutton.h> + QT_BEGIN_NAMESPACE QFilterNameDialog::QFilterNameDialog(QWidget *parent) @@ -40,8 +15,7 @@ QFilterNameDialog::QFilterNameDialog(QWidget *parent) this, &QDialog::accept); connect(m_ui.buttonBox->button(QDialogButtonBox::Cancel), &QAbstractButton::clicked, this, &QDialog::reject); - connect(m_ui.lineEdit, &QLineEdit::textChanged, - this, &QFilterNameDialog::updateOkButton); + connect(m_ui.lineEdit, &QLineEdit::textChanged, this, &QFilterNameDialog::updateOkButton); m_ui.buttonBox->button(QDialogButtonBox::Ok)->setDisabled(true); } @@ -51,15 +25,9 @@ void QFilterNameDialog::setFilterName(const QString &filter) m_ui.lineEdit->selectAll(); } -QString QFilterNameDialog::filterName() const -{ - return m_ui.lineEdit->text(); -} - void QFilterNameDialog::updateOkButton() { - m_ui.buttonBox->button(QDialogButtonBox::Ok) - ->setDisabled(m_ui.lineEdit->text().isEmpty()); + m_ui.buttonBox->button(QDialogButtonBox::Ok)->setDisabled(m_ui.lineEdit->text().isEmpty()); } QT_END_NAMESPACE diff --git a/src/assistant/help/qfilternamedialog_p.h b/src/assistant/help/qfilternamedialog_p.h index 76a495d78..76110abba 100644 --- a/src/assistant/help/qfilternamedialog_p.h +++ b/src/assistant/help/qfilternamedialog_p.h @@ -1,30 +1,5 @@ -/**************************************************************************** -** -** 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:GPL-EXCEPT$ -** 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 General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** 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-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2020 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only #ifndef QFILTERNAMEDIALOG_H #define QFILTERNAMEDIALOG_H @@ -40,9 +15,10 @@ // We mean it. // -#include <QtWidgets/QDialog> #include "ui_qfilternamedialog.h" +#include <QtWidgets/qdialog.h> + QT_BEGIN_NAMESPACE class QFilterNameDialog : public QDialog @@ -53,7 +29,7 @@ public: QFilterNameDialog(QWidget *parent = nullptr); void setFilterName(const QString &filter); - QString filterName() const; + QString filterName() const { return m_ui.lineEdit->text(); } private slots: void updateOkButton(); diff --git a/src/assistant/help/qhelp_global.cpp b/src/assistant/help/qhelp_global.cpp index d86ce767b..bd4c85ff4 100644 --- a/src/assistant/help/qhelp_global.cpp +++ b/src/assistant/help/qhelp_global.cpp @@ -1,69 +1,34 @@ -/**************************************************************************** -** -** Copyright (C) 2016 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 <QtCore/QCoreApplication> -#include <QtCore/QRegularExpression> -#include <QtCore/QMutexLocker> -#include <QtGui/QTextDocument> +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only #include "qhelp_global.h" +#include <QtCore/qcoreapplication.h> +#include <QtCore/qhash.h> +#include <QtCore/qmutex.h> +#include <QtGui/qtextdocument.h> + +QT_BEGIN_NAMESPACE + +using namespace Qt::StringLiterals; + QString QHelpGlobal::uniquifyConnectionName(const QString &name, void *pointer) { static QMutex mutex; QMutexLocker locker(&mutex); - - static QHash<QString,quint16> idHash; - - return QString::fromLatin1("%1-%2-%3"). - arg(name).arg(quintptr(pointer)).arg(++idHash[name]); + static QHash<QString, quint16> idHash; + return QString::asprintf("%ls-%p-%d", qUtf16Printable(name), pointer, ++idHash[name]); } QString QHelpGlobal::documentTitle(const QString &content) { QString title = QCoreApplication::translate("QHelp", "Untitled"); if (!content.isEmpty()) { - const int start = content.indexOf(QLatin1String("<title>"), 0, Qt::CaseInsensitive) + 7; - const int end = content.indexOf(QLatin1String("</title>"), 0, Qt::CaseInsensitive); + const int start = content.indexOf("<title>"_L1, 0, Qt::CaseInsensitive) + 7; + const int end = content.indexOf("</title>"_L1, 0, Qt::CaseInsensitive); if ((end - start) > 0) { title = content.mid(start, end - start); - if (Qt::mightBeRichText(title) || title.contains(QLatin1Char('&'))) { + if (Qt::mightBeRichText(title) || title.contains(u'&')) { QTextDocument doc; doc.setHtml(title); title = doc.toPlainText(); @@ -72,3 +37,5 @@ QString QHelpGlobal::documentTitle(const QString &content) } return title; } + +QT_END_NAMESPACE diff --git a/src/assistant/help/qhelp_global.h b/src/assistant/help/qhelp_global.h index c0354083d..b7367ee37 100644 --- a/src/assistant/help/qhelp_global.h +++ b/src/assistant/help/qhelp_global.h @@ -1,51 +1,14 @@ -/**************************************************************************** -** -** Copyright (C) 2016 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$ -** -****************************************************************************/ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only #ifndef QHELP_GLOBAL_H #define QHELP_GLOBAL_H #include <QtCore/qglobal.h> -#include <QtCore/QString> -#include <QtCore/QObject> QT_BEGIN_NAMESPACE +class QString; #ifdef QT_STATIC # define QHELP_EXPORT @@ -55,7 +18,10 @@ QT_BEGIN_NAMESPACE # define QHELP_EXPORT Q_DECL_IMPORT #endif -class QHELP_EXPORT QHelpGlobal { +// TODO Qt 7.0: Remove the class and make it a namespace with a collection of functions. +// Review, if they are still need to be public. +class QHELP_EXPORT QHelpGlobal +{ public: static QString uniquifyConnectionName(const QString &name, void *pointer); static QString documentTitle(const QString &content); diff --git a/src/assistant/help/qhelpcollectionhandler.cpp b/src/assistant/help/qhelpcollectionhandler.cpp index 595cc0e29..56251309c 100644 --- a/src/assistant/help/qhelpcollectionhandler.cpp +++ b/src/assistant/help/qhelpcollectionhandler.cpp @@ -1,66 +1,32 @@ -/**************************************************************************** -** -** Copyright (C) 2016 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$ -** -****************************************************************************/ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only #include "qhelpcollectionhandler_p.h" #include "qhelp_global.h" #include "qhelpdbreader_p.h" #include "qhelpfilterdata.h" - -#include <QtCore/QDataStream> -#include <QtCore/QDateTime> -#include <QtCore/QDir> -#include <QtCore/QFile> -#include <QtCore/QFileInfo> -#include <QtCore/QList> -#include <QtCore/QTimer> -#include <QtCore/QVersionNumber> - -#include <QtHelp/QHelpLink> - -#include <QtSql/QSqlError> -#include <QtSql/QSqlDriver> +#include "qhelplink.h" + +#include <QtCore/qdatastream.h> +#include <QtCore/qdatetime.h> +#include <QtCore/qdir.h> +#include <QtCore/qfileinfo.h> +#include <QtCore/qmap.h> +#include <QtCore/qtimer.h> +#include <QtCore/qversionnumber.h> +#include <QtSql/qsqldriver.h> +#include <QtSql/qsqlerror.h> +#include <QtSql/qsqlquery.h> QT_BEGIN_NAMESPACE +using namespace Qt::StringLiterals; + class Transaction { public: + Q_DISABLE_COPY_MOVE(Transaction); + Transaction(const QString &connectionName) : m_db(QSqlDatabase::database(connectionName)), m_inTransaction(m_db.driver()->hasFeature(QSqlDriver::Transactions)) @@ -107,8 +73,8 @@ bool QHelpCollectionHandler::isDBOpened() const { if (m_query) return true; - emit error(tr("The collection file \"%1\" is not set up yet."). - arg(m_collectionFile)); + auto *that = const_cast<QHelpCollectionHandler *>(this); + emit that->error(tr("The collection file \"%1\" is not set up yet.").arg(m_collectionFile)); return false; } @@ -117,15 +83,9 @@ void QHelpCollectionHandler::closeDB() if (!m_query) return; - delete m_query; - m_query = nullptr; + m_query.reset(); QSqlDatabase::removeDatabase(m_connectionName); - m_connectionName = QString(); -} - -QString QHelpCollectionHandler::collectionFile() const -{ - return m_collectionFile; + m_connectionName.clear(); } bool QHelpCollectionHandler::openCollectionFile() @@ -133,11 +93,9 @@ bool QHelpCollectionHandler::openCollectionFile() if (m_query) return true; - m_connectionName = QHelpGlobal::uniquifyConnectionName( - QLatin1String("QHelpCollectionHandler"), this); + m_connectionName = QHelpGlobal::uniquifyConnectionName("QHelpCollectionHandler"_L1, this); { - QSqlDatabase db = QSqlDatabase::addDatabase(QLatin1String("QSQLITE"), - m_connectionName); + QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE"_L1, m_connectionName); if (db.driver() && db.driver()->lastError().type() == QSqlError::ConnectionError) { emit error(tr("Cannot load sqlite database driver.")); @@ -146,7 +104,7 @@ bool QHelpCollectionHandler::openCollectionFile() db.setDatabaseName(collectionFile()); if (db.open()) - m_query = new QSqlQuery(db); + m_query.reset(new QSqlQuery(db)); if (!m_query) { QSqlDatabase::removeDatabase(m_connectionName); @@ -158,16 +116,16 @@ bool QHelpCollectionHandler::openCollectionFile() if (m_readOnly) return true; - m_query->exec(QLatin1String("PRAGMA synchronous=OFF")); - m_query->exec(QLatin1String("PRAGMA cache_size=3000")); + m_query->exec("PRAGMA synchronous=OFF"_L1); + m_query->exec("PRAGMA cache_size=3000"_L1); - m_query->exec(QLatin1String("SELECT COUNT(*) FROM sqlite_master WHERE TYPE=\'table\' " - "AND Name=\'NamespaceTable\'")); + m_query->exec("SELECT COUNT(*) FROM sqlite_master WHERE TYPE=\'table\' " + "AND Name=\'NamespaceTable\'"_L1); m_query->next(); const bool tablesExist = m_query->value(0).toInt() > 0; if (!tablesExist) { - if (!createTables(m_query)) { + if (!createTables(m_query.get())) { closeDB(); emit error(tr("Cannot create tables in file %1.").arg(collectionFile())); return false; @@ -177,34 +135,32 @@ bool QHelpCollectionHandler::openCollectionFile() bool indexAndNamespaceFilterTablesMissing = false; const QStringList newTables = { - QLatin1String("IndexTable"), - QLatin1String("FileNameTable"), - QLatin1String("ContentsTable"), - QLatin1String("FileFilterTable"), - QLatin1String("IndexFilterTable"), - QLatin1String("ContentsFilterTable"), - QLatin1String("FileAttributeSetTable"), - QLatin1String("OptimizedFilterTable"), - QLatin1String("TimeStampTable"), - QLatin1String("VersionTable"), - QLatin1String("Filter"), - QLatin1String("ComponentTable"), - QLatin1String("ComponentMapping"), - QLatin1String("ComponentFilter"), - QLatin1String("VersionFilter") + "IndexTable"_L1, + "FileNameTable"_L1, + "ContentsTable"_L1, + "FileFilterTable"_L1, + "IndexFilterTable"_L1, + "ContentsFilterTable"_L1, + "FileAttributeSetTable"_L1, + "OptimizedFilterTable"_L1, + "TimeStampTable"_L1, + "VersionTable"_L1, + "Filter"_L1, + "ComponentTable"_L1, + "ComponentMapping"_L1, + "ComponentFilter"_L1, + "VersionFilter"_L1 }; - QString queryString = QLatin1String("SELECT COUNT(*) " - "FROM sqlite_master " - "WHERE TYPE=\'table\'"); - queryString.append(QLatin1String(" AND (Name=\'")); - queryString.append(newTables.join(QLatin1String("\' OR Name=\'"))); - queryString.append(QLatin1String("\')")); + QString queryString = "SELECT COUNT(*) FROM sqlite_master WHERE TYPE=\'table\'"_L1; + queryString.append(" AND (Name=\'"_L1); + queryString.append(newTables.join("\' OR Name=\'"_L1)); + queryString.append("\')"_L1); m_query->exec(queryString); m_query->next(); - if (m_query->value(0).toInt() != newTables.count()) { - if (!recreateIndexAndNamespaceFilterTables(m_query)) { + if (m_query->value(0).toInt() != newTables.size()) { + if (!recreateIndexAndNamespaceFilterTables(m_query.get())) { emit error(tr("Cannot create index tables in file %1.").arg(collectionFile())); return false; } @@ -225,15 +181,14 @@ bool QHelpCollectionHandler::openCollectionFile() } QList<TimeStamp> timeStamps; - m_query->exec(QLatin1String("SELECT NamespaceId, FolderId, FilePath, Size, TimeStamp " - "FROM TimeStampTable")); + m_query->exec("SELECT NamespaceId, FolderId, FilePath, Size, TimeStamp FROM TimeStampTable"_L1); while (m_query->next()) { TimeStamp timeStamp; timeStamp.namespaceId = m_query->value(0).toInt(); timeStamp.folderId = m_query->value(1).toInt(); timeStamp.fileName = m_query->value(2).toString(); timeStamp.size = m_query->value(3).toInt(); - timeStamp.timeStamp = m_query->value(4).toString(); + timeStamp.timeStamp = m_query->value(4).toDateTime(); timeStamps.append(timeStamp); } @@ -262,7 +217,6 @@ bool QHelpCollectionHandler::openCollectionFile() unregisterDocumentation(info.namespaceName); } } - return true; } @@ -271,8 +225,7 @@ QString QHelpCollectionHandler::absoluteDocPath(const QString &fileName) const const QFileInfo fi(collectionFile()); return QDir::isAbsolutePath(fileName) ? fileName - : QFileInfo(fi.absolutePath() + QLatin1Char('/') + fileName) - .absoluteFilePath(); + : QFileInfo(fi.absolutePath() + u'/' + fileName).absoluteFilePath(); } bool QHelpCollectionHandler::isTimeStampCorrect(const TimeStamp &timeStamp) const @@ -285,12 +238,10 @@ bool QHelpCollectionHandler::isTimeStampCorrect(const TimeStamp &timeStamp) cons if (fi.size() != timeStamp.size) return false; - if (fi.lastModified().toString(Qt::ISODate) != timeStamp.timeStamp) + if (fi.lastModified(QTimeZone::UTC) != timeStamp.timeStamp) return false; - m_query->prepare(QLatin1String("SELECT FilePath " - "FROM NamespaceTable " - "WHERE Id = ?")); + m_query->prepare("SELECT FilePath FROM NamespaceTable WHERE Id = ?"_L1); m_query->bindValue(0, timeStamp.namespaceId); if (!m_query->exec() || !m_query->next()) return false; @@ -305,13 +256,14 @@ bool QHelpCollectionHandler::isTimeStampCorrect(const TimeStamp &timeStamp) cons bool QHelpCollectionHandler::hasTimeStampInfo(const QString &nameSpace) const { - m_query->prepare(QLatin1String("SELECT " - "TimeStampTable.NamespaceId " - "FROM " - "NamespaceTable, " - "TimeStampTable " - "WHERE NamespaceTable.Id = TimeStampTable.NamespaceId " - "AND NamespaceTable.Name = ? LIMIT 1")); + m_query->prepare( + "SELECT " + "TimeStampTable.NamespaceId " + "FROM " + "NamespaceTable, " + "TimeStampTable " + "WHERE NamespaceTable.Id = TimeStampTable.NamespaceId " + "AND NamespaceTable.Name = ? LIMIT 1"_L1); m_query->bindValue(0, nameSpace); if (!m_query->exec()) return false; @@ -337,7 +289,7 @@ void QHelpCollectionHandler::execVacuum() if (!m_query) return; - m_query->exec(QLatin1String("VACUUM")); + m_query->exec("VACUUM"_L1); m_vacuumScheduled = false; } @@ -348,8 +300,7 @@ bool QHelpCollectionHandler::copyCollectionFile(const QString &fileName) const QFileInfo fi(fileName); if (fi.exists()) { - emit error(tr("The collection file \"%1\" already exists."). - arg(fileName)); + emit error(tr("The collection file \"%1\" already exists.").arg(fileName)); return false; } @@ -359,114 +310,106 @@ bool QHelpCollectionHandler::copyCollectionFile(const QString &fileName) } const QString &colFile = fi.absoluteFilePath(); - const QString &connectionName = QHelpGlobal::uniquifyConnectionName( - QLatin1String("QHelpCollectionHandlerCopy"), this); - QSqlQuery *copyQuery = nullptr; - bool openingOk = true; - { - QSqlDatabase db = QSqlDatabase::addDatabase(QLatin1String("QSQLITE"), connectionName); - db.setDatabaseName(colFile); - openingOk = db.open(); - if (openingOk) - copyQuery = new QSqlQuery(db); - } - - if (!openingOk) { + const QString &connectionName = + QHelpGlobal::uniquifyConnectionName("QHelpCollectionHandlerCopy"_L1, this); + QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE"_L1, connectionName); + db.setDatabaseName(colFile); + if (!db.open()) { emit error(tr("Cannot open collection file: %1").arg(colFile)); return false; } - copyQuery->exec(QLatin1String("PRAGMA synchronous=OFF")); - copyQuery->exec(QLatin1String("PRAGMA cache_size=3000")); + QSqlQuery copyQuery(db); + copyQuery.exec("PRAGMA synchronous=OFF"_L1); + copyQuery.exec("PRAGMA cache_size=3000"_L1); - if (!createTables(copyQuery) || !recreateIndexAndNamespaceFilterTables(copyQuery)) { + if (!createTables(©Query) || !recreateIndexAndNamespaceFilterTables(©Query)) { emit error(tr("Cannot copy collection file: %1").arg(colFile)); - delete copyQuery; return false; } const QString &oldBaseDir = QFileInfo(collectionFile()).absolutePath(); const QFileInfo newColFi(colFile); - m_query->exec(QLatin1String("SELECT Name, FilePath FROM NamespaceTable")); + m_query->exec("SELECT Name, FilePath FROM NamespaceTable"_L1); while (m_query->next()) { - copyQuery->prepare(QLatin1String("INSERT INTO NamespaceTable VALUES(NULL, ?, ?)")); - copyQuery->bindValue(0, m_query->value(0).toString()); + copyQuery.prepare("INSERT INTO NamespaceTable VALUES(NULL, ?, ?)"_L1); + copyQuery.bindValue(0, m_query->value(0).toString()); QString oldFilePath = m_query->value(1).toString(); if (!QDir::isAbsolutePath(oldFilePath)) - oldFilePath = oldBaseDir + QLatin1Char('/') + oldFilePath; - copyQuery->bindValue(1, newColFi.absoluteDir().relativeFilePath(oldFilePath)); - copyQuery->exec(); + oldFilePath = oldBaseDir + u'/' + oldFilePath; + copyQuery.bindValue(1, newColFi.absoluteDir().relativeFilePath(oldFilePath)); + copyQuery.exec(); } - m_query->exec(QLatin1String("SELECT NamespaceId, Name FROM FolderTable")); + m_query->exec("SELECT NamespaceId, Name FROM FolderTable"_L1); while (m_query->next()) { - copyQuery->prepare(QLatin1String("INSERT INTO FolderTable VALUES(NULL, ?, ?)")); - copyQuery->bindValue(0, m_query->value(0).toString()); - copyQuery->bindValue(1, m_query->value(1).toString()); - copyQuery->exec(); + copyQuery.prepare("INSERT INTO FolderTable VALUES(NULL, ?, ?)"_L1); + copyQuery.bindValue(0, m_query->value(0).toString()); + copyQuery.bindValue(1, m_query->value(1).toString()); + copyQuery.exec(); } - m_query->exec(QLatin1String("SELECT Name FROM FilterAttributeTable")); + m_query->exec("SELECT Name FROM FilterAttributeTable"_L1); while (m_query->next()) { - copyQuery->prepare(QLatin1String("INSERT INTO FilterAttributeTable VALUES(NULL, ?)")); - copyQuery->bindValue(0, m_query->value(0).toString()); - copyQuery->exec(); + copyQuery.prepare("INSERT INTO FilterAttributeTable VALUES(NULL, ?)"_L1); + copyQuery.bindValue(0, m_query->value(0).toString()); + copyQuery.exec(); } - m_query->exec(QLatin1String("SELECT Name FROM FilterNameTable")); + m_query->exec("SELECT Name FROM FilterNameTable"_L1); while (m_query->next()) { - copyQuery->prepare(QLatin1String("INSERT INTO FilterNameTable VALUES(NULL, ?)")); - copyQuery->bindValue(0, m_query->value(0).toString()); - copyQuery->exec(); + copyQuery.prepare("INSERT INTO FilterNameTable VALUES(NULL, ?)"_L1); + copyQuery.bindValue(0, m_query->value(0).toString()); + copyQuery.exec(); } - m_query->exec(QLatin1String("SELECT NameId, FilterAttributeId FROM FilterTable")); + m_query->exec("SELECT NameId, FilterAttributeId FROM FilterTable"_L1); while (m_query->next()) { - copyQuery->prepare(QLatin1String("INSERT INTO FilterTable VALUES(?, ?)")); - copyQuery->bindValue(0, m_query->value(0).toInt()); - copyQuery->bindValue(1, m_query->value(1).toInt()); - copyQuery->exec(); + copyQuery.prepare("INSERT INTO FilterTable VALUES(?, ?)"_L1); + copyQuery.bindValue(0, m_query->value(0).toInt()); + copyQuery.bindValue(1, m_query->value(1).toInt()); + copyQuery.exec(); } - m_query->exec(QLatin1String("SELECT Key, Value FROM SettingsTable")); + m_query->exec("SELECT Key, Value FROM SettingsTable"_L1); while (m_query->next()) { - if (m_query->value(0).toString() == QLatin1String("FTS5IndexedNamespaces")) + if (m_query->value(0).toString() == "FTS5IndexedNamespaces"_L1) continue; - copyQuery->prepare(QLatin1String("INSERT INTO SettingsTable VALUES(?, ?)")); - copyQuery->bindValue(0, m_query->value(0).toString()); - copyQuery->bindValue(1, m_query->value(1)); - copyQuery->exec(); + copyQuery.prepare("INSERT INTO SettingsTable VALUES(?, ?)"_L1); + copyQuery.bindValue(0, m_query->value(0).toString()); + copyQuery.bindValue(1, m_query->value(1)); + copyQuery.exec(); } - copyQuery->clear(); - delete copyQuery; + copyQuery.clear(); QSqlDatabase::removeDatabase(connectionName); return true; } bool QHelpCollectionHandler::createTables(QSqlQuery *query) { - const QStringList tables = QStringList() - << QLatin1String("CREATE TABLE NamespaceTable (" - "Id INTEGER PRIMARY KEY, " - "Name TEXT, " - "FilePath TEXT )") - << QLatin1String("CREATE TABLE FolderTable (" - "Id INTEGER PRIMARY KEY, " - "NamespaceId INTEGER, " - "Name TEXT )") - << QLatin1String("CREATE TABLE FilterAttributeTable (" - "Id INTEGER PRIMARY KEY, " - "Name TEXT )") - << QLatin1String("CREATE TABLE FilterNameTable (" - "Id INTEGER PRIMARY KEY, " - "Name TEXT )") - << QLatin1String("CREATE TABLE FilterTable (" - "NameId INTEGER, " - "FilterAttributeId INTEGER )") - << QLatin1String("CREATE TABLE SettingsTable (" - "Key TEXT PRIMARY KEY, " - "Value BLOB )"); + const QStringList tables = { + "CREATE TABLE NamespaceTable (" + "Id INTEGER PRIMARY KEY, " + "Name TEXT, " + "FilePath TEXT )"_L1, + "CREATE TABLE FolderTable (" + "Id INTEGER PRIMARY KEY, " + "NamespaceId INTEGER, " + "Name TEXT )"_L1, + "CREATE TABLE FilterAttributeTable (" + "Id INTEGER PRIMARY KEY, " + "Name TEXT )"_L1, + "CREATE TABLE FilterNameTable (" + "Id INTEGER PRIMARY KEY, " + "Name TEXT )"_L1, + "CREATE TABLE FilterTable (" + "NameId INTEGER, " + "FilterAttributeId INTEGER )"_L1, + "CREATE TABLE SettingsTable (" + "Key TEXT PRIMARY KEY, " + "Value BLOB )"_L1 + }; for (const QString &q : tables) { if (!query->exec(q)) @@ -477,78 +420,79 @@ bool QHelpCollectionHandler::createTables(QSqlQuery *query) bool QHelpCollectionHandler::recreateIndexAndNamespaceFilterTables(QSqlQuery *query) { - const QStringList tables = QStringList() - << QLatin1String("DROP TABLE IF EXISTS FileNameTable") - << QLatin1String("DROP TABLE IF EXISTS IndexTable") - << QLatin1String("DROP TABLE IF EXISTS ContentsTable") - << QLatin1String("DROP TABLE IF EXISTS FileFilterTable") // legacy - << QLatin1String("DROP TABLE IF EXISTS IndexFilterTable") // legacy - << QLatin1String("DROP TABLE IF EXISTS ContentsFilterTable") // legacy - << QLatin1String("DROP TABLE IF EXISTS FileAttributeSetTable") // legacy - << QLatin1String("DROP TABLE IF EXISTS OptimizedFilterTable") // legacy - << QLatin1String("DROP TABLE IF EXISTS TimeStampTable") - << QLatin1String("DROP TABLE IF EXISTS VersionTable") - << QLatin1String("DROP TABLE IF EXISTS Filter") - << QLatin1String("DROP TABLE IF EXISTS ComponentTable") - << QLatin1String("DROP TABLE IF EXISTS ComponentMapping") - << QLatin1String("DROP TABLE IF EXISTS ComponentFilter") - << QLatin1String("DROP TABLE IF EXISTS VersionFilter") - << QLatin1String("CREATE TABLE FileNameTable (" - "FolderId INTEGER, " - "Name TEXT, " - "FileId INTEGER PRIMARY KEY, " - "Title TEXT)") - << QLatin1String("CREATE TABLE IndexTable (" - "Id INTEGER PRIMARY KEY, " - "Name TEXT, " - "Identifier TEXT, " - "NamespaceId INTEGER, " - "FileId INTEGER, " - "Anchor TEXT)") - << QLatin1String("CREATE TABLE ContentsTable (" - "Id INTEGER PRIMARY KEY, " - "NamespaceId INTEGER, " - "Data BLOB)") - << QLatin1String("CREATE TABLE FileFilterTable (" - "FilterAttributeId INTEGER, " - "FileId INTEGER)") - << QLatin1String("CREATE TABLE IndexFilterTable (" - "FilterAttributeId INTEGER, " - "IndexId INTEGER)") - << QLatin1String("CREATE TABLE ContentsFilterTable (" - "FilterAttributeId INTEGER, " - "ContentsId INTEGER )") - << QLatin1String("CREATE TABLE FileAttributeSetTable (" - "NamespaceId INTEGER, " - "FilterAttributeSetId INTEGER, " - "FilterAttributeId INTEGER)") - << QLatin1String("CREATE TABLE OptimizedFilterTable (" - "NamespaceId INTEGER, " - "FilterAttributeId INTEGER)") - << QLatin1String("CREATE TABLE TimeStampTable (" - "NamespaceId INTEGER, " - "FolderId INTEGER, " - "FilePath TEXT, " - "Size INTEGER, " - "TimeStamp TEXT)") - << QLatin1String("CREATE TABLE VersionTable (" - "NamespaceId INTEGER, " - "Version TEXT)") - << QLatin1String("CREATE TABLE Filter (" - "FilterId INTEGER PRIMARY KEY, " - "Name TEXT)") - << QLatin1String("CREATE TABLE ComponentTable (" - "ComponentId INTEGER PRIMARY KEY, " - "Name TEXT)") - << QLatin1String("CREATE TABLE ComponentMapping (" - "ComponentId INTEGER, " - "NamespaceId INTEGER)") - << QLatin1String("CREATE TABLE ComponentFilter (" - "ComponentName TEXT, " - "FilterId INTEGER)") - << QLatin1String("CREATE TABLE VersionFilter (" - "Version TEXT, " - "FilterId INTEGER)"); + const QStringList tables = { + "DROP TABLE IF EXISTS FileNameTable"_L1, + "DROP TABLE IF EXISTS IndexTable"_L1, + "DROP TABLE IF EXISTS ContentsTable"_L1, + "DROP TABLE IF EXISTS FileFilterTable"_L1, // legacy + "DROP TABLE IF EXISTS IndexFilterTable"_L1, // legacy + "DROP TABLE IF EXISTS ContentsFilterTable"_L1, // legacy + "DROP TABLE IF EXISTS FileAttributeSetTable"_L1, // legacy + "DROP TABLE IF EXISTS OptimizedFilterTable"_L1, // legacy + "DROP TABLE IF EXISTS TimeStampTable"_L1, + "DROP TABLE IF EXISTS VersionTable"_L1, + "DROP TABLE IF EXISTS Filter"_L1, + "DROP TABLE IF EXISTS ComponentTable"_L1, + "DROP TABLE IF EXISTS ComponentMapping"_L1, + "DROP TABLE IF EXISTS ComponentFilter"_L1, + "DROP TABLE IF EXISTS VersionFilter"_L1, + "CREATE TABLE FileNameTable (" + "FolderId INTEGER, " + "Name TEXT, " + "FileId INTEGER PRIMARY KEY, " + "Title TEXT)"_L1, + "CREATE TABLE IndexTable (" + "Id INTEGER PRIMARY KEY, " + "Name TEXT, " + "Identifier TEXT, " + "NamespaceId INTEGER, " + "FileId INTEGER, " + "Anchor TEXT)"_L1, + "CREATE TABLE ContentsTable (" + "Id INTEGER PRIMARY KEY, " + "NamespaceId INTEGER, " + "Data BLOB)"_L1, + "CREATE TABLE FileFilterTable (" + "FilterAttributeId INTEGER, " + "FileId INTEGER)"_L1, + "CREATE TABLE IndexFilterTable (" + "FilterAttributeId INTEGER, " + "IndexId INTEGER)"_L1, + "CREATE TABLE ContentsFilterTable (" + "FilterAttributeId INTEGER, " + "ContentsId INTEGER )"_L1, + "CREATE TABLE FileAttributeSetTable (" + "NamespaceId INTEGER, " + "FilterAttributeSetId INTEGER, " + "FilterAttributeId INTEGER)"_L1, + "CREATE TABLE OptimizedFilterTable (" + "NamespaceId INTEGER, " + "FilterAttributeId INTEGER)"_L1, + "CREATE TABLE TimeStampTable (" + "NamespaceId INTEGER, " + "FolderId INTEGER, " + "FilePath TEXT, " + "Size INTEGER, " + "TimeStamp TEXT)"_L1, + "CREATE TABLE VersionTable (" + "NamespaceId INTEGER, " + "Version TEXT)"_L1, + "CREATE TABLE Filter (" + "FilterId INTEGER PRIMARY KEY, " + "Name TEXT)"_L1, + "CREATE TABLE ComponentTable (" + "ComponentId INTEGER PRIMARY KEY, " + "Name TEXT)"_L1, + "CREATE TABLE ComponentMapping (" + "ComponentId INTEGER, " + "NamespaceId INTEGER)"_L1, + "CREATE TABLE ComponentFilter (" + "ComponentName TEXT, " + "FilterId INTEGER)"_L1, + "CREATE TABLE VersionFilter (" + "Version TEXT, " + "FilterId INTEGER)"_L1 + }; for (const QString &q : tables) { if (!query->exec(q)) @@ -561,19 +505,18 @@ QStringList QHelpCollectionHandler::customFilters() const { QStringList list; if (m_query) { - m_query->exec(QLatin1String("SELECT Name FROM FilterNameTable")); + m_query->exec("SELECT Name FROM FilterNameTable"_L1); while (m_query->next()) list.append(m_query->value(0).toString()); } return list; } - QStringList QHelpCollectionHandler::filters() const { QStringList list; if (m_query) { - m_query->exec(QLatin1String("SELECT Name FROM Filter ORDER BY Name")); + m_query->exec("SELECT Name FROM Filter ORDER BY Name"_L1); while (m_query->next()) list.append(m_query->value(0).toString()); } @@ -584,7 +527,7 @@ QStringList QHelpCollectionHandler::availableComponents() const { QStringList list; if (m_query) { - m_query->exec(QLatin1String("SELECT DISTINCT Name FROM ComponentTable ORDER BY Name")); + m_query->exec("SELECT DISTINCT Name FROM ComponentTable ORDER BY Name"_L1); while (m_query->next()) list.append(m_query->value(0).toString()); } @@ -595,7 +538,7 @@ QList<QVersionNumber> QHelpCollectionHandler::availableVersions() const { QList<QVersionNumber> list; if (m_query) { - m_query->exec(QLatin1String("SELECT DISTINCT Version FROM VersionTable ORDER BY Version")); + m_query->exec("SELECT DISTINCT Version FROM VersionTable ORDER BY Version"_L1); while (m_query->next()) list.append(QVersionNumber::fromString(m_query->value(0).toString())); } @@ -606,14 +549,15 @@ QMap<QString, QString> QHelpCollectionHandler::namespaceToComponent() const { QMap<QString, QString> result; if (m_query) { - m_query->exec(QLatin1String("SELECT " - "NamespaceTable.Name, " - "ComponentTable.Name " - "FROM NamespaceTable, " - "ComponentTable, " - "ComponentMapping " - "WHERE NamespaceTable.Id = ComponentMapping.NamespaceId " - "AND ComponentMapping.ComponentId = ComponentTable.ComponentId")); + m_query->exec( + "SELECT " + "NamespaceTable.Name, " + "ComponentTable.Name " + "FROM NamespaceTable, " + "ComponentTable, " + "ComponentMapping " + "WHERE NamespaceTable.Id = ComponentMapping.NamespaceId " + "AND ComponentMapping.ComponentId = ComponentTable.ComponentId"_L1); while (m_query->next()) result.insert(m_query->value(0).toString(), m_query->value(1).toString()); } @@ -624,12 +568,13 @@ QMap<QString, QVersionNumber> QHelpCollectionHandler::namespaceToVersion() const { QMap<QString, QVersionNumber> result; if (m_query) { - m_query->exec(QLatin1String("SELECT " - "NamespaceTable.Name, " - "VersionTable.Version " - "FROM NamespaceTable, " - "VersionTable " - "WHERE NamespaceTable.Id = VersionTable.NamespaceId")); + m_query->exec( + "SELECT " + "NamespaceTable.Name, " + "VersionTable.Version " + "FROM NamespaceTable, " + "VersionTable " + "WHERE NamespaceTable.Id = VersionTable.NamespaceId"_L1); while (m_query->next()) { result.insert(m_query->value(0).toString(), QVersionNumber::fromString(m_query->value(1).toString())); @@ -643,21 +588,23 @@ QHelpFilterData QHelpCollectionHandler::filterData(const QString &filterName) co QStringList components; QList<QVersionNumber> versions; if (m_query) { - m_query->prepare(QLatin1String("SELECT ComponentFilter.ComponentName " - "FROM ComponentFilter, Filter " - "WHERE ComponentFilter.FilterId = Filter.FilterId " - "AND Filter.Name = ? " - "ORDER BY ComponentFilter.ComponentName")); + m_query->prepare( + "SELECT ComponentFilter.ComponentName " + "FROM ComponentFilter, Filter " + "WHERE ComponentFilter.FilterId = Filter.FilterId " + "AND Filter.Name = ? " + "ORDER BY ComponentFilter.ComponentName"_L1); m_query->bindValue(0, filterName); m_query->exec(); while (m_query->next()) components.append(m_query->value(0).toString()); - m_query->prepare(QLatin1String("SELECT VersionFilter.Version " - "FROM VersionFilter, Filter " - "WHERE VersionFilter.FilterId = Filter.FilterId " - "AND Filter.Name = ? " - "ORDER BY VersionFilter.Version")); + m_query->prepare( + "SELECT VersionFilter.Version " + "FROM VersionFilter, Filter " + "WHERE VersionFilter.FilterId = Filter.FilterId " + "AND Filter.Name = ? " + "ORDER BY VersionFilter.Version"_L1); m_query->bindValue(0, filterName); m_query->exec(); while (m_query->next()) @@ -676,8 +623,7 @@ bool QHelpCollectionHandler::setFilterData(const QString &filterName, if (!removeFilter(filterName)) return false; - m_query->prepare(QLatin1String("INSERT INTO Filter " - "VALUES (NULL, ?)")); + m_query->prepare("INSERT INTO Filter VALUES (NULL, ?)"_L1); m_query->bindValue(0, filterName); if (!m_query->exec()) return false; @@ -693,8 +639,7 @@ bool QHelpCollectionHandler::setFilterData(const QString &filterName, filterIdList.append(filterId); } - m_query->prepare(QLatin1String("INSERT INTO ComponentFilter " - "VALUES (?, ?)")); + m_query->prepare("INSERT INTO ComponentFilter VALUES (?, ?)"_L1); m_query->addBindValue(componentList); m_query->addBindValue(filterIdList); if (!m_query->execBatch()) @@ -706,8 +651,7 @@ bool QHelpCollectionHandler::setFilterData(const QString &filterName, filterIdList.append(filterId); } - m_query->prepare(QLatin1String("INSERT INTO VersionFilter " - "VALUES (?, ?)")); + m_query->prepare("INSERT INTO VersionFilter VALUES (?, ?)"_L1); m_query->addBindValue(versionList); m_query->addBindValue(filterIdList); if (!m_query->execBatch()) @@ -718,9 +662,7 @@ bool QHelpCollectionHandler::setFilterData(const QString &filterName, bool QHelpCollectionHandler::removeFilter(const QString &filterName) { - m_query->prepare(QLatin1String("SELECT FilterId " - "FROM Filter " - "WHERE Name = ?")); + m_query->prepare("SELECT FilterId FROM Filter WHERE Name = ?"_L1); m_query->bindValue(0, filterName); if (!m_query->exec()) return false; @@ -730,20 +672,17 @@ bool QHelpCollectionHandler::removeFilter(const QString &filterName) const int filterId = m_query->value(0).toInt(); - m_query->prepare(QLatin1String("DELETE FROM Filter " - "WHERE Filter.Name = ?")); + m_query->prepare("DELETE FROM Filter WHERE Filter.Name = ?"_L1); m_query->bindValue(0, filterName); if (!m_query->exec()) return false; - m_query->prepare(QLatin1String("DELETE FROM ComponentFilter " - "WHERE ComponentFilter.FilterId = ?")); + m_query->prepare("DELETE FROM ComponentFilter WHERE ComponentFilter.FilterId = ?"_L1); m_query->bindValue(0, filterId); if (!m_query->exec()) return false; - m_query->prepare(QLatin1String("DELETE FROM VersionFilter " - "WHERE VersionFilter.FilterId = ?")); + m_query->prepare("DELETE FROM VersionFilter WHERE VersionFilter.FilterId = ?"_L1); m_query->bindValue(0, filterId); if (!m_query->exec()) return false; @@ -757,7 +696,7 @@ bool QHelpCollectionHandler::removeCustomFilter(const QString &filterName) return false; int filterNameId = -1; - m_query->prepare(QLatin1String("SELECT Id FROM FilterNameTable WHERE Name=?")); + m_query->prepare("SELECT Id FROM FilterNameTable WHERE Name=?"_L1); m_query->bindValue(0, filterName); m_query->exec(); if (m_query->next()) @@ -768,11 +707,11 @@ bool QHelpCollectionHandler::removeCustomFilter(const QString &filterName) return false; } - m_query->prepare(QLatin1String("DELETE FROM FilterTable WHERE NameId=?")); + m_query->prepare("DELETE FROM FilterTable WHERE NameId=?"_L1); m_query->bindValue(0, filterNameId); m_query->exec(); - m_query->prepare(QLatin1String("DELETE FROM FilterNameTable WHERE Id=?")); + m_query->prepare("DELETE FROM FilterNameTable WHERE Id=?"_L1); m_query->bindValue(0, filterNameId); m_query->exec(); @@ -786,32 +725,31 @@ bool QHelpCollectionHandler::addCustomFilter(const QString &filterName, return false; int nameId = -1; - m_query->prepare(QLatin1String("SELECT Id FROM FilterNameTable WHERE Name=?")); + m_query->prepare("SELECT Id FROM FilterNameTable WHERE Name=?"_L1); m_query->bindValue(0, filterName); m_query->exec(); if (m_query->next()) nameId = m_query->value(0).toInt(); - m_query->exec(QLatin1String("SELECT Id, Name FROM FilterAttributeTable")); + m_query->exec("SELECT Id, Name FROM FilterAttributeTable"_L1); QStringList idsToInsert = attributes; QMap<QString, int> attributeMap; while (m_query->next()) { // all old attributes const QString attributeName = m_query->value(1).toString(); attributeMap.insert(attributeName, m_query->value(0).toInt()); - if (idsToInsert.contains(attributeName)) - idsToInsert.removeAll(attributeName); + idsToInsert.removeAll(attributeName); } - for (const QString &id : qAsConst(idsToInsert)) { - m_query->prepare(QLatin1String("INSERT INTO FilterAttributeTable VALUES(NULL, ?)")); + for (const QString &id : std::as_const(idsToInsert)) { + m_query->prepare("INSERT INTO FilterAttributeTable VALUES(NULL, ?)"_L1); m_query->bindValue(0, id); m_query->exec(); attributeMap.insert(id, m_query->lastInsertId().toInt()); } if (nameId < 0) { - m_query->prepare(QLatin1String("INSERT INTO FilterNameTable VALUES(NULL, ?)")); + m_query->prepare("INSERT INTO FilterNameTable VALUES(NULL, ?)"_L1); m_query->bindValue(0, filterName); if (m_query->exec()) nameId = m_query->lastInsertId().toInt(); @@ -822,12 +760,12 @@ bool QHelpCollectionHandler::addCustomFilter(const QString &filterName, return false; } - m_query->prepare(QLatin1String("DELETE FROM FilterTable WHERE NameId=?")); + m_query->prepare("DELETE FROM FilterTable WHERE NameId=?"_L1); m_query->bindValue(0, nameId); m_query->exec(); for (const QString &att : attributes) { - m_query->prepare(QLatin1String("INSERT INTO FilterTable VALUES(?, ?)")); + m_query->prepare("INSERT INTO FilterTable VALUES(?, ?)"_L1); m_query->bindValue(0, nameId); m_query->bindValue(1, attributeMap[att]); if (!m_query->exec()) @@ -844,15 +782,16 @@ QHelpCollectionHandler::FileInfo QHelpCollectionHandler::registeredDocumentation if (!m_query) return fileInfo; - m_query->prepare(QLatin1String("SELECT " - "NamespaceTable.Name, " - "NamespaceTable.FilePath, " - "FolderTable.Name " - "FROM " - "NamespaceTable, " - "FolderTable " - "WHERE NamespaceTable.Id = FolderTable.NamespaceId " - "AND NamespaceTable.Name = ? LIMIT 1")); + m_query->prepare( + "SELECT " + "NamespaceTable.Name, " + "NamespaceTable.FilePath, " + "FolderTable.Name " + "FROM " + "NamespaceTable, " + "FolderTable " + "WHERE NamespaceTable.Id = FolderTable.NamespaceId " + "AND NamespaceTable.Name = ? LIMIT 1"_L1); m_query->bindValue(0, namespaceName); if (!m_query->exec() || !m_query->next()) return fileInfo; @@ -872,14 +811,15 @@ QHelpCollectionHandler::FileInfoList QHelpCollectionHandler::registeredDocumenta if (!m_query) return list; - m_query->exec(QLatin1String("SELECT " - "NamespaceTable.Name, " - "NamespaceTable.FilePath, " - "FolderTable.Name " - "FROM " - "NamespaceTable, " - "FolderTable " - "WHERE NamespaceTable.Id = FolderTable.NamespaceId")); + m_query->exec( + "SELECT " + "NamespaceTable.Name, " + "NamespaceTable.FilePath, " + "FolderTable.Name " + "FROM " + "NamespaceTable, " + "FolderTable " + "WHERE NamespaceTable.Id = FolderTable.NamespaceId"_L1); while (m_query->next()) { FileInfo fileInfo; @@ -898,7 +838,7 @@ bool QHelpCollectionHandler::registerDocumentation(const QString &fileName) return false; QHelpDBReader reader(fileName, QHelpGlobal::uniquifyConnectionName( - QLatin1String("QHelpCollectionHandler"), this), nullptr); + "QHelpCollectionHandler"_L1, this), nullptr); if (!reader.init()) { emit error(tr("Cannot open documentation file %1.").arg(fileName)); return false; @@ -934,7 +874,7 @@ bool QHelpCollectionHandler::unregisterDocumentation(const QString &namespaceNam if (!isDBOpened()) return false; - m_query->prepare(QLatin1String("SELECT Id FROM NamespaceTable WHERE Name = ?")); + m_query->prepare("SELECT Id FROM NamespaceTable WHERE Name = ?"_L1); m_query->bindValue(0, namespaceName); m_query->exec(); @@ -945,12 +885,12 @@ bool QHelpCollectionHandler::unregisterDocumentation(const QString &namespaceNam const int nsId = m_query->value(0).toInt(); - m_query->prepare(QLatin1String("DELETE FROM NamespaceTable WHERE Id = ?")); + m_query->prepare("DELETE FROM NamespaceTable WHERE Id = ?"_L1); m_query->bindValue(0, nsId); if (!m_query->exec()) return false; - m_query->prepare(QLatin1String("SELECT Id FROM FolderTable WHERE NamespaceId = ?")); + m_query->prepare("SELECT Id FROM FolderTable WHERE NamespaceId = ?"_L1); m_query->bindValue(0, nsId); m_query->exec(); @@ -961,12 +901,12 @@ bool QHelpCollectionHandler::unregisterDocumentation(const QString &namespaceNam const int vfId = m_query->value(0).toInt(); - m_query->prepare(QLatin1String("DELETE FROM NamespaceTable WHERE Id = ?")); + m_query->prepare("DELETE FROM NamespaceTable WHERE Id = ?"_L1); m_query->bindValue(0, nsId); if (!m_query->exec()) return false; - m_query->prepare(QLatin1String("DELETE FROM FolderTable WHERE NamespaceId = ?")); + m_query->prepare("DELETE FROM FolderTable WHERE NamespaceId = ?"_L1); m_query->bindValue(0, nsId); if (!m_query->exec()) return false; @@ -983,17 +923,17 @@ static QHelpCollectionHandler::FileInfo extractFileInfo(const QUrl &url) { QHelpCollectionHandler::FileInfo fileInfo; - if (!url.isValid() || url.toString().count(QLatin1Char('/')) < 4 - || url.scheme() != QLatin1String("qthelp")) { + if (!url.isValid() || url.toString().count(u'/') < 4 + || url.scheme() != "qthelp"_L1) { return fileInfo; } fileInfo.namespaceName = url.authority(); fileInfo.fileName = url.path(); - if (fileInfo.fileName.startsWith(QLatin1Char('/'))) + if (fileInfo.fileName.startsWith(u'/')) fileInfo.fileName = fileInfo.fileName.mid(1); - fileInfo.folderName = fileInfo.fileName.mid(0, fileInfo.fileName.indexOf(QLatin1Char('/'), 1)); - fileInfo.fileName.remove(0, fileInfo.folderName.length() + 1); + fileInfo.folderName = fileInfo.fileName.mid(0, fileInfo.fileName.indexOf(u'/', 1)); + fileInfo.fileName.remove(0, fileInfo.folderName.size() + 1); return fileInfo; } @@ -1007,15 +947,16 @@ bool QHelpCollectionHandler::fileExists(const QUrl &url) const if (fileInfo.namespaceName.isEmpty()) return false; - m_query->prepare(QLatin1String("SELECT COUNT (DISTINCT NamespaceTable.Id) " - "FROM " - "FileNameTable, " - "NamespaceTable, " - "FolderTable " - "WHERE FolderTable.Name = ? " - "AND FileNameTable.Name = ? " - "AND FileNameTable.FolderId = FolderTable.Id " - "AND FolderTable.NamespaceId = NamespaceTable.Id")); + m_query->prepare( + "SELECT COUNT (DISTINCT NamespaceTable.Id) " + "FROM " + "FileNameTable, " + "NamespaceTable, " + "FolderTable " + "WHERE FolderTable.Name = ? " + "AND FileNameTable.Name = ? " + "AND FileNameTable.FolderId = FolderTable.Id " + "AND FolderTable.NamespaceId = NamespaceTable.Id"_L1); m_query->bindValue(0, fileInfo.folderName); m_query->bindValue(1, fileInfo.fileName); if (!m_query->exec() || !m_query->next()) @@ -1030,52 +971,52 @@ bool QHelpCollectionHandler::fileExists(const QUrl &url) const static QString prepareFilterQuery(const QString &filterName) { if (filterName.isEmpty()) - return QString(); - - return QString::fromLatin1(" AND EXISTS(SELECT * FROM Filter WHERE Filter.Name = ?) " - "AND (" - "(NOT EXISTS(" // 1. filter by component - "SELECT * FROM " - "ComponentFilter, " - "Filter " - "WHERE ComponentFilter.FilterId = Filter.FilterId " - "AND Filter.Name = ?) " - "OR NamespaceTable.Id IN (" - "SELECT " - "NamespaceTable.Id " - "FROM " - "NamespaceTable, " - "ComponentTable, " - "ComponentMapping, " - "ComponentFilter, " - "Filter " - "WHERE ComponentMapping.NamespaceId = NamespaceTable.Id " - "AND ComponentTable.ComponentId = ComponentMapping.ComponentId " - "AND ((ComponentTable.Name = ComponentFilter.ComponentName) " - "OR (ComponentTable.Name IS NULL AND ComponentFilter.ComponentName IS NULL)) " - "AND ComponentFilter.FilterId = Filter.FilterId " - "AND Filter.Name = ?))" - " AND " - "(NOT EXISTS(" // 2. filter by version - "SELECT * FROM " - "VersionFilter, " - "Filter " - "WHERE VersionFilter.FilterId = Filter.FilterId " - "AND Filter.Name = ?) " - "OR NamespaceTable.Id IN (" - "SELECT " - "NamespaceTable.Id " - "FROM " - "NamespaceTable, " - "VersionFilter, " - "VersionTable, " - "Filter " - "WHERE VersionFilter.FilterId = Filter.FilterId " - "AND ((VersionFilter.Version = VersionTable.Version) " - "OR (VersionFilter.Version IS NULL AND VersionTable.Version IS NULL)) " - "AND VersionTable.NamespaceId = NamespaceTable.Id " - "AND Filter.Name = ?))" - ")"); + return {}; + + return " AND EXISTS(SELECT * FROM Filter WHERE Filter.Name = ?) " + "AND (" + "(NOT EXISTS(" // 1. filter by component + "SELECT * FROM " + "ComponentFilter, " + "Filter " + "WHERE ComponentFilter.FilterId = Filter.FilterId " + "AND Filter.Name = ?) " + "OR NamespaceTable.Id IN (" + "SELECT " + "NamespaceTable.Id " + "FROM " + "NamespaceTable, " + "ComponentTable, " + "ComponentMapping, " + "ComponentFilter, " + "Filter " + "WHERE ComponentMapping.NamespaceId = NamespaceTable.Id " + "AND ComponentTable.ComponentId = ComponentMapping.ComponentId " + "AND ((ComponentTable.Name = ComponentFilter.ComponentName) " + "OR (ComponentTable.Name IS NULL AND ComponentFilter.ComponentName IS NULL)) " + "AND ComponentFilter.FilterId = Filter.FilterId " + "AND Filter.Name = ?))" + " AND " + "(NOT EXISTS(" // 2. filter by version + "SELECT * FROM " + "VersionFilter, " + "Filter " + "WHERE VersionFilter.FilterId = Filter.FilterId " + "AND Filter.Name = ?) " + "OR NamespaceTable.Id IN (" + "SELECT " + "NamespaceTable.Id " + "FROM " + "NamespaceTable, " + "VersionFilter, " + "VersionTable, " + "Filter " + "WHERE VersionFilter.FilterId = Filter.FilterId " + "AND ((VersionFilter.Version = VersionTable.Version) " + "OR (VersionFilter.Version IS NULL AND VersionTable.Version IS NULL)) " + "AND VersionTable.NamespaceId = NamespaceTable.Id " + "AND Filter.Name = ?))" + ")"_L1; } static void bindFilterQuery(QSqlQuery *query, int bindStart, const QString &filterName) @@ -1097,47 +1038,46 @@ static QString prepareFilterQuery(int attributesCount, const QString &filterColumnName) { if (!attributesCount) - return QString(); + return {}; - QString filterQuery = QString::fromLatin1(" AND (%1.%2 IN (").arg(idTableName, idColumnName); + QString filterQuery = " AND (%1.%2 IN ("_L1.arg(idTableName, idColumnName); - const QString filterQueryTemplate = QString::fromLatin1( - "SELECT %1.%2 " - "FROM %1, FilterAttributeTable " - "WHERE %1.FilterAttributeId = FilterAttributeTable.Id " - "AND FilterAttributeTable.Name = ?") - .arg(filterTableName, filterColumnName); + const QString filterQueryTemplate = + "SELECT %1.%2 " + "FROM %1, FilterAttributeTable " + "WHERE %1.FilterAttributeId = FilterAttributeTable.Id " + "AND FilterAttributeTable.Name = ?"_L1.arg(filterTableName, filterColumnName); for (int i = 0; i < attributesCount; ++i) { if (i > 0) - filterQuery.append(QLatin1String(" INTERSECT ")); + filterQuery.append(" INTERSECT "_L1); filterQuery.append(filterQueryTemplate); } - filterQuery.append(QLatin1String(") OR NamespaceTable.Id IN (")); + filterQuery.append(") OR NamespaceTable.Id IN ("_L1); - const QString optimizedFilterQueryTemplate = QLatin1String( - "SELECT OptimizedFilterTable.NamespaceId " - "FROM OptimizedFilterTable, FilterAttributeTable " - "WHERE OptimizedFilterTable.FilterAttributeId = FilterAttributeTable.Id " - "AND FilterAttributeTable.Name = ?"); + const QString optimizedFilterQueryTemplate = + "SELECT OptimizedFilterTable.NamespaceId " + "FROM OptimizedFilterTable, FilterAttributeTable " + "WHERE OptimizedFilterTable.FilterAttributeId = FilterAttributeTable.Id " + "AND FilterAttributeTable.Name = ?"_L1; for (int i = 0; i < attributesCount; ++i) { if (i > 0) - filterQuery.append(QLatin1String(" INTERSECT ")); + filterQuery.append(" INTERSECT "_L1); filterQuery.append(optimizedFilterQueryTemplate); } - filterQuery.append(QLatin1String("))")); + filterQuery.append("))"_L1); return filterQuery; } -void bindFilterQuery(QSqlQuery *query, int startingBindPos, const QStringList &filterAttributes) +static void bindFilterQuery(QSqlQuery *query, int startingBindPos, const QStringList &filterAttributes) { for (int i = 0; i < 2; ++i) { - for (int j = 0; j < filterAttributes.count(); j++) { - query->bindValue(i * filterAttributes.count() + j + startingBindPos, + for (int j = 0; j < filterAttributes.size(); j++) { + query->bindValue(i * filterAttributes.size() + j + startingBindPos, filterAttributes.at(j)); } } @@ -1147,45 +1087,42 @@ QString QHelpCollectionHandler::namespaceForFile(const QUrl &url, const QStringList &filterAttributes) const { if (!isDBOpened()) - return QString(); + return {}; const FileInfo fileInfo = extractFileInfo(url); if (fileInfo.namespaceName.isEmpty()) - return QString(); - - const QString filterlessQuery = QLatin1String( - "SELECT DISTINCT " - "NamespaceTable.Name " - "FROM " - "FileNameTable, " - "NamespaceTable, " - "FolderTable " - "WHERE FolderTable.Name = ? " - "AND FileNameTable.Name = ? " - "AND FileNameTable.FolderId = FolderTable.Id " - "AND FolderTable.NamespaceId = NamespaceTable.Id"); + return {}; + + const QString filterlessQuery = + "SELECT DISTINCT " + "NamespaceTable.Name " + "FROM " + "FileNameTable, " + "NamespaceTable, " + "FolderTable " + "WHERE FolderTable.Name = ? " + "AND FileNameTable.Name = ? " + "AND FileNameTable.FolderId = FolderTable.Id " + "AND FolderTable.NamespaceId = NamespaceTable.Id"_L1; const QString filterQuery = filterlessQuery - + prepareFilterQuery(filterAttributes.count(), - QLatin1String("FileNameTable"), - QLatin1String("FileId"), - QLatin1String("FileFilterTable"), - QLatin1String("FileId")); + + prepareFilterQuery(filterAttributes.size(), "FileNameTable"_L1, "FileId"_L1, + "FileFilterTable"_L1, "FileId"_L1); m_query->prepare(filterQuery); m_query->bindValue(0, fileInfo.folderName); m_query->bindValue(1, fileInfo.fileName); - bindFilterQuery(m_query, 2, filterAttributes); + bindFilterQuery(m_query.get(), 2, filterAttributes); if (!m_query->exec()) - return QString(); + return {}; - QList<QString> namespaceList; + QStringList namespaceList; while (m_query->next()) namespaceList.append(m_query->value(0).toString()); if (namespaceList.isEmpty()) - return QString(); + return {}; if (namespaceList.contains(fileInfo.namespaceName)) return fileInfo.namespaceName; @@ -1206,23 +1143,23 @@ QString QHelpCollectionHandler::namespaceForFile(const QUrl &url, const QString &filterName) const { if (!isDBOpened()) - return QString(); + return {}; const FileInfo fileInfo = extractFileInfo(url); if (fileInfo.namespaceName.isEmpty()) - return QString(); - - const QString filterlessQuery = QLatin1String( - "SELECT DISTINCT " - "NamespaceTable.Name " - "FROM " - "FileNameTable, " - "NamespaceTable, " - "FolderTable " - "WHERE FolderTable.Name = ? " - "AND FileNameTable.Name = ? " - "AND FileNameTable.FolderId = FolderTable.Id " - "AND FolderTable.NamespaceId = NamespaceTable.Id"); + return {}; + + const QString filterlessQuery = + "SELECT DISTINCT " + "NamespaceTable.Name " + "FROM " + "FileNameTable, " + "NamespaceTable, " + "FolderTable " + "WHERE FolderTable.Name = ? " + "AND FileNameTable.Name = ? " + "AND FileNameTable.FolderId = FolderTable.Id " + "AND FolderTable.NamespaceId = NamespaceTable.Id"_L1; const QString filterQuery = filterlessQuery + prepareFilterQuery(filterName); @@ -1230,17 +1167,17 @@ QString QHelpCollectionHandler::namespaceForFile(const QUrl &url, m_query->prepare(filterQuery); m_query->bindValue(0, fileInfo.folderName); m_query->bindValue(1, fileInfo.fileName); - bindFilterQuery(m_query, 2, filterName); + bindFilterQuery(m_query.get(), 2, filterName); if (!m_query->exec()) - return QString(); + return {}; - QList<QString> namespaceList; + QStringList namespaceList; while (m_query->next()) namespaceList.append(m_query->value(0).toString()); if (namespaceList.isEmpty()) - return QString(); + return {}; if (namespaceList.contains(fileInfo.namespaceName)) return fileInfo.namespaceName; @@ -1262,48 +1199,41 @@ QStringList QHelpCollectionHandler::files(const QString &namespaceName, const QString &extensionFilter) const { if (!isDBOpened()) - return QStringList(); + return {}; const QString extensionQuery = extensionFilter.isEmpty() - ? QString() : QLatin1String(" AND FileNameTable.Name LIKE ?"); - const QString filterlessQuery = QLatin1String( - "SELECT " - "FolderTable.Name, " - "FileNameTable.Name " - "FROM " - "FileNameTable, " - "FolderTable, " - "NamespaceTable " - "WHERE FileNameTable.FolderId = FolderTable.Id " - "AND FolderTable.NamespaceId = NamespaceTable.Id " - "AND NamespaceTable.Name = ?") + extensionQuery; + ? QString() : " AND FileNameTable.Name LIKE ?"_L1; + const QString filterlessQuery = + "SELECT " + "FolderTable.Name, " + "FileNameTable.Name " + "FROM " + "FileNameTable, " + "FolderTable, " + "NamespaceTable " + "WHERE FileNameTable.FolderId = FolderTable.Id " + "AND FolderTable.NamespaceId = NamespaceTable.Id " + "AND NamespaceTable.Name = ?"_L1 + extensionQuery; const QString filterQuery = filterlessQuery - + prepareFilterQuery(filterAttributes.count(), - QLatin1String("FileNameTable"), - QLatin1String("FileId"), - QLatin1String("FileFilterTable"), - QLatin1String("FileId")); + + prepareFilterQuery(filterAttributes.size(), "FileNameTable"_L1, "FileId"_L1, + "FileFilterTable"_L1, "FileId"_L1); m_query->prepare(filterQuery); m_query->bindValue(0, namespaceName); int bindCount = 1; if (!extensionFilter.isEmpty()) { - m_query->bindValue(bindCount, QString::fromLatin1("%.%1").arg(extensionFilter)); + m_query->bindValue(bindCount, "%.%1"_L1.arg(extensionFilter)); ++bindCount; } - bindFilterQuery(m_query, bindCount, filterAttributes); + bindFilterQuery(m_query.get(), bindCount, filterAttributes); if (!m_query->exec()) - return QStringList(); + return {}; QStringList fileNames; - while (m_query->next()) { - fileNames.append(m_query->value(0).toString() - + QLatin1Char('/') - + m_query->value(1).toString()); - } - + while (m_query->next()) + fileNames.append(m_query->value(0).toString() + u'/' + m_query->value(1).toString()); return fileNames; } @@ -1312,21 +1242,21 @@ QStringList QHelpCollectionHandler::files(const QString &namespaceName, const QString &extensionFilter) const { if (!isDBOpened()) - return QStringList(); + return {}; const QString extensionQuery = extensionFilter.isEmpty() - ? QString() : QLatin1String(" AND FileNameTable.Name LIKE ?"); - const QString filterlessQuery = QLatin1String( - "SELECT " - "FolderTable.Name, " - "FileNameTable.Name " - "FROM " - "FileNameTable, " - "FolderTable, " - "NamespaceTable " - "WHERE FileNameTable.FolderId = FolderTable.Id " - "AND FolderTable.NamespaceId = NamespaceTable.Id " - "AND NamespaceTable.Name = ?") + extensionQuery; + ? QString() : " AND FileNameTable.Name LIKE ?"_L1; + const QString filterlessQuery = + "SELECT " + "FolderTable.Name, " + "FileNameTable.Name " + "FROM " + "FileNameTable, " + "FolderTable, " + "NamespaceTable " + "WHERE FileNameTable.FolderId = FolderTable.Id " + "AND FolderTable.NamespaceId = NamespaceTable.Id " + "AND NamespaceTable.Name = ?"_L1 + extensionQuery; const QString filterQuery = filterlessQuery + prepareFilterQuery(filterName); @@ -1335,33 +1265,29 @@ QStringList QHelpCollectionHandler::files(const QString &namespaceName, m_query->bindValue(0, namespaceName); int bindCount = 1; if (!extensionFilter.isEmpty()) { - m_query->bindValue(bindCount, QString::fromLatin1("%.%1").arg(extensionFilter)); + m_query->bindValue(bindCount, "%.%1"_L1.arg(extensionFilter)); ++bindCount; } - bindFilterQuery(m_query, bindCount, filterName); + bindFilterQuery(m_query.get(), bindCount, filterName); if (!m_query->exec()) - return QStringList(); + return{}; QStringList fileNames; - while (m_query->next()) { - fileNames.append(m_query->value(0).toString() - + QLatin1Char('/') - + m_query->value(1).toString()); - } - + while (m_query->next()) + fileNames.append(m_query->value(0).toString() + u'/' + m_query->value(1).toString()); return fileNames; } QUrl QHelpCollectionHandler::findFile(const QUrl &url, const QStringList &filterAttributes) const { if (!isDBOpened()) - return QUrl(); + return {}; const QString namespaceName = namespaceForFile(url, filterAttributes); if (namespaceName.isEmpty()) - return QUrl(); + return {}; QUrl result = url; result.setAuthority(namespaceName); @@ -1371,11 +1297,11 @@ QUrl QHelpCollectionHandler::findFile(const QUrl &url, const QStringList &filter QUrl QHelpCollectionHandler::findFile(const QUrl &url, const QString &filterName) const { if (!isDBOpened()) - return QUrl(); + return {}; const QString namespaceName = namespaceForFile(url, filterName); if (namespaceName.isEmpty()) - return QUrl(); + return {}; QUrl result = url; result.setAuthority(namespaceName); @@ -1385,11 +1311,11 @@ QUrl QHelpCollectionHandler::findFile(const QUrl &url, const QString &filterName QByteArray QHelpCollectionHandler::fileData(const QUrl &url) const { if (!isDBOpened()) - return QByteArray(); + return {}; const QString namespaceName = namespaceForFile(url, QString()); if (namespaceName.isEmpty()) - return QByteArray(); + return {}; const FileInfo fileInfo = extractFileInfo(url); @@ -1397,9 +1323,9 @@ QByteArray QHelpCollectionHandler::fileData(const QUrl &url) const const QString absFileName = absoluteDocPath(docInfo.fileName); QHelpDBReader reader(absFileName, QHelpGlobal::uniquifyConnectionName( - docInfo.fileName, const_cast<QHelpCollectionHandler *>(this)), nullptr); + docInfo.fileName, const_cast<QHelpCollectionHandler *>(this)), nullptr); if (!reader.init()) - return QByteArray(); + return {}; return reader.fileData(fileInfo.folderName, fileInfo.fileName); } @@ -1411,29 +1337,26 @@ QStringList QHelpCollectionHandler::indicesForFilter(const QStringList &filterAt if (!isDBOpened()) return indices; - const QString filterlessQuery = QString::fromLatin1( - "SELECT DISTINCT " - "IndexTable.Name " - "FROM " - "IndexTable, " - "FileNameTable, " - "FolderTable, " - "NamespaceTable " - "WHERE IndexTable.FileId = FileNameTable.FileId " - "AND FileNameTable.FolderId = FolderTable.Id " - "AND IndexTable.NamespaceId = NamespaceTable.Id"); + const QString filterlessQuery = + "SELECT DISTINCT " + "IndexTable.Name " + "FROM " + "IndexTable, " + "FileNameTable, " + "FolderTable, " + "NamespaceTable " + "WHERE IndexTable.FileId = FileNameTable.FileId " + "AND FileNameTable.FolderId = FolderTable.Id " + "AND IndexTable.NamespaceId = NamespaceTable.Id"_L1; const QString filterQuery = filterlessQuery - + prepareFilterQuery(filterAttributes.count(), - QLatin1String("IndexTable"), - QLatin1String("Id"), - QLatin1String("IndexFilterTable"), - QLatin1String("IndexId")) - + QLatin1String(" ORDER BY LOWER(IndexTable.Name), IndexTable.Name"); + + prepareFilterQuery(filterAttributes.size(), "IndexTable"_L1, "Id"_L1, + "IndexFilterTable"_L1, "IndexId"_L1) + + " ORDER BY LOWER(IndexTable.Name), IndexTable.Name"_L1; // this doesn't work: ASC COLLATE NOCASE m_query->prepare(filterQuery); - bindFilterQuery(m_query, 0, filterAttributes); + bindFilterQuery(m_query.get(), 0, filterAttributes); m_query->exec(); @@ -1443,7 +1366,6 @@ QStringList QHelpCollectionHandler::indicesForFilter(const QStringList &filterAt return indices; } - QStringList QHelpCollectionHandler::indicesForFilter(const QString &filterName) const { QStringList indices; @@ -1451,24 +1373,24 @@ QStringList QHelpCollectionHandler::indicesForFilter(const QString &filterName) if (!isDBOpened()) return indices; - const QString filterlessQuery = QString::fromLatin1( - "SELECT DISTINCT " - "IndexTable.Name " - "FROM " - "IndexTable, " - "FileNameTable, " - "FolderTable, " - "NamespaceTable " - "WHERE IndexTable.FileId = FileNameTable.FileId " - "AND FileNameTable.FolderId = FolderTable.Id " - "AND IndexTable.NamespaceId = NamespaceTable.Id"); + const QString filterlessQuery = + "SELECT DISTINCT " + "IndexTable.Name " + "FROM " + "IndexTable, " + "FileNameTable, " + "FolderTable, " + "NamespaceTable " + "WHERE IndexTable.FileId = FileNameTable.FileId " + "AND FileNameTable.FolderId = FolderTable.Id " + "AND IndexTable.NamespaceId = NamespaceTable.Id"_L1; const QString filterQuery = filterlessQuery + prepareFilterQuery(filterName) - + QLatin1String(" ORDER BY LOWER(IndexTable.Name), IndexTable.Name"); + + " ORDER BY LOWER(IndexTable.Name), IndexTable.Name"_L1; m_query->prepare(filterQuery); - bindFilterQuery(m_query, 0, filterName); + bindFilterQuery(m_query.get(), 0, filterName); m_query->exec(); @@ -1481,7 +1403,7 @@ QStringList QHelpCollectionHandler::indicesForFilter(const QString &filterName) static QString getTitle(const QByteArray &contents) { if (!contents.size()) - return QString(); + return {}; int depth = 0; QString link; @@ -1499,33 +1421,30 @@ QList<QHelpCollectionHandler::ContentsData> QHelpCollectionHandler::contentsForF const QStringList &filterAttributes) const { if (!isDBOpened()) - return QList<ContentsData>(); - - const QString filterlessQuery = QString::fromLatin1( - "SELECT DISTINCT " - "NamespaceTable.Name, " - "FolderTable.Name, " - "ContentsTable.Data, " - "VersionTable.Version " - "FROM " - "FolderTable, " - "NamespaceTable, " - "ContentsTable, " - "VersionTable " - "WHERE ContentsTable.NamespaceId = NamespaceTable.Id " - "AND NamespaceTable.Id = FolderTable.NamespaceId " - "AND ContentsTable.NamespaceId = NamespaceTable.Id " - "AND VersionTable.NamespaceId = NamespaceTable.Id"); + return {}; + + const QString filterlessQuery = + "SELECT DISTINCT " + "NamespaceTable.Name, " + "FolderTable.Name, " + "ContentsTable.Data, " + "VersionTable.Version " + "FROM " + "FolderTable, " + "NamespaceTable, " + "ContentsTable, " + "VersionTable " + "WHERE ContentsTable.NamespaceId = NamespaceTable.Id " + "AND NamespaceTable.Id = FolderTable.NamespaceId " + "AND ContentsTable.NamespaceId = NamespaceTable.Id " + "AND VersionTable.NamespaceId = NamespaceTable.Id"_L1; const QString filterQuery = filterlessQuery - + prepareFilterQuery(filterAttributes.count(), - QLatin1String("ContentsTable"), - QLatin1String("Id"), - QLatin1String("ContentsFilterTable"), - QLatin1String("ContentsId")); + + prepareFilterQuery(filterAttributes.size(), "ContentsTable"_L1, "Id"_L1, + "ContentsFilterTable"_L1, "ContentsId"_L1); m_query->prepare(filterQuery); - bindFilterQuery(m_query, 0, filterAttributes); + bindFilterQuery(m_query.get(), 0, filterAttributes); m_query->exec(); @@ -1546,7 +1465,7 @@ QList<QHelpCollectionHandler::ContentsData> QHelpCollectionHandler::contentsForF } QList<QHelpCollectionHandler::ContentsData> result; - for (const auto &versionContents : qAsConst(contentsMap)) { + for (const auto &versionContents : std::as_const(contentsMap)) { // insert items in the reverse order of version number const auto itBegin = versionContents.constBegin(); auto it = versionContents.constEnd(); @@ -1555,36 +1474,34 @@ QList<QHelpCollectionHandler::ContentsData> QHelpCollectionHandler::contentsForF result.append(it.value()); } } - return result; } QList<QHelpCollectionHandler::ContentsData> QHelpCollectionHandler::contentsForFilter(const QString &filterName) const { if (!isDBOpened()) - return QList<ContentsData>(); - - const QString filterlessQuery = QString::fromLatin1( - "SELECT DISTINCT " - "NamespaceTable.Name, " - "FolderTable.Name, " - "ContentsTable.Data, " - "VersionTable.Version " - "FROM " - "FolderTable, " - "NamespaceTable, " - "ContentsTable, " - "VersionTable " - "WHERE ContentsTable.NamespaceId = NamespaceTable.Id " - "AND NamespaceTable.Id = FolderTable.NamespaceId " - "AND ContentsTable.NamespaceId = NamespaceTable.Id " - "AND VersionTable.NamespaceId = NamespaceTable.Id"); - - const QString filterQuery = filterlessQuery - + prepareFilterQuery(filterName); + return {}; + + const QString filterlessQuery = + "SELECT DISTINCT " + "NamespaceTable.Name, " + "FolderTable.Name, " + "ContentsTable.Data, " + "VersionTable.Version " + "FROM " + "FolderTable, " + "NamespaceTable, " + "ContentsTable, " + "VersionTable " + "WHERE ContentsTable.NamespaceId = NamespaceTable.Id " + "AND NamespaceTable.Id = FolderTable.NamespaceId " + "AND ContentsTable.NamespaceId = NamespaceTable.Id " + "AND VersionTable.NamespaceId = NamespaceTable.Id"_L1; + + const QString filterQuery = filterlessQuery + prepareFilterQuery(filterName); m_query->prepare(filterQuery); - bindFilterQuery(m_query, 0, filterName); + bindFilterQuery(m_query.get(), 0, filterName); m_query->exec(); @@ -1605,7 +1522,7 @@ QList<QHelpCollectionHandler::ContentsData> QHelpCollectionHandler::contentsForF } QList<QHelpCollectionHandler::ContentsData> result; - for (const auto &versionContents : qAsConst(contentsMap)) { + for (const auto &versionContents : std::as_const(contentsMap)) { // insert items in the reverse order of version number const auto itBegin = versionContents.constBegin(); auto it = versionContents.constEnd(); @@ -1614,7 +1531,6 @@ QList<QHelpCollectionHandler::ContentsData> QHelpCollectionHandler::contentsForF result.append(it.value()); } } - return result; } @@ -1623,7 +1539,7 @@ bool QHelpCollectionHandler::removeCustomValue(const QString &key) if (!isDBOpened()) return false; - m_query->prepare(QLatin1String("DELETE FROM SettingsTable WHERE Key=?")); + m_query->prepare("DELETE FROM SettingsTable WHERE Key=?"_L1); m_query->bindValue(0, key); return m_query->exec(); } @@ -1634,7 +1550,7 @@ QVariant QHelpCollectionHandler::customValue(const QString &key, if (!m_query) return defaultValue; - m_query->prepare(QLatin1String("SELECT COUNT(Key) FROM SettingsTable WHERE Key=?")); + m_query->prepare("SELECT COUNT(Key) FROM SettingsTable WHERE Key=?"_L1); m_query->bindValue(0, key); if (!m_query->exec() || !m_query->next() || !m_query->value(0).toInt()) { m_query->clear(); @@ -1642,14 +1558,13 @@ QVariant QHelpCollectionHandler::customValue(const QString &key, } m_query->clear(); - m_query->prepare(QLatin1String("SELECT Value FROM SettingsTable WHERE Key=?")); + m_query->prepare("SELECT Value FROM SettingsTable WHERE Key=?"_L1); m_query->bindValue(0, key); if (m_query->exec() && m_query->next()) { const QVariant &value = m_query->value(0); m_query->clear(); return value; } - return defaultValue; } @@ -1659,15 +1574,15 @@ bool QHelpCollectionHandler::setCustomValue(const QString &key, if (!isDBOpened()) return false; - m_query->prepare(QLatin1String("SELECT Value FROM SettingsTable WHERE Key=?")); + m_query->prepare("SELECT Value FROM SettingsTable WHERE Key=?"_L1); m_query->bindValue(0, key); m_query->exec(); if (m_query->next()) { - m_query->prepare(QLatin1String("UPDATE SettingsTable SET Value=? where Key=?")); + m_query->prepare("UPDATE SettingsTable SET Value=? where Key=?"_L1); m_query->bindValue(0, value); m_query->bindValue(1, key); } else { - m_query->prepare(QLatin1String("INSERT INTO SettingsTable VALUES(?, ?)")); + m_query->prepare("INSERT INTO SettingsTable VALUES(?, ?)"_L1); m_query->bindValue(0, key); m_query->bindValue(1, value); } @@ -1680,7 +1595,7 @@ bool QHelpCollectionHandler::registerFilterAttributes(const QList<QStringList> & if (!isDBOpened()) return false; - m_query->exec(QLatin1String("SELECT Name FROM FilterAttributeTable")); + m_query->exec("SELECT Name FROM FilterAttributeTable"_L1); QSet<QString> atts; while (m_query->next()) atts.insert(m_query->value(0).toString()); @@ -1688,7 +1603,7 @@ bool QHelpCollectionHandler::registerFilterAttributes(const QList<QStringList> & for (const QStringList &attributeSet : attributeSets) { for (const QString &attribute : attributeSet) { if (!atts.contains(attribute)) { - m_query->prepare(QLatin1String("INSERT INTO FilterAttributeTable VALUES(NULL, ?)")); + m_query->prepare("INSERT INTO FilterAttributeTable VALUES(NULL, ?)"_L1); m_query->bindValue(0, attribute); m_query->exec(); } @@ -1710,8 +1625,8 @@ bool QHelpCollectionHandler::registerFileAttributeSets(const QList<QStringList> QVariantList attributeSetIds; QVariantList filterAttributeIds; - if (!m_query->exec(QLatin1String("SELECT MAX(FilterAttributeSetId) FROM FileAttributeSetTable")) - || !m_query->next()) { + if (!m_query->exec("SELECT MAX(FilterAttributeSetId) FROM FileAttributeSetTable"_L1) + || !m_query->next()) { return false; } @@ -1721,8 +1636,7 @@ bool QHelpCollectionHandler::registerFileAttributeSets(const QList<QStringList> ++attributeSetId; for (const QString &attribute : attributeSet) { - - m_query->prepare(QLatin1String("SELECT Id FROM FilterAttributeTable WHERE Name=?")); + m_query->prepare("SELECT Id FROM FilterAttributeTable WHERE Name=?"_L1); m_query->bindValue(0, attribute); if (!m_query->exec() || !m_query->next()) @@ -1734,9 +1648,9 @@ bool QHelpCollectionHandler::registerFileAttributeSets(const QList<QStringList> } } - m_query->prepare(QLatin1String("INSERT INTO FileAttributeSetTable " - "(NamespaceId, FilterAttributeSetId, FilterAttributeId) " - "VALUES(?, ?, ?)")); + m_query->prepare("INSERT INTO FileAttributeSetTable " + "(NamespaceId, FilterAttributeSetId, FilterAttributeId) " + "VALUES(?, ?, ?)"_L1); m_query->addBindValue(nsIds); m_query->addBindValue(attributeSetIds); m_query->addBindValue(filterAttributeIds); @@ -1747,7 +1661,7 @@ QStringList QHelpCollectionHandler::filterAttributes() const { QStringList list; if (m_query) { - m_query->exec(QLatin1String("SELECT Name FROM FilterAttributeTable")); + m_query->exec("SELECT Name FROM FilterAttributeTable"_L1); while (m_query->next()) list.append(m_query->value(0).toString()); } @@ -1758,16 +1672,16 @@ QStringList QHelpCollectionHandler::filterAttributes(const QString &filterName) { QStringList list; if (m_query) { - m_query->prepare(QLatin1String( - "SELECT " - "FilterAttributeTable.Name " - "FROM " - "FilterAttributeTable, " - "FilterTable, " - "FilterNameTable " - "WHERE FilterAttributeTable.Id = FilterTable.FilterAttributeId " - "AND FilterTable.NameId = FilterNameTable.Id " - "AND FilterNameTable.Name=?")); + m_query->prepare( + "SELECT " + "FilterAttributeTable.Name " + "FROM " + "FilterAttributeTable, " + "FilterTable, " + "FilterNameTable " + "WHERE FilterAttributeTable.Id = FilterTable.FilterAttributeId " + "AND FilterTable.NameId = FilterNameTable.Id " + "AND FilterNameTable.Name=?"_L1); m_query->bindValue(0, filterName); m_query->exec(); while (m_query->next()) @@ -1778,25 +1692,25 @@ QStringList QHelpCollectionHandler::filterAttributes(const QString &filterName) QList<QStringList> QHelpCollectionHandler::filterAttributeSets(const QString &namespaceName) const { - QList<QStringList> result; if (!isDBOpened()) - return result; - - m_query->prepare(QLatin1String( - "SELECT " - "FileAttributeSetTable.FilterAttributeSetId, " - "FilterAttributeTable.Name " - "FROM " - "FileAttributeSetTable, " - "FilterAttributeTable, " - "NamespaceTable " - "WHERE FileAttributeSetTable.FilterAttributeId = FilterAttributeTable.Id " - "AND FileAttributeSetTable.NamespaceId = NamespaceTable.Id " - "AND NamespaceTable.Name = ? " - "ORDER BY FileAttributeSetTable.FilterAttributeSetId")); + return {}; + + m_query->prepare( + "SELECT " + "FileAttributeSetTable.FilterAttributeSetId, " + "FilterAttributeTable.Name " + "FROM " + "FileAttributeSetTable, " + "FilterAttributeTable, " + "NamespaceTable " + "WHERE FileAttributeSetTable.FilterAttributeId = FilterAttributeTable.Id " + "AND FileAttributeSetTable.NamespaceId = NamespaceTable.Id " + "AND NamespaceTable.Name = ? " + "ORDER BY FileAttributeSetTable.FilterAttributeSetId"_L1); m_query->bindValue(0, namespaceName); m_query->exec(); int oldId = -1; + QList<QStringList> result; while (m_query->next()) { const int id = m_query->value(0).toInt(); if (id != oldId) { @@ -1808,29 +1722,28 @@ QList<QStringList> QHelpCollectionHandler::filterAttributeSets(const QString &na if (result.isEmpty()) result.append(QStringList()); - return result; } QString QHelpCollectionHandler::namespaceVersion(const QString &namespaceName) const { if (!m_query) - return QString(); - - m_query->prepare(QLatin1String("SELECT " - "VersionTable.Version " - "FROM " - "NamespaceTable, " - "VersionTable " - "WHERE NamespaceTable.Name = ? " - "AND NamespaceTable.Id = VersionTable.NamespaceId")); + return {}; + + m_query->prepare( + "SELECT " + "VersionTable.Version " + "FROM " + "NamespaceTable, " + "VersionTable " + "WHERE NamespaceTable.Name = ? " + "AND NamespaceTable.Id = VersionTable.NamespaceId"_L1); m_query->bindValue(0, namespaceName); if (!m_query->exec() || !m_query->next()) - return QString(); + return {}; const QString ret = m_query->value(0).toString(); m_query->clear(); - return ret; } @@ -1840,7 +1753,7 @@ int QHelpCollectionHandler::registerNamespace(const QString &nspace, const QStri if (!m_query) return errorValue; - m_query->prepare(QLatin1String("SELECT COUNT(Id) FROM NamespaceTable WHERE Name=?")); + m_query->prepare("SELECT COUNT(Id) FROM NamespaceTable WHERE Name=?"_L1); m_query->bindValue(0, nspace); m_query->exec(); while (m_query->next()) { @@ -1851,7 +1764,7 @@ int QHelpCollectionHandler::registerNamespace(const QString &nspace, const QStri } QFileInfo fi(m_collectionFile); - m_query->prepare(QLatin1String("INSERT INTO NamespaceTable VALUES(NULL, ?, ?)")); + m_query->prepare("INSERT INTO NamespaceTable VALUES(NULL, ?, ?)"_L1); m_query->bindValue(0, nspace); m_query->bindValue(1, fi.absoluteDir().relativeFilePath(fileName)); int namespaceId = errorValue; @@ -1871,7 +1784,7 @@ int QHelpCollectionHandler::registerVirtualFolder(const QString &folderName, int if (!m_query) return false; - m_query->prepare(QLatin1String("INSERT INTO FolderTable VALUES(NULL, ?, ?)")); + m_query->prepare("INSERT INTO FolderTable VALUES(NULL, ?, ?)"_L1); m_query->bindValue(0, namespaceId); m_query->bindValue(1, folderName); @@ -1884,27 +1797,25 @@ int QHelpCollectionHandler::registerVirtualFolder(const QString &folderName, int emit error(tr("Cannot register virtual folder '%1'.").arg(folderName)); return -1; } - if (registerComponent(folderName, namespaceId) < 0) return -1; - return virtualId; } int QHelpCollectionHandler::registerComponent(const QString &componentName, int namespaceId) { - m_query->prepare(QLatin1String("SELECT ComponentId FROM ComponentTable WHERE Name = ?")); + m_query->prepare("SELECT ComponentId FROM ComponentTable WHERE Name = ?"_L1); m_query->bindValue(0, componentName); if (!m_query->exec()) return -1; if (!m_query->next()) { - m_query->prepare(QLatin1String("INSERT INTO ComponentTable VALUES(NULL, ?)")); + m_query->prepare("INSERT INTO ComponentTable VALUES(NULL, ?)"_L1); m_query->bindValue(0, componentName); if (!m_query->exec()) return -1; - m_query->prepare(QLatin1String("SELECT ComponentId FROM ComponentTable WHERE Name = ?")); + m_query->prepare("SELECT ComponentId FROM ComponentTable WHERE Name = ?"_L1); m_query->bindValue(0, componentName); if (!m_query->exec() || !m_query->next()) return -1; @@ -1912,7 +1823,7 @@ int QHelpCollectionHandler::registerComponent(const QString &componentName, int const int componentId = m_query->value(0).toInt(); - m_query->prepare(QLatin1String("INSERT INTO ComponentMapping VALUES(?, ?)")); + m_query->prepare("INSERT INTO ComponentMapping VALUES(?, ?)"_L1); m_query->bindValue(0, componentId); m_query->bindValue(1, namespaceId); if (!m_query->exec()) @@ -1926,9 +1837,7 @@ bool QHelpCollectionHandler::registerVersion(const QString &version, int namespa if (!m_query) return false; - m_query->prepare(QLatin1String("INSERT INTO VersionTable " - "(NamespaceId, Version) " - "VALUES(?, ?)")); + m_query->prepare("INSERT INTO VersionTable (NamespaceId, Version) VALUES(?, ?)"_L1); m_query->addBindValue(namespaceId); m_query->addBindValue(version); return m_query->exec(); @@ -1940,7 +1849,7 @@ bool QHelpCollectionHandler::registerIndexAndNamespaceFilterTables( if (!isDBOpened()) return false; - m_query->prepare(QLatin1String("SELECT Id, FilePath FROM NamespaceTable WHERE Name=?")); + m_query->prepare("SELECT Id, FilePath FROM NamespaceTable WHERE Name=?"_L1); m_query->bindValue(0, nameSpace); m_query->exec(); if (!m_query->next()) @@ -1949,7 +1858,7 @@ bool QHelpCollectionHandler::registerIndexAndNamespaceFilterTables( const int nsId = m_query->value(0).toInt(); const QString fileName = m_query->value(1).toString(); - m_query->prepare(QLatin1String("SELECT Id, Name FROM FolderTable WHERE NamespaceId=?")); + m_query->prepare("SELECT Id, Name FROM FolderTable WHERE NamespaceId=?"_L1); m_query->bindValue(0, nsId); m_query->exec(); if (!m_query->next()) @@ -1974,7 +1883,6 @@ bool QHelpCollectionHandler::registerIndexAndNamespaceFilterTables( if (createDefaultVersionFilter) createVersionFilter(reader.version()); - return true; } @@ -1992,7 +1900,7 @@ void QHelpCollectionHandler::createVersionFilter(const QString &version) return; QHelpFilterData filterData; - filterData.setVersions(QList<QVersionNumber>() << versionNumber); + filterData.setVersions({versionNumber}); setFilterData(filterName, filterData); } @@ -2011,7 +1919,7 @@ bool QHelpCollectionHandler::registerIndexTable(const QHelpDBReader::IndexTable fileNames.reserve(fileSize); fileTitles.reserve(fileSize); - if (!m_query->exec(QLatin1String("SELECT MAX(FileId) FROM FileNameTable")) || !m_query->next()) + if (!m_query->exec("SELECT MAX(FileId) FROM FileNameTable"_L1) || !m_query->next()) return false; const int maxFileId = m_query->value(0).toInt(); @@ -2027,7 +1935,7 @@ bool QHelpCollectionHandler::registerIndexTable(const QHelpDBReader::IndexTable ++newFileId; } - m_query->prepare(QLatin1String("INSERT INTO FileNameTable VALUES(?, ?, NULL, ?)")); + m_query->prepare("INSERT INTO FileNameTable VALUES(?, ?, NULL, ?)"_L1); m_query->addBindValue(fileFolderIds); m_query->addBindValue(fileNames); m_query->addBindValue(fileTitles); @@ -2037,7 +1945,7 @@ bool QHelpCollectionHandler::registerIndexTable(const QHelpDBReader::IndexTable for (auto it = filterAttributeToNewFileId.cbegin(), end = filterAttributeToNewFileId.cend(); it != end; ++it) { const QString filterAttribute = it.key(); - m_query->prepare(QLatin1String("SELECT Id From FilterAttributeTable WHERE Name = ?")); + m_query->prepare("SELECT Id From FilterAttributeTable WHERE Name = ?"_L1); m_query->bindValue(0, filterAttribute); if (!m_query->exec() || !m_query->next()) return false; @@ -2045,10 +1953,10 @@ bool QHelpCollectionHandler::registerIndexTable(const QHelpDBReader::IndexTable const int attributeId = m_query->value(0).toInt(); QVariantList attributeIds; - for (int i = 0; i < it.value().count(); i++) + for (int i = 0; i < it.value().size(); i++) attributeIds.append(attributeId); - m_query->prepare(QLatin1String("INSERT INTO FileFilterTable VALUES(?, ?)")); + m_query->prepare("INSERT INTO FileFilterTable VALUES(?, ?)"_L1); m_query->addBindValue(attributeIds); m_query->addBindValue(it.value()); if (!m_query->execBatch()) @@ -2057,7 +1965,7 @@ bool QHelpCollectionHandler::registerIndexTable(const QHelpDBReader::IndexTable QMap<QString, QVariantList> filterAttributeToNewIndexId; - if (!m_query->exec(QLatin1String("SELECT MAX(Id) FROM IndexTable")) || !m_query->next()) + if (!m_query->exec("SELECT MAX(Id) FROM IndexTable"_L1) || !m_query->next()) return false; const int maxIndexId = m_query->value(0).toInt(); @@ -2087,7 +1995,7 @@ bool QHelpCollectionHandler::registerIndexTable(const QHelpDBReader::IndexTable ++newIndexId; } - m_query->prepare(QLatin1String("INSERT INTO IndexTable VALUES(NULL, ?, ?, ?, ?, ?)")); + m_query->prepare("INSERT INTO IndexTable VALUES(NULL, ?, ?, ?, ?, ?)"_L1); m_query->addBindValue(indexNames); m_query->addBindValue(indexIdentifiers); m_query->addBindValue(indexNamespaceIds); @@ -2099,7 +2007,7 @@ bool QHelpCollectionHandler::registerIndexTable(const QHelpDBReader::IndexTable for (auto it = filterAttributeToNewIndexId.cbegin(), end = filterAttributeToNewIndexId.cend(); it != end; ++it) { const QString filterAttribute = it.key(); - m_query->prepare(QLatin1String("SELECT Id From FilterAttributeTable WHERE Name = ?")); + m_query->prepare("SELECT Id From FilterAttributeTable WHERE Name = ?"_L1); m_query->bindValue(0, filterAttribute); if (!m_query->exec() || !m_query->next()) return false; @@ -2107,10 +2015,10 @@ bool QHelpCollectionHandler::registerIndexTable(const QHelpDBReader::IndexTable const int attributeId = m_query->value(0).toInt(); QVariantList attributeIds; - for (int i = 0; i < it.value().count(); i++) + for (int i = 0; i < it.value().size(); i++) attributeIds.append(attributeId); - m_query->prepare(QLatin1String("INSERT INTO IndexFilterTable VALUES(?, ?)")); + m_query->prepare("INSERT INTO IndexFilterTable VALUES(?, ?)"_L1); m_query->addBindValue(attributeIds); m_query->addBindValue(it.value()); if (!m_query->execBatch()) @@ -2125,7 +2033,7 @@ bool QHelpCollectionHandler::registerIndexTable(const QHelpDBReader::IndexTable contentsNsIds.reserve(contentsSize); contentsData.reserve(contentsSize); - if (!m_query->exec(QLatin1String("SELECT MAX(Id) FROM ContentsTable")) || !m_query->next()) + if (!m_query->exec("SELECT MAX(Id) FROM ContentsTable"_L1) || !m_query->next()) return false; const int maxContentsId = m_query->value(0).toInt(); @@ -2142,7 +2050,7 @@ bool QHelpCollectionHandler::registerIndexTable(const QHelpDBReader::IndexTable ++newContentsId; } - m_query->prepare(QLatin1String("INSERT INTO ContentsTable VALUES(NULL, ?, ?)")); + m_query->prepare("INSERT INTO ContentsTable VALUES(NULL, ?, ?)"_L1); m_query->addBindValue(contentsNsIds); m_query->addBindValue(contentsData); if (!m_query->execBatch()) @@ -2151,7 +2059,7 @@ bool QHelpCollectionHandler::registerIndexTable(const QHelpDBReader::IndexTable for (auto it = filterAttributeToNewContentsId.cbegin(), end = filterAttributeToNewContentsId.cend(); it != end; ++it) { const QString filterAttribute = it.key(); - m_query->prepare(QLatin1String("SELECT Id From FilterAttributeTable WHERE Name = ?")); + m_query->prepare("SELECT Id From FilterAttributeTable WHERE Name = ?"_L1); m_query->bindValue(0, filterAttribute); if (!m_query->exec() || !m_query->next()) return false; @@ -2159,10 +2067,10 @@ bool QHelpCollectionHandler::registerIndexTable(const QHelpDBReader::IndexTable const int attributeId = m_query->value(0).toInt(); QVariantList attributeIds; - for (int i = 0; i < it.value().count(); i++) + for (int i = 0; i < it.value().size(); i++) attributeIds.append(attributeId); - m_query->prepare(QLatin1String("INSERT INTO ContentsFilterTable VALUES(?, ?)")); + m_query->prepare("INSERT INTO ContentsFilterTable VALUES(?, ?)"_L1); m_query->addBindValue(attributeIds); m_query->addBindValue(it.value()); if (!m_query->execBatch()) @@ -2174,7 +2082,7 @@ bool QHelpCollectionHandler::registerIndexTable(const QHelpDBReader::IndexTable for (const QString &filterAttribute : indexTable.usedFilterAttributes) { filterNsIds.append(nsId); - m_query->prepare(QLatin1String("SELECT Id From FilterAttributeTable WHERE Name = ?")); + m_query->prepare("SELECT Id From FilterAttributeTable WHERE Name = ?"_L1); m_query->bindValue(0, filterAttribute); if (!m_query->exec() || !m_query->next()) return false; @@ -2182,22 +2090,22 @@ bool QHelpCollectionHandler::registerIndexTable(const QHelpDBReader::IndexTable filterAttributeIds.append(m_query->value(0).toInt()); } - m_query->prepare(QLatin1String("INSERT INTO OptimizedFilterTable " - "(NamespaceId, FilterAttributeId) VALUES(?, ?)")); + m_query->prepare("INSERT INTO OptimizedFilterTable " + "(NamespaceId, FilterAttributeId) VALUES(?, ?)"_L1); m_query->addBindValue(filterNsIds); m_query->addBindValue(filterAttributeIds); if (!m_query->execBatch()) return false; - m_query->prepare(QLatin1String("INSERT INTO TimeStampTable " - "(NamespaceId, FolderId, FilePath, Size, TimeStamp) " - "VALUES(?, ?, ?, ?, ?)")); + m_query->prepare("INSERT INTO TimeStampTable " + "(NamespaceId, FolderId, FilePath, Size, TimeStamp) " + "VALUES(?, ?, ?, ?, ?)"_L1); m_query->addBindValue(nsId); m_query->addBindValue(vfId); m_query->addBindValue(fileName); const QFileInfo fi(absoluteDocPath(fileName)); m_query->addBindValue(fi.size()); - QDateTime lastModified = fi.lastModified(); + QDateTime lastModified = fi.lastModified(QTimeZone::UTC); if (qEnvironmentVariableIsSet("SOURCE_DATE_EPOCH")) { const QString sourceDateEpochStr = qEnvironmentVariable("SOURCE_DATE_EPOCH"); bool ok; @@ -2205,7 +2113,7 @@ bool QHelpCollectionHandler::registerIndexTable(const QHelpDBReader::IndexTable if (ok && sourceDateEpoch < lastModified.toSecsSinceEpoch()) lastModified.setSecsSinceEpoch(sourceDateEpoch); } - m_query->addBindValue(lastModified.toString(Qt::ISODate)); + m_query->addBindValue(lastModified); if (!m_query->exec()) return false; @@ -2215,60 +2123,60 @@ bool QHelpCollectionHandler::registerIndexTable(const QHelpDBReader::IndexTable bool QHelpCollectionHandler::unregisterIndexTable(int nsId, int vfId) { - m_query->prepare(QLatin1String("DELETE FROM IndexFilterTable WHERE IndexId IN " - "(SELECT Id FROM IndexTable WHERE NamespaceId = ?)")); + m_query->prepare("DELETE FROM IndexFilterTable WHERE IndexId IN " + "(SELECT Id FROM IndexTable WHERE NamespaceId = ?)"_L1); m_query->bindValue(0, nsId); if (!m_query->exec()) return false; - m_query->prepare(QLatin1String("DELETE FROM IndexTable WHERE NamespaceId = ?")); + m_query->prepare("DELETE FROM IndexTable WHERE NamespaceId = ?"_L1); m_query->bindValue(0, nsId); if (!m_query->exec()) return false; - m_query->prepare(QLatin1String("DELETE FROM FileFilterTable WHERE FileId IN " - "(SELECT FileId FROM FileNameTable WHERE FolderId = ?)")); + m_query->prepare("DELETE FROM FileFilterTable WHERE FileId IN " + "(SELECT FileId FROM FileNameTable WHERE FolderId = ?)"_L1); m_query->bindValue(0, vfId); if (!m_query->exec()) return false; - m_query->prepare(QLatin1String("DELETE FROM FileNameTable WHERE FolderId = ?")); + m_query->prepare("DELETE FROM FileNameTable WHERE FolderId = ?"_L1); m_query->bindValue(0, vfId); if (!m_query->exec()) return false; - m_query->prepare(QLatin1String("DELETE FROM ContentsFilterTable WHERE ContentsId IN " - "(SELECT Id FROM ContentsTable WHERE NamespaceId = ?)")); + m_query->prepare("DELETE FROM ContentsFilterTable WHERE ContentsId IN " + "(SELECT Id FROM ContentsTable WHERE NamespaceId = ?)"_L1); m_query->bindValue(0, nsId); if (!m_query->exec()) return false; - m_query->prepare(QLatin1String("DELETE FROM ContentsTable WHERE NamespaceId = ?")); + m_query->prepare("DELETE FROM ContentsTable WHERE NamespaceId = ?"_L1); m_query->bindValue(0, nsId); if (!m_query->exec()) return false; - m_query->prepare(QLatin1String("DELETE FROM FileAttributeSetTable WHERE NamespaceId = ?")); + m_query->prepare("DELETE FROM FileAttributeSetTable WHERE NamespaceId = ?"_L1); m_query->bindValue(0, nsId); if (!m_query->exec()) return false; - m_query->prepare(QLatin1String("DELETE FROM OptimizedFilterTable WHERE NamespaceId = ?")); + m_query->prepare("DELETE FROM OptimizedFilterTable WHERE NamespaceId = ?"_L1); m_query->bindValue(0, nsId); if (!m_query->exec()) return false; - m_query->prepare(QLatin1String("DELETE FROM TimeStampTable WHERE NamespaceId = ?")); + m_query->prepare("DELETE FROM TimeStampTable WHERE NamespaceId = ?"_L1); m_query->bindValue(0, nsId); if (!m_query->exec()) return false; - m_query->prepare(QLatin1String("DELETE FROM VersionTable WHERE NamespaceId = ?")); + m_query->prepare("DELETE FROM VersionTable WHERE NamespaceId = ?"_L1); m_query->bindValue(0, nsId); if (!m_query->exec()) return false; - m_query->prepare(QLatin1String("SELECT ComponentId FROM ComponentMapping WHERE NamespaceId = ?")); + m_query->prepare("SELECT ComponentId FROM ComponentMapping WHERE NamespaceId = ?"_L1); m_query->bindValue(0, nsId); if (!m_query->exec()) return false; @@ -2278,18 +2186,18 @@ bool QHelpCollectionHandler::unregisterIndexTable(int nsId, int vfId) const int componentId = m_query->value(0).toInt(); - m_query->prepare(QLatin1String("DELETE FROM ComponentMapping WHERE NamespaceId = ?")); + m_query->prepare("DELETE FROM ComponentMapping WHERE NamespaceId = ?"_L1); m_query->bindValue(0, nsId); if (!m_query->exec()) return false; - m_query->prepare(QLatin1String("SELECT ComponentId FROM ComponentMapping WHERE ComponentId = ?")); + m_query->prepare("SELECT ComponentId FROM ComponentMapping WHERE ComponentId = ?"_L1); m_query->bindValue(0, componentId); if (!m_query->exec()) return false; if (!m_query->next()) { // no more namespaces refer to the componentId - m_query->prepare(QLatin1String("DELETE FROM ComponentTable WHERE ComponentId = ?")); + m_query->prepare("DELETE FROM ComponentTable WHERE ComponentId = ?"_L1); m_query->bindValue(0, componentId); if (!m_query->exec()) return false; @@ -2298,102 +2206,67 @@ bool QHelpCollectionHandler::unregisterIndexTable(int nsId, int vfId) return true; } -static QUrl buildQUrl(const QString &ns, const QString &folder, - const QString &relFileName, const QString &anchor) +QUrl QHelpCollectionHandler::buildQUrl(const QString &ns, const QString &folder, + const QString &relFileName, const QString &anchor) { QUrl url; - url.setScheme(QLatin1String("qthelp")); + url.setScheme("qthelp"_L1); url.setAuthority(ns); - url.setPath(QLatin1Char('/') + folder + QLatin1Char('/') + relFileName); + url.setPath(u'/' + folder + u'/' + relFileName); url.setFragment(anchor); return url; } -QMultiMap<QString, QUrl> QHelpCollectionHandler::linksForIdentifier( - const QString &id, - const QStringList &filterAttributes) const -{ - return linksForField(QLatin1String("Identifier"), id, filterAttributes); -} - -QMultiMap<QString, QUrl> QHelpCollectionHandler::linksForKeyword( - const QString &keyword, - const QStringList &filterAttributes) const -{ - return linksForField(QLatin1String("Name"), keyword, filterAttributes); -} - QList<QHelpLink> QHelpCollectionHandler::documentsForIdentifier( - const QString &id, - const QStringList &filterAttributes) const + const QString &id, const QStringList &filterAttributes) const { - return documentsForField(QLatin1String("Identifier"), id, filterAttributes); + return documentsForField("Identifier"_L1, id, filterAttributes); } QList<QHelpLink> QHelpCollectionHandler::documentsForKeyword( - const QString &keyword, - const QStringList &filterAttributes) const -{ - return documentsForField(QLatin1String("Name"), keyword, filterAttributes); -} - -QMultiMap<QString, QUrl> QHelpCollectionHandler::linksForField( - const QString &fieldName, - const QString &fieldValue, - const QStringList &filterAttributes) const + const QString &keyword, const QStringList &filterAttributes) const { - QMultiMap<QString, QUrl> linkMap; - const auto documents = documentsForField(fieldName, fieldValue, filterAttributes); - for (const auto &document : documents) - linkMap.insert(document.title, document.url); - - return linkMap; + return documentsForField("Name"_L1, keyword, filterAttributes); } -QList<QHelpLink> QHelpCollectionHandler::documentsForField( - const QString &fieldName, - const QString &fieldValue, - const QStringList &filterAttributes) const +QList<QHelpLink> QHelpCollectionHandler::documentsForField(const QString &fieldName, + const QString &fieldValue, const QStringList &filterAttributes) const { - QList<QHelpLink> docList; - if (!isDBOpened()) - return docList; - - const QString filterlessQuery = QString::fromLatin1( - "SELECT " - "FileNameTable.Title, " - "NamespaceTable.Name, " - "FolderTable.Name, " - "FileNameTable.Name, " - "IndexTable.Anchor " - "FROM " - "IndexTable, " - "FileNameTable, " - "FolderTable, " - "NamespaceTable " - "WHERE IndexTable.FileId = FileNameTable.FileId " - "AND FileNameTable.FolderId = FolderTable.Id " - "AND IndexTable.NamespaceId = NamespaceTable.Id " - "AND IndexTable.%1 = ?").arg(fieldName); + return {}; + + const QString filterlessQuery = + "SELECT " + "FileNameTable.Title, " + "NamespaceTable.Name, " + "FolderTable.Name, " + "FileNameTable.Name, " + "IndexTable.Anchor " + "FROM " + "IndexTable, " + "FileNameTable, " + "FolderTable, " + "NamespaceTable " + "WHERE IndexTable.FileId = FileNameTable.FileId " + "AND FileNameTable.FolderId = FolderTable.Id " + "AND IndexTable.NamespaceId = NamespaceTable.Id " + "AND IndexTable.%1 = ?"_L1.arg(fieldName); const QString filterQuery = filterlessQuery - + prepareFilterQuery(filterAttributes.count(), - QLatin1String("IndexTable"), - QLatin1String("Id"), - QLatin1String("IndexFilterTable"), - QLatin1String("IndexId")); + + prepareFilterQuery(filterAttributes.size(), "IndexTable"_L1, "Id"_L1, + "IndexFilterTable"_L1, "IndexId"_L1); m_query->prepare(filterQuery); m_query->bindValue(0, fieldValue); - bindFilterQuery(m_query, 1, filterAttributes); + bindFilterQuery(m_query.get(), 1, filterAttributes); m_query->exec(); + QList<QHelpLink> docList; while (m_query->next()) { QString title = m_query->value(0).toString(); if (title.isEmpty()) // generate a title + corresponding path - title = fieldValue + QLatin1String(" : ") + m_query->value(3).toString(); + title = fieldValue + " : "_L1 + m_query->value(3).toString(); const QUrl url = buildQUrl(m_query->value(1).toString(), m_query->value(2).toString(), @@ -2404,88 +2277,66 @@ QList<QHelpLink> QHelpCollectionHandler::documentsForField( return docList; } -QMultiMap<QString, QUrl> QHelpCollectionHandler::linksForIdentifier( - const QString &id, - const QString &filterName) const -{ - return linksForField(QLatin1String("Identifier"), id, filterName); -} - -QMultiMap<QString, QUrl> QHelpCollectionHandler::linksForKeyword( - const QString &keyword, - const QString &filterName) const -{ - return linksForField(QLatin1String("Name"), keyword, filterName); -} - QList<QHelpLink> QHelpCollectionHandler::documentsForIdentifier( - const QString &id, - const QString &filterName) const + const QString &id, const QString &filterName) const { - return documentsForField(QLatin1String("Identifier"), id, filterName); + return documentsForField("Identifier"_L1, id, filterName); } QList<QHelpLink> QHelpCollectionHandler::documentsForKeyword( - const QString &keyword, - const QString &filterName) const + const QString &keyword, const QString &filterName) const { - return documentsForField(QLatin1String("Name"), keyword, filterName); + return documentsForField("Name"_L1, keyword, filterName); } -QMultiMap<QString, QUrl> QHelpCollectionHandler::linksForField( - const QString &fieldName, - const QString &fieldValue, - const QString &filterName) const +QMultiMap<QString, QUrl> QHelpCollectionHandler::linksForField(const QString &fieldName, + const QString &fieldValue, const QString &filterName) const { QMultiMap<QString, QUrl> linkMap; const auto documents = documentsForField(fieldName, fieldValue, filterName); for (const auto &document : documents) linkMap.insert(document.title, document.url); - return linkMap; } -QList<QHelpLink> QHelpCollectionHandler::documentsForField( - const QString &fieldName, - const QString &fieldValue, - const QString &filterName) const +QList<QHelpLink> QHelpCollectionHandler::documentsForField(const QString &fieldName, + const QString &fieldValue, const QString &filterName) const { - QList<QHelpLink> docList; - if (!isDBOpened()) - return docList; - - const QString filterlessQuery = QString::fromLatin1( - "SELECT " - "FileNameTable.Title, " - "NamespaceTable.Name, " - "FolderTable.Name, " - "FileNameTable.Name, " - "IndexTable.Anchor " - "FROM " - "IndexTable, " - "FileNameTable, " - "FolderTable, " - "NamespaceTable " - "WHERE IndexTable.FileId = FileNameTable.FileId " - "AND FileNameTable.FolderId = FolderTable.Id " - "AND IndexTable.NamespaceId = NamespaceTable.Id " - "AND IndexTable.%1 = ?").arg(fieldName); + return {}; + + const QString filterlessQuery = + "SELECT " + "FileNameTable.Title, " + "NamespaceTable.Name, " + "FolderTable.Name, " + "FileNameTable.Name, " + "IndexTable.Anchor " + "FROM " + "IndexTable, " + "FileNameTable, " + "FolderTable, " + "NamespaceTable " + "WHERE IndexTable.FileId = FileNameTable.FileId " + "AND FileNameTable.FolderId = FolderTable.Id " + "AND IndexTable.NamespaceId = NamespaceTable.Id " + "AND IndexTable.%1 = ?"_L1.arg(fieldName); const QString filterQuery = filterlessQuery + prepareFilterQuery(filterName) - + QLatin1String(" ORDER BY LOWER(FileNameTable.Title), FileNameTable.Title"); + + " ORDER BY LOWER(FileNameTable.Title), FileNameTable.Title"_L1; m_query->prepare(filterQuery); m_query->bindValue(0, fieldValue); - bindFilterQuery(m_query, 1, filterName); + bindFilterQuery(m_query.get(), 1, filterName); m_query->exec(); + QList<QHelpLink> docList; while (m_query->next()) { QString title = m_query->value(0).toString(); if (title.isEmpty()) // generate a title + corresponding path - title = fieldValue + QLatin1String(" : ") + m_query->value(3).toString(); + title = fieldValue + " : "_L1 + m_query->value(3).toString(); const QUrl url = buildQUrl(m_query->value(1).toString(), m_query->value(2).toString(), @@ -2503,30 +2354,24 @@ QStringList QHelpCollectionHandler::namespacesForFilter(const QString &filterNam if (!isDBOpened()) return namespaceList; - const QString filterlessQuery = QString::fromLatin1( - "SELECT " - "NamespaceTable.Name " - "FROM " - "NamespaceTable " - "WHERE TRUE"); + const QString filterlessQuery = + "SELECT " + "NamespaceTable.Name " + "FROM " + "NamespaceTable " + "WHERE TRUE"_L1; const QString filterQuery = filterlessQuery + prepareFilterQuery(filterName); m_query->prepare(filterQuery); - bindFilterQuery(m_query, 0, filterName); + bindFilterQuery(m_query.get(), 0, filterName); m_query->exec(); while (m_query->next()) namespaceList.append(m_query->value(0).toString()); - return namespaceList; } -void QHelpCollectionHandler::setReadOnly(bool readOnly) -{ - m_readOnly = readOnly; -} - QT_END_NAMESPACE diff --git a/src/assistant/help/qhelpcollectionhandler_p.h b/src/assistant/help/qhelpcollectionhandler_p.h index fb26aabb5..28f13e541 100644 --- a/src/assistant/help/qhelpcollectionhandler_p.h +++ b/src/assistant/help/qhelpcollectionhandler_p.h @@ -1,41 +1,5 @@ -/**************************************************************************** -** -** Copyright (C) 2016 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$ -** -****************************************************************************/ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only #ifndef QHELPCOLLECTIONHANDLER_H #define QHELPCOLLECTIONHANDLER_H @@ -51,21 +15,19 @@ // We mean it. // -#include <QtCore/QList> -#include <QtCore/QString> -#include <QtCore/QObject> -#include <QtCore/QVariant> -#include <QtCore/QStringList> - -#include <QtSql/QSqlQuery> - #include "qhelpdbreader_p.h" #include "qhelplink.h" +#include <QtCore/qdatetime.h> +#include <QtCore/qobject.h> +#include <QtCore/qstringlist.h> + QT_BEGIN_NAMESPACE -class QVersionNumber; class QHelpFilterData; +class QSqlQuery; +class QVariant; +class QVersionNumber; class QHelpCollectionHandler : public QObject { @@ -86,7 +48,7 @@ public: int folderId = -1; QString fileName; int size = 0; - QString timeStamp; + QDateTime timeStamp; }; struct ContentsData @@ -96,11 +58,10 @@ public: QList<QByteArray> contentsList; }; - explicit QHelpCollectionHandler(const QString &collectionFile, - QObject *parent = nullptr); + explicit QHelpCollectionHandler(const QString &collectionFile, QObject *parent = nullptr); ~QHelpCollectionHandler(); - QString collectionFile() const; + QString collectionFile() const { return m_collectionFile; } bool openCollectionFile(); bool copyCollectionFile(const QString &fileName); @@ -115,8 +76,7 @@ public: bool removeCustomFilter(const QString &filterName); // use QHelpFilterEngine::setFilterData() instead - bool addCustomFilter(const QString &filterName, - const QStringList &attributes); + bool addCustomFilter(const QString &filterName, const QStringList &attributes); // use files(const QString &, const QString &, const QString &) instead QStringList files(const QString &namespaceName, @@ -124,12 +84,10 @@ public: const QString &extensionFilter) const; // use namespaceForFile(const QUrl &, const QString &) instead - QString namespaceForFile(const QUrl &url, - const QStringList &filterAttributes) const; + QString namespaceForFile(const QUrl &url, const QStringList &filterAttributes) const; // use findFile(const QUrl &, const QString &) instead - QUrl findFile(const QUrl &url, - const QStringList &filterAttributes) const; + QUrl findFile(const QUrl &url, const QStringList &filterAttributes) const; // use indicesForFilter(const QString &) instead QStringList indicesForFilter(const QStringList &filterAttributes) const; @@ -146,20 +104,6 @@ public: // use filterData(const QString &) instead QList<QStringList> filterAttributeSets(const QString &namespaceName) const; - // use linksForIdentifier(const QString &, const QString &) instead - QMultiMap<QString, QUrl> linksForIdentifier(const QString &id, - const QStringList &filterAttributes) const; - - // use linksForKeyword(const QString &, const QString &) instead - QMultiMap<QString, QUrl> linksForKeyword(const QString &keyword, - const QStringList &filterAttributes) const; - - // use documentsForIdentifier instead - QMultiMap<QString, QUrl> linksForIdentifier(const QString &id, const QString &filterName) const; - - // use documentsForKeyword instead - QMultiMap<QString, QUrl> linksForKeyword(const QString &keyword, - const QString &filterName) const; // *** Legacy block end *** QStringList filters() const; @@ -172,24 +116,19 @@ public: bool setFilterData(const QString &filterName, const QHelpFilterData &filterData); bool removeFilter(const QString &filterName); - FileInfo registeredDocumentation(const QString &namespaceName) const; FileInfoList registeredDocumentations() const; bool registerDocumentation(const QString &fileName); bool unregisterDocumentation(const QString &namespaceName); - bool fileExists(const QUrl &url) const; QStringList files(const QString &namespaceName, const QString &filterName, const QString &extensionFilter) const; - QString namespaceForFile(const QUrl &url, - const QString &filterName) const; - QUrl findFile(const QUrl &url, - const QString &filterName) const; + QString namespaceForFile(const QUrl &url, const QString &filterName) const; + QUrl findFile(const QUrl &url, const QString &filterName) const; QByteArray fileData(const QUrl &url) const; - QStringList indicesForFilter(const QString &filterName) const; QList<ContentsData> contentsForFilter(const QString &filterName) const; @@ -197,16 +136,13 @@ public: QVariant customValue(const QString &key, const QVariant &defaultValue) const; bool setCustomValue(const QString &key, const QVariant &value); - int registerNamespace(const QString &nspace, const QString &fileName); int registerVirtualFolder(const QString &folderName, int namespaceId); int registerComponent(const QString &componentName, int namespaceId); bool registerVersion(const QString &version, int namespaceId); - QList<QHelpLink> documentsForIdentifier(const QString &id, - const QString &filterName) const; - QList<QHelpLink> documentsForKeyword(const QString &keyword, - const QString &filterName) const; + QList<QHelpLink> documentsForIdentifier(const QString &id, const QString &filterName) const; + QList<QHelpLink> documentsForKeyword(const QString &keyword, const QString &filterName) const; QList<QHelpLink> documentsForIdentifier(const QString &id, const QStringList &filterAttributes) const; QList<QHelpLink> documentsForKeyword(const QString &keyword, @@ -214,16 +150,16 @@ public: QStringList namespacesForFilter(const QString &filterName) const; - void setReadOnly(bool readOnly); + void setReadOnly(bool readOnly) { m_readOnly = readOnly; } + + static QUrl buildQUrl(const QString &ns, const QString &folder, + const QString &relFileName, const QString &anchor); signals: - void error(const QString &msg) const; + void error(const QString &msg); private: // legacy stuff - QMultiMap<QString, QUrl> linksForField(const QString &fieldName, - const QString &fieldValue, - const QStringList &filterAttributes) const; QList<QHelpLink> documentsForField(const QString &fieldName, const QString &fieldValue, const QStringList &filterAttributes) const; @@ -255,11 +191,11 @@ private: QString m_collectionFile; QString m_connectionName; - QSqlQuery *m_query = nullptr; + std::unique_ptr<QSqlQuery> m_query; bool m_vacuumScheduled = false; bool m_readOnly = true; }; QT_END_NAMESPACE -#endif //QHELPCOLLECTIONHANDLER_H +#endif // QHELPCOLLECTIONHANDLER_H diff --git a/src/assistant/help/qhelpcontentitem.cpp b/src/assistant/help/qhelpcontentitem.cpp new file mode 100644 index 000000000..3c437efe0 --- /dev/null +++ b/src/assistant/help/qhelpcontentitem.cpp @@ -0,0 +1,102 @@ +// Copyright (C) 2024 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#include "qhelpcontentitem.h" + +#include <QtCore/qstring.h> +#include <QtCore/qurl.h> + +QT_BEGIN_NAMESPACE + +class QHelpContentItemPrivate +{ +public: + QString title; + QUrl link; + QHelpContentItem *parent; + QList<QHelpContentItem *> childItems = {}; +}; + +/*! + \class QHelpContentItem + \inmodule QtHelp + \brief The QHelpContentItem class provides an item for use with QHelpContentModel. + \since 4.4 +*/ + +QHelpContentItem::QHelpContentItem(const QString &name, const QUrl &link, QHelpContentItem *parent) + : d(new QHelpContentItemPrivate{name, link, parent}) +{ + if (parent) + parent->d->childItems.append(this); +} + +/*! + Destroys the help content item. +*/ +QHelpContentItem::~QHelpContentItem() +{ + qDeleteAll(d->childItems); + delete d; +} + +/*! + Returns the child of the content item in the give \a row. + + \sa parent() +*/ +QHelpContentItem *QHelpContentItem::child(int row) const +{ + return d->childItems.value(row); +} + +/*! + Returns the number of child items. +*/ +int QHelpContentItem::childCount() const +{ + return d->childItems.size(); +} + +/*! + Returns the row of this item from its parents view. +*/ +int QHelpContentItem::row() const +{ + // TODO: Optimize by keeping the index internally. + return d->parent ? d->parent->d->childItems.indexOf(const_cast<QHelpContentItem*>(this)) : 0; +} + +/*! + Returns the title of the content item. +*/ +QString QHelpContentItem::title() const +{ + return d->title; +} + +/*! + Returns the URL of this content item. +*/ +QUrl QHelpContentItem::url() const +{ + return d->link; +} + +/*! + Returns the parent content item. +*/ +QHelpContentItem *QHelpContentItem::parent() const +{ + return d->parent; +} + +/*! + Returns the position of a given \a child. +*/ +int QHelpContentItem::childPosition(QHelpContentItem *child) const +{ + return d->childItems.indexOf(child); +} + +QT_END_NAMESPACE diff --git a/src/assistant/help/qhelpcontentitem.h b/src/assistant/help/qhelpcontentitem.h new file mode 100644 index 000000000..176ae05ed --- /dev/null +++ b/src/assistant/help/qhelpcontentitem.h @@ -0,0 +1,37 @@ +// Copyright (C) 2024 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#ifndef QHELPCONTENTITEM_H +#define QHELPCONTENTITEM_H + +#include <QtHelp/qhelp_global.h> + +QT_BEGIN_NAMESPACE + +class QHelpContentItemPrivate; +class QString; +class QUrl; + +class QHELP_EXPORT QHelpContentItem +{ +public: + ~QHelpContentItem(); + + QHelpContentItem *child(int row) const; + int childCount() const; + QString title() const; + QUrl url() const; + int row() const; + QHelpContentItem *parent() const; + int childPosition(QHelpContentItem *child) const; + +private: + QHelpContentItem(const QString &name, const QUrl &link, QHelpContentItem *parent = nullptr); + + QHelpContentItemPrivate *d; + friend QHelpContentItem *createContentItem(const QString &, const QUrl &, QHelpContentItem *); +}; + +QT_END_NAMESPACE + +#endif // QHELPCONTENTITEM_H diff --git a/src/assistant/help/qhelpcontentwidget.cpp b/src/assistant/help/qhelpcontentwidget.cpp index 5045f2750..24837611d 100644 --- a/src/assistant/help/qhelpcontentwidget.cpp +++ b/src/assistant/help/qhelpcontentwidget.cpp @@ -1,348 +1,79 @@ -/**************************************************************************** -** -** Copyright (C) 2016 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$ -** -****************************************************************************/ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only #include "qhelpcontentwidget.h" #include "qhelpenginecore.h" -#include "qhelpengine_p.h" -#include "qhelpcollectionhandler_p.h" -#include <QDir> -#include <QtCore/QStack> -#include <QtCore/QThread> -#include <QtCore/QMutex> -#include <QtWidgets/QHeaderView> +#if QT_CONFIG(future) +#include <QtCore/qfuturewatcher.h> +#endif -QT_BEGIN_NAMESPACE +#include <QtCore/qdir.h> +#include <QtWidgets/qheaderview.h> -class QHelpContentItemPrivate -{ -public: - QHelpContentItemPrivate(const QString &t, const QUrl &l, QHelpContentItem *p) - : parent(p), - title(t), - link(l) - { - } - - void appendChild(QHelpContentItem *item) { childItems.append(item); } +QT_BEGIN_NAMESPACE - QList<QHelpContentItem*> childItems; - QHelpContentItem *parent; - QString title; - QUrl link; -}; - -class QHelpContentProvider : public QThread -{ - Q_OBJECT -public: - QHelpContentProvider(QHelpEnginePrivate *helpEngine); - ~QHelpContentProvider() override; - void collectContents(const QString &customFilterName); - void stopCollecting(); - QHelpContentItem *takeContentItem(); - -private: - void run() override; - - QHelpEnginePrivate *m_helpEngine; - QString m_currentFilter; - QStringList m_filterAttributes; - QString m_collectionFile; - QHelpContentItem *m_rootItem = nullptr; - QMutex m_mutex; - bool m_usesFilterEngine = false; - bool m_abort = false; -}; +using namespace Qt::StringLiterals; class QHelpContentModelPrivate { -public: - QHelpContentItem *rootItem = nullptr; - QHelpContentProvider *qhelpContentProvider; -}; - +#if QT_CONFIG(future) + using ItemFutureProvider = std::function<QFuture<std::shared_ptr<QHelpContentItem>>()>; + struct WatcherDeleter + { + void operator()(QFutureWatcherBase *watcher) { + watcher->disconnect(); + watcher->cancel(); + watcher->waitForFinished(); + delete watcher; + } + }; +#endif -/*! - \class QHelpContentItem - \inmodule QtHelp - \brief The QHelpContentItem class provides an item for use with QHelpContentModel. - \since 4.4 -*/ - -QHelpContentItem::QHelpContentItem(const QString &name, const QUrl &link, QHelpContentItem *parent) -{ - d = new QHelpContentItemPrivate(name, link, parent); -} - -/*! - Destroys the help content item. -*/ -QHelpContentItem::~QHelpContentItem() -{ - qDeleteAll(d->childItems); - delete d; -} - -/*! - Returns the child of the content item in the give \a row. - - \sa parent() -*/ -QHelpContentItem *QHelpContentItem::child(int row) const -{ - return d->childItems.value(row); -} - -/*! - Returns the number of child items. -*/ -int QHelpContentItem::childCount() const -{ - return d->childItems.count(); -} - -/*! - Returns the row of this item from its parents view. -*/ -int QHelpContentItem::row() const -{ - if (d->parent) - return d->parent->d->childItems.indexOf(const_cast<QHelpContentItem*>(this)); - return 0; -} - -/*! - Returns the title of the content item. -*/ -QString QHelpContentItem::title() const -{ - return d->title; -} - -/*! - Returns the URL of this content item. -*/ -QUrl QHelpContentItem::url() const -{ - return d->link; -} - -/*! - Returns the parent content item. -*/ -QHelpContentItem *QHelpContentItem::parent() const -{ - return d->parent; -} - -/*! - Returns the position of a given \a child. -*/ -int QHelpContentItem::childPosition(QHelpContentItem *child) const -{ - return d->childItems.indexOf(child); -} - - - -QHelpContentProvider::QHelpContentProvider(QHelpEnginePrivate *helpEngine) - : QThread(helpEngine) -{ - m_helpEngine = helpEngine; -} - -QHelpContentProvider::~QHelpContentProvider() -{ - stopCollecting(); -} - -void QHelpContentProvider::collectContents(const QString &customFilterName) -{ - m_mutex.lock(); - m_currentFilter = customFilterName; - m_filterAttributes = m_helpEngine->q->filterAttributes(customFilterName); - m_collectionFile = m_helpEngine->collectionHandler->collectionFile(); - m_usesFilterEngine = m_helpEngine->usesFilterEngine; - m_mutex.unlock(); - - if (isRunning()) - stopCollecting(); - start(LowPriority); -} - -void QHelpContentProvider::stopCollecting() -{ - if (isRunning()) { - m_mutex.lock(); - m_abort = true; - m_mutex.unlock(); - wait(); - // we need to force-set m_abort to false, because the thread might either have - // finished between the isRunning() check and the "m_abort = true" above, or the - // isRunning() check might already happen after the "m_abort = false" in the run() method, - // either way never resetting m_abort to false from within the run() method - m_abort = false; - } - delete m_rootItem; - m_rootItem = nullptr; -} - -QHelpContentItem *QHelpContentProvider::takeContentItem() -{ - QMutexLocker locker(&m_mutex); - QHelpContentItem *content = m_rootItem; - m_rootItem = nullptr; - return content; -} - -// TODO: this is a copy from helpcollectionhandler, make it common -static QUrl buildQUrl(const QString &ns, const QString &folder, - const QString &relFileName, const QString &anchor) -{ - QUrl url; - url.setScheme(QLatin1String("qthelp")); - url.setAuthority(ns); - url.setPath(QLatin1Char('/') + folder + QLatin1Char('/') + relFileName); - url.setFragment(anchor); - return url; -} - -static QUrl constructUrl(const QString &namespaceName, - const QString &folderName, - const QString &relativePath) -{ - const int idx = relativePath.indexOf(QLatin1Char('#')); - const QString &rp = idx < 0 ? relativePath : relativePath.left(idx); - const QString anchor = idx < 0 ? QString() : relativePath.mid(idx + 1); - return buildQUrl(namespaceName, folderName, rp, anchor); -} +public: +#if QT_CONFIG(future) + void createContents(const ItemFutureProvider &futureProvider); +#endif + + QHelpContentModel *q = nullptr; + QHelpEngineCore *helpEngine = nullptr; + std::shared_ptr<QHelpContentItem> rootItem = {}; +#if QT_CONFIG(future) + std::unique_ptr<QFutureWatcher<std::shared_ptr<QHelpContentItem>>, WatcherDeleter> watcher = {}; +#endif +}; -void QHelpContentProvider::run() -{ - m_mutex.lock(); - const QString currentFilter = m_currentFilter; - const QStringList attributes = m_filterAttributes; - const QString collectionFile = m_collectionFile; - const bool usesFilterEngine = m_usesFilterEngine; - delete m_rootItem; - m_rootItem = nullptr; - m_mutex.unlock(); - - if (collectionFile.isEmpty()) - return; +#if QT_CONFIG(future) +void QHelpContentModelPrivate::createContents(const ItemFutureProvider &futureProvider) +{ + const bool wasRunning = bool(watcher); + watcher.reset(new QFutureWatcher<std::shared_ptr<QHelpContentItem>>); + QObject::connect(watcher.get(), &QFutureWatcherBase::finished, q, [this] { + if (!watcher->isCanceled()) { + const std::shared_ptr<QHelpContentItem> result = watcher->result(); + if (result && result.get()) { + q->beginResetModel(); + rootItem = result; + q->endResetModel(); + } + } + watcher.release()->deleteLater(); + emit q->contentsCreated(); + }); + watcher->setFuture(futureProvider()); - QHelpCollectionHandler collectionHandler(collectionFile); - if (!collectionHandler.openCollectionFile()) + if (wasRunning) return; - QString title; - QString link; - int depth = 0; - QHelpContentItem *item = nullptr; - QHelpContentItem * const rootItem = new QHelpContentItem(QString(), QString(), nullptr); - - const QList<QHelpCollectionHandler::ContentsData> result = usesFilterEngine - ? collectionHandler.contentsForFilter(currentFilter) - : collectionHandler.contentsForFilter(attributes); - - for (const auto &contentsData : result) { - m_mutex.lock(); - if (m_abort) { - delete rootItem; - m_abort = false; - m_mutex.unlock(); - return; - } - m_mutex.unlock(); - - const QString namespaceName = contentsData.namespaceName; - const QString folderName = contentsData.folderName; - for (const QByteArray &contents : contentsData.contentsList) { - if (contents.size() < 1) - continue; - - int _depth = 0; - bool _root = false; - QStack<QHelpContentItem*> stack; - - QDataStream s(contents); - for (;;) { - s >> depth; - s >> link; - s >> title; - if (title.isEmpty()) - break; - const QUrl url = constructUrl(namespaceName, folderName, link); -CHECK_DEPTH: - if (depth == 0) { - m_mutex.lock(); - item = new QHelpContentItem(title, url, rootItem); - rootItem->d->appendChild(item); - m_mutex.unlock(); - stack.push(item); - _depth = 1; - _root = true; - } else { - if (depth > _depth && _root) { - _depth = depth; - stack.push(item); - } - if (depth == _depth) { - item = new QHelpContentItem(title, url, stack.top()); - stack.top()->d->appendChild(item); - } else if (depth < _depth) { - stack.pop(); - --_depth; - goto CHECK_DEPTH; - } - } - } - } + if (rootItem) { + q->beginResetModel(); + rootItem.reset(); + q->endResetModel(); } - - m_mutex.lock(); - m_rootItem = rootItem; - m_abort = false; - m_mutex.unlock(); + emit q->contentsCreationStarted(); } +#endif /*! \class QHelpContentModel @@ -367,67 +98,57 @@ CHECK_DEPTH: This signal is emitted when the contents have been created. */ -QHelpContentModel::QHelpContentModel(QHelpEnginePrivate *helpEngine) +QHelpContentModel::QHelpContentModel(QHelpEngineCore *helpEngine) : QAbstractItemModel(helpEngine) -{ - d = new QHelpContentModelPrivate(); - d->qhelpContentProvider = new QHelpContentProvider(helpEngine); - - connect(d->qhelpContentProvider, &QThread::finished, - this, &QHelpContentModel::insertContents); -} + , d(new QHelpContentModelPrivate{this, helpEngine}) +{} /*! Destroys the help content model. */ QHelpContentModel::~QHelpContentModel() { - delete d->rootItem; delete d; } /*! - Creates new contents by querying the help system - for contents specified for the \a customFilterName. + \since 6.8 + + Creates new contents by querying the help system for contents specified for the current filter. */ -void QHelpContentModel::createContents(const QString &customFilterName) +void QHelpContentModel::createContentsForCurrentFilter() { - const bool running = d->qhelpContentProvider->isRunning(); - d->qhelpContentProvider->collectContents(customFilterName); - if (running) - return; - - if (d->rootItem) { - beginResetModel(); - delete d->rootItem; - d->rootItem = nullptr; - endResetModel(); - } - emit contentsCreationStarted(); +#if QT_CONFIG(future) + d->createContents([this] { return d->helpEngine->requestContentForCurrentFilter(); }); +#endif } -void QHelpContentModel::insertContents() +/*! + Creates new contents by querying the help system + for contents specified for the custom \a filter name. +*/ +void QHelpContentModel::createContents(const QString &filter) { - if (d->qhelpContentProvider->isRunning()) - return; - - QHelpContentItem * const newRootItem = d->qhelpContentProvider->takeContentItem(); - if (!newRootItem) - return; - beginResetModel(); - delete d->rootItem; - d->rootItem = newRootItem; - endResetModel(); - emit contentsCreated(); +#if QT_CONFIG(future) + d->createContents([this, filter] { return d->helpEngine->requestContent(filter); }); +#endif } +// TODO: Remove me +void QHelpContentModel::insertContents() +{} + /*! Returns true if the contents are currently rebuilt, otherwise false. */ bool QHelpContentModel::isCreatingContents() const { - return d->qhelpContentProvider->isRunning(); +#if QT_CONFIG(future) + return bool(d->watcher); +#else + return false; +#endif } /*! @@ -436,10 +157,8 @@ bool QHelpContentModel::isCreatingContents() const */ QHelpContentItem *QHelpContentModel::contentItemAt(const QModelIndex &index) const { - if (index.isValid()) - return static_cast<QHelpContentItem*>(index.internalPointer()); - else - return d->rootItem; + return index.isValid() ? static_cast<QHelpContentItem *>(index.internalPointer()) + : d->rootItem.get(); } /*! @@ -449,12 +168,12 @@ QHelpContentItem *QHelpContentModel::contentItemAt(const QModelIndex &index) con QModelIndex QHelpContentModel::index(int row, int column, const QModelIndex &parent) const { if (!d->rootItem) - return QModelIndex(); + return {}; QHelpContentItem *parentItem = contentItemAt(parent); QHelpContentItem *item = parentItem->child(row); if (!item) - return QModelIndex(); + return {}; return createIndex(row, column, item); } @@ -466,17 +185,17 @@ QModelIndex QHelpContentModel::parent(const QModelIndex &index) const { QHelpContentItem *item = contentItemAt(index); if (!item) - return QModelIndex(); + return {}; QHelpContentItem *parentItem = static_cast<QHelpContentItem*>(item->parent()); if (!parentItem) - return QModelIndex(); + return {}; QHelpContentItem *grandparentItem = static_cast<QHelpContentItem*>(parentItem->parent()); if (!grandparentItem) - return QModelIndex(); + return {}; - int row = grandparentItem->childPosition(parentItem); + const int row = grandparentItem->childPosition(parentItem); return createIndex(row, index.column(), parentItem); } @@ -486,9 +205,9 @@ QModelIndex QHelpContentModel::parent(const QModelIndex &index) const int QHelpContentModel::rowCount(const QModelIndex &parent) const { QHelpContentItem *parentItem = contentItemAt(parent); - if (!parentItem) - return 0; - return parentItem->childCount(); + if (parentItem) + return parentItem->childCount(); + return 0; } /*! @@ -497,7 +216,6 @@ int QHelpContentModel::rowCount(const QModelIndex &parent) const int QHelpContentModel::columnCount(const QModelIndex &parent) const { Q_UNUSED(parent); - return 1; } @@ -507,17 +225,14 @@ int QHelpContentModel::columnCount(const QModelIndex &parent) const */ QVariant QHelpContentModel::data(const QModelIndex &index, int role) const { - if (role != Qt::DisplayRole) - return QVariant(); - - QHelpContentItem *item = contentItemAt(index); - if (!item) - return QVariant(); - return item->title(); + if (role == Qt::DisplayRole) { + QHelpContentItem *item = contentItemAt(index); + if (item) + return item->title(); + } + return {}; } - - /*! \class QHelpContentWidget \inmodule QtHelp @@ -533,12 +248,10 @@ QVariant QHelpContentModel::data(const QModelIndex &index, int role) const */ QHelpContentWidget::QHelpContentWidget() - : QTreeView(nullptr) { header()->hide(); setUniformRowHeights(true); - connect(this, &QAbstractItemView::activated, - this, &QHelpContentWidget::showLink); + connect(this, &QAbstractItemView::activated, this, &QHelpContentWidget::showLink); } /*! @@ -548,10 +261,10 @@ QHelpContentWidget::QHelpContentWidget() QModelIndex QHelpContentWidget::indexOf(const QUrl &link) { QHelpContentModel *contentModel = qobject_cast<QHelpContentModel*>(model()); - if (!contentModel || link.scheme() != QLatin1String("qthelp")) - return QModelIndex(); + if (!contentModel || link.scheme() != "qthelp"_L1) + return {}; - m_syncIndex = QModelIndex(); + m_syncIndex = {}; for (int i = 0; i < contentModel->rowCount(); ++i) { QHelpContentItem *itm = contentModel->contentItemAt(contentModel->index(i, 0)); if (itm && itm->url().host() == link.host()) { @@ -559,11 +272,11 @@ QModelIndex QHelpContentWidget::indexOf(const QUrl &link) return m_syncIndex; } } - return QModelIndex(); + return {}; } bool QHelpContentWidget::searchContentItem(QHelpContentModel *model, const QModelIndex &parent, - const QString &cleanPath) + const QString &cleanPath) { QHelpContentItem *parentItem = model->contentItemAt(parent); if (!parentItem) @@ -596,5 +309,3 @@ void QHelpContentWidget::showLink(const QModelIndex &index) } QT_END_NAMESPACE - -#include "qhelpcontentwidget.moc" diff --git a/src/assistant/help/qhelpcontentwidget.h b/src/assistant/help/qhelpcontentwidget.h index b316ebba9..cf9668835 100644 --- a/src/assistant/help/qhelpcontentwidget.h +++ b/src/assistant/help/qhelpcontentwidget.h @@ -1,80 +1,19 @@ -/**************************************************************************** -** -** Copyright (C) 2016 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$ -** -****************************************************************************/ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only #ifndef QHELPCONTENTWIDGET_H #define QHELPCONTENTWIDGET_H #include <QtHelp/qhelp_global.h> - -#include <QtCore/QQueue> -#include <QtCore/QString> -#include <QtWidgets/QTreeView> +#include <QtHelp/qhelpcontentitem.h> +#include <QtWidgets/qtreeview.h> QT_BEGIN_NAMESPACE - -class QHelpEnginePrivate; -class QHelpContentItemPrivate; class QHelpContentModelPrivate; class QHelpEngine; -class QHelpContentProvider; - -class QHELP_EXPORT QHelpContentItem -{ -public: - ~QHelpContentItem(); - - QHelpContentItem *child(int row) const; - int childCount() const; - QString title() const; - QUrl url() const; - int row() const; - QHelpContentItem *parent() const; - int childPosition(QHelpContentItem *child) const; - -private: - QHelpContentItem(const QString &name, const QUrl &link, - QHelpContentItem *parent = nullptr); - - QHelpContentItemPrivate *d; - friend class QHelpContentProvider; -}; +class QHelpEngineCore; +class QUrl; class QHELP_EXPORT QHelpContentModel : public QAbstractItemModel { @@ -83,15 +22,15 @@ class QHELP_EXPORT QHelpContentModel : public QAbstractItemModel public: ~QHelpContentModel() override; + void createContentsForCurrentFilter(); void createContents(const QString &customFilterName); QHelpContentItem *contentItemAt(const QModelIndex &index) const; QVariant data(const QModelIndex &index, int role) const override; - QModelIndex index(int row, int column, - const QModelIndex &parent = QModelIndex()) const override; + QModelIndex index(int row, int column, const QModelIndex &parent = {}) const override; QModelIndex parent(const QModelIndex &index) const override; - int rowCount(const QModelIndex &parent = QModelIndex()) const override; - int columnCount(const QModelIndex &parent = QModelIndex()) const override; + int rowCount(const QModelIndex &parent = {}) const override; + int columnCount(const QModelIndex &parent = {}) const override; bool isCreatingContents() const; Q_SIGNALS: @@ -102,9 +41,10 @@ private Q_SLOTS: void insertContents(); private: - QHelpContentModel(QHelpEnginePrivate *helpEngine); + QHelpContentModel(QHelpEngineCore *helpEngine); QHelpContentModelPrivate *d; friend class QHelpEnginePrivate; + friend class QHelpContentModelPrivate; }; class QHELP_EXPORT QHelpContentWidget : public QTreeView @@ -121,8 +61,8 @@ private Q_SLOTS: void showLink(const QModelIndex &index); private: - bool searchContentItem(QHelpContentModel *model, - const QModelIndex &parent, const QString &path); + bool searchContentItem(QHelpContentModel *model, const QModelIndex &parent, + const QString &path); QModelIndex m_syncIndex; private: @@ -132,5 +72,4 @@ private: QT_END_NAMESPACE -#endif - +#endif // QHELPCONTENTWIDGET_H diff --git a/src/assistant/help/qhelpdbreader.cpp b/src/assistant/help/qhelpdbreader.cpp index 2d99a2a3c..cfe1b6839 100644 --- a/src/assistant/help/qhelpdbreader.cpp +++ b/src/assistant/help/qhelpdbreader.cpp @@ -1,75 +1,35 @@ -/**************************************************************************** -** -** Copyright (C) 2016 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$ -** -****************************************************************************/ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only #include "qhelpdbreader_p.h" #include "qhelp_global.h" -#include <QtCore/QFile> -#include <QtCore/QList> -#include <QtCore/QVariant> -#include <QtSql/QSqlError> -#include <QtSql/QSqlQuery> +#include <QtCore/qfile.h> +#include <QtCore/qmap.h> +#include <QtCore/qvariant.h> +#include <QtSql/qsqldatabase.h> +#include <QtSql/qsqlerror.h> +#include <QtSql/qsqlquery.h> QT_BEGIN_NAMESPACE +using namespace Qt::StringLiterals; + QHelpDBReader::QHelpDBReader(const QString &dbName) - : QObject(nullptr), - m_dbName(dbName), - m_uniqueId(QHelpGlobal::uniquifyConnectionName(QLatin1String("QHelpDBReader"), - this)) -{ -} + : m_dbName(dbName) + , m_uniqueId(QHelpGlobal::uniquifyConnectionName("QHelpDBReader"_L1, this)) +{} -QHelpDBReader::QHelpDBReader(const QString &dbName, const QString &uniqueId, - QObject *parent) - : QObject(parent), - m_dbName(dbName), - m_uniqueId(uniqueId) -{ -} +QHelpDBReader::QHelpDBReader(const QString &dbName, const QString &uniqueId, QObject *parent) + : QObject(parent) + , m_dbName(dbName) + , m_uniqueId(uniqueId) +{} QHelpDBReader::~QHelpDBReader() { - if (m_initDone) { - delete m_query; + if (m_initDone) QSqlDatabase::removeDatabase(m_uniqueId); - } } bool QHelpDBReader::init() @@ -86,15 +46,14 @@ bool QHelpDBReader::init() } m_initDone = true; - m_query = new QSqlQuery(QSqlDatabase::database(m_uniqueId)); - + m_query.reset(new QSqlQuery(QSqlDatabase::database(m_uniqueId))); return true; } bool QHelpDBReader::initDB() { - QSqlDatabase db = QSqlDatabase::addDatabase(QLatin1String("QSQLITE"), m_uniqueId); - db.setConnectOptions(QLatin1String("QSQLITE_OPEN_READONLY")); + QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE"_L1, m_uniqueId); + db.setConnectOptions("QSQLITE_OPEN_READONLY"_L1); db.setDatabaseName(m_dbName); if (!db.open()) { /*: The placeholders are: %1 - The name of the database which cannot be opened @@ -111,7 +70,7 @@ QString QHelpDBReader::namespaceName() const if (!m_namespace.isEmpty()) return m_namespace; if (m_query) { - m_query->exec(QLatin1String("SELECT Name FROM NamespaceTable")); + m_query->exec("SELECT Name FROM NamespaceTable"_L1); if (m_query->next()) m_namespace = m_query->value(0).toString(); } @@ -121,16 +80,16 @@ QString QHelpDBReader::namespaceName() const QString QHelpDBReader::virtualFolder() const { if (m_query) { - m_query->exec(QLatin1String("SELECT Name FROM FolderTable WHERE Id=1")); + m_query->exec("SELECT Name FROM FolderTable WHERE Id=1"_L1); if (m_query->next()) return m_query->value(0).toString(); } - return QString(); + return {}; } QString QHelpDBReader::version() const { - const QString versionString = metaData(QLatin1String("version")).toString(); + const QString versionString = metaData("version"_L1).toString(); if (versionString.isEmpty()) return qtVersionHeuristic(); return versionString; @@ -139,14 +98,14 @@ QString QHelpDBReader::version() const QString QHelpDBReader::qtVersionHeuristic() const { const QString nameSpace = namespaceName(); - if (!nameSpace.startsWith(QLatin1String("org.qt-project."))) - return QString(); + if (!nameSpace.startsWith("org.qt-project."_L1)) + return {}; // We take the namespace tail, starting from the last letter in namespace name. // We drop any non digit characters. - const QChar dot(QLatin1Char('.')); + const QChar dot(u'.'); QString tail; - for (int i = nameSpace.count(); i > 0; --i) { + for (int i = nameSpace.size(); i > 0; --i) { const QChar c = nameSpace.at(i - 1); if (c.isDigit() || c == dot) tail.prepend(c); @@ -172,30 +131,29 @@ QString QHelpDBReader::qtVersionHeuristic() const tail.chop(1); if (tail.count(dot) == 0) { - if (tail.count() > 5) + if (tail.size() > 5) return tail; // When we have 3 digits, we split it like: ABC -> A.B.C // When we have 4 digits, we split it like: ABCD -> A.BC.D // When we have 5 digits, we split it like: ABCDE -> A.BC.DE const int major = tail.left(1).toInt(); - const int minor = tail.count() == 3 + const int minor = tail.size() == 3 ? tail.mid(1, 1).toInt() : tail.mid(1, 2).toInt(); - const int patch = tail.count() == 5 + const int patch = tail.size() == 5 ? tail.right(2).toInt() : tail.right(1).toInt(); return QString::fromUtf8("%1.%2.%3").arg(major).arg(minor).arg(patch); } - return tail; } static bool isAttributeUsed(QSqlQuery *query, const QString &tableName, int attributeId) { query->prepare(QString::fromLatin1("SELECT FilterAttributeId " - "FROM %1 " - "WHERE FilterAttributeId = ? " - "LIMIT 1").arg(tableName)); + "FROM %1 " + "WHERE FilterAttributeId = ? " + "LIMIT 1").arg(tableName)); query->bindValue(0, attributeId); query->exec(); return query->next(); // if we got a result it means it was used @@ -204,7 +162,7 @@ static bool isAttributeUsed(QSqlQuery *query, const QString &tableName, int attr static int filterDataCount(QSqlQuery *query, const QString &tableName) { query->exec(QString::fromLatin1("SELECT COUNT(*) FROM" - "(SELECT DISTINCT * FROM %1)").arg(tableName)); + "(SELECT DISTINCT * FROM %1)").arg(tableName)); query->next(); return query->value(0).toInt(); } @@ -216,7 +174,7 @@ QHelpDBReader::IndexTable QHelpDBReader::indexTable() const return table; QMap<int, QString> attributeIds; - m_query->exec(QLatin1String("SELECT DISTINCT Id, Name FROM FilterAttributeTable ORDER BY Id")); + m_query->exec("SELECT DISTINCT Id, Name FROM FilterAttributeTable ORDER BY Id"_L1); while (m_query->next()) attributeIds.insert(m_query->value(0).toInt(), m_query->value(1).toString()); @@ -225,27 +183,22 @@ QHelpDBReader::IndexTable QHelpDBReader::indexTable() const QList<int> usedAttributeIds; for (auto it = attributeIds.cbegin(), end = attributeIds.cend(); it != end; ++it) { const int attributeId = it.key(); - if (isAttributeUsed(m_query, QLatin1String("IndexFilterTable"), attributeId) - || isAttributeUsed(m_query, QLatin1String("ContentsFilterTable"), attributeId) - || isAttributeUsed(m_query, QLatin1String("FileFilterTable"), attributeId)) { + if (isAttributeUsed(m_query.get(), "IndexFilterTable"_L1, attributeId) + || isAttributeUsed(m_query.get(), "ContentsFilterTable"_L1, attributeId) + || isAttributeUsed(m_query.get(), "FileFilterTable"_L1, attributeId)) { usedAttributeIds.append(attributeId); } } bool legacy = false; - m_query->exec(QLatin1String("SELECT * FROM pragma_table_info('IndexTable') " - "WHERE name='ContextName'")); + m_query->exec("SELECT * FROM pragma_table_info('IndexTable') WHERE name='ContextName'"_L1); if (m_query->next()) legacy = true; - const QString identifierColumnName = legacy - ? QLatin1String("ContextName") - : QLatin1String("Identifier"); - - const int usedAttributeCount = usedAttributeIds.count(); + const QString identifierColumnName = legacy ? "ContextName"_L1 : "Identifier"_L1; + const int usedAttributeCount = usedAttributeIds.size(); QMap<int, IndexItem> idToIndexItem; - m_query->exec(QString::fromLatin1("SELECT Name, %1, FileId, Anchor, Id " "FROM IndexTable " "ORDER BY Id").arg(identifierColumnName)); @@ -264,13 +217,14 @@ QHelpDBReader::IndexTable QHelpDBReader::indexTable() const QMap<int, int> originalFileIdToNewFileId; int filesCount = 0; - m_query->exec(QLatin1String("SELECT " - "FileNameTable.FileId, " - "FileNameTable.Name, " - "FileNameTable.Title " - "FROM FileNameTable, FolderTable " - "WHERE FileNameTable.FolderId = FolderTable.Id " - "ORDER BY FileId")); + m_query->exec( + "SELECT " + "FileNameTable.FileId, " + "FileNameTable.Name, " + "FileNameTable.Title " + "FROM FileNameTable, FolderTable " + "WHERE FileNameTable.FolderId = FolderTable.Id " + "ORDER BY FileId"_L1); while (m_query->next()) { const int fileId = m_query->value(0).toInt(); FileItem fileItem; @@ -284,9 +238,7 @@ QHelpDBReader::IndexTable QHelpDBReader::indexTable() const QMap<int, ContentsItem> idToContentsItem; - m_query->exec(QLatin1String("SELECT Data, Id " - "FROM ContentsTable " - "ORDER BY Id")); + m_query->exec("SELECT Data, Id FROM ContentsTable ORDER BY Id"_L1); while (m_query->next()) { ContentsItem contentsItem; contentsItem.data = m_query->value(0).toByteArray(); @@ -306,27 +258,25 @@ QHelpDBReader::IndexTable QHelpDBReader::indexTable() const // which we want to optimize). The same with FileNameTable and // FileFilterTable. - const bool mayOptimizeIndexTable - = filterDataCount(m_query, QLatin1String("IndexFilterTable")) - == idToIndexItem.count() * usedAttributeCount; - const bool mayOptimizeFileTable - = filterDataCount(m_query, QLatin1String("FileFilterTable")) - == idToFileItem.count() * usedAttributeCount; - const bool mayOptimizeContentsTable - = filterDataCount(m_query, QLatin1String("ContentsFilterTable")) - == idToContentsItem.count() * usedAttributeCount; + const bool mayOptimizeIndexTable = filterDataCount(m_query.get(), "IndexFilterTable"_L1) + == idToIndexItem.size() * usedAttributeCount; + const bool mayOptimizeFileTable = filterDataCount(m_query.get(), "FileFilterTable"_L1) + == idToFileItem.size() * usedAttributeCount; + const bool mayOptimizeContentsTable = + filterDataCount(m_query.get(), "ContentsFilterTable"_L1) + == idToContentsItem.size() * usedAttributeCount; optimized = mayOptimizeIndexTable && mayOptimizeFileTable && mayOptimizeContentsTable; if (!optimized) { - m_query->exec(QLatin1String( - "SELECT " - "IndexFilterTable.IndexId, " - "FilterAttributeTable.Name " - "FROM " - "IndexFilterTable, " - "FilterAttributeTable " - "WHERE " - "IndexFilterTable.FilterAttributeId = FilterAttributeTable.Id")); + m_query->exec( + "SELECT " + "IndexFilterTable.IndexId, " + "FilterAttributeTable.Name " + "FROM " + "IndexFilterTable, " + "FilterAttributeTable " + "WHERE " + "IndexFilterTable.FilterAttributeId = FilterAttributeTable.Id"_L1); while (m_query->next()) { const int indexId = m_query->value(0).toInt(); auto it = idToIndexItem.find(indexId); @@ -334,15 +284,15 @@ QHelpDBReader::IndexTable QHelpDBReader::indexTable() const it.value().filterAttributes.append(m_query->value(1).toString()); } - m_query->exec(QLatin1String( - "SELECT " - "FileFilterTable.FileId, " - "FilterAttributeTable.Name " - "FROM " - "FileFilterTable, " - "FilterAttributeTable " - "WHERE " - "FileFilterTable.FilterAttributeId = FilterAttributeTable.Id")); + m_query->exec( + "SELECT " + "FileFilterTable.FileId, " + "FilterAttributeTable.Name " + "FROM " + "FileFilterTable, " + "FilterAttributeTable " + "WHERE " + "FileFilterTable.FilterAttributeId = FilterAttributeTable.Id"_L1); while (m_query->next()) { const int fileId = m_query->value(0).toInt(); auto it = idToFileItem.find(fileId); @@ -350,15 +300,15 @@ QHelpDBReader::IndexTable QHelpDBReader::indexTable() const it.value().filterAttributes.append(m_query->value(1).toString()); } - m_query->exec(QLatin1String( - "SELECT " - "ContentsFilterTable.ContentsId, " - "FilterAttributeTable.Name " - "FROM " - "ContentsFilterTable, " - "FilterAttributeTable " - "WHERE " - "ContentsFilterTable.FilterAttributeId = FilterAttributeTable.Id")); + m_query->exec( + "SELECT " + "ContentsFilterTable.ContentsId, " + "FilterAttributeTable.Name " + "FROM " + "ContentsFilterTable, " + "FilterAttributeTable " + "WHERE " + "ContentsFilterTable.FilterAttributeId = FilterAttributeTable.Id"_L1); while (m_query->next()) { const int contentsId = m_query->value(0).toInt(); auto it = idToContentsItem.find(contentsId); @@ -382,7 +332,6 @@ QHelpDBReader::IndexTable QHelpDBReader::indexTable() const for (int attributeId : usedAttributeIds) table.usedFilterAttributes.append(attributeIds.value(attributeId)); } - return table; } @@ -390,15 +339,15 @@ QList<QStringList> QHelpDBReader::filterAttributeSets() const { QList<QStringList> result; if (m_query) { - m_query->exec(QLatin1String( - "SELECT " - "FileAttributeSetTable.Id, " - "FilterAttributeTable.Name " - "FROM " - "FileAttributeSetTable, " - "FilterAttributeTable " - "WHERE FileAttributeSetTable.FilterAttributeId = FilterAttributeTable.Id " - "ORDER BY FileAttributeSetTable.Id")); + m_query->exec( + "SELECT " + "FileAttributeSetTable.Id, " + "FilterAttributeTable.Name " + "FROM " + "FileAttributeSetTable, " + "FilterAttributeTable " + "WHERE FileAttributeSetTable.FilterAttributeId = FilterAttributeTable.Id " + "ORDER BY FileAttributeSetTable.Id"_L1); int oldId = -1; while (m_query->next()) { const int id = m_query->value(0).toInt(); @@ -420,22 +369,22 @@ QByteArray QHelpDBReader::fileData(const QString &virtualFolder, return ba; namespaceName(); - m_query->prepare(QLatin1String( - "SELECT " - "FileDataTable.Data " - "FROM " - "FileDataTable, " - "FileNameTable, " - "FolderTable, " - "NamespaceTable " - "WHERE FileDataTable.Id = FileNameTable.FileId " - "AND (FileNameTable.Name = ? OR FileNameTable.Name = ?) " - "AND FileNameTable.FolderId = FolderTable.Id " - "AND FolderTable.Name = ? " - "AND FolderTable.NamespaceId = NamespaceTable.Id " - "AND NamespaceTable.Name = ?")); + m_query->prepare( + "SELECT " + "FileDataTable.Data " + "FROM " + "FileDataTable, " + "FileNameTable, " + "FolderTable, " + "NamespaceTable " + "WHERE FileDataTable.Id = FileNameTable.FileId " + "AND (FileNameTable.Name = ? OR FileNameTable.Name = ?) " + "AND FileNameTable.FolderId = FolderTable.Id " + "AND FolderTable.Name = ? " + "AND FolderTable.NamespaceId = NamespaceTable.Id " + "AND NamespaceTable.Name = ?"_L1); m_query->bindValue(0, filePath); - m_query->bindValue(1, QString(QLatin1String("./") + filePath)); + m_query->bindValue(1, QString("./"_L1 + filePath)); m_query->bindValue(2, virtualFolder); m_query->bindValue(3, m_namespace); m_query->exec(); @@ -448,7 +397,7 @@ QStringList QHelpDBReader::customFilters() const { QStringList lst; if (m_query) { - m_query->exec(QLatin1String("SELECT Name FROM FilterNameTable")); + m_query->exec("SELECT Name FROM FilterNameTable"_L1); while (m_query->next()) lst.append(m_query->value(0).toString()); } @@ -460,18 +409,18 @@ QStringList QHelpDBReader::filterAttributes(const QString &filterName) const QStringList lst; if (m_query) { if (filterName.isEmpty()) { - m_query->prepare(QLatin1String("SELECT Name FROM FilterAttributeTable")); + m_query->prepare("SELECT Name FROM FilterAttributeTable"_L1); } else { - m_query->prepare(QLatin1String( - "SELECT " - "FilterAttributeTable.Name " - "FROM " - "FilterAttributeTable, " - "FilterTable, " - "FilterNameTable " - "WHERE FilterNameTable.Name = ? " - "AND FilterNameTable.Id = FilterTable.NameId " - "AND FilterTable.FilterAttributeId = FilterAttributeTable.Id")); + m_query->prepare( + "SELECT " + "FilterAttributeTable.Name " + "FROM " + "FilterAttributeTable, " + "FilterTable, " + "FilterNameTable " + "WHERE FilterNameTable.Name = ? " + "AND FilterNameTable.Id = FilterTable.NameId " + "AND FilterTable.FilterAttributeId = FilterAttributeTable.Id"_L1); m_query->bindValue(0, filterName); } m_query->exec(); @@ -484,76 +433,70 @@ QStringList QHelpDBReader::filterAttributes(const QString &filterName) const QMultiMap<QString, QByteArray> QHelpDBReader::filesData(const QStringList &filterAttributes, const QString &extensionFilter) const { - QMultiMap<QString, QByteArray> result; if (!m_query) - return result; + return {}; QString query; QString extension; if (!extensionFilter.isEmpty()) - extension = QString(QLatin1String("AND FileNameTable.Name " - "LIKE \'%.%1\'")).arg(extensionFilter); + extension = "AND FileNameTable.Name LIKE \'%.%1\'"_L1.arg(extensionFilter); if (filterAttributes.isEmpty()) { - query = QString(QLatin1String("SELECT " - "FileNameTable.Name, " - "FileDataTable.Data " - "FROM " - "FolderTable, " - "FileNameTable, " - "FileDataTable " - "WHERE FileDataTable.Id = FileNameTable.FileId " - "AND FileNameTable.FolderId = FolderTable.Id %1")) - .arg(extension); + query = + "SELECT " + "FileNameTable.Name, " + "FileDataTable.Data " + "FROM " + "FolderTable, " + "FileNameTable, " + "FileDataTable " + "WHERE FileDataTable.Id = FileNameTable.FileId " + "AND FileNameTable.FolderId = FolderTable.Id %1"_L1.arg(extension); } else { - for (int i = 0; i < filterAttributes.count(); ++i) { + for (int i = 0; i < filterAttributes.size(); ++i) { if (i > 0) - query.append(QLatin1String(" INTERSECT ")); - query.append(QString(QLatin1String( - "SELECT " - "FileNameTable.Name, " - "FileDataTable.Data " - "FROM " - "FolderTable, " - "FileNameTable, " - "FileDataTable, " - "FileFilterTable, " - "FilterAttributeTable " - "WHERE FileDataTable.Id = FileNameTable.FileId " - "AND FileNameTable.FolderId = FolderTable.Id " - "AND FileNameTable.FileId = FileFilterTable.FileId " - "AND FileFilterTable.FilterAttributeId = FilterAttributeTable.Id " - "AND FilterAttributeTable.Name = \'%1\' %2")) - .arg(quote(filterAttributes.at(i))) - .arg(extension)); + query.append(" INTERSECT "_L1); + query.append( + "SELECT " + "FileNameTable.Name, " + "FileDataTable.Data " + "FROM " + "FolderTable, " + "FileNameTable, " + "FileDataTable, " + "FileFilterTable, " + "FilterAttributeTable " + "WHERE FileDataTable.Id = FileNameTable.FileId " + "AND FileNameTable.FolderId = FolderTable.Id " + "AND FileNameTable.FileId = FileFilterTable.FileId " + "AND FileFilterTable.FilterAttributeId = FilterAttributeTable.Id " + "AND FilterAttributeTable.Name = \'%1\' %2"_L1 + .arg(quote(filterAttributes.at(i)), extension)); } } m_query->exec(query); + QMultiMap<QString, QByteArray> result; while (m_query->next()) result.insert(m_query->value(0).toString(), qUncompress(m_query->value(1).toByteArray())); - return result; } QVariant QHelpDBReader::metaData(const QString &name) const { - QVariant v; if (!m_query) - return v; + return {}; - m_query->prepare(QLatin1String("SELECT COUNT(Value), Value FROM MetaDataTable " - "WHERE Name=?")); + m_query->prepare("SELECT COUNT(Value), Value FROM MetaDataTable WHERE Name=?"_L1); m_query->bindValue(0, name); - if (m_query->exec() && m_query->next() - && m_query->value(0).toInt() == 1) - v = m_query->value(1); - return v; + if (m_query->exec() && m_query->next() && m_query->value(0).toInt() == 1) + return m_query->value(1); + return {}; } QString QHelpDBReader::quote(const QString &string) const { QString s = string; - s.replace(QLatin1Char('\''), QLatin1String("\'\'")); + s.replace(u'\'', "\'\'"_L1); return s; } diff --git a/src/assistant/help/qhelpdbreader_p.h b/src/assistant/help/qhelpdbreader_p.h index 9abc3c06f..1bc4fc7c9 100644 --- a/src/assistant/help/qhelpdbreader_p.h +++ b/src/assistant/help/qhelpdbreader_p.h @@ -1,41 +1,5 @@ -/**************************************************************************** -** -** Copyright (C) 2016 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$ -** -****************************************************************************/ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only #ifndef QHELPDBREADER_H #define QHELPDBREADER_H @@ -51,11 +15,9 @@ // We mean it. // -#include <QtCore/QObject> -#include <QtCore/QStringList> -#include <QtCore/QUrl> -#include <QtCore/QByteArray> -#include <QtCore/QSet> +#include <QtCore/qbytearray.h> +#include <QtCore/qobject.h> +#include <QtCore/qstringlist.h> QT_BEGIN_NAMESPACE @@ -69,7 +31,6 @@ public: class IndexItem { public: - IndexItem() = default; QString name; QString identifier; int fileId = 0; @@ -80,7 +41,6 @@ public: class FileItem { public: - FileItem() = default; QString name; QString title; QStringList filterAttributes; @@ -89,7 +49,6 @@ public: class ContentsItem { public: - ContentsItem() = default; QByteArray data; QStringList filterAttributes; }; @@ -104,8 +63,7 @@ public: }; QHelpDBReader(const QString &dbName); - QHelpDBReader(const QString &dbName, const QString &uniqueId, - QObject *parent); + QHelpDBReader(const QString &dbName, const QString &uniqueId, QObject *parent); ~QHelpDBReader(); bool init(); @@ -116,12 +74,11 @@ public: IndexTable indexTable() const; QList<QStringList> filterAttributeSets() const; QMultiMap<QString, QByteArray> filesData(const QStringList &filterAttributes, - const QString &extensionFilter = QString()) const; - QByteArray fileData(const QString &virtualFolder, - const QString &filePath) const; + const QString &extensionFilter = {}) const; + QByteArray fileData(const QString &virtualFolder, const QString &filePath) const; QStringList customFilters() const; - QStringList filterAttributes(const QString &filterName = QString()) const; + QStringList filterAttributes(const QString &filterName = {}) const; QVariant metaData(const QString &name) const; @@ -134,10 +91,10 @@ private: QString m_dbName; QString m_uniqueId; QString m_error; - QSqlQuery *m_query = nullptr; + std::unique_ptr<QSqlQuery> m_query; mutable QString m_namespace; }; QT_END_NAMESPACE -#endif +#endif // QHELPDBREADER_H diff --git a/src/assistant/help/qhelpengine.cpp b/src/assistant/help/qhelpengine.cpp index bb1475fdf..e773018e5 100644 --- a/src/assistant/help/qhelpengine.cpp +++ b/src/assistant/help/qhelpengine.cpp @@ -1,126 +1,64 @@ -/**************************************************************************** -** -** Copyright (C) 2016 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$ -** -****************************************************************************/ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only #include "qhelpengine.h" -#include "qhelpengine_p.h" -#include "qhelpdbreader_p.h" #include "qhelpcontentwidget.h" +#include "qhelpfilterengine.h" #include "qhelpindexwidget.h" #include "qhelpsearchengine.h" -#include "qhelpcollectionhandler_p.h" -#include "qhelpfilterengine.h" -#include <QtCore/QDir> -#include <QtCore/QFile> -#include <QtCore/QPluginLoader> -#include <QtCore/QTimer> -#include <QtWidgets/QApplication> -#include <QtSql/QSqlQuery> +#include <QtCore/qtimer.h> QT_BEGIN_NAMESPACE -void QHelpEnginePrivate::init(const QString &collectionFile, - QHelpEngineCore *helpEngineCore) +class QHelpEnginePrivate { - QHelpEngineCorePrivate::init(collectionFile, helpEngineCore); +public: + QHelpEnginePrivate(QHelpEngineCore *helpEngineCore); - if (!contentModel) - contentModel = new QHelpContentModel(this); - if (!indexModel) - indexModel = new QHelpIndexModel(this); - - connect(helpEngineCore, &QHelpEngineCore::setupFinished, - this, &QHelpEnginePrivate::scheduleApplyCurrentFilter); - connect(helpEngineCore, &QHelpEngineCore::currentFilterChanged, - this, &QHelpEnginePrivate::scheduleApplyCurrentFilter); - connect(helpEngineCore->filterEngine(), &QHelpFilterEngine::filterActivated, - this, &QHelpEnginePrivate::scheduleApplyCurrentFilter); -} + QHelpContentModel *contentModel = nullptr; + QHelpContentWidget *contentWidget = nullptr; -void QHelpEnginePrivate::scheduleApplyCurrentFilter() -{ - if (!error.isEmpty()) - return; - - if (m_isApplyCurrentFilterScheduled) - return; - - m_isApplyCurrentFilterScheduled = true; - QTimer::singleShot(0, this, &QHelpEnginePrivate::applyCurrentFilter); -} + QHelpIndexModel *indexModel = nullptr; + QHelpIndexWidget *indexWidget = nullptr; -void QHelpEnginePrivate::applyCurrentFilter() -{ - m_isApplyCurrentFilterScheduled = false; - const QString filter = usesFilterEngine - ? q->filterEngine()->activeFilter() - : currentFilter; - contentModel->createContents(filter); - indexModel->createIndex(filter); -} + QHelpSearchEngine *searchEngine = nullptr; -void QHelpEnginePrivate::setContentsWidgetBusy() -{ -#if QT_CONFIG(cursor) - contentWidget->setCursor(Qt::WaitCursor); -#endif -} + bool m_isApplyCurrentFilterScheduled = false; + QHelpEngineCore *m_helpEngineCore = nullptr; +}; -void QHelpEnginePrivate::unsetContentsWidgetBusy() +QHelpEnginePrivate::QHelpEnginePrivate(QHelpEngineCore *helpEngineCore) + : m_helpEngineCore(helpEngineCore) { -#if QT_CONFIG(cursor) - contentWidget->unsetCursor(); -#endif -} - -void QHelpEnginePrivate::setIndexWidgetBusy() -{ -#if QT_CONFIG(cursor) - indexWidget->setCursor(Qt::WaitCursor); -#endif -} - -void QHelpEnginePrivate::unsetIndexWidgetBusy() -{ -#if QT_CONFIG(cursor) - indexWidget->unsetCursor(); -#endif + if (!contentModel) + contentModel = new QHelpContentModel(helpEngineCore); + if (!indexModel) + indexModel = new QHelpIndexModel(m_helpEngineCore); + + const auto applyCurrentFilter = [this] { + m_isApplyCurrentFilterScheduled = false; + contentModel->createContentsForCurrentFilter(); + indexModel->createIndexForCurrentFilter(); + }; + + const auto scheduleApplyCurrentFilter = [this, applyCurrentFilter] { + if (!m_helpEngineCore->error().isEmpty()) + return; + + if (m_isApplyCurrentFilterScheduled) + return; + + m_isApplyCurrentFilterScheduled = true; + QTimer::singleShot(0, m_helpEngineCore, applyCurrentFilter); + }; + + QObject::connect(m_helpEngineCore, &QHelpEngineCore::setupFinished, + m_helpEngineCore, scheduleApplyCurrentFilter); + QObject::connect(m_helpEngineCore, &QHelpEngineCore::currentFilterChanged, + m_helpEngineCore, scheduleApplyCurrentFilter); + QObject::connect(m_helpEngineCore->filterEngine(), &QHelpFilterEngine::filterActivated, + m_helpEngineCore, scheduleApplyCurrentFilter); } /*! @@ -138,16 +76,16 @@ void QHelpEnginePrivate::unsetIndexWidgetBusy() it will be created. */ QHelpEngine::QHelpEngine(const QString &collectionFile, QObject *parent) - : QHelpEngineCore(d = new QHelpEnginePrivate(), parent) -{ - d->init(collectionFile, this); -} + : QHelpEngineCore(collectionFile, parent) + , d(new QHelpEnginePrivate(this)) +{} /*! Destroys the help engine object. */ QHelpEngine::~QHelpEngine() { + delete d; } /*! @@ -172,12 +110,16 @@ QHelpIndexModel *QHelpEngine::indexModel() const QHelpContentWidget *QHelpEngine::contentWidget() { if (!d->contentWidget) { - d->contentWidget = new QHelpContentWidget(); + d->contentWidget = new QHelpContentWidget; d->contentWidget->setModel(d->contentModel); - connect(d->contentModel, &QHelpContentModel::contentsCreationStarted, - d, &QHelpEnginePrivate::setContentsWidgetBusy); - connect(d->contentModel, &QHelpContentModel::contentsCreated, - d, &QHelpEnginePrivate::unsetContentsWidgetBusy); +#if QT_CONFIG(cursor) + connect(d->contentModel, &QHelpContentModel::contentsCreationStarted, this, [this] { + d->contentWidget->setCursor(Qt::WaitCursor); + }); + connect(d->contentModel, &QHelpContentModel::contentsCreated, this, [this] { + d->contentWidget->unsetCursor(); + }); +#endif } return d->contentWidget; } @@ -188,12 +130,16 @@ QHelpContentWidget *QHelpEngine::contentWidget() QHelpIndexWidget *QHelpEngine::indexWidget() { if (!d->indexWidget) { - d->indexWidget = new QHelpIndexWidget(); + d->indexWidget = new QHelpIndexWidget; d->indexWidget->setModel(d->indexModel); - connect(d->indexModel, &QHelpIndexModel::indexCreationStarted, - d, &QHelpEnginePrivate::setIndexWidgetBusy); - connect(d->indexModel, &QHelpIndexModel::indexCreated, - d, &QHelpEnginePrivate::unsetIndexWidgetBusy); +#if QT_CONFIG(cursor) + connect(d->indexModel, &QHelpIndexModel::indexCreationStarted, this, [this] { + d->indexWidget->setCursor(Qt::WaitCursor); + }); + connect(d->indexModel, &QHelpIndexModel::indexCreated, this, [this] { + d->indexWidget->unsetCursor(); + }); +#endif } return d->indexWidget; } diff --git a/src/assistant/help/qhelpengine.h b/src/assistant/help/qhelpengine.h index b09724f62..31b8fb3ef 100644 --- a/src/assistant/help/qhelpengine.h +++ b/src/assistant/help/qhelpengine.h @@ -1,41 +1,5 @@ -/**************************************************************************** -** -** Copyright (C) 2016 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$ -** -****************************************************************************/ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only #ifndef QHELPENGINE_H #define QHELPENGINE_H @@ -44,7 +8,6 @@ QT_BEGIN_NAMESPACE - class QHelpContentModel; class QHelpContentWidget; class QHelpIndexModel; @@ -76,4 +39,4 @@ private: QT_END_NAMESPACE -#endif +#endif // QHELPENGINE_H diff --git a/src/assistant/help/qhelpengine_p.h b/src/assistant/help/qhelpengine_p.h deleted file mode 100644 index 76bdbb421..000000000 --- a/src/assistant/help/qhelpengine_p.h +++ /dev/null @@ -1,139 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 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 QHELPENGINE_P_H -#define QHELPENGINE_P_H - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists for the convenience -// of the help generator tools. This header file may change from version -// to version without notice, or even be removed. -// -// We mean it. -// - -#include <QtCore/QHash> -#include <QtCore/QMap> -#include <QtCore/QStringList> -#include <QtCore/QObject> - -QT_BEGIN_NAMESPACE - -class QSqlQuery; - -class QHelpEngineCore; -class QHelpDBReader; -class QHelpContentModel; -class QHelpContentWidget; -class QHelpIndexModel; -class QHelpIndexWidget; -class QHelpSearchEngine; -class QHelpCollectionHandler; -class QHelpFilterEngine; - -class QHelpEngineCorePrivate : public QObject -{ - Q_OBJECT - -public: - virtual ~QHelpEngineCorePrivate(); - - virtual void init(const QString &collectionFile, - QHelpEngineCore *helpEngineCore); - - bool setup(); - - QHelpCollectionHandler *collectionHandler = nullptr; - QHelpFilterEngine *filterEngine = nullptr; - QString currentFilter; - QString error; - bool needsSetup = true; - bool autoSaveFilter = true; - bool usesFilterEngine = false; - bool readOnly = true; - -protected: - QHelpEngineCore *q; - -private slots: - void errorReceived(const QString &msg); -}; - -class QHelpEnginePrivate : public QHelpEngineCorePrivate -{ - Q_OBJECT - -public: - void init(const QString &collectionFile, - QHelpEngineCore *helpEngineCore) override; - - QHelpContentModel *contentModel = nullptr; - QHelpContentWidget *contentWidget = nullptr; - - QHelpIndexModel *indexModel = nullptr; - QHelpIndexWidget *indexWidget = nullptr; - - QHelpSearchEngine *searchEngine = nullptr; - - friend class QHelpContentProvider; - friend class QHelpContentModel; - friend class QHelpIndexProvider; - friend class QHelpIndexModel; - -public slots: - void setContentsWidgetBusy(); - void unsetContentsWidgetBusy(); - void setIndexWidgetBusy(); - void unsetIndexWidgetBusy(); - -private slots: - void scheduleApplyCurrentFilter(); - void applyCurrentFilter(); - -private: - bool m_isApplyCurrentFilterScheduled = false; - -}; - -QT_END_NAMESPACE - -#endif diff --git a/src/assistant/help/qhelpenginecore.cpp b/src/assistant/help/qhelpenginecore.cpp index 4dee74325..f4be7c5cf 100644 --- a/src/assistant/help/qhelpenginecore.cpp +++ b/src/assistant/help/qhelpenginecore.cpp @@ -1,73 +1,59 @@ -/**************************************************************************** -** -** Copyright (C) 2016 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$ -** -****************************************************************************/ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only #include "qhelpenginecore.h" -#include "qhelpengine_p.h" -#include "qhelpdbreader_p.h" #include "qhelpcollectionhandler_p.h" +#include "qhelpdbreader_p.h" #include "qhelpfilterengine.h" +#include "qhelplink.h" -#include <QtCore/QDir> -#include <QtCore/QFile> -#include <QtCore/QPluginLoader> -#include <QtCore/QFileInfo> -#include <QtCore/QThread> -#include <QtHelp/QHelpLink> -#include <QtWidgets/QApplication> -#include <QtSql/QSqlQuery> +#if QT_CONFIG(future) +#include <QtConcurrent/qtconcurrentrun.h> +#include <QtCore/qpromise.h> +#endif + +#include <QtCore/qdir.h> +#include <QtCore/qfileinfo.h> QT_BEGIN_NAMESPACE -void QHelpEngineCorePrivate::init(const QString &collectionFile, - QHelpEngineCore *helpEngineCore) +using namespace Qt::StringLiterals; + +class QHelpEngineCorePrivate +{ +public: + QHelpEngineCorePrivate(const QString &collectionFile, QHelpEngineCore *helpEngineCore); + + void init(const QString &collectionFile); + bool setup(); + + std::unique_ptr<QHelpCollectionHandler> collectionHandler; + QHelpFilterEngine *filterEngine = nullptr; + QString currentFilter; + QString error; + bool needsSetup = true; + bool autoSaveFilter = true; + bool usesFilterEngine = false; + bool readOnly = true; + + QHelpEngineCore *q; +}; + +QHelpEngineCorePrivate::QHelpEngineCorePrivate(const QString &collectionFile, + QHelpEngineCore *helpEngineCore) { q = helpEngineCore; - collectionHandler = new QHelpCollectionHandler(collectionFile, helpEngineCore); - connect(collectionHandler, &QHelpCollectionHandler::error, - this, &QHelpEngineCorePrivate::errorReceived); - filterEngine->setCollectionHandler(collectionHandler); - needsSetup = true; + filterEngine = new QHelpFilterEngine(q); + init(collectionFile); } -QHelpEngineCorePrivate::~QHelpEngineCorePrivate() +void QHelpEngineCorePrivate::init(const QString &collectionFile) { - delete collectionHandler; + collectionHandler.reset(new QHelpCollectionHandler(collectionFile, q)); + QObject::connect(collectionHandler.get(), &QHelpCollectionHandler::error, q, + [this](const QString &msg) { error = msg; }); + filterEngine->setCollectionHandler(collectionHandler.get()); + needsSetup = true; } bool QHelpEngineCorePrivate::setup() @@ -79,24 +65,15 @@ bool QHelpEngineCorePrivate::setup() needsSetup = false; emit q->setupStarted(); - const QVariant readOnlyVariant = q->property("_q_readonly"); - const bool readOnly = readOnlyVariant.isValid() - ? readOnlyVariant.toBool() : q->isReadOnly(); - collectionHandler->setReadOnly(readOnly); + collectionHandler->setReadOnly(q->isReadOnly()); const bool opened = collectionHandler->openCollectionFile(); if (opened) q->currentFilter(); emit q->setupFinished(); - return opened; } -void QHelpEngineCorePrivate::errorReceived(const QString &msg) -{ - error = msg; -} - /*! \class QHelpEngineCore \since 4.4 @@ -113,7 +90,7 @@ void QHelpEngineCorePrivate::errorReceived(const QString &msg) The core help engine can be used to perform different tasks. By calling documentsForIdentifier() the engine returns URLs specifying the file locations inside the help system. The - actual file data can then be retrived by calling fileData(). + actual file data can then be retrieved by calling fileData(). The help engine can contain any number of custom filters. The management of the filters, including adding new filters, @@ -187,22 +164,18 @@ void QHelpEngineCorePrivate::errorReceived(const QString &msg) */ QHelpEngineCore::QHelpEngineCore(const QString &collectionFile, QObject *parent) : QObject(parent) -{ - d = new QHelpEngineCorePrivate(); - d->filterEngine = new QHelpFilterEngine(this); - d->init(collectionFile, this); -} + , d(new QHelpEngineCorePrivate(collectionFile, this)) +{} /*! \internal */ -QHelpEngineCore::QHelpEngineCore(QHelpEngineCorePrivate *helpEngineCorePrivate, - QObject *parent) +#if QT_DEPRECATED_SINCE(6, 8) +QHelpEngineCore::QHelpEngineCore(QHelpEngineCorePrivate *helpEngineCorePrivate, QObject *parent) : QObject(parent) -{ - d = helpEngineCorePrivate; - d->filterEngine = new QHelpFilterEngine(this); -} + , d(helpEngineCorePrivate) +{} +#endif /*! Destructs the help engine. @@ -228,15 +201,8 @@ QString QHelpEngineCore::collectionFile() const void QHelpEngineCore::setCollectionFile(const QString &fileName) { - if (fileName == collectionFile()) - return; - - if (d->collectionHandler) { - delete d->collectionHandler; - d->collectionHandler = nullptr; - } - d->init(fileName, this); - d->needsSetup = true; + if (fileName != collectionFile()) + d->init(fileName); } /*! @@ -261,7 +227,11 @@ bool QHelpEngineCore::isReadOnly() const void QHelpEngineCore::setReadOnly(bool enable) { + if (d->readOnly == enable) + return; + d->readOnly = enable; + d->init(collectionFile()); } /*! @@ -321,12 +291,12 @@ bool QHelpEngineCore::copyCollectionFile(const QString &fileName) */ QString QHelpEngineCore::namespaceName(const QString &documentationFileName) { - QHelpDBReader reader(documentationFileName, - QHelpGlobal::uniquifyConnectionName(QLatin1String("GetNamespaceName"), - QThread::currentThread()), nullptr); + void *pointer = const_cast<QString *>(&documentationFileName); + QHelpDBReader reader(documentationFileName, QHelpGlobal::uniquifyConnectionName( + "GetNamespaceName"_L1, pointer), nullptr); if (reader.init()) return reader.namespaceName(); - return QString(); + return {}; } /*! @@ -369,19 +339,19 @@ bool QHelpEngineCore::unregisterDocumentation(const QString &namespaceName) QString QHelpEngineCore::documentationFileName(const QString &namespaceName) { if (!d->setup()) - return QString(); + return {}; const QHelpCollectionHandler::FileInfo fileInfo = d->collectionHandler->registeredDocumentation(namespaceName); if (fileInfo.namespaceName.isEmpty()) - return QString(); + return {}; if (QDir::isAbsolutePath(fileInfo.fileName)) return fileInfo.fileName; return QFileInfo(QFileInfo(d->collectionHandler->collectionFile()).absolutePath() - + QLatin1Char('/') + fileInfo.fileName).absoluteFilePath(); + + u'/' + fileInfo.fileName).absoluteFilePath(); } /*! @@ -390,11 +360,10 @@ QString QHelpEngineCore::documentationFileName(const QString &namespaceName) */ QStringList QHelpEngineCore::registeredDocumentations() const { - QStringList list; if (!d->setup()) - return list; - const QHelpCollectionHandler::FileInfoList &docList - = d->collectionHandler->registeredDocumentations(); + return {}; + const auto &docList = d->collectionHandler->registeredDocumentations(); + QStringList list; for (const QHelpCollectionHandler::FileInfo &info : docList) list.append(info.namespaceName); return list; @@ -412,7 +381,7 @@ QStringList QHelpEngineCore::registeredDocumentations() const QStringList QHelpEngineCore::customFilters() const { if (!d->setup()) - return QStringList(); + return {}; return d->collectionHandler->customFilters(); } @@ -463,7 +432,7 @@ bool QHelpEngineCore::removeCustomFilter(const QString &filterName) QStringList QHelpEngineCore::filterAttributes() const { if (!d->setup()) - return QStringList(); + return {}; return d->collectionHandler->filterAttributes(); } @@ -478,7 +447,7 @@ QStringList QHelpEngineCore::filterAttributes() const QStringList QHelpEngineCore::filterAttributes(const QString &filterName) const { if (!d->setup()) - return QStringList(); + return {}; return d->collectionHandler->filterAttributes(filterName); } @@ -499,14 +468,12 @@ QStringList QHelpEngineCore::filterAttributes(const QString &filterName) const QString QHelpEngineCore::currentFilter() const { if (!d->setup()) - return QString(); + return {}; if (d->currentFilter.isEmpty()) { const QString &filter = - d->collectionHandler->customValue(QLatin1String("CurrentFilter"), - QString()).toString(); - if (!filter.isEmpty() - && d->collectionHandler->customFilters().contains(filter)) + d->collectionHandler->customValue("CurrentFilter"_L1, QString()).toString(); + if (!filter.isEmpty() && d->collectionHandler->customFilters().contains(filter)) d->currentFilter = filter; } return d->currentFilter; @@ -517,10 +484,8 @@ void QHelpEngineCore::setCurrentFilter(const QString &filterName) if (!d->setup() || filterName == d->currentFilter) return; d->currentFilter = filterName; - if (d->autoSaveFilter) { - d->collectionHandler->setCustomValue(QLatin1String("CurrentFilter"), - d->currentFilter); - } + if (d->autoSaveFilter) + d->collectionHandler->setCustomValue("CurrentFilter"_L1, d->currentFilter); emit currentFilterChanged(d->currentFilter); } @@ -536,8 +501,7 @@ void QHelpEngineCore::setCurrentFilter(const QString &filterName) QList<QStringList> QHelpEngineCore::filterAttributeSets(const QString &namespaceName) const { if (!d->setup()) - return QList<QStringList>(); - + return {}; return d->collectionHandler->filterAttributeSets(namespaceName); } @@ -559,13 +523,13 @@ QList<QUrl> QHelpEngineCore::files(const QString namespaceName, return res; QUrl url; - url.setScheme(QLatin1String("qthelp")); + url.setScheme("qthelp"_L1); url.setAuthority(namespaceName); const QStringList &files = d->collectionHandler->files( namespaceName, filterAttributes, extensionFilter); for (const QString &file : files) { - url.setPath(QLatin1String("/") + file); + url.setPath("/"_L1 + file); res.append(url); } return res; @@ -585,13 +549,13 @@ QList<QUrl> QHelpEngineCore::files(const QString namespaceName, return res; QUrl url; - url.setScheme(QLatin1String("qthelp")); + url.setScheme("qthelp"_L1); url.setAuthority(namespaceName); const QStringList &files = d->collectionHandler->files( namespaceName, filterName, extensionFilter); for (const QString &file : files) { - url.setPath(QLatin1String("/") + file); + url.setPath("/"_L1 + file); res.append(url); } return res; @@ -636,8 +600,7 @@ QUrl QHelpEngineCore::findFile(const QUrl &url) const QByteArray QHelpEngineCore::fileData(const QUrl &url) const { if (!d->setup()) - return QByteArray(); - + return {}; return d->collectionHandler->fileData(url); } @@ -650,9 +613,8 @@ QByteArray QHelpEngineCore::fileData(const QUrl &url) const */ QList<QHelpLink> QHelpEngineCore::documentsForIdentifier(const QString &id) const { - return documentsForIdentifier(id, d->usesFilterEngine - ? d->filterEngine->activeFilter() - : d->currentFilter); + return documentsForIdentifier( + id, d->usesFilterEngine ? d->filterEngine->activeFilter() : d->currentFilter); } /*! @@ -666,11 +628,10 @@ QList<QHelpLink> QHelpEngineCore::documentsForIdentifier(const QString &id) cons QList<QHelpLink> QHelpEngineCore::documentsForIdentifier(const QString &id, const QString &filterName) const { if (!d->setup()) - return QList<QHelpLink>(); + return {}; if (d->usesFilterEngine) return d->collectionHandler->documentsForIdentifier(id, filterName); - return d->collectionHandler->documentsForIdentifier(id, filterAttributes(filterName)); } @@ -683,9 +644,8 @@ QList<QHelpLink> QHelpEngineCore::documentsForIdentifier(const QString &id, cons */ QList<QHelpLink> QHelpEngineCore::documentsForKeyword(const QString &keyword) const { - return documentsForKeyword(keyword, d->usesFilterEngine - ? d->filterEngine->activeFilter() - : d->currentFilter); + return documentsForKeyword( + keyword, d->usesFilterEngine ? d->filterEngine->activeFilter() : d->currentFilter); } /*! @@ -699,11 +659,10 @@ QList<QHelpLink> QHelpEngineCore::documentsForKeyword(const QString &keyword) co QList<QHelpLink> QHelpEngineCore::documentsForKeyword(const QString &keyword, const QString &filterName) const { if (!d->setup()) - return QList<QHelpLink>(); + return {}; if (d->usesFilterEngine) return d->collectionHandler->documentsForKeyword(keyword, filterName); - return d->collectionHandler->documentsForKeyword(keyword, filterAttributes(filterName)); } @@ -730,7 +689,7 @@ bool QHelpEngineCore::removeCustomValue(const QString &key) QVariant QHelpEngineCore::customValue(const QString &key, const QVariant &defaultValue) const { if (!d->setup()) - return QVariant(); + return {}; return d->collectionHandler->customValue(key, defaultValue); } @@ -758,11 +717,11 @@ bool QHelpEngineCore::setCustomValue(const QString &key, const QVariant &value) QVariant QHelpEngineCore::metaData(const QString &documentationFileName, const QString &name) { - QHelpDBReader reader(documentationFileName, QLatin1String("GetMetaData"), nullptr); + QHelpDBReader reader(documentationFileName, "GetMetaData"_L1, nullptr); if (reader.init()) return reader.metaData(name); - return QVariant(); + return {}; } /*! @@ -819,4 +778,165 @@ bool QHelpEngineCore::usesFilterEngine() const return d->usesFilterEngine; } +#if QT_CONFIG(future) +static QUrl constructUrl(const QString &namespaceName, const QString &folderName, + const QString &relativePath) +{ + const int idx = relativePath.indexOf(u'#'); + const QString &rp = idx < 0 ? relativePath : relativePath.left(idx); + const QString anchor = idx < 0 ? QString() : relativePath.mid(idx + 1); + return QHelpCollectionHandler::buildQUrl(namespaceName, folderName, rp, anchor); +} + +using ContentProviderResult = QList<QHelpCollectionHandler::ContentsData>; +using ContentProvider = std::function<ContentProviderResult(const QString &)>; +using ContentResult = std::shared_ptr<QHelpContentItem>; + +// This trick is needed because the c'tor of QHelpContentItem is private. +QHelpContentItem *createContentItem(const QString &name = {}, const QUrl &link = {}, + QHelpContentItem *parent = {}) +{ + return new QHelpContentItem(name, link, parent); +} + +static void requestContentHelper(QPromise<ContentResult> &promise, const ContentProvider &provider, + const QString &collectionFile) +{ + ContentResult rootItem(createContentItem()); + const ContentProviderResult result = provider(collectionFile); + for (const auto &contentsData : result) { + const QString namespaceName = contentsData.namespaceName; + const QString folderName = contentsData.folderName; + for (const QByteArray &contents : contentsData.contentsList) { + if (promise.isCanceled()) + return; + + if (contents.isEmpty()) + continue; + + QList<QHelpContentItem *> stack; + QDataStream s(contents); + while (true) { + int depth = 0; + QString link, title; + s >> depth; + s >> link; + s >> title; + if (title.isEmpty()) + break; + +// The example input (depth, link, title): +// +// 0 "graphicaleffects5.html" "Qt 5 Compatibility APIs: Qt Graphical Effects" +// 1 "qtgraphicaleffects5-index.html" "QML Types" +// 2 "qml-qt5compat-graphicaleffects-blend.html" "Blend Type Reference" +// 3 "qml-qt5compat-graphicaleffects-blend-members.html" "List of all members" +// 2 "qml-qt5compat-graphicaleffects-brightnesscontrast.html" "BrightnessContrast Type Reference" +// +// Thus, the valid order of depths is: +// 1. Whenever the item's depth is < 0, we insert the item as its depth is 0. +// 2. The first item's depth must be 0, otherwise we insert the item as its depth is 0. +// 3. When the previous depth was N, the next depth must be in range [0, N+1] inclusively. +// If next item's depth is M > N+1, we insert the item as its depth is N+1. + + if (depth <= 0) { + stack.clear(); + } else if (depth < stack.size()) { + stack = stack.sliced(0, depth); + } else if (depth > stack.size()) { + // Fill the gaps with the last item from the stack (or with the root). + // This branch handles the case when depths are broken, e.g. 0, 2, 2, 1. + // In this case, the 1st item is a root, and 2nd - 4th are all direct + // children of the 1st. + QHelpContentItem *substituteItem = + stack.isEmpty() ? rootItem.get() : stack.constLast(); + while (depth > stack.size()) + stack.append(substituteItem); + } + + const QUrl url = constructUrl(namespaceName, folderName, link); + QHelpContentItem *parent = stack.isEmpty() ? rootItem.get() : stack.constLast(); + stack.push_back(createContentItem(title, url, parent)); + } + } + } + promise.addResult(rootItem); +} + +static ContentProvider contentProviderFromFilterEngine(const QString &filter) +{ + return [filter](const QString &collectionFile) -> ContentProviderResult { + QHelpCollectionHandler collectionHandler(collectionFile); + if (!collectionHandler.openCollectionFile()) + return {}; + return collectionHandler.contentsForFilter(filter); + }; +} + +static ContentProvider contentProviderFromAttributes(const QStringList &attributes) +{ + return [attributes](const QString &collectionFile) -> ContentProviderResult { + QHelpCollectionHandler collectionHandler(collectionFile); + if (!collectionHandler.openCollectionFile()) + return {}; + return collectionHandler.contentsForFilter(attributes); + }; +} + +QFuture<ContentResult> QHelpEngineCore::requestContentForCurrentFilter() const +{ + const ContentProvider provider = usesFilterEngine() + ? contentProviderFromFilterEngine(filterEngine()->activeFilter()) + : contentProviderFromAttributes(filterAttributes(d->currentFilter)); + return QtConcurrent::run(requestContentHelper, provider, collectionFile()); +} + +QFuture<ContentResult> QHelpEngineCore::requestContent(const QString &filter) const +{ + const ContentProvider provider = usesFilterEngine() + ? contentProviderFromFilterEngine(filter) + : contentProviderFromAttributes(filterAttributes(filter)); + return QtConcurrent::run(requestContentHelper, provider, collectionFile()); +} + +using IndexProvider = std::function<QStringList(const QString &)>; +using IndexResult = QStringList; + +static IndexProvider indexProviderFromFilterEngine(const QString &filter) +{ + return [filter](const QString &collectionFile) -> IndexResult { + QHelpCollectionHandler collectionHandler(collectionFile); + if (!collectionHandler.openCollectionFile()) + return {}; + return collectionHandler.indicesForFilter(filter); + }; +} + +static IndexProvider indexProviderFromAttributes(const QStringList &attributes) +{ + return [attributes](const QString &collectionFile) -> IndexResult { + QHelpCollectionHandler collectionHandler(collectionFile); + if (!collectionHandler.openCollectionFile()) + return {}; + return collectionHandler.indicesForFilter(attributes); + }; +} + +QFuture<IndexResult> QHelpEngineCore::requestIndexForCurrentFilter() const +{ + const IndexProvider provider = usesFilterEngine() + ? indexProviderFromFilterEngine(filterEngine()->activeFilter()) + : indexProviderFromAttributes(filterAttributes(d->currentFilter)); + return QtConcurrent::run(std::move(provider), collectionFile()); +} + +QFuture<IndexResult> QHelpEngineCore::requestIndex(const QString &filter) const +{ + const IndexProvider provider = usesFilterEngine() + ? indexProviderFromFilterEngine(filter) + : indexProviderFromAttributes(filterAttributes(filter)); + return QtConcurrent::run(std::move(provider), collectionFile()); +} +#endif + QT_END_NAMESPACE diff --git a/src/assistant/help/qhelpenginecore.h b/src/assistant/help/qhelpenginecore.h index dc4cd7695..8d3861dd4 100644 --- a/src/assistant/help/qhelpenginecore.h +++ b/src/assistant/help/qhelpenginecore.h @@ -1,51 +1,19 @@ -/**************************************************************************** -** -** Copyright (C) 2016 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$ -** -****************************************************************************/ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only #ifndef QHELPENGINECORE_H #define QHELPENGINECORE_H #include <QtHelp/qhelp_global.h> +#include <QtHelp/qhelpcontentitem.h> -#include <QtCore/QUrl> -#include <QtCore/QMap> -#include <QtCore/QObject> -#include <QtCore/QVariant> +#if QT_CONFIG(future) +#include <QtCore/qfuture.h> +#endif + +#include <QtCore/qobject.h> +#include <QtCore/qurl.h> +#include <QtCore/qvariant.h> QT_BEGIN_NAMESPACE @@ -86,7 +54,7 @@ public: QStringList registeredDocumentations() const; QByteArray fileData(const QUrl &url) const; -#if QT_DEPRECATED_SINCE(5,13) +// #if QT_DEPRECATED_SINCE(5,13) QStringList customFilters() const; bool removeCustomFilter(const QString &filterName); bool addCustomFilter(const QString &filterName, @@ -99,14 +67,12 @@ public: void setCurrentFilter(const QString &filterName); QList<QStringList> filterAttributeSets(const QString &namespaceName) const; - QList<QUrl> files(const QString namespaceName, - const QStringList &filterAttributes, - const QString &extensionFilter = QString()); -#endif + QList<QUrl> files(const QString namespaceName, const QStringList &filterAttributes, + const QString &extensionFilter = {}); +// #endif - QList<QUrl> files(const QString namespaceName, - const QString &filterName, - const QString &extensionFilter = QString()); + QList<QUrl> files(const QString namespaceName, const QString &filterName, + const QString &extensionFilter = {}); QUrl findFile(const QUrl &url) const; QList<QHelpLink> documentsForIdentifier(const QString &id) const; @@ -115,12 +81,10 @@ public: QList<QHelpLink> documentsForKeyword(const QString &keyword, const QString &filterName) const; bool removeCustomValue(const QString &key); - QVariant customValue(const QString &key, - const QVariant &defaultValue = QVariant()) const; + QVariant customValue(const QString &key, const QVariant &defaultValue = {}) const; bool setCustomValue(const QString &key, const QVariant &value); - static QVariant metaData(const QString &documentationFileName, - const QString &name); + static QVariant metaData(const QString &documentationFileName, const QString &name); QString error() const; @@ -130,23 +94,31 @@ public: void setUsesFilterEngine(bool uses); bool usesFilterEngine() const; +#if QT_CONFIG(future) + QFuture<std::shared_ptr<QHelpContentItem>> requestContentForCurrentFilter() const; + QFuture<std::shared_ptr<QHelpContentItem>> requestContent(const QString &filter) const; + + QFuture<QStringList> requestIndexForCurrentFilter() const; + QFuture<QStringList> requestIndex(const QString &filter) const; +#endif + Q_SIGNALS: void setupStarted(); void setupFinished(); void warning(const QString &msg); -#if QT_DEPRECATED_SINCE(5,13) +// #if QT_DEPRECATED_SINCE(5,13) void currentFilterChanged(const QString &newFilter); void readersAboutToBeInvalidated(); -#endif +// #endif protected: - QHelpEngineCore(QHelpEngineCorePrivate *helpEngineCorePrivate, - QObject *parent); +#if QT_DEPRECATED_SINCE(6, 8) + QHelpEngineCore(QHelpEngineCorePrivate *helpEngineCorePrivate, QObject *parent); +#endif private: QHelpEngineCorePrivate *d; - friend class QHelpEngineCorePrivate; }; QT_END_NAMESPACE diff --git a/src/assistant/help/qhelpfilterdata.cpp b/src/assistant/help/qhelpfilterdata.cpp index b90aeb6c8..2baa7ce3c 100644 --- a/src/assistant/help/qhelpfilterdata.cpp +++ b/src/assistant/help/qhelpfilterdata.cpp @@ -1,44 +1,9 @@ -/**************************************************************************** -** -** Copyright (C) 2018 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$ -** -****************************************************************************/ +// Copyright (C) 2018 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only #include "qhelpfilterdata.h" -#include <QtCore/QVersionNumber> + +#include <QtCore/qversionnumber.h> QT_BEGIN_NAMESPACE @@ -50,8 +15,7 @@ public: : QSharedData(other) , m_components(other.m_components) , m_versions(other.m_versions) - { } - ~QHelpFilterDataPrivate() = default; + {} QStringList m_components; QList<QVersionNumber> m_versions; @@ -75,10 +39,7 @@ public: /*! Constructs the empty filter. */ -QHelpFilterData::QHelpFilterData() - : d(new QHelpFilterDataPrivate) -{ -} +QHelpFilterData::QHelpFilterData() : d(new QHelpFilterDataPrivate) { } /*! Constructs a copy of \a other. @@ -100,7 +61,6 @@ QHelpFilterData::~QHelpFilterData() = default; */ QHelpFilterData &QHelpFilterData::operator=(const QHelpFilterData &) = default; - /*! Move-assigns \a other to this QHelpFilterData instance. */ @@ -115,8 +75,7 @@ QHelpFilterData &QHelpFilterData::operator=(QHelpFilterData &&) = default; bool QHelpFilterData::operator==(const QHelpFilterData &other) const { - return (d->m_components == other.d->m_components && - d->m_versions == other.d->m_versions); + return (d->m_components == other.d->m_components && d->m_versions == other.d->m_versions); } /*! diff --git a/src/assistant/help/qhelpfilterdata.h b/src/assistant/help/qhelpfilterdata.h index b51ee495b..aaf35a2df 100644 --- a/src/assistant/help/qhelpfilterdata.h +++ b/src/assistant/help/qhelpfilterdata.h @@ -1,48 +1,12 @@ -/**************************************************************************** -** -** Copyright (C) 2018 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$ -** -****************************************************************************/ +// Copyright (C) 2018 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only #ifndef QHELPFILTERDATA_H #define QHELPFILTERDATA_H #include <QtHelp/qhelp_global.h> -#include <QtCore/QSharedDataPointer> +#include <QtCore/qshareddata.h> QT_BEGIN_NAMESPACE diff --git a/src/assistant/help/qhelpfilterengine.cpp b/src/assistant/help/qhelpfilterengine.cpp index b465d6c91..dc139bffd 100644 --- a/src/assistant/help/qhelpfilterengine.cpp +++ b/src/assistant/help/qhelpfilterengine.cpp @@ -1,50 +1,13 @@ -/**************************************************************************** -** -** Copyright (C) 2018 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$ -** -****************************************************************************/ +// Copyright (C) 2018 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only #include "qhelpfilterengine.h" +#include "qhelpcollectionhandler_p.h" #include "qhelpenginecore.h" #include "qhelpfilterdata.h" -#include "qhelpdbreader_p.h" -#include "qhelpcollectionhandler_p.h" -#include <QtCore/QThread> -#include <QtCore/QVersionNumber> +#include <QtCore/qthread.h> +#include <QtCore/qversionnumber.h> QT_BEGIN_NAMESPACE @@ -81,7 +44,7 @@ bool QHelpFilterEnginePrivate::setup() } const QString filter = m_collectionHandler->customValue( - QLatin1String(ActiveFilter), QString()).toString(); + QLatin1StringView(ActiveFilter), QString()).toString(); if (!filter.isEmpty() && m_collectionHandler->filters().contains(filter)) m_currentFilter = filter; @@ -160,7 +123,7 @@ QHelpFilterEngine::~QHelpFilterEngine() void QHelpFilterEngine::setCollectionHandler(QHelpCollectionHandler *collectionHandler) { d->m_collectionHandler = collectionHandler; - d->m_currentFilter = QString(); + d->m_currentFilter.clear(); d->m_needsSetup = true; } @@ -171,7 +134,7 @@ void QHelpFilterEngine::setCollectionHandler(QHelpCollectionHandler *collectionH QMap<QString, QString> QHelpFilterEngine::namespaceToComponent() const { if (!d->setup()) - return QMap<QString, QString>(); + return {}; return d->m_collectionHandler->namespaceToComponent(); } @@ -182,8 +145,7 @@ QMap<QString, QString> QHelpFilterEngine::namespaceToComponent() const QMap<QString, QVersionNumber> QHelpFilterEngine::namespaceToVersion() const { if (!d->setup()) - return QMap<QString, QVersionNumber>(); - + return {}; return d->m_collectionHandler->namespaceToVersion(); } @@ -193,7 +155,7 @@ QMap<QString, QVersionNumber> QHelpFilterEngine::namespaceToVersion() const QStringList QHelpFilterEngine::filters() const { if (!d->setup()) - return QStringList(); + return {}; return d->m_collectionHandler->filters(); } @@ -204,7 +166,7 @@ QStringList QHelpFilterEngine::filters() const QStringList QHelpFilterEngine::availableComponents() const { if (!d->setup()) - return QStringList(); + return {}; return d->m_collectionHandler->availableComponents(); } @@ -217,7 +179,7 @@ QStringList QHelpFilterEngine::availableComponents() const QList<QVersionNumber> QHelpFilterEngine::availableVersions() const { if (!d->setup()) - return QList<QVersionNumber>(); + return {}; return d->m_collectionHandler->availableVersions(); } @@ -227,7 +189,7 @@ QList<QVersionNumber> QHelpFilterEngine::availableVersions() const QHelpFilterData QHelpFilterEngine::filterData(const QString &filterName) const { if (!d->setup()) - return QHelpFilterData(); + return {}; return d->m_collectionHandler->filterData(filterName); } @@ -264,7 +226,7 @@ bool QHelpFilterEngine::removeFilter(const QString &filterName) QString QHelpFilterEngine::activeFilter() const { if (!d->setup()) - return QString(); + return {}; return d->m_currentFilter; } @@ -286,11 +248,8 @@ bool QHelpFilterEngine::setActiveFilter(const QString &filterName) return false; d->m_currentFilter = filterName; - d->m_collectionHandler->setCustomValue(QLatin1String(ActiveFilter), - d->m_currentFilter); - + d->m_collectionHandler->setCustomValue(QLatin1StringView(ActiveFilter), d->m_currentFilter); emit filterActivated(d->m_currentFilter); - return true; } @@ -301,7 +260,7 @@ bool QHelpFilterEngine::setActiveFilter(const QString &filterName) QStringList QHelpFilterEngine::namespacesForFilter(const QString &filterName) const { if (!d->setup()) - return QStringList(); + return {}; return d->m_collectionHandler->namespacesForFilter(filterName); } @@ -329,7 +288,7 @@ QStringList QHelpFilterEngine::indices() const QStringList QHelpFilterEngine::indices(const QString &filterName) const { if (!d->setup()) - return QStringList(); + return {}; return d->m_collectionHandler->indicesForFilter(filterName); } diff --git a/src/assistant/help/qhelpfilterengine.h b/src/assistant/help/qhelpfilterengine.h index d06d18b04..a16a20483 100644 --- a/src/assistant/help/qhelpfilterengine.h +++ b/src/assistant/help/qhelpfilterengine.h @@ -1,59 +1,22 @@ -/**************************************************************************** -** -** Copyright (C) 2018 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$ -** -****************************************************************************/ +// Copyright (C) 2018 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only #ifndef QHELPFILTERENGINE_H #define QHELPFILTERENGINE_H #include <QtHelp/qhelp_global.h> -#include <QtCore/QObject> +#include <QtCore/qobject.h> QT_BEGIN_NAMESPACE -template <class K, class T> -class QMap; -class QVersionNumber; - class QHelpCollectionHandler; class QHelpEngineCore; class QHelpFilterData; class QHelpFilterEnginePrivate; +template <class K, class T> +class QMap; +class QVersionNumber; class QHELP_EXPORT QHelpFilterEngine : public QObject { @@ -91,7 +54,6 @@ private: void setCollectionHandler(QHelpCollectionHandler *collectionHandler); QHelpFilterEnginePrivate *d; - friend class QHelpEngineCore; friend class QHelpEngineCorePrivate; }; diff --git a/src/assistant/help/qhelpfiltersettings.cpp b/src/assistant/help/qhelpfiltersettings.cpp deleted file mode 100644 index 206692179..000000000 --- a/src/assistant/help/qhelpfiltersettings.cpp +++ /dev/null @@ -1,170 +0,0 @@ -/**************************************************************************** -** -** 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(const 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 deleted file mode 100644 index cf5622b6d..000000000 --- a/src/assistant/help/qhelpfiltersettings_p.h +++ /dev/null @@ -1,96 +0,0 @@ -/**************************************************************************** -** -** 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 - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists for the convenience -// of the help generator tools. This header file may change from version -// to version without notice, or even be removed. -// -// We mean it. -// - -#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(const 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 index c5f8ac29c..319111f6c 100644 --- a/src/assistant/help/qhelpfiltersettingswidget.cpp +++ b/src/assistant/help/qhelpfiltersettingswidget.cpp @@ -1,53 +1,94 @@ -/**************************************************************************** -** -** 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$ -** -****************************************************************************/ +// Copyright (C) 2020 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only #include "qhelpfilterdata.h" -#include "qhelpfiltersettings_p.h" +#include "qfilternamedialog_p.h" #include "qhelpfiltersettingswidget.h" #include "ui_qhelpfiltersettingswidget.h" -#include "qfilternamedialog_p.h" -#include <QtWidgets/QMessageBox> -#include <QtCore/QVersionNumber> +#include <QtCore/qversionnumber.h> +#include <QtHelp/qhelpfilterdata.h> +#include <QtHelp/qhelpfilterengine.h> +#include <QtWidgets/qmessagebox.h> QT_BEGIN_NAMESPACE +using namespace Qt::StringLiterals; + +class QHelpFilterSettings final +{ +public: + void setFilter(const QString &filterName, const QHelpFilterData &filterData) + { + m_filterToData.insert(filterName, filterData); + } + void removeFilter(const QString &filterName) { m_filterToData.remove(filterName); } + QHelpFilterData filterData(const QString &filterName) const + { + return m_filterToData.value(filterName); + } + QMap<QString, QHelpFilterData> filters() const { return m_filterToData; } + + void setCurrentFilter(const QString &filterName) { m_currentFilter = filterName; } + QString currentFilter() const { return m_currentFilter; } + +private: + QMap<QString, QHelpFilterData> m_filterToData; + QString m_currentFilter; +}; + +static QHelpFilterSettings readSettingsHelper(const 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; +} + +static bool applySettingsHelper(QHelpFilterEngine *filterEngine, const QHelpFilterSettings &settings) +{ + bool changed = false; + const QHelpFilterSettings oldSettings = readSettingsHelper(filterEngine); + + const auto filtersToRemove = subtract(oldSettings.filters(), settings.filters()); + const auto filtersToAdd = subtract(settings.filters(), oldSettings.filters()); + + const QString ¤tFilter = filterEngine->activeFilter(); + + for (auto it = filtersToRemove.cbegin(); it != filtersToRemove.cend(); ++it) { + filterEngine->removeFilter(it.key()); + if (currentFilter == it.key() && !filtersToAdd.contains(it.key())) + filterEngine->setActiveFilter({}); + 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; +} + static QStringList versionsToStringList(const QList<QVersionNumber> &versions) { QStringList versionList; @@ -67,11 +108,11 @@ static QList<QVersionNumber> stringListToVersions(const QStringList &versionList class QHelpFilterSettingsWidgetPrivate { QHelpFilterSettingsWidget *q_ptr; - Q_DECLARE_PUBLIC(QHelpFilterSettingsWidget) + Q_DECLARE_PUBLIC(QHelpFilterSettingsWidget) // TODO: remove Q_DECLARE_PUBLIC public: QHelpFilterSettingsWidgetPrivate() = default; - QHelpFilterSettings filterSettings() const; + QHelpFilterSettings filterSettings() const { return m_filterSettings; } void setFilterSettings(const QHelpFilterSettings &settings); void updateCurrentFilter(); @@ -80,11 +121,9 @@ public: void addFilterClicked(); void renameFilterClicked(); void removeFilterClicked(); - void addFilter(const QString &filterName, - const QHelpFilterData &filterData = QHelpFilterData()); + void addFilter(const QString &filterName, const QHelpFilterData &filterData = {}); void removeFilter(const QString &filterName); - QString getUniqueFilterName(const QString &windowTitle, - const QString &initialFilterName); + QString getUniqueFilterName(const QString &windowTitle, const QString &initialFilterName); QString suggestedNewFilterName(const QString &initialFilterName) const; QMap<QString, QListWidgetItem *> m_filterToItem; @@ -114,7 +153,9 @@ void QHelpFilterSettingsWidgetPrivate::setFilterSettings(const QHelpFilterSettin m_itemToFilter.clear(); m_filterToItem.clear(); - for (const QString &filterName : m_filterSettings.filterNames()) { + const auto filters = m_filterSettings.filters(); + for (auto it = filters.cbegin(); it != filters.cend(); ++it) { + const QString &filterName = it.key(); QListWidgetItem *item = new QListWidgetItem(filterName); m_ui.filterWidget->addItem(item); m_itemToFilter.insert(item, filterName); @@ -129,11 +170,6 @@ void QHelpFilterSettingsWidgetPrivate::setFilterSettings(const QHelpFilterSettin updateCurrentFilter(); } -QHelpFilterSettings QHelpFilterSettingsWidgetPrivate::filterSettings() const -{ - return m_filterSettings; -} - void QHelpFilterSettingsWidgetPrivate::updateCurrentFilter() { const QString ¤tFilter = m_itemToFilter.value(m_ui.filterWidget->currentItem()); @@ -209,17 +245,15 @@ void QHelpFilterSettingsWidgetPrivate::removeFilterClicked() return; if (QMessageBox::question(q, QHelpFilterSettingsWidget::tr("Remove Filter"), - QHelpFilterSettingsWidget::tr("Are you sure you want to remove the \"%1\" filter?") - .arg(currentFilter), - QMessageBox::Yes | QMessageBox::No) - != QMessageBox::Yes) { + QHelpFilterSettingsWidget::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()); + m_filterSettings.setCurrentFilter({}); } void QHelpFilterSettingsWidgetPrivate::addFilter(const QString &filterName, @@ -241,7 +275,6 @@ void QHelpFilterSettingsWidgetPrivate::removeFilter(const QString &filterName) m_itemToFilter.remove(item); m_filterToItem.remove(filterName); delete item; - m_filterSettings.removeFilter(filterName); } @@ -251,39 +284,32 @@ QString QHelpFilterSettingsWidgetPrivate::getUniqueFilterName(const QString &win Q_Q(QHelpFilterSettingsWidget); QString newFilterName = initialFilterName; - while (1) { + while (true) { QFilterNameDialog dialog(q); dialog.setWindowTitle(windowTitle); dialog.setFilterName(newFilterName); if (dialog.exec() == QDialog::Rejected) - return QString(); + return {}; newFilterName = dialog.filterName(); if (!m_filterToItem.contains(newFilterName)) break; if (QMessageBox::warning(q, QHelpFilterSettingsWidget::tr("Filter Exists"), - QHelpFilterSettingsWidget::tr("The filter \"%1\" already exists.") - .arg(newFilterName), - QMessageBox::Retry | QMessageBox::Cancel) - == QMessageBox::Cancel) { - return QString(); + QHelpFilterSettingsWidget::tr("The filter \"%1\" already exists.").arg(newFilterName), + QMessageBox::Retry | QMessageBox::Cancel) == QMessageBox::Cancel) { + return {}; } } - 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); - } - + while (m_filterToItem.contains(newFilterName)) + newFilterName = initialFilterName + u' ' + QString::number(++counter); return newFilterName; } @@ -319,22 +345,22 @@ QHelpFilterSettingsWidget::QHelpFilterSettingsWidget(QWidget *parent) d->m_ui.setupUi(this); // TODO: make resources configurable - QString resourcePath = QLatin1String(":/qt-project.org/assistant/images/"); + QString resourcePath = ":/qt-project.org/assistant/images/"_L1; #ifdef Q_OS_MACOS - resourcePath.append(QLatin1String("mac")); + resourcePath.append("mac"_L1); #else - resourcePath.append(QLatin1String("win")); + resourcePath.append("win"_L1); #endif - d->m_ui.addButton->setIcon(QIcon(resourcePath + QLatin1String("/plus.png"))); - d->m_ui.removeButton->setIcon(QIcon(resourcePath + QLatin1String("/minus.png"))); + d->m_ui.addButton->setIcon(QIcon(resourcePath + "/plus.png"_L1)); + d->m_ui.removeButton->setIcon(QIcon(resourcePath + "/minus.png"_L1)); connect(d->m_ui.componentWidget, &QOptionsWidget::optionSelectionChanged, - [this](const QStringList &options) { + this, [this](const QStringList &options) { Q_D(QHelpFilterSettingsWidget); d->componentsChanged(options); }); connect(d->m_ui.versionWidget, &QOptionsWidget::optionSelectionChanged, - [this](const QStringList &options) { + this, [this](const QStringList &options) { Q_D(QHelpFilterSettingsWidget); d->versionsChanged(options); }); @@ -344,24 +370,21 @@ QHelpFilterSettingsWidget::QHelpFilterSettingsWidget(QWidget *parent) d->updateCurrentFilter(); }); connect(d->m_ui.filterWidget, &QListWidget::itemDoubleClicked, - [this](QListWidgetItem *) { + this, [this](QListWidgetItem *) { Q_D(QHelpFilterSettingsWidget); d->renameFilterClicked(); }); // TODO: repeat these actions on context menu - connect(d->m_ui.addButton, &QAbstractButton::clicked, - [this]() { + connect(d->m_ui.addButton, &QAbstractButton::clicked, this, [this] { Q_D(QHelpFilterSettingsWidget); d->addFilterClicked(); }); - connect(d->m_ui.renameButton, &QAbstractButton::clicked, - [this]() { + connect(d->m_ui.renameButton, &QAbstractButton::clicked, this, [this] { Q_D(QHelpFilterSettingsWidget); d->renameFilterClicked(); }); - connect(d->m_ui.removeButton, &QAbstractButton::clicked, - [this]() { + connect(d->m_ui.removeButton, &QAbstractButton::clicked, this, [this] { Q_D(QHelpFilterSettingsWidget); d->removeFilterClicked(); }); @@ -406,7 +429,7 @@ void QHelpFilterSettingsWidget::setAvailableVersions(const QList<QVersionNumber> void QHelpFilterSettingsWidget::readSettings(const QHelpFilterEngine *filterEngine) { Q_D(QHelpFilterSettingsWidget); - const QHelpFilterSettings settings = QHelpFilterSettings::readSettings(filterEngine); + const QHelpFilterSettings settings = readSettingsHelper(filterEngine); d->setFilterSettings(settings); } @@ -418,7 +441,7 @@ void QHelpFilterSettingsWidget::readSettings(const QHelpFilterEngine *filterEngi bool QHelpFilterSettingsWidget::applySettings(QHelpFilterEngine *filterEngine) const { Q_D(const QHelpFilterSettingsWidget); - return QHelpFilterSettings::applySettings(filterEngine, d->filterSettings()); + return applySettingsHelper(filterEngine, d->filterSettings()); } QT_END_NAMESPACE diff --git a/src/assistant/help/qhelpfiltersettingswidget.h b/src/assistant/help/qhelpfiltersettingswidget.h index c3c77305f..136c4f703 100644 --- a/src/assistant/help/qhelpfiltersettingswidget.h +++ b/src/assistant/help/qhelpfiltersettingswidget.h @@ -1,41 +1,5 @@ -/**************************************************************************** -** -** 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$ -** -****************************************************************************/ +// Copyright (C) 2020 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only #ifndef QHELPFILTERSETTINGSWIDGET_H #define QHELPFILTERSETTINGSWIDGET_H @@ -46,10 +10,9 @@ QT_BEGIN_NAMESPACE -class QVersionNumber; - class QHelpFilterEngine; class QHelpFilterSettingsWidgetPrivate; +class QVersionNumber; class QHELP_EXPORT QHelpFilterSettingsWidget : public QWidget { diff --git a/src/assistant/help/qhelpindexwidget.cpp b/src/assistant/help/qhelpindexwidget.cpp index eaaf44ed3..39fc9f94c 100644 --- a/src/assistant/help/qhelpindexwidget.cpp +++ b/src/assistant/help/qhelpindexwidget.cpp @@ -1,151 +1,68 @@ -/**************************************************************************** -** -** Copyright (C) 2016 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$ -** -****************************************************************************/ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only #include "qhelpindexwidget.h" #include "qhelpenginecore.h" -#include "qhelpengine_p.h" -#include "qhelpdbreader_p.h" -#include "qhelpcollectionhandler_p.h" +#include "qhelplink.h" -#include <QtCore/QThread> -#include <QtCore/QMutex> -#include <QtHelp/QHelpLink> -#include <QtWidgets/QListView> -#include <QtWidgets/QHeaderView> - -#include <algorithm> +#if QT_CONFIG(future) +#include <QtCore/qfuturewatcher.h> +#endif QT_BEGIN_NAMESPACE -class QHelpIndexProvider : public QThread -{ -public: - QHelpIndexProvider(QHelpEnginePrivate *helpEngine); - ~QHelpIndexProvider() override; - void collectIndices(const QString &customFilterName); - void stopCollecting(); - QStringList indices() const; - -private: - void run() override; - - QHelpEnginePrivate *m_helpEngine; - QString m_currentFilter; - QStringList m_filterAttributes; - QStringList m_indices; - mutable QMutex m_mutex; -}; - class QHelpIndexModelPrivate { -public: - QHelpIndexModelPrivate(QHelpEnginePrivate *hE) - : helpEngine(hE), - indexProvider(new QHelpIndexProvider(helpEngine)) +#if QT_CONFIG(future) + using FutureProvider = std::function<QFuture<QStringList>()>; + + struct WatcherDeleter { - } + void operator()(QFutureWatcherBase *watcher) { + watcher->disconnect(); + watcher->cancel(); + watcher->waitForFinished(); + delete watcher; + } + }; +#endif - QHelpEnginePrivate *helpEngine; - QHelpIndexProvider *indexProvider; - QStringList indices; +public: +#if QT_CONFIG(future) + void createIndex(const FutureProvider &futureProvider); +#endif + + QHelpIndexModel *q = nullptr; + QHelpEngineCore *helpEngine = nullptr; + QStringList indices = {}; +#if QT_CONFIG(future) + std::unique_ptr<QFutureWatcher<QStringList>, WatcherDeleter> watcher = {}; +#endif }; -QHelpIndexProvider::QHelpIndexProvider(QHelpEnginePrivate *helpEngine) - : QThread(helpEngine), - m_helpEngine(helpEngine) -{ -} - -QHelpIndexProvider::~QHelpIndexProvider() +#if QT_CONFIG(future) +void QHelpIndexModelPrivate::createIndex(const FutureProvider &futureProvider) { - stopCollecting(); -} - -void QHelpIndexProvider::collectIndices(const QString &customFilterName) -{ - m_mutex.lock(); - m_currentFilter = customFilterName; - m_filterAttributes = m_helpEngine->q->filterAttributes(customFilterName); - m_mutex.unlock(); - - if (isRunning()) - stopCollecting(); - start(LowPriority); -} - -void QHelpIndexProvider::stopCollecting() -{ - if (!isRunning()) - return; - wait(); -} - -QStringList QHelpIndexProvider::indices() const -{ - QMutexLocker lck(&m_mutex); - return m_indices; -} - -void QHelpIndexProvider::run() -{ - m_mutex.lock(); - const QString currentFilter = m_currentFilter; - const QStringList attributes = m_filterAttributes; - const QString collectionFile = m_helpEngine->collectionHandler->collectionFile(); - m_indices = QStringList(); - m_mutex.unlock(); - - if (collectionFile.isEmpty()) - return; + const bool wasRunning = bool(watcher); + watcher.reset(new QFutureWatcher<QStringList>); + QObject::connect(watcher.get(), &QFutureWatcherBase::finished, q, [this] { + if (!watcher->isCanceled()) { + indices = watcher->result(); + q->filter({}); + } + watcher.release()->deleteLater(); + emit q->indexCreated(); + }); + watcher->setFuture(futureProvider()); - QHelpCollectionHandler collectionHandler(collectionFile); - if (!collectionHandler.openCollectionFile()) + if (wasRunning) return; - const QStringList result = m_helpEngine->usesFilterEngine - ? collectionHandler.indicesForFilter(currentFilter) - : collectionHandler.indicesForFilter(attributes); - - m_mutex.lock(); - m_indices = result; - m_mutex.unlock(); + indices.clear(); + q->filter({}); + emit q->indexCreationStarted(); } +#endif /*! \class QHelpIndexModel @@ -153,8 +70,6 @@ void QHelpIndexProvider::run() \inmodule QtHelp \brief The QHelpIndexModel class provides a model that supplies index keywords to views. - - */ /*! @@ -173,14 +88,10 @@ void QHelpIndexProvider::run() This signal is emitted when the index has been created. */ -QHelpIndexModel::QHelpIndexModel(QHelpEnginePrivate *helpEngine) +QHelpIndexModel::QHelpIndexModel(QHelpEngineCore *helpEngine) : QStringListModel(helpEngine) -{ - d = new QHelpIndexModelPrivate(helpEngine); - - connect(d->indexProvider, &QThread::finished, - this, &QHelpIndexModel::insertIndices); -} + , d(new QHelpIndexModelPrivate{this, helpEngine}) +{} QHelpIndexModel::~QHelpIndexModel() { @@ -188,38 +99,43 @@ QHelpIndexModel::~QHelpIndexModel() } /*! - Creates a new index by querying the help system for - keywords for the specified \a customFilterName. + \since 6.8 + + Creates a new index by querying the help system for keywords for the current filter. */ -void QHelpIndexModel::createIndex(const QString &customFilterName) +void QHelpIndexModel::createIndexForCurrentFilter() { - const bool running = d->indexProvider->isRunning(); - d->indexProvider->collectIndices(customFilterName); - if (running) - return; - - d->indices = QStringList(); - filter(QString()); - emit indexCreationStarted(); +#if QT_CONFIG(future) + d->createIndex([this] { return d->helpEngine->requestIndexForCurrentFilter(); }); +#endif } -void QHelpIndexModel::insertIndices() +/*! + Creates a new index by querying the help system for + keywords for the specified custom \a filter name. +*/ +void QHelpIndexModel::createIndex(const QString &filter) { - if (d->indexProvider->isRunning()) - return; - - d->indices = d->indexProvider->indices(); - filter(QString()); - emit indexCreated(); +#if QT_CONFIG(future) + d->createIndex([this, filter] { return d->helpEngine->requestIndex(filter); }); +#endif } +// TODO: Remove me +void QHelpIndexModel::insertIndices() +{} + /*! Returns true if the index is currently built up, otherwise false. */ bool QHelpIndexModel::isCreatingIndex() const { - return d->indexProvider->isRunning(); +#if QT_CONFIG(future) + return bool(d->watcher); +#else + return false; +#endif } /*! @@ -229,7 +145,7 @@ bool QHelpIndexModel::isCreatingIndex() const */ QHelpEngineCore *QHelpIndexModel::helpEngine() const { - return d->helpEngine->q; + return d->helpEngine; } /*! @@ -246,58 +162,47 @@ QModelIndex QHelpIndexModel::filter(const QString &filter, const QString &wildca { if (filter.isEmpty()) { setStringList(d->indices); - return index(-1, 0, QModelIndex()); + return index(-1, 0, {}); } - QStringList lst; - int goodMatch = -1; - int perfectMatch = -1; - - if (!wildcard.isEmpty()) { - auto re = QRegularExpression::wildcardToRegularExpression(wildcard, - QRegularExpression::UnanchoredWildcardConversion); - const QRegularExpression regExp(re, QRegularExpression::CaseInsensitiveOption); - for (const QString &index : qAsConst(d->indices)) { - if (index.contains(regExp)) { - lst.append(index); + using Checker = std::function<bool(const QString &)>; + const auto checkIndices = [this, filter](const Checker &checker) { + QStringList filteredList; + int goodMatch = -1; + int perfectMatch = -1; + for (const QString &index : std::as_const(d->indices)) { + if (checker(index)) { + filteredList.append(index); if (perfectMatch == -1 && index.startsWith(filter, Qt::CaseInsensitive)) { if (goodMatch == -1) - goodMatch = lst.count() - 1; - if (filter.length() == index.length()){ - perfectMatch = lst.count() - 1; - } + goodMatch = filteredList.size() - 1; + if (filter.size() == index.size()) + perfectMatch = filteredList.size() - 1; } else if (perfectMatch > -1 && index == filter) { - perfectMatch = lst.count() - 1; - } - } - } - } else { - for (const QString &index : qAsConst(d->indices)) { - if (index.contains(filter, Qt::CaseInsensitive)) { - lst.append(index); - if (perfectMatch == -1 && index.startsWith(filter, Qt::CaseInsensitive)) { - if (goodMatch == -1) - goodMatch = lst.count() - 1; - if (filter.length() == index.length()){ - perfectMatch = lst.count() - 1; - } - } else if (perfectMatch > -1 && index == filter) { - perfectMatch = lst.count() - 1; + perfectMatch = filteredList.size() - 1; } } } + setStringList(filteredList); + return perfectMatch >= 0 ? perfectMatch : qMax(0, goodMatch); + }; + int perfectMatch = -1; + if (!wildcard.isEmpty()) { + const auto re = QRegularExpression::wildcardToRegularExpression(wildcard, + QRegularExpression::UnanchoredWildcardConversion); + const QRegularExpression regExp(re, QRegularExpression::CaseInsensitiveOption); + perfectMatch = checkIndices([regExp](const QString &index) { + return index.contains(regExp); + }); + } else { + perfectMatch = checkIndices([filter](const QString &index) { + return index.contains(filter, Qt::CaseInsensitive); + }); } - - if (perfectMatch == -1) - perfectMatch = qMax(0, goodMatch); - - setStringList(lst); - return index(perfectMatch, 0, QModelIndex()); + return index(perfectMatch, 0, {}); } - - /*! \class QHelpIndexWidget \inmodule QtHelp @@ -342,12 +247,10 @@ QModelIndex QHelpIndexModel::filter(const QString &filter, const QString &wildca */ QHelpIndexWidget::QHelpIndexWidget() - : QListView(nullptr) { setEditTriggers(QAbstractItemView::NoEditTriggers); setUniformItemSizes(true); - connect(this, &QAbstractItemView::activated, - this, &QHelpIndexWidget::showLink); + connect(this, &QAbstractItemView::activated, this, &QHelpIndexWidget::showLink); } void QHelpIndexWidget::showLink(const QModelIndex &index) @@ -363,8 +266,9 @@ void QHelpIndexWidget::showLink(const QModelIndex &index) const QString name = v.isValid() ? v.toString() : QString(); const QList<QHelpLink> &docs = indexModel->helpEngine()->documentsForKeyword(name); - if (docs.count() > 1) { + if (docs.size() > 1) { emit documentsActivated(docs, name); +#if QT_DEPRECATED_SINCE(5, 15) QT_WARNING_PUSH QT_WARNING_DISABLE_DEPRECATED QMultiMap<QString, QUrl> links; @@ -372,12 +276,15 @@ void QHelpIndexWidget::showLink(const QModelIndex &index) links.insert(doc.title, doc.url); emit linksActivated(links, name); QT_WARNING_POP +#endif } else if (!docs.isEmpty()) { emit documentActivated(docs.first(), name); +#if QT_DEPRECATED_SINCE(5, 15) QT_WARNING_PUSH QT_WARNING_DISABLE_DEPRECATED emit linkActivated(docs.first().url, name); QT_WARNING_POP +#endif } } @@ -399,7 +306,7 @@ void QHelpIndexWidget::activateCurrentItem() */ void QHelpIndexWidget::filterIndices(const QString &filter, const QString &wildcard) { - QHelpIndexModel *indexModel = qobject_cast<QHelpIndexModel*>(model()); + QHelpIndexModel *indexModel = qobject_cast<QHelpIndexModel *>(model()); if (!indexModel) return; const QModelIndex &idx = indexModel->filter(filter, wildcard); diff --git a/src/assistant/help/qhelpindexwidget.h b/src/assistant/help/qhelpindexwidget.h index e3ffcba80..c3518367b 100644 --- a/src/assistant/help/qhelpindexwidget.h +++ b/src/assistant/help/qhelpindexwidget.h @@ -1,56 +1,20 @@ -/**************************************************************************** -** -** Copyright (C) 2016 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$ -** -****************************************************************************/ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only #ifndef QHELPINDEXWIDGET_H #define QHELPINDEXWIDGET_H #include <QtHelp/qhelp_global.h> -#include <QtCore/QUrl> -#include <QtCore/QStringListModel> -#include <QtWidgets/QListView> +#include <QtCore/qstringlistmodel.h> +#include <QtCore/qurl.h> -QT_BEGIN_NAMESPACE +#include <QtWidgets/qlistview.h> +QT_BEGIN_NAMESPACE -class QHelpEnginePrivate; class QHelpEngineCore; +class QHelpEnginePrivate; class QHelpIndexModelPrivate; struct QHelpLink; @@ -59,9 +23,9 @@ class QHELP_EXPORT QHelpIndexModel : public QStringListModel Q_OBJECT public: + void createIndexForCurrentFilter(); void createIndex(const QString &customFilterName); - QModelIndex filter(const QString &filter, - const QString &wildcard = QString()); + QModelIndex filter(const QString &filter, const QString &wildcard = {}); bool isCreatingIndex() const; QHelpEngineCore *helpEngine() const; @@ -74,7 +38,7 @@ private Q_SLOTS: void insertIndices(); private: - QHelpIndexModel(QHelpEnginePrivate *helpEngine); + QHelpIndexModel(QHelpEngineCore *helpEngine); ~QHelpIndexModel(); QHelpIndexModelPrivate *d; @@ -93,14 +57,11 @@ Q_SIGNALS: QT_DEPRECATED_X("Use documentsActivated() instead") void linksActivated(const QMultiMap<QString, QUrl> &links, const QString &keyword); #endif - void documentActivated(const QHelpLink &document, - const QString &keyword); - void documentsActivated(const QList<QHelpLink> &documents, - const QString &keyword); + void documentActivated(const QHelpLink &document, const QString &keyword); + void documentsActivated(const QList<QHelpLink> &documents, const QString &keyword); public Q_SLOTS: - void filterIndices(const QString &filter, - const QString &wildcard = QString()); + void filterIndices(const QString &filter, const QString &wildcard = {}); void activateCurrentItem(); private Q_SLOTS: @@ -113,4 +74,4 @@ private: QT_END_NAMESPACE -#endif +#endif // QHELPINDEXWIDGET_H diff --git a/src/assistant/help/qhelplink.cpp b/src/assistant/help/qhelplink.cpp index 75cb16ab8..91c1f4fbc 100644 --- a/src/assistant/help/qhelplink.cpp +++ b/src/assistant/help/qhelplink.cpp @@ -1,41 +1,5 @@ -/**************************************************************************** -** -** 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$ -** -****************************************************************************/ +// Copyright (C) 2020 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only #include "qhelplink.h" diff --git a/src/assistant/help/qhelplink.h b/src/assistant/help/qhelplink.h index 92b5ec6d0..831c4a3dd 100644 --- a/src/assistant/help/qhelplink.h +++ b/src/assistant/help/qhelplink.h @@ -1,48 +1,12 @@ -/**************************************************************************** -** -** 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$ -** -****************************************************************************/ +// Copyright (C) 2020 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only #ifndef QHELPLINK_H #define QHELPLINK_H #include <QtHelp/qhelp_global.h> -#include <QtCore/QUrl> +#include <QtCore/qurl.h> QT_BEGIN_NAMESPACE diff --git a/src/assistant/help/qhelpsearchengine.cpp b/src/assistant/help/qhelpsearchengine.cpp index 1053a9b6e..43f41deb9 100644 --- a/src/assistant/help/qhelpsearchengine.cpp +++ b/src/assistant/help/qhelpsearchengine.cpp @@ -1,276 +1,22 @@ -/**************************************************************************** -** -** Copyright (C) 2016 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$ -** -****************************************************************************/ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only -#include "qhelpenginecore.h" #include "qhelpsearchengine.h" +#include "qhelpenginecore.h" +#include "qhelpsearchenginecore.h" #include "qhelpsearchquerywidget.h" #include "qhelpsearchresultwidget.h" -#include "qhelpsearchindexreader_p.h" -#include "qhelpsearchindexreader_default_p.h" -#include "qhelpsearchindexwriter_default_p.h" - -#include <QtCore/QDir> -#include <QtCore/QFile> -#include <QtCore/QFileInfo> -#include <QtCore/QVariant> -#include <QtCore/QThread> -#include <QtCore/QPointer> -#include <QtCore/QTimer> - QT_BEGIN_NAMESPACE -using namespace fulltextsearch::qt; - -class QHelpSearchResultData : public QSharedData +class QHelpSearchEnginePrivate { public: - QUrl m_url; - QString m_title; - QString m_snippet; -}; - -/*! - \class QHelpSearchResult - \since 5.9 - \inmodule QtHelp - \brief The QHelpSearchResult class provides the data associated with the - search result. - - The QHelpSearchResult object is a data object that describes a single search result. - The vector of search result objects is returned by QHelpSearchEngine::searchResults(). - The description of the search result contains the document title and URL - that the search input matched. It also contains the snippet from - the document content containing the best match of the search input. - \sa QHelpSearchEngine -*/ - -/*! - Constructs a new empty QHelpSearchResult. -*/ -QHelpSearchResult::QHelpSearchResult() - : d(new QHelpSearchResultData) -{ -} - -/*! - Constructs a copy of \a other. -*/ -QHelpSearchResult::QHelpSearchResult(const QHelpSearchResult &other) - : d(other.d) -{ -} - -/*! - Constructs the search result containing \a url, \a title and \a snippet - as the description of the result. -*/ -QHelpSearchResult::QHelpSearchResult(const QUrl &url, const QString &title, const QString &snippet) - : d(new QHelpSearchResultData) -{ - d->m_url = url; - d->m_title = title; - d->m_snippet = snippet; -} - -/*! - Destroys the search result. -*/ -QHelpSearchResult::~QHelpSearchResult() -{ -} - -/*! - Assigns \a other to this search result and returns a reference to this search result. -*/ -QHelpSearchResult &QHelpSearchResult::operator=(const QHelpSearchResult &other) -{ - d = other.d; - return *this; -} - -/*! - Returns the document title of the search result. -*/ -QString QHelpSearchResult::title() const -{ - return d->m_title; -} - -/*! - Returns the document URL of the search result. -*/ -QUrl QHelpSearchResult::url() const -{ - return d->m_url; -} - -/*! - Returns the document snippet containing the search phrase of the search result. -*/ -QString QHelpSearchResult::snippet() const -{ - return d->m_snippet; -} - - -class QHelpSearchEnginePrivate : public QObject -{ - Q_OBJECT - -signals: - void indexingStarted(); - void indexingFinished(); - - void searchingStarted(); - void searchingFinished(int searchResultCount); - -private: - QHelpSearchEnginePrivate(QHelpEngineCore *helpEngine) - : helpEngine(helpEngine) - { - } - - ~QHelpSearchEnginePrivate() - { - delete indexReader; - delete indexWriter; - } - - int searchResultCount() const - { - return indexReader ? indexReader->searchResultCount() : 0; - } - - QList<QHelpSearchResult> searchResults(int start, int end) const - { - return indexReader ? - indexReader->searchResults(start, end) : - QList<QHelpSearchResult>(); - } - - void updateIndex(bool reindex = false) - { - if (helpEngine.isNull()) - return; - - if (!QFile::exists(QFileInfo(helpEngine->collectionFile()).path())) - return; - - if (!indexWriter) { - indexWriter = new QHelpSearchIndexWriter(); - - connect(indexWriter, &QHelpSearchIndexWriter::indexingStarted, - this, &QHelpSearchEnginePrivate::indexingStarted); - connect(indexWriter, &QHelpSearchIndexWriter::indexingFinished, - this, &QHelpSearchEnginePrivate::indexingFinished); - } - - indexWriter->cancelIndexing(); - indexWriter->updateIndex(helpEngine->collectionFile(), - indexFilesFolder(), reindex); - } - - void cancelIndexing() - { - if (indexWriter) - indexWriter->cancelIndexing(); - } - - void search(const QString &searchInput) - { - if (helpEngine.isNull()) - return; - - if (!QFile::exists(QFileInfo(helpEngine->collectionFile()).path())) - return; - - if (!indexReader) { - indexReader = new QHelpSearchIndexReaderDefault(); - connect(indexReader, &fulltextsearch::QHelpSearchIndexReader::searchingStarted, - this, &QHelpSearchEnginePrivate::searchingStarted); - connect(indexReader, &fulltextsearch::QHelpSearchIndexReader::searchingFinished, - this, &QHelpSearchEnginePrivate::searchingFinished); - } - - m_searchInput = searchInput; - indexReader->cancelSearching(); - indexReader->search(helpEngine->collectionFile(), indexFilesFolder(), - searchInput, helpEngine->usesFilterEngine()); - } - - void cancelSearching() - { - if (indexReader) - indexReader->cancelSearching(); - } - - QString indexFilesFolder() const - { - QString indexFilesFolder = QLatin1String(".fulltextsearch"); - if (helpEngine && !helpEngine->collectionFile().isEmpty()) { - QFileInfo fi(helpEngine->collectionFile()); - indexFilesFolder = fi.absolutePath() + QDir::separator() - + QLatin1Char('.') - + fi.fileName().left(fi.fileName().lastIndexOf(QLatin1String(".qhc"))); - } - return indexFilesFolder; - } - -private: - friend class QHelpSearchEngine; - - bool m_isIndexingScheduled = false; - + QHelpSearchEngineCore m_searchEngine; QHelpSearchQueryWidget *queryWidget = nullptr; QHelpSearchResultWidget *resultWidget = nullptr; - - fulltextsearch::QHelpSearchIndexReader *indexReader = nullptr; - QHelpSearchIndexWriter *indexWriter = nullptr; - - QPointer<QHelpEngineCore> helpEngine; - - QString m_searchInput; }; -#include "qhelpsearchengine.moc" - /*! \class QHelpSearchQuery \deprecated @@ -386,19 +132,15 @@ private: */ QHelpSearchEngine::QHelpSearchEngine(QHelpEngineCore *helpEngine, QObject *parent) : QObject(parent) + , d(new QHelpSearchEnginePrivate{QHelpSearchEngineCore(helpEngine)}) { - d = new QHelpSearchEnginePrivate(helpEngine); - - connect(helpEngine, &QHelpEngineCore::setupFinished, - this, &QHelpSearchEngine::scheduleIndexDocumentation); - - connect(d, &QHelpSearchEnginePrivate::indexingStarted, + connect(&d->m_searchEngine, &QHelpSearchEngineCore::indexingStarted, this, &QHelpSearchEngine::indexingStarted); - connect(d, &QHelpSearchEnginePrivate::indexingFinished, + connect(&d->m_searchEngine, &QHelpSearchEngineCore::indexingFinished, this, &QHelpSearchEngine::indexingFinished); - connect(d, &QHelpSearchEnginePrivate::searchingStarted, + connect(&d->m_searchEngine, &QHelpSearchEngineCore::searchingStarted, this, &QHelpSearchEngine::searchingStarted); - connect(d, &QHelpSearchEnginePrivate::searchingFinished, + connect(&d->m_searchEngine, &QHelpSearchEngineCore::searchingFinished, this, &QHelpSearchEngine::searchingFinished); } @@ -418,7 +160,6 @@ QHelpSearchQueryWidget* QHelpSearchEngine::queryWidget() { if (!d->queryWidget) d->queryWidget = new QHelpSearchQueryWidget(); - return d->queryWidget; } @@ -429,17 +170,17 @@ QHelpSearchResultWidget* QHelpSearchEngine::resultWidget() { if (!d->resultWidget) d->resultWidget = new QHelpSearchResultWidget(this); - return d->resultWidget; } +#if QT_DEPRECATED_SINCE(5, 9) /*! \deprecated Use searchResultCount() instead. */ int QHelpSearchEngine::hitsCount() const { - return d->searchResultCount(); + return searchResultCount(); } /*! @@ -449,8 +190,9 @@ int QHelpSearchEngine::hitsCount() const */ int QHelpSearchEngine::hitCount() const { - return d->searchResultCount(); + return searchResultCount(); } +#endif // QT_DEPRECATED_SINCE(5, 9) /*! \since 5.9 @@ -458,9 +200,10 @@ int QHelpSearchEngine::hitCount() const */ int QHelpSearchEngine::searchResultCount() const { - return d->searchResultCount(); + return d->m_searchEngine.searchResultCount(); } +#if QT_DEPRECATED_SINCE(5, 9) /*! \typedef QHelpSearchEngine::SearchHit \deprecated @@ -484,6 +227,7 @@ QList<QHelpSearchEngine::SearchHit> QHelpSearchEngine::hits(int start, int end) hits.append(qMakePair(result.url().toString(), result.title())); return hits; } +#endif // QT_DEPRECATED_SINCE(5, 9) /*! \since 5.9 @@ -492,7 +236,7 @@ QList<QHelpSearchEngine::SearchHit> QHelpSearchEngine::hits(int start, int end) */ QList<QHelpSearchResult> QHelpSearchEngine::searchResults(int start, int end) const { - return d->searchResults(start, end); + return d->m_searchEngine.searchResults(start, end); } /*! @@ -501,9 +245,12 @@ QList<QHelpSearchResult> QHelpSearchEngine::searchResults(int start, int end) co */ QString QHelpSearchEngine::searchInput() const { - return d->m_searchInput; + return d->m_searchEngine.searchInput(); } +#if QT_DEPRECATED_SINCE(5, 9) +QT_WARNING_PUSH +QT_WARNING_DISABLE_DEPRECATED /*! \deprecated \since 4.5 @@ -511,16 +258,17 @@ QString QHelpSearchEngine::searchInput() const */ QList<QHelpSearchQuery> QHelpSearchEngine::query() const { - return QList<QHelpSearchQuery>() << QHelpSearchQuery(QHelpSearchQuery::DEFAULT, - d->m_searchInput.split(QChar::Space)); + return {{QHelpSearchQuery::DEFAULT, searchInput().split(QChar::Space)}}; } +QT_WARNING_POP +#endif // QT_DEPRECATED_SINCE(5, 9) /*! Forces the search engine to reindex all documentation files. */ void QHelpSearchEngine::reindexDocumentation() { - d->updateIndex(true); + d->m_searchEngine.reindexDocumentation(); } /*! @@ -528,7 +276,7 @@ void QHelpSearchEngine::reindexDocumentation() */ void QHelpSearchEngine::cancelIndexing() { - d->cancelIndexing(); + d->m_searchEngine.cancelIndexing(); } /*! @@ -536,7 +284,7 @@ void QHelpSearchEngine::cancelIndexing() */ void QHelpSearchEngine::cancelSearching() { - d->cancelSearching(); + d->m_searchEngine.cancelSearching(); } /*! @@ -558,9 +306,10 @@ void QHelpSearchEngine::cancelSearching() */ void QHelpSearchEngine::search(const QString &searchInput) { - d->search(searchInput); + d->m_searchEngine.search(searchInput); } +#if QT_DEPRECATED_SINCE(5, 9) /*! \deprecated Use search(const QString &searchInput) instead. @@ -570,25 +319,20 @@ void QHelpSearchEngine::search(const QList<QHelpSearchQuery> &queryList) if (queryList.isEmpty()) return; - d->search(queryList.first().wordList.join(QChar::Space)); + d->m_searchEngine.search(queryList.first().wordList.join(QChar::Space)); } +#endif // QT_DEPRECATED_SINCE(5, 9) /*! \internal */ void QHelpSearchEngine::scheduleIndexDocumentation() { - if (d->m_isIndexingScheduled) - return; - - d->m_isIndexingScheduled = true; - QTimer::singleShot(0, this, &QHelpSearchEngine::indexDocumentation); + d->m_searchEngine.scheduleIndexDocumentation(); } +// TODO: Deprecate me (but it's private???) void QHelpSearchEngine::indexDocumentation() -{ - d->m_isIndexingScheduled = false; - d->updateIndex(); -} +{} QT_END_NAMESPACE diff --git a/src/assistant/help/qhelpsearchengine.h b/src/assistant/help/qhelpsearchengine.h index f1ddb1634..f782e6174 100644 --- a/src/assistant/help/qhelpsearchengine.h +++ b/src/assistant/help/qhelpsearchengine.h @@ -1,93 +1,40 @@ -/**************************************************************************** -** -** Copyright (C) 2016 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$ -** -****************************************************************************/ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only #ifndef QHELPSEARCHENGINE_H #define QHELPSEARCHENGINE_H #include <QtHelp/qhelp_global.h> +#include <QtHelp/qhelpsearchresult.h> -#include <QtCore/QMap> -#include <QtCore/QUrl> -#include <QtCore/QObject> -#include <QtCore/QSharedDataPointer> -#include <QtCore/QString> -#include <QtCore/QStringList> +#include <QtCore/qobject.h> +#include <QtCore/qshareddata.h> +#include <QtCore/qstringlist.h> QT_BEGIN_NAMESPACE class QHelpEngineCore; -class QHelpSearchQueryWidget; class QHelpSearchEnginePrivate; -class QHelpSearchResultData; +class QHelpSearchQueryWidget; class QHelpSearchResultWidget; +#if QT_DEPRECATED_SINCE(6, 7) class QHELP_EXPORT QHelpSearchQuery { public: enum FieldName { DEFAULT = 0, FUZZY, WITHOUT, PHRASE, ALL, ATLEAST }; + QT_DEPRECATED_VERSION_X_6_7("Use QString instead") QHelpSearchQuery() : fieldName(DEFAULT) { wordList.clear(); } + QT_DEPRECATED_VERSION_X_6_7("Use QString instead") QHelpSearchQuery(FieldName field, const QStringList &wordList_) : fieldName(field), wordList(wordList_) {} FieldName fieldName; QStringList wordList; }; - -class QHELP_EXPORT QHelpSearchResult -{ -public: - QHelpSearchResult(); - QHelpSearchResult(const QHelpSearchResult &other); - QHelpSearchResult(const QUrl &url, const QString &title, const QString &snippet); - ~QHelpSearchResult(); - - QHelpSearchResult &operator=(const QHelpSearchResult &other); - - QString title() const; - QUrl url() const; - QString snippet() const; - -private: - QSharedDataPointer<QHelpSearchResultData> d; -}; +#endif // QT_DEPRECATED_SINCE(6, 7) class QHELP_EXPORT QHelpSearchEngine : public QObject { @@ -97,8 +44,8 @@ public: explicit QHelpSearchEngine(QHelpEngineCore *helpEngine, QObject *parent = nullptr); ~QHelpSearchEngine(); - QHelpSearchQueryWidget* queryWidget(); - QHelpSearchResultWidget* resultWidget(); + QHelpSearchQueryWidget *queryWidget(); + QHelpSearchResultWidget *resultWidget(); #if QT_DEPRECATED_SINCE(5, 9) typedef QPair<QString, QString> SearchHit; @@ -142,4 +89,4 @@ private: QT_END_NAMESPACE -#endif // QHELPSEARCHENGINE_H +#endif // QHELPSEARCHENGINE_H diff --git a/src/assistant/help/qhelpsearchenginecore.cpp b/src/assistant/help/qhelpsearchenginecore.cpp new file mode 100644 index 000000000..5ed8f453d --- /dev/null +++ b/src/assistant/help/qhelpsearchenginecore.cpp @@ -0,0 +1,256 @@ +// Copyright (C) 2024 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#include "qhelpsearchenginecore.h" +#include "qhelpenginecore.h" + +#include "qhelpsearchindexreader_p.h" +#include "qhelpsearchindexwriter_p.h" + +#include <QtCore/qdir.h> +#include <QtCore/qfile.h> +#include <QtCore/qfileinfo.h> +#include <QtCore/qpointer.h> +#include <QtCore/qtimer.h> + +QT_BEGIN_NAMESPACE + +using namespace fulltextsearch; +using namespace Qt::StringLiterals; + +class QHelpSearchEngineCorePrivate +{ +public: + QString indexFilesFolder() const + { + QString indexFilesFolder = ".fulltextsearch"_L1; + if (m_helpEngine && !m_helpEngine->collectionFile().isEmpty()) { + const QFileInfo fi(m_helpEngine->collectionFile()); + indexFilesFolder = fi.absolutePath() + QDir::separator() + u'.' + + fi.fileName().left(fi.fileName().lastIndexOf(".qhc"_L1)); + } + return indexFilesFolder; + } + + void updateIndex(bool reindex) + { + if (m_helpEngine.isNull()) + return; + + if (!QFile::exists(QFileInfo(m_helpEngine->collectionFile()).path())) + return; + + if (!m_indexWriter) { + m_indexWriter.reset(new QHelpSearchIndexWriter); + + QObject::connect(m_indexWriter.get(), &QHelpSearchIndexWriter::indexingStarted, + q, &QHelpSearchEngineCore::indexingStarted); + QObject::connect(m_indexWriter.get(), &QHelpSearchIndexWriter::indexingFinished, + q, &QHelpSearchEngineCore::indexingFinished); + } + + m_indexWriter->cancelIndexing(); + m_indexWriter->updateIndex(m_helpEngine->collectionFile(), indexFilesFolder(), reindex); + } + + void search(const QString &searchInput) + { + if (m_helpEngine.isNull()) + return; + + if (!QFile::exists(QFileInfo(m_helpEngine->collectionFile()).path())) + return; + + if (!m_indexReader) { + m_indexReader.reset(new QHelpSearchIndexReader); + QObject::connect(m_indexReader.get(), &QHelpSearchIndexReader::searchingStarted, + q, &QHelpSearchEngineCore::searchingStarted); + QObject::connect(m_indexReader.get(), &QHelpSearchIndexReader::searchingFinished, + q, &QHelpSearchEngineCore::searchingFinished); + } + + m_searchInput = searchInput; + m_indexReader->cancelSearching(); + m_indexReader->search(m_helpEngine->collectionFile(), indexFilesFolder(), searchInput, + m_helpEngine->usesFilterEngine()); + } + + QHelpSearchEngineCore *q = nullptr; + + bool m_isIndexingScheduled = false; + + std::unique_ptr<QHelpSearchIndexReader> m_indexReader; + std::unique_ptr<QHelpSearchIndexWriter> m_indexWriter; + + QPointer<QHelpEngineCore> m_helpEngine; + QString m_searchInput; +}; + +/*! + \class QHelpSearchEngineCore + \since 6.8 + \inmodule QtHelp + \brief The QHelpSearchEngineCore class provides access to index and + search documentation. + + Before the search engine can be used, one has to instantiate at least a + QHelpEngineCore object that needs to be passed to the search engines constructor. + This is required as the search engine needs to be connected to the help + engines setupFinished() signal to know when it can start to index documentation. + + After starting the indexing process the signal indexingStarted() is emitted and + on the end of the indexing process the indexingFinished() is emitted. To stop + the indexing one can call cancelIndexing(). + + When the indexing process has finished, the search engine can be used to + search through the index for a given term using the search() function. When + the search input is passed to the search engine, the searchingStarted() + signal is emitted. When the search finishes, the searchingFinished() signal + is emitted. The search process can be stopped by calling cancelSearching(). + + If the search succeeds, searchingFinished() is called with the search result + count to fetch the search results from the search engine. Calling the + searchResults() function with a range returns a list of QHelpSearchResult + objects within the range. The results consist of the document title and URL, + as well as a snippet from the document that contains the best match for the + search input. +*/ + +/*! + \fn void QHelpSearchEngineCore::indexingStarted() + + This signal is emitted when indexing process is started. +*/ + +/*! + \fn void QHelpSearchEngineCore::indexingFinished() + + This signal is emitted when the indexing process is complete. +*/ + +/*! + \fn void QHelpSearchEngineCore::searchingStarted() + + This signal is emitted when the search process is started. +*/ + +/*! + \fn void QHelpSearchEngineCore::searchingFinished(int searchResultCount) + + This signal is emitted when the search process is complete. + The search result count is stored in \a searchResultCount. +*/ + +/*! + Constructs a new search engine. The search engine uses the given + \a helpEngine to access the documentation that needs to be indexed. + The QHelpEngine's setupFinished() signal is automatically connected to the + QHelpSearchEngineCore's indexing function, so that new documentation will + be indexed after the signal is emitted. +*/ +QHelpSearchEngineCore::QHelpSearchEngineCore(QHelpEngineCore *helpEngine) + : d(new QHelpSearchEngineCorePrivate) +{ + d->q = this; + d->m_helpEngine = helpEngine; + connect(helpEngine, &QHelpEngineCore::setupFinished, + this, &QHelpSearchEngineCore::scheduleIndexDocumentation); +} + +/*! + Destructs the search engine. +*/ +QHelpSearchEngineCore::~QHelpSearchEngineCore() +{ + delete d; +} + +/*! + Returns the number of results the search engine found. +*/ +int QHelpSearchEngineCore::searchResultCount() const +{ + return d->m_indexReader ? d->m_indexReader->searchResultCount() : 0;; +} + +/*! + Returns a list of search results within the range from the index + specified by \a start to the index specified by \a end. +*/ +QList<QHelpSearchResult> QHelpSearchEngineCore::searchResults(int start, int end) const +{ + return d->m_indexReader ? d->m_indexReader->searchResults(start, end) + : QList<QHelpSearchResult>(); +} + +/*! + Returns the phrase that was last searched for. +*/ +QString QHelpSearchEngineCore::searchInput() const +{ + return d->m_searchInput; +} + +/*! + Forces the search engine to reindex all documentation files. +*/ +void QHelpSearchEngineCore::reindexDocumentation() +{ + d->updateIndex(true); +} + +/*! + Stops the indexing process. +*/ +void QHelpSearchEngineCore::cancelIndexing() +{ + if (d->m_indexWriter) + d->m_indexWriter->cancelIndexing(); +} + +/*! + Stops the search process. +*/ +void QHelpSearchEngineCore::cancelSearching() +{ + if (d->m_indexReader) + d->m_indexReader->cancelSearching(); +} + +/*! + Starts the search process using the given search phrase \a searchInput. + + The phrase may consist of several words. By default, the search engine returns + the list of documents that contain all the specified words. + The phrase may contain any combination of the logical operators AND, OR, and + NOT. The operator must be written in all capital letters, otherwise it will + be considered a part of the search phrase. + + If double quotation marks are used to group the words, + the search engine will search for an exact match of the quoted phrase. + + For more information about the text query syntax, + see \l {https://sqlite.org/fts5.html#full_text_query_syntax} + {SQLite FTS5 Extension}. +*/ +void QHelpSearchEngineCore::search(const QString &searchInput) +{ + d->search(searchInput); +} + +/*! + \internal +*/ +void QHelpSearchEngineCore::scheduleIndexDocumentation() +{ + if (d->m_isIndexingScheduled) + return; + + d->m_isIndexingScheduled = true; + QTimer::singleShot(0, this, [this] { + d->m_isIndexingScheduled = false; + d->updateIndex(false); + }); +} + +QT_END_NAMESPACE diff --git a/src/assistant/help/qhelpsearchenginecore.h b/src/assistant/help/qhelpsearchenginecore.h new file mode 100644 index 000000000..df4e4fabd --- /dev/null +++ b/src/assistant/help/qhelpsearchenginecore.h @@ -0,0 +1,51 @@ +// Copyright (C) 2024 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#ifndef QHELPSEARCHENGINECORE_H +#define QHELPSEARCHENGINECORE_H + +#include <QtHelp/qhelp_global.h> +#include <QtHelp/qhelpsearchresult.h> + +#include <QtCore/qobject.h> +#include <QtCore/qshareddata.h> + +QT_BEGIN_NAMESPACE + +class QHelpEngineCore; +class QHelpSearchEngineCorePrivate; + +class QHELP_EXPORT QHelpSearchEngineCore : public QObject +{ + Q_OBJECT + +public: + explicit QHelpSearchEngineCore(QHelpEngineCore *helpEngine); + ~QHelpSearchEngineCore(); + + int searchResultCount() const; + QList<QHelpSearchResult> searchResults(int start, int end) const; + QString searchInput() const; + + void reindexDocumentation(); + void cancelIndexing(); + + void search(const QString &searchInput); + void cancelSearching(); + + void scheduleIndexDocumentation(); + +Q_SIGNALS: + void indexingStarted(); + void indexingFinished(); + + void searchingStarted(); + void searchingFinished(int searchResultCount); + +private: + QHelpSearchEngineCorePrivate *d; +}; + +QT_END_NAMESPACE + +#endif // QHELPSEARCHENGINECORE_H diff --git a/src/assistant/help/qhelpsearchindexreader.cpp b/src/assistant/help/qhelpsearchindexreader.cpp index e2172deda..5fd583335 100644 --- a/src/assistant/help/qhelpsearchindexreader.cpp +++ b/src/assistant/help/qhelpsearchindexreader.cpp @@ -1,48 +1,193 @@ -/**************************************************************************** -** -** Copyright (C) 2016 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$ -** -****************************************************************************/ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only #include "qhelpsearchindexreader_p.h" +#include "qhelpenginecore.h" +#include "qhelpfilterengine.h" + +#include <QtCore/qmap.h> +#include <QtCore/qset.h> +#include <QtSql/qsqldatabase.h> +#include <QtSql/qsqlquery.h> QT_BEGIN_NAMESPACE +using namespace Qt::StringLiterals; + namespace fulltextsearch { +class Reader +{ +public: + void setIndexPath(const QString &path) + { + m_indexPath = path; + m_namespaceAttributes.clear(); + m_filterEngineNamespaceList.clear(); + m_useFilterEngine = false; + } + void addNamespaceAttributes(const QString &namespaceName, const QStringList &attributes) + { + m_namespaceAttributes.insert(namespaceName, attributes); + } + void setFilterEngineNamespaceList(const QStringList &namespaceList) + { + m_useFilterEngine = true; + m_filterEngineNamespaceList = namespaceList; + } + + void searchInDB(const QString &term); + QList<QHelpSearchResult> searchResults() const { return m_searchResults; } + +private: + QList<QHelpSearchResult> queryTable(const QSqlDatabase &db, const QString &tableName, + const QString &searchInput) const; + + QMultiMap<QString, QStringList> m_namespaceAttributes; + QStringList m_filterEngineNamespaceList; + QList<QHelpSearchResult> m_searchResults; + QString m_indexPath; + bool m_useFilterEngine = false; +}; + +static QString namespacePlaceholders(const QMultiMap<QString, QStringList> &namespaces) +{ + QString placeholders; + const auto &namespaceList = namespaces.uniqueKeys(); + bool firstNS = true; + for (const QString &ns : namespaceList) { + if (firstNS) + firstNS = false; + else + placeholders += " OR "_L1; + placeholders += "(namespace = ?"_L1; + + const QList<QStringList> &attributeSets = namespaces.values(ns); + bool firstAS = true; + for (const QStringList &attributeSet : attributeSets) { + if (!attributeSet.isEmpty()) { + if (firstAS) { + firstAS = false; + placeholders += " AND ("_L1; + } else { + placeholders += " OR "_L1; + } + placeholders += "attributes = ?"_L1; + } + } + if (!firstAS) + placeholders += u')'; // close "AND (" + placeholders += u')'; + } + return placeholders; +} + +static void bindNamespacesAndAttributes(QSqlQuery *query, + const QMultiMap<QString, QStringList> &namespaces) +{ + const auto &namespaceList = namespaces.uniqueKeys(); + for (const QString &ns : namespaceList) { + query->addBindValue(ns); + + const QList<QStringList> &attributeSets = namespaces.values(ns); + for (const QStringList &attributeSet : attributeSets) { + if (!attributeSet.isEmpty()) + query->addBindValue(attributeSet.join(u'|')); + } + } +} + +static QString namespacePlaceholders(const QStringList &namespaceList) +{ + QString placeholders; + bool firstNS = true; + for (int i = namespaceList.size(); i; --i) { + if (firstNS) + firstNS = false; + else + placeholders += " OR "_L1; + placeholders += "namespace = ?"_L1; + } + return placeholders; +} + +static void bindNamespacesAndAttributes(QSqlQuery *query, const QStringList &namespaceList) +{ + for (const QString &ns : namespaceList) + query->addBindValue(ns); +} + +QList<QHelpSearchResult> Reader::queryTable(const QSqlDatabase &db, const QString &tableName, + const QString &searchInput) const +{ + const QString nsPlaceholders = m_useFilterEngine + ? namespacePlaceholders(m_filterEngineNamespaceList) + : namespacePlaceholders(m_namespaceAttributes); + QSqlQuery query(db); + query.prepare("SELECT url, title, snippet("_L1 + tableName + + ", -1, '<b>', '</b>', '...', '10') FROM "_L1 + tableName + + " WHERE ("_L1 + nsPlaceholders + + ") AND "_L1 + tableName + + " MATCH ? ORDER BY rank"_L1); + m_useFilterEngine + ? bindNamespacesAndAttributes(&query, m_filterEngineNamespaceList) + : bindNamespacesAndAttributes(&query, m_namespaceAttributes); + query.addBindValue(searchInput); + query.exec(); + + QList<QHelpSearchResult> results; + + while (query.next()) { + const QString &url = query.value("url"_L1).toString(); + const QString &title = query.value("title"_L1).toString(); + const QString &snippet = query.value(2).toString(); + results.append(QHelpSearchResult(url, title, snippet)); + } + return results; +} + +void Reader::searchInDB(const QString &searchInput) +{ + const QString &uniqueId = QHelpGlobal::uniquifyConnectionName("QHelpReader"_L1, this); + { + QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE"_L1, uniqueId); + db.setConnectOptions("QSQLITE_OPEN_READONLY"_L1); + db.setDatabaseName(m_indexPath + "/fts"_L1); + + if (db.open()) { + const QList<QHelpSearchResult> titleResults = queryTable(db, "titles"_L1, searchInput); + const QList<QHelpSearchResult> contentResults = + queryTable(db, "contents"_L1, searchInput); + + // merge results form title and contents searches + m_searchResults.clear(); + QSet<QUrl> urls; + for (const QHelpSearchResult &result : titleResults) { + const auto size = urls.size(); + urls.insert(result.url()); + if (size != urls.size()) // insertion took place + m_searchResults.append(result); + } + for (const QHelpSearchResult &result : contentResults) { + const auto size = urls.size(); + urls.insert(result.url()); + if (size != urls.size()) // insertion took place + m_searchResults.append(result); + } + } + } + QSqlDatabase::removeDatabase(uniqueId); +} + +static bool attributesMatchFilter(const QStringList &attributes, const QStringList &filter) +{ + for (const QString &attribute : filter) { + if (!attributes.contains(attribute, Qt::CaseInsensitive)) + return false; + } + return true; +} + QHelpSearchIndexReader::~QHelpSearchIndexReader() { cancelSearching(); @@ -56,7 +201,7 @@ void QHelpSearchIndexReader::cancelSearching() } void QHelpSearchIndexReader::search(const QString &collectionFile, const QString &indexFilesFolder, - const QString &searchInput, bool usesFilterEngine) + const QString &searchInput, bool usesFilterEngine) { wait(); @@ -73,17 +218,74 @@ void QHelpSearchIndexReader::search(const QString &collectionFile, const QString int QHelpSearchIndexReader::searchResultCount() const { QMutexLocker lock(&m_mutex); - return m_searchResults.count(); + return m_searchResults.size(); } -QList<QHelpSearchResult> QHelpSearchIndexReader::searchResults(int start, - int end) const +QList<QHelpSearchResult> QHelpSearchIndexReader::searchResults(int start, int end) const { QMutexLocker lock(&m_mutex); return m_searchResults.mid(start, end - start); } +void QHelpSearchIndexReader::run() +{ + QMutexLocker lock(&m_mutex); + + if (m_cancel) + return; + + const QString searchInput = m_searchInput; + const QString collectionFile = m_collectionFile; + const QString indexPath = m_indexFilesFolder; + const bool usesFilterEngine = m_usesFilterEngine; + + lock.unlock(); + + QHelpEngineCore engine(collectionFile, nullptr); + if (!engine.setupData()) + return; + + emit searchingStarted(); + + // setup the reader + Reader reader; + reader.setIndexPath(indexPath); + + if (usesFilterEngine) { + reader.setFilterEngineNamespaceList( + engine.filterEngine()->namespacesForFilter(engine.filterEngine()->activeFilter())); + } else { + const QStringList ®isteredDocs = engine.registeredDocumentations(); + const QStringList ¤tFilter = engine.filterAttributes(engine.currentFilter()); + + for (const QString &namespaceName : registeredDocs) { + const QList<QStringList> &attributeSets = + engine.filterAttributeSets(namespaceName); + + for (const QStringList &attributes : attributeSets) { + if (attributesMatchFilter(attributes, currentFilter)) + reader.addNamespaceAttributes(namespaceName, attributes); + } + } + } + + lock.relock(); + if (m_cancel) { + emit searchingFinished(0); // TODO: check this, speed issue while locking??? + return; + } + lock.unlock(); + + m_searchResults.clear(); + reader.searchInDB(searchInput); // TODO: should this be interruptible as well ??? + + lock.relock(); + m_searchResults = reader.searchResults(); + lock.unlock(); + + emit searchingFinished(m_searchResults.size()); +} -} // namespace fulltextsearch +} // namespace fulltextsearch QT_END_NAMESPACE diff --git a/src/assistant/help/qhelpsearchindexreader_default.cpp b/src/assistant/help/qhelpsearchindexreader_default.cpp deleted file mode 100644 index cbd01ee7b..000000000 --- a/src/assistant/help/qhelpsearchindexreader_default.cpp +++ /dev/null @@ -1,287 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 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 "qhelpenginecore.h" -#include "qhelpfilterengine.h" -#include "qhelpsearchindexreader_default_p.h" - -#include <QtCore/QSet> -#include <QtSql/QSqlDatabase> -#include <QtSql/QSqlQuery> - -QT_BEGIN_NAMESPACE - -namespace fulltextsearch { -namespace qt { - -void Reader::setIndexPath(const QString &path) -{ - m_indexPath = path; - m_namespaceAttributes.clear(); - m_filterEngineNamespaceList.clear(); - m_useFilterEngine = false; -} - -void Reader::addNamespaceAttributes(const QString &namespaceName, const QStringList &attributes) -{ - m_namespaceAttributes.insert(namespaceName, attributes); -} - -void Reader::setFilterEngineNamespaceList(const QStringList &namespaceList) -{ - m_useFilterEngine = true; - m_filterEngineNamespaceList = namespaceList; -} - -static QString namespacePlaceholders(const QMultiMap<QString, QStringList> &namespaces) -{ - QString placeholders; - const auto &namespaceList = namespaces.uniqueKeys(); - bool firstNS = true; - for (const QString &ns : namespaceList) { - if (firstNS) - firstNS = false; - else - placeholders += QLatin1String(" OR "); - placeholders += QLatin1String("(namespace = ?"); - - const QList<QStringList> &attributeSets = namespaces.values(ns); - bool firstAS = true; - for (const QStringList &attributeSet : attributeSets) { - if (!attributeSet.isEmpty()) { - if (firstAS) { - firstAS = false; - placeholders += QLatin1String(" AND ("); - } else { - placeholders += QLatin1String(" OR "); - } - placeholders += QLatin1String("attributes = ?"); - } - } - if (!firstAS) - placeholders += QLatin1Char(')'); // close "AND (" - placeholders += QLatin1Char(')'); - } - return placeholders; -} - -static void bindNamespacesAndAttributes(QSqlQuery *query, const QMultiMap<QString, QStringList> &namespaces) -{ - const auto &namespaceList = namespaces.uniqueKeys(); - for (const QString &ns : namespaceList) { - query->addBindValue(ns); - - const QList<QStringList> &attributeSets = namespaces.values(ns); - for (const QStringList &attributeSet : attributeSets) { - if (!attributeSet.isEmpty()) - query->addBindValue(attributeSet.join(QLatin1Char('|'))); - } - } -} - -static QString namespacePlaceholders(const QStringList &namespaceList) -{ - QString placeholders; - bool firstNS = true; - for (int i = namespaceList.count(); i; --i) { - if (firstNS) - firstNS = false; - else - placeholders += QLatin1String(" OR "); - placeholders += QLatin1String("namespace = ?"); - } - return placeholders; -} - -static void bindNamespacesAndAttributes(QSqlQuery *query, const QStringList &namespaceList) -{ - for (const QString &ns : namespaceList) - query->addBindValue(ns); -} - -QList<QHelpSearchResult> Reader::queryTable(const QSqlDatabase &db, - const QString &tableName, - const QString &searchInput) const -{ - const QString nsPlaceholders = m_useFilterEngine - ? namespacePlaceholders(m_filterEngineNamespaceList) - : namespacePlaceholders(m_namespaceAttributes); - QSqlQuery query(db); - query.prepare(QLatin1String("SELECT url, title, snippet(") + tableName + - QLatin1String(", -1, '<b>', '</b>', '...', '10') FROM ") + tableName + - QLatin1String(" WHERE (") + nsPlaceholders + - QLatin1String(") AND ") + tableName + - QLatin1String(" MATCH ? ORDER BY rank")); - m_useFilterEngine - ? bindNamespacesAndAttributes(&query, m_filterEngineNamespaceList) - : bindNamespacesAndAttributes(&query, m_namespaceAttributes); - query.addBindValue(searchInput); - query.exec(); - - QList<QHelpSearchResult> results; - - while (query.next()) { - const QString &url = query.value(QLatin1String("url")).toString(); - const QString &title = query.value(QLatin1String("title")).toString(); - const QString &snippet = query.value(2).toString(); - results.append(QHelpSearchResult(url, title, snippet)); - } - - return results; -} - -void Reader::searchInDB(const QString &searchInput) -{ - const QString &uniqueId = QHelpGlobal::uniquifyConnectionName(QLatin1String("QHelpReader"), this); - { - QSqlDatabase db = QSqlDatabase::addDatabase(QLatin1String("QSQLITE"), uniqueId); - db.setConnectOptions(QLatin1String("QSQLITE_OPEN_READONLY")); - db.setDatabaseName(m_indexPath + QLatin1String("/fts")); - - if (db.open()) { - const QList<QHelpSearchResult> titleResults = queryTable(db, - QLatin1String("titles"), searchInput); - const QList<QHelpSearchResult> contentResults = queryTable(db, - QLatin1String("contents"), searchInput); - - // merge results form title and contents searches - m_searchResults = QList<QHelpSearchResult>(); - - QSet<QUrl> urls; - - for (const QHelpSearchResult &result : titleResults) { - const QUrl &url = result.url(); - if (!urls.contains(url)) { - urls.insert(url); - m_searchResults.append(result); - } - } - - for (const QHelpSearchResult &result : contentResults) { - const QUrl &url = result.url(); - if (!urls.contains(url)) { - urls.insert(url); - m_searchResults.append(result); - } - } - } - } - QSqlDatabase::removeDatabase(uniqueId); -} - -QList<QHelpSearchResult> Reader::searchResults() const -{ - return m_searchResults; -} - -static bool attributesMatchFilter(const QStringList &attributes, - const QStringList &filter) -{ - for (const QString &attribute : filter) { - if (!attributes.contains(attribute, Qt::CaseInsensitive)) - return false; - } - - return true; -} - -void QHelpSearchIndexReaderDefault::run() -{ - QMutexLocker lock(&m_mutex); - - if (m_cancel) - return; - - const QString searchInput = m_searchInput; - const QString collectionFile = m_collectionFile; - const QString indexPath = m_indexFilesFolder; - const bool usesFilterEngine = m_usesFilterEngine; - - lock.unlock(); - - QHelpEngineCore engine(collectionFile, nullptr); - if (!engine.setupData()) - return; - - emit searchingStarted(); - - // setup the reader - m_reader.setIndexPath(indexPath); - - if (usesFilterEngine) { - m_reader.setFilterEngineNamespaceList( - engine.filterEngine()->namespacesForFilter( - engine.filterEngine()->activeFilter())); - } else { - const QStringList ®isteredDocs = engine.registeredDocumentations(); - const QStringList ¤tFilter = engine.filterAttributes(engine.currentFilter()); - - for (const QString &namespaceName : registeredDocs) { - const QList<QStringList> &attributeSets = - engine.filterAttributeSets(namespaceName); - - for (const QStringList &attributes : attributeSets) { - if (attributesMatchFilter(attributes, currentFilter)) { - m_reader.addNamespaceAttributes(namespaceName, attributes); - } - } - } - } - - lock.relock(); - if (m_cancel) { - emit searchingFinished(0); // TODO: check this, speed issue while locking??? - return; - } - lock.unlock(); - - m_searchResults.clear(); - m_reader.searchInDB(searchInput); // TODO: should this be interruptible as well ??? - - lock.relock(); - m_searchResults = m_reader.searchResults(); - lock.unlock(); - - emit searchingFinished(m_searchResults.count()); -} - -} // namespace std -} // namespace fulltextsearch - -QT_END_NAMESPACE diff --git a/src/assistant/help/qhelpsearchindexreader_default_p.h b/src/assistant/help/qhelpsearchindexreader_default_p.h deleted file mode 100644 index 6990b2c21..000000000 --- a/src/assistant/help/qhelpsearchindexreader_default_p.h +++ /dev/null @@ -1,102 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 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 QHELPSEARCHINDEXREADERDEFAULT_H -#define QHELPSEARCHINDEXREADERDEFAULT_H - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists for the convenience -// of the help generator tools. This header file may change from version -// to version without notice, or even be removed. -// -// We mean it. -// - -#include "qhelpsearchindexreader_p.h" - -QT_FORWARD_DECLARE_CLASS(QSqlDatabase) - -QT_BEGIN_NAMESPACE - -namespace fulltextsearch { -namespace qt { - -class Reader -{ -public: - void setIndexPath(const QString &path); - void addNamespaceAttributes(const QString &namespaceName, const QStringList &attributes); - void setFilterEngineNamespaceList(const QStringList &namespaceList); - - void searchInDB(const QString &term); - QList<QHelpSearchResult> searchResults() const; - -private: - QList<QHelpSearchResult> queryTable(const QSqlDatabase &db, - const QString &tableName, - const QString &searchInput) const; - - QMultiMap<QString, QStringList> m_namespaceAttributes; - QStringList m_filterEngineNamespaceList; - QList<QHelpSearchResult> m_searchResults; - QString m_indexPath; - bool m_useFilterEngine = false; -}; - - -class QHelpSearchIndexReaderDefault : public QHelpSearchIndexReader -{ - Q_OBJECT - -private: - void run() override; - -private: - Reader m_reader; -}; - -} // namespace std -} // namespace fulltextsearch - -QT_END_NAMESPACE - -#endif // QHELPSEARCHINDEXREADERDEFAULT_H diff --git a/src/assistant/help/qhelpsearchindexreader_p.h b/src/assistant/help/qhelpsearchindexreader_p.h index 883446fea..835c44f97 100644 --- a/src/assistant/help/qhelpsearchindexreader_p.h +++ b/src/assistant/help/qhelpsearchindexreader_p.h @@ -1,41 +1,5 @@ -/**************************************************************************** -** -** Copyright (C) 2016 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$ -** -****************************************************************************/ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only #ifndef QHELPSEARCHINDEXREADER_H #define QHELPSEARCHINDEXREADER_H @@ -51,18 +15,17 @@ // We mean it. // -#include "qhelpsearchengine.h" +#include "qhelpsearchresult.h" -#include <QtCore/QList> -#include <QtCore/QMutex> -#include <QtCore/QThread> +#include <QtCore/qlist.h> +#include <QtCore/qmutex.h> +#include <QtCore/qthread.h> QT_BEGIN_NAMESPACE -class QHelpEngineCore; - namespace fulltextsearch { +// TODO: Employ QFuture / QtConcurrent::run() ? class QHelpSearchIndexReader : public QThread { Q_OBJECT @@ -71,10 +34,8 @@ public: ~QHelpSearchIndexReader() override; void cancelSearching(); - void search(const QString &collectionFile, - const QString &indexFilesFolder, - const QString &searchInput, - bool usesFilterEngine = false); + void search(const QString &collectionFile, const QString &indexFilesFolder, + const QString &searchInput, bool usesFilterEngine = false); int searchResultCount() const; QList<QHelpSearchResult> searchResults(int start, int end) const; @@ -82,7 +43,9 @@ signals: void searchingStarted(); void searchingFinished(int searchResultCount); -protected: +private: + void run() override; + mutable QMutex m_mutex; QList<QHelpSearchResult> m_searchResults; bool m_cancel = false; @@ -90,13 +53,10 @@ protected: QString m_searchInput; QString m_indexFilesFolder; bool m_usesFilterEngine = false; - -private: - void run() override = 0; }; -} // namespace fulltextsearch +} // namespace fulltextsearch QT_END_NAMESPACE -#endif // QHELPSEARCHINDEXREADER_H +#endif // QHELPSEARCHINDEXREADER_H diff --git a/src/assistant/help/qhelpsearchindexwriter.cpp b/src/assistant/help/qhelpsearchindexwriter.cpp new file mode 100644 index 000000000..2cccbade3 --- /dev/null +++ b/src/assistant/help/qhelpsearchindexwriter.cpp @@ -0,0 +1,515 @@ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#include "qhelpsearchindexwriter_p.h" +#include "qhelp_global.h" +#include "qhelpdbreader_p.h" +#include "qhelpenginecore.h" + +#include <QtCore/qdatastream.h> +#include <QtCore/qdatetime.h> +#include <QtCore/qdir.h> +#include <QtCore/qstringconverter.h> +#include <QtCore/qtextstream.h> +#include <QtCore/qurl.h> +#include <QtCore/qvariant.h> +#include <QtGui/qtextdocument.h> +#include <QtSql/qsqldatabase.h> +#include <QtSql/qsqldriver.h> +#include <QtSql/qsqlerror.h> +#include <QtSql/qsqlquery.h> + +QT_BEGIN_NAMESPACE + +using namespace Qt::StringLiterals; + +namespace fulltextsearch { + +const char FTS_DB_NAME[] = "fts"; + +class Writer +{ +public: + Writer(const QString &path); + ~Writer(); + + bool tryInit(bool reindex); + void flush(); + + void removeNamespace(const QString &namespaceName); + bool hasNamespace(const QString &namespaceName); + void insertDoc(const QString &namespaceName, + const QString &attributes, + const QString &url, + const QString &title, + const QString &contents); + void startTransaction(); + void endTransaction(); + +private: + void init(bool reindex); + bool hasDB(); + void clearLegacyIndex(); + + const QString m_dbDir; + QString m_uniqueId; + + bool m_needOptimize = false; + QSqlDatabase m_db; + QVariantList m_namespaces; + QVariantList m_attributes; + QVariantList m_urls; + QVariantList m_titles; + QVariantList m_contents; +}; + +Writer::Writer(const QString &path) + : m_dbDir(path) +{ + clearLegacyIndex(); + QDir().mkpath(m_dbDir); + m_uniqueId = QHelpGlobal::uniquifyConnectionName("QHelpWriter"_L1, this); + m_db = QSqlDatabase::addDatabase("QSQLITE"_L1, m_uniqueId); + const QString dbPath = m_dbDir + u'/' + QLatin1StringView(FTS_DB_NAME); + m_db.setDatabaseName(dbPath); + if (!m_db.open()) { + const QString &error = QHelpSearchIndexWriter::tr( + "Cannot open database \"%1\" using connection \"%2\": %3") + .arg(dbPath, m_uniqueId, m_db.lastError().text()); + qWarning("%s", qUtf8Printable(error)); + m_db = {}; + QSqlDatabase::removeDatabase(m_uniqueId); + m_uniqueId.clear(); + } else { + startTransaction(); + } +} + +bool Writer::tryInit(bool reindex) +{ + if (!m_db.isValid()) + return true; + + QSqlQuery query(m_db); + // HACK: we try to perform any modifying command just to check if + // we don't get SQLITE_BUSY code (SQLITE_BUSY is defined to 5 in sqlite driver) + if (!query.exec("CREATE TABLE foo ();"_L1) && query.lastError().nativeErrorCode() == "5"_L1) // db is locked + return false; + + // HACK: clear what we have created + query.exec("DROP TABLE foo;"_L1); + + init(reindex); + return true; +} + +bool Writer::hasDB() +{ + if (!m_db.isValid()) + return false; + + QSqlQuery query(m_db); + query.prepare("SELECT id FROM info LIMIT 1"_L1); + query.exec(); + return query.next(); +} + +void Writer::clearLegacyIndex() +{ + // Clear old legacy clucene index. + // More important in case of Creator, since + // the index folder is common for all Creator versions + QDir dir(m_dbDir); + if (!dir.exists()) + return; + + const QStringList &list = dir.entryList(QDir::Files | QDir::Hidden); + if (!list.contains(QLatin1StringView(FTS_DB_NAME))) { + for (const QString &item : list) + dir.remove(item); + } +} + +void Writer::init(bool reindex) +{ + if (!m_db.isValid()) + return; + + QSqlQuery query(m_db); + + if (reindex && hasDB()) { + m_needOptimize = true; + + query.exec("DROP TABLE titles;"_L1); + query.exec("DROP TABLE contents;"_L1); + query.exec("DROP TABLE info;"_L1); + } + + query.exec("CREATE TABLE info (id INTEGER PRIMARY KEY, namespace, attributes, url, title, data);"_L1); + + query.exec("CREATE VIRTUAL TABLE titles USING fts5(" + "namespace UNINDEXED, attributes UNINDEXED, " + "url UNINDEXED, title, " + "tokenize = 'porter unicode61', content = 'info', content_rowid='id');"_L1); + query.exec("CREATE TRIGGER titles_insert AFTER INSERT ON info BEGIN " + "INSERT INTO titles(rowid, namespace, attributes, url, title) " + "VALUES(new.id, new.namespace, new.attributes, new.url, new.title); " + "END;"_L1); + query.exec("CREATE TRIGGER titles_delete AFTER DELETE ON info BEGIN " + "INSERT INTO titles(titles, rowid, namespace, attributes, url, title) " + "VALUES('delete', old.id, old.namespace, old.attributes, old.url, old.title); " + "END;"_L1); + query.exec("CREATE TRIGGER titles_update AFTER UPDATE ON info BEGIN " + "INSERT INTO titles(titles, rowid, namespace, attributes, url, title) " + "VALUES('delete', old.id, old.namespace, old.attributes, old.url, old.title); " + "INSERT INTO titles(rowid, namespace, attributes, url, title) " + "VALUES(new.id, new.namespace, new.attributes, new.url, new.title); " + "END;"_L1); + + query.exec("CREATE VIRTUAL TABLE contents USING fts5(" + "namespace UNINDEXED, attributes UNINDEXED, " + "url UNINDEXED, title, data, " + "tokenize = 'porter unicode61', content = 'info', content_rowid='id');"_L1); + query.exec("CREATE TRIGGER contents_insert AFTER INSERT ON info BEGIN " + "INSERT INTO contents(rowid, namespace, attributes, url, title, data) " + "VALUES(new.id, new.namespace, new.attributes, new.url, new.title, new.data); " + "END;"_L1); + query.exec("CREATE TRIGGER contents_delete AFTER DELETE ON info BEGIN " + "INSERT INTO contents(contents, rowid, namespace, attributes, url, title, data) " + "VALUES('delete', old.id, old.namespace, old.attributes, old.url, old.title, old.data); " + "END;"_L1); + query.exec("CREATE TRIGGER contents_update AFTER UPDATE ON info BEGIN " + "INSERT INTO contents(contents, rowid, namespace, attributes, url, title, data) " + "VALUES('delete', old.id, old.namespace, old.attributes, old.url, old.title, old.data); " + "INSERT INTO contents(rowid, namespace, attributes, url, title, data) " + "VALUES(new.id, new.namespace, new.attributes, new.url, new.title, new.data); " + "END;"_L1); +} + +Writer::~Writer() +{ + if (m_db.isValid()) + m_db.close(); + m_db = {}; + if (!m_uniqueId.isEmpty()) + QSqlDatabase::removeDatabase(m_uniqueId); +} + +void Writer::flush() +{ + if (!m_db.isValid()) + return; + + QSqlQuery query(m_db); + query.prepare("INSERT INTO info (namespace, attributes, url, title, data) VALUES (?, ?, ?, ?, ?)"_L1); + query.addBindValue(m_namespaces); + query.addBindValue(m_attributes); + query.addBindValue(m_urls); + query.addBindValue(m_titles); + query.addBindValue(m_contents); + query.execBatch(); + + m_namespaces.clear(); + m_attributes.clear(); + m_urls.clear(); + m_titles.clear(); + m_contents.clear(); +} + +void Writer::removeNamespace(const QString &namespaceName) +{ + if (!m_db.isValid() || !hasNamespace(namespaceName)) // no data to delete + return; + + m_needOptimize = true; + QSqlQuery query(m_db); + query.prepare("DELETE FROM info WHERE namespace = ?"_L1); + query.addBindValue(namespaceName); + query.exec(); +} + +bool Writer::hasNamespace(const QString &namespaceName) +{ + if (!m_db.isValid()) + return false; + + QSqlQuery query(m_db); + query.prepare("SELECT id FROM info WHERE namespace = ? LIMIT 1"_L1); + query.addBindValue(namespaceName); + query.exec(); + return query.next(); +} + +void Writer::insertDoc(const QString &namespaceName, + const QString &attributes, + const QString &url, + const QString &title, + const QString &contents) +{ + m_namespaces.append(namespaceName); + m_attributes.append(attributes); + m_urls.append(url); + m_titles.append(title); + m_contents.append(contents); +} + +void Writer::startTransaction() +{ + if (!m_db.isValid()) + return; + + m_needOptimize = false; + if (m_db.driver()->hasFeature(QSqlDriver::Transactions)) + m_db.transaction(); +} + +void Writer::endTransaction() +{ + if (!m_db.isValid()) + return; + + QSqlQuery query(m_db); + + if (m_needOptimize) { + query.exec("INSERT INTO titles(titles) VALUES('rebuild')"_L1); + query.exec("INSERT INTO contents(contents) VALUES('rebuild')"_L1); + } + + if (m_db.driver()->hasFeature(QSqlDriver::Transactions)) + m_db.commit(); + + if (m_needOptimize) + query.exec("VACUUM"_L1); +} + +QHelpSearchIndexWriter::~QHelpSearchIndexWriter() +{ + m_mutex.lock(); + this->m_cancel = true; + m_mutex.unlock(); + wait(); +} + +void QHelpSearchIndexWriter::cancelIndexing() +{ + QMutexLocker lock(&m_mutex); + m_cancel = true; +} + +void QHelpSearchIndexWriter::updateIndex(const QString &collectionFile, + const QString &indexFilesFolder, bool reindex) +{ + wait(); + QMutexLocker lock(&m_mutex); + + m_cancel = false; + m_reindex = reindex; + m_collectionFile = collectionFile; + m_indexFilesFolder = indexFilesFolder; + + lock.unlock(); + + start(QThread::LowestPriority); +} + +static const char IndexedNamespacesKey[] = "FTS5IndexedNamespaces"; + +static QMap<QString, QDateTime> readIndexMap(const QHelpEngineCore &engine) +{ + QMap<QString, QDateTime> indexMap; + QDataStream dataStream( + engine.customValue(QLatin1StringView(IndexedNamespacesKey)).toByteArray()); + dataStream >> indexMap; + return indexMap; +} + +static bool writeIndexMap(QHelpEngineCore *engine, const QMap<QString, QDateTime> &indexMap) +{ + QByteArray data; + QDataStream dataStream(&data, QIODevice::ReadWrite); + dataStream << indexMap; + return engine->setCustomValue(QLatin1StringView(IndexedNamespacesKey), data); +} + +static bool clearIndexMap(QHelpEngineCore *engine) +{ + return engine->removeCustomValue(QLatin1StringView(IndexedNamespacesKey)); +} + +void QHelpSearchIndexWriter::run() +{ + QMutexLocker lock(&m_mutex); + + if (m_cancel) + return; + + const bool reindex(m_reindex); + const QString collectionFile(m_collectionFile); + const QString indexPath(m_indexFilesFolder); + + lock.unlock(); + + QHelpEngineCore engine(collectionFile, nullptr); + if (!engine.setupData()) + return; + + if (reindex) + clearIndexMap(&engine); + + emit indexingStarted(); + + Writer writer(indexPath); + + while (!writer.tryInit(reindex)) + sleep(1); + + const QStringList ®isteredDocs = engine.registeredDocumentations(); + QMap<QString, QDateTime> indexMap = readIndexMap(engine); + + if (!reindex) { + for (const QString &namespaceName : registeredDocs) { + const auto it = indexMap.constFind(namespaceName); + if (it != indexMap.constEnd()) { + const QString path = engine.documentationFileName(namespaceName); + if (*it < QFileInfo(path).lastModified()) { + // Remove some outdated indexed stuff + indexMap.erase(it); + writer.removeNamespace(namespaceName); + } else if (!writer.hasNamespace(namespaceName)) { + // No data in fts db for namespace. + // The namespace could have been removed from fts db + // or the whole fts db have been removed + // without removing it from indexMap. + indexMap.erase(it); + } + } else { + // Needed in case namespaceName was removed from indexMap + // without removing it from fts db. + // May happen when e.g. qch file was removed manually + // without removing fts db. + writer.removeNamespace(namespaceName); + } + // TODO: we may also detect if there are any other data + // and remove it + } + } else { + indexMap.clear(); + } + + auto it = indexMap.begin(); + while (it != indexMap.end()) { + if (!registeredDocs.contains(it.key())) { + writer.removeNamespace(it.key()); + it = indexMap.erase(it); + } else { + ++it; + } + } + + for (const QString &namespaceName : registeredDocs) { + lock.relock(); + if (m_cancel) { + // store what we have done so far + writeIndexMap(&engine, indexMap); + writer.endTransaction(); + emit indexingFinished(); + return; + } + lock.unlock(); + + // if indexed, continue + if (indexMap.contains(namespaceName)) + continue; + + const QString fileName = engine.documentationFileName(namespaceName); + QHelpDBReader reader(fileName, QHelpGlobal::uniquifyConnectionName( + fileName, this), nullptr); + if (!reader.init()) + continue; + + const QString virtualFolder = reader.virtualFolder(); + + const QList<QStringList> &attributeSets = + engine.filterAttributeSets(namespaceName); + + for (const QStringList &attributes : attributeSets) { + const QString &attributesString = attributes.join(u'|'); + + const auto htmlFiles = reader.filesData(attributes, "html"_L1); + const auto htmFiles = reader.filesData(attributes, "htm"_L1); + const auto txtFiles = reader.filesData(attributes, "txt"_L1); + + auto files = htmlFiles; + files.unite(htmFiles); + files.unite(txtFiles); + + for (auto it = files.cbegin(), end = files.cend(); it != end ; ++it) { + lock.relock(); + if (m_cancel) { + // store what we have done so far + writeIndexMap(&engine, indexMap); + writer.endTransaction(); + emit indexingFinished(); + return; + } + lock.unlock(); + + const QString &file = it.key(); + const QByteArray &data = it.value(); + + if (data.isEmpty()) + continue; + + QUrl url; + url.setScheme("qthelp"_L1); + url.setAuthority(namespaceName); + url.setPath(u'/' + virtualFolder + u'/' + file); + + if (url.hasFragment()) + url.setFragment({}); + + const QString &fullFileName = url.toString(); + if (!fullFileName.endsWith(".html"_L1) && !fullFileName.endsWith(".htm"_L1) + && !fullFileName.endsWith(".txt"_L1)) { + continue; + } + + QTextStream s(data); + auto encoding = QStringDecoder::encodingForHtml(data); + if (encoding) + s.setEncoding(*encoding); + + const QString &text = s.readAll(); + if (text.isEmpty()) + continue; + + QString title; + QString contents; + if (fullFileName.endsWith(".txt"_L1)) { + title = fullFileName.mid(fullFileName.lastIndexOf(u'/') + 1); + contents = text.toHtmlEscaped(); + } else { + QTextDocument doc; + doc.setHtml(text); + + title = doc.metaInformation(QTextDocument::DocumentTitle).toHtmlEscaped(); + contents = doc.toPlainText().toHtmlEscaped(); + } + + writer.insertDoc(namespaceName, attributesString, fullFileName, title, contents); + } + } + writer.flush(); + const QString &path = engine.documentationFileName(namespaceName); + indexMap.insert(namespaceName, QFileInfo(path).lastModified()); + } + + writeIndexMap(&engine, indexMap); + + writer.endTransaction(); + emit indexingFinished(); +} + +} // namespace fulltextsearch + +QT_END_NAMESPACE diff --git a/src/assistant/help/qhelpsearchindexwriter_default.cpp b/src/assistant/help/qhelpsearchindexwriter_default.cpp deleted file mode 100644 index a814598f3..000000000 --- a/src/assistant/help/qhelpsearchindexwriter_default.cpp +++ /dev/null @@ -1,543 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 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 "qhelpsearchindexwriter_default_p.h" -#include "qhelp_global.h" -#include "qhelpenginecore.h" -#include "qhelpdbreader_p.h" - -#include <QtCore/QDataStream> -#include <QtCore/QDateTime> -#include <QtCore/QDir> -#include <QtCore/QStringDecoder> -#include <QtCore/QTextStream> -#include <QtCore/QSet> -#include <QtCore/QUrl> -#include <QtCore/QVariant> -#include <QtSql/QSqlDatabase> -#include <QtSql/QSqlDriver> -#include <QtSql/QSqlError> -#include <QtSql/QSqlQuery> - -#include <QTextDocument> - -QT_BEGIN_NAMESPACE - -namespace fulltextsearch { -namespace qt { - -const char FTS_DB_NAME[] = "fts"; - -Writer::Writer(const QString &path) - : m_dbDir(path) -{ - clearLegacyIndex(); - QDir().mkpath(m_dbDir); - m_uniqueId = QHelpGlobal::uniquifyConnectionName(QLatin1String("QHelpWriter"), this); - m_db = new QSqlDatabase(); - *m_db = QSqlDatabase::addDatabase(QLatin1String("QSQLITE"), m_uniqueId); - const QString dbPath = m_dbDir + QLatin1Char('/') + QLatin1String(FTS_DB_NAME); - m_db->setDatabaseName(dbPath); - if (!m_db->open()) { - const QString &error = QHelpSearchIndexWriter::tr("Cannot open database \"%1\" using connection \"%2\": %3") - .arg(dbPath, m_uniqueId, m_db->lastError().text()); - qWarning("%s", qUtf8Printable(error)); - delete m_db; - m_db = nullptr; - QSqlDatabase::removeDatabase(m_uniqueId); - m_uniqueId = QString(); - } else { - startTransaction(); - } -} - -bool Writer::tryInit(bool reindex) -{ - if (!m_db) - return true; - - QSqlQuery query(*m_db); - // HACK: we try to perform any modifying command just to check if - // we don't get SQLITE_BUSY code (SQLITE_BUSY is defined to 5 in sqlite driver) - if (!query.exec(QLatin1String("CREATE TABLE foo ();"))) { - if (query.lastError().nativeErrorCode() == QLatin1String("5")) // db is locked - return false; - } - // HACK: clear what we have created - query.exec(QLatin1String("DROP TABLE foo;")); - - init(reindex); - return true; -} - -bool Writer::hasDB() -{ - if (!m_db) - return false; - - QSqlQuery query(*m_db); - - query.prepare(QLatin1String("SELECT id FROM info LIMIT 1")); - query.exec(); - - return query.next(); -} - -void Writer::clearLegacyIndex() -{ - // Clear old legacy clucene index. - // More important in case of Creator, since - // the index folder is common for all Creator versions - QDir dir(m_dbDir); - if (!dir.exists()) - return; - - const QStringList &list = dir.entryList(QDir::Files | QDir::Hidden); - if (!list.contains(QLatin1String(FTS_DB_NAME))) { - for (const QString &item : list) - dir.remove(item); - } -} - -void Writer::init(bool reindex) -{ - if (!m_db) - return; - - QSqlQuery query(*m_db); - - if (reindex && hasDB()) { - m_needOptimize = true; - - query.exec(QLatin1String("DROP TABLE titles;")); - query.exec(QLatin1String("DROP TABLE contents;")); - query.exec(QLatin1String("DROP TABLE info;")); - } - - query.exec(QLatin1String("CREATE TABLE info (id INTEGER PRIMARY KEY, namespace, attributes, url, title, data);")); - - query.exec(QLatin1String("CREATE VIRTUAL TABLE titles USING fts5(" - "namespace UNINDEXED, attributes UNINDEXED, " - "url UNINDEXED, title, " - "tokenize = 'porter unicode61', content = 'info', content_rowid='id');")); - query.exec(QLatin1String("CREATE TRIGGER titles_insert AFTER INSERT ON info BEGIN " - "INSERT INTO titles(rowid, namespace, attributes, url, title) " - "VALUES(new.id, new.namespace, new.attributes, new.url, new.title); " - "END;")); - query.exec(QLatin1String("CREATE TRIGGER titles_delete AFTER DELETE ON info BEGIN " - "INSERT INTO titles(titles, rowid, namespace, attributes, url, title) " - "VALUES('delete', old.id, old.namespace, old.attributes, old.url, old.title); " - "END;")); - query.exec(QLatin1String("CREATE TRIGGER titles_update AFTER UPDATE ON info BEGIN " - "INSERT INTO titles(titles, rowid, namespace, attributes, url, title) " - "VALUES('delete', old.id, old.namespace, old.attributes, old.url, old.title); " - "INSERT INTO titles(rowid, namespace, attributes, url, title) " - "VALUES(new.id, new.namespace, new.attributes, new.url, new.title); " - "END;")); - - query.exec(QLatin1String("CREATE VIRTUAL TABLE contents USING fts5(" - "namespace UNINDEXED, attributes UNINDEXED, " - "url UNINDEXED, title, data, " - "tokenize = 'porter unicode61', content = 'info', content_rowid='id');")); - query.exec(QLatin1String("CREATE TRIGGER contents_insert AFTER INSERT ON info BEGIN " - "INSERT INTO contents(rowid, namespace, attributes, url, title, data) " - "VALUES(new.id, new.namespace, new.attributes, new.url, new.title, new.data); " - "END;")); - query.exec(QLatin1String("CREATE TRIGGER contents_delete AFTER DELETE ON info BEGIN " - "INSERT INTO contents(contents, rowid, namespace, attributes, url, title, data) " - "VALUES('delete', old.id, old.namespace, old.attributes, old.url, old.title, old.data); " - "END;")); - query.exec(QLatin1String("CREATE TRIGGER contents_update AFTER UPDATE ON info BEGIN " - "INSERT INTO contents(contents, rowid, namespace, attributes, url, title, data) " - "VALUES('delete', old.id, old.namespace, old.attributes, old.url, old.title, old.data); " - "INSERT INTO contents(rowid, namespace, attributes, url, title, data) " - "VALUES(new.id, new.namespace, new.attributes, new.url, new.title, new.data); " - "END;")); -} - -Writer::~Writer() -{ - if (m_db) { - m_db->close(); - delete m_db; - } - - if (!m_uniqueId.isEmpty()) - QSqlDatabase::removeDatabase(m_uniqueId); -} - -void Writer::flush() -{ - if (!m_db) - return; - - QSqlQuery query(*m_db); - - query.prepare(QLatin1String("INSERT INTO info (namespace, attributes, url, title, data) VALUES (?, ?, ?, ?, ?)")); - query.addBindValue(m_namespaces); - query.addBindValue(m_attributes); - query.addBindValue(m_urls); - query.addBindValue(m_titles); - query.addBindValue(m_contents); - query.execBatch(); - - m_namespaces = QVariantList(); - m_attributes = QVariantList(); - m_urls = QVariantList(); - m_titles = QVariantList(); - m_contents = QVariantList(); -} - -void Writer::removeNamespace(const QString &namespaceName) -{ - if (!m_db) - return; - - if (!hasNamespace(namespaceName)) - return; // no data to delete - - m_needOptimize = true; - - QSqlQuery query(*m_db); - - query.prepare(QLatin1String("DELETE FROM info WHERE namespace = ?")); - query.addBindValue(namespaceName); - query.exec(); -} - -bool Writer::hasNamespace(const QString &namespaceName) -{ - if (!m_db) - return false; - - QSqlQuery query(*m_db); - - query.prepare(QLatin1String("SELECT id FROM info WHERE namespace = ? LIMIT 1")); - query.addBindValue(namespaceName); - query.exec(); - - return query.next(); -} - -void Writer::insertDoc(const QString &namespaceName, - const QString &attributes, - const QString &url, - const QString &title, - const QString &contents) -{ - m_namespaces.append(namespaceName); - m_attributes.append(attributes); - m_urls.append(url); - m_titles.append(title); - m_contents.append(contents); -} - -void Writer::startTransaction() -{ - if (!m_db) - return; - - m_needOptimize = false; - if (m_db && m_db->driver()->hasFeature(QSqlDriver::Transactions)) - m_db->transaction(); -} - -void Writer::endTransaction() -{ - if (!m_db) - return; - - QSqlQuery query(*m_db); - - if (m_needOptimize) { - query.exec(QLatin1String("INSERT INTO titles(titles) VALUES('rebuild')")); - query.exec(QLatin1String("INSERT INTO contents(contents) VALUES('rebuild')")); - } - - if (m_db && m_db->driver()->hasFeature(QSqlDriver::Transactions)) - m_db->commit(); - - if (m_needOptimize) - query.exec(QLatin1String("VACUUM")); -} - -QHelpSearchIndexWriter::QHelpSearchIndexWriter() - : QThread() - , m_cancel(false) -{ -} - -QHelpSearchIndexWriter::~QHelpSearchIndexWriter() -{ - m_mutex.lock(); - this->m_cancel = true; - m_mutex.unlock(); - - wait(); -} - -void QHelpSearchIndexWriter::cancelIndexing() -{ - QMutexLocker lock(&m_mutex); - m_cancel = true; -} - -void QHelpSearchIndexWriter::updateIndex(const QString &collectionFile, - const QString &indexFilesFolder, - bool reindex) -{ - wait(); - QMutexLocker lock(&m_mutex); - - m_cancel = false; - m_reindex = reindex; - m_collectionFile = collectionFile; - m_indexFilesFolder = indexFilesFolder; - - lock.unlock(); - - start(QThread::LowestPriority); -} - -static const char IndexedNamespacesKey[] = "FTS5IndexedNamespaces"; - -static QMap<QString, QDateTime> readIndexMap(const QHelpEngineCore &engine) -{ - QMap<QString, QDateTime> indexMap; - QDataStream dataStream(engine.customValue( - QLatin1String(IndexedNamespacesKey)).toByteArray()); - dataStream >> indexMap; - return indexMap; -} - -static bool writeIndexMap(QHelpEngineCore *engine, - const QMap<QString, QDateTime> &indexMap) -{ - QByteArray data; - - QDataStream dataStream(&data, QIODevice::ReadWrite); - dataStream << indexMap; - - return engine->setCustomValue( - QLatin1String(IndexedNamespacesKey), data); -} - -static bool clearIndexMap(QHelpEngineCore *engine) -{ - return engine->removeCustomValue(QLatin1String(IndexedNamespacesKey)); -} - -void QHelpSearchIndexWriter::run() -{ - QMutexLocker lock(&m_mutex); - - if (m_cancel) - return; - - const bool reindex(m_reindex); - const QString collectionFile(m_collectionFile); - const QString indexPath(m_indexFilesFolder); - - lock.unlock(); - - QHelpEngineCore engine(collectionFile, nullptr); - if (!engine.setupData()) - return; - - if (reindex) - clearIndexMap(&engine); - - emit indexingStarted(); - - Writer writer(indexPath); - - while (!writer.tryInit(reindex)) - sleep(1); - - const QStringList ®isteredDocs = engine.registeredDocumentations(); - QMap<QString, QDateTime> indexMap = readIndexMap(engine); - - if (!reindex) { - for (const QString &namespaceName : registeredDocs) { - if (indexMap.contains(namespaceName)) { - const QString path = engine.documentationFileName(namespaceName); - if (indexMap.value(namespaceName) < QFileInfo(path).lastModified()) { - // Remove some outdated indexed stuff - indexMap.remove(namespaceName); - writer.removeNamespace(namespaceName); - } else if (!writer.hasNamespace(namespaceName)) { - // No data in fts db for namespace. - // The namespace could have been removed from fts db - // or the whole fts db have been removed - // without removing it from indexMap. - indexMap.remove(namespaceName); - } - } else { - // Needed in case namespaceName was removed from indexMap - // without removing it from fts db. - // May happen when e.g. qch file was removed manually - // without removing fts db. - writer.removeNamespace(namespaceName); - } - // TODO: we may also detect if there are any other data - // and remove it - } - } else { - indexMap.clear(); - } - - for (const QString &namespaceName : indexMap.keys()) { - if (!registeredDocs.contains(namespaceName)) { - indexMap.remove(namespaceName); - writer.removeNamespace(namespaceName); - } - } - - for (const QString &namespaceName : registeredDocs) { - lock.relock(); - if (m_cancel) { - // store what we have done so far - writeIndexMap(&engine, indexMap); - writer.endTransaction(); - emit indexingFinished(); - return; - } - lock.unlock(); - - // if indexed, continue - if (indexMap.contains(namespaceName)) - continue; - - const QString fileName = engine.documentationFileName(namespaceName); - QHelpDBReader reader(fileName, QHelpGlobal::uniquifyConnectionName( - fileName, this), nullptr); - if (!reader.init()) - continue; - - const QString virtualFolder = reader.virtualFolder(); - - const QList<QStringList> &attributeSets = - engine.filterAttributeSets(namespaceName); - - for (const QStringList &attributes : attributeSets) { - const QString &attributesString = attributes.join(QLatin1Char('|')); - - const QMultiMap<QString, QByteArray> htmlFiles = - reader.filesData(attributes, QLatin1String("html")); - const QMultiMap<QString, QByteArray> htmFiles = - reader.filesData(attributes, QLatin1String("htm")); - const QMultiMap<QString, QByteArray> txtFiles = - reader.filesData(attributes, QLatin1String("txt")); - - QMultiMap<QString, QByteArray> files = htmlFiles; - files.unite(htmFiles); - files.unite(txtFiles); - - for (auto it = files.cbegin(), end = files.cend(); it != end ; ++it) { - lock.relock(); - if (m_cancel) { - // store what we have done so far - writeIndexMap(&engine, indexMap); - writer.endTransaction(); - emit indexingFinished(); - return; - } - lock.unlock(); - - const QString &file = it.key(); - const QByteArray &data = it.value(); - - if (data.isEmpty()) - continue; - - QUrl url; - url.setScheme(QLatin1String("qthelp")); - url.setAuthority(namespaceName); - url.setPath(QLatin1Char('/') + virtualFolder + QLatin1Char('/') + file); - - if (url.hasFragment()) - url.setFragment(QString()); - - const QString &fullFileName = url.toString(); - if (!fullFileName.endsWith(QLatin1String(".html")) - && !fullFileName.endsWith(QLatin1String(".htm")) - && !fullFileName.endsWith(QLatin1String(".txt"))) { - continue; - } - - QTextStream s(data); - auto encoding = QStringDecoder::encodingForHtml(data); - if (encoding) - s.setEncoding(*encoding); - - const QString &text = s.readAll(); - if (text.isEmpty()) - continue; - - QString title; - QString contents; - if (fullFileName.endsWith(QLatin1String(".txt"))) { - title = fullFileName.mid(fullFileName.lastIndexOf(QLatin1Char('/')) + 1); - contents = text.toHtmlEscaped(); - } else { - QTextDocument doc; - doc.setHtml(text); - - title = doc.metaInformation(QTextDocument::DocumentTitle).toHtmlEscaped(); - contents = doc.toPlainText().toHtmlEscaped(); - } - - writer.insertDoc(namespaceName, attributesString, fullFileName, title, contents); - } - } - writer.flush(); - const QString &path = engine.documentationFileName(namespaceName); - indexMap.insert(namespaceName, QFileInfo(path).lastModified()); - } - - writeIndexMap(&engine, indexMap); - - writer.endTransaction(); - emit indexingFinished(); -} - -} // namespace std -} // namespace fulltextsearch - -QT_END_NAMESPACE diff --git a/src/assistant/help/qhelpsearchindexwriter_default_p.h b/src/assistant/help/qhelpsearchindexwriter_default_p.h deleted file mode 100644 index d6233d574..000000000 --- a/src/assistant/help/qhelpsearchindexwriter_default_p.h +++ /dev/null @@ -1,133 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 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 QHELPSEARCHINDEXWRITERDEFAULT_H -#define QHELPSEARCHINDEXWRITERDEFAULT_H - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists for the convenience -// of the help generator tools. This header file may change from version -// to version without notice, or even be removed. -// -// We mean it. -// - -#include <QtCore/QMutex> -#include <QtCore/QThread> - -QT_FORWARD_DECLARE_CLASS(QSqlDatabase) - -QT_BEGIN_NAMESPACE - -namespace fulltextsearch { -namespace qt { - -class Writer -{ -public: - Writer(const QString &path); - ~Writer(); - - bool tryInit(bool reindex); - void flush(); - - void removeNamespace(const QString &namespaceName); - bool hasNamespace(const QString &namespaceName); - void insertDoc(const QString &namespaceName, - const QString &attributes, - const QString &url, - const QString &title, - const QString &contents); - void startTransaction(); - void endTransaction(); -private: - void init(bool reindex); - bool hasDB(); - void clearLegacyIndex(); - - const QString m_dbDir; - QString m_uniqueId; - - bool m_needOptimize = false; - QSqlDatabase *m_db = nullptr; - QVariantList m_namespaces; - QVariantList m_attributes; - QVariantList m_urls; - QVariantList m_titles; - QVariantList m_contents; -}; - - -class QHelpSearchIndexWriter : public QThread -{ - Q_OBJECT - -public: - QHelpSearchIndexWriter(); - ~QHelpSearchIndexWriter() override; - - void cancelIndexing(); - void updateIndex(const QString &collectionFile, - const QString &indexFilesFolder, bool reindex); - -signals: - void indexingStarted(); - void indexingFinished(); - -private: - void run() override; - -private: - QMutex m_mutex; - - bool m_cancel; - bool m_reindex; - QString m_collectionFile; - QString m_indexFilesFolder; -}; - -} // namespace std -} // namespace fulltextsearch - -QT_END_NAMESPACE - -#endif // QHELPSEARCHINDEXWRITERDEFAULT_H diff --git a/src/assistant/help/qhelpsearchindexwriter_p.h b/src/assistant/help/qhelpsearchindexwriter_p.h new file mode 100644 index 000000000..61e004794 --- /dev/null +++ b/src/assistant/help/qhelpsearchindexwriter_p.h @@ -0,0 +1,58 @@ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#ifndef QHELPSEARCHINDEXWRITER_H +#define QHELPSEARCHINDEXWRITER_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists for the convenience +// of the help generator tools. This header file may change from version +// to version without notice, or even be removed. +// +// We mean it. +// + +#include <QtCore/qmutex.h> +#include <QtCore/qthread.h> + +QT_BEGIN_NAMESPACE + +class QSqlDatabase; + +namespace fulltextsearch { + +// TODO: Employ QFuture / QtConcurrent::run() ? +class QHelpSearchIndexWriter : public QThread +{ + Q_OBJECT + +public: + ~QHelpSearchIndexWriter() override; + + void cancelIndexing(); + void updateIndex(const QString &collectionFile, const QString &indexFilesFolder, bool reindex); + +signals: + void indexingStarted(); + void indexingFinished(); + +private: + void run() override; + +private: + QMutex m_mutex; + + bool m_cancel = false; + bool m_reindex; + QString m_collectionFile; + QString m_indexFilesFolder; +}; + +} // namespace fulltextsearch + +QT_END_NAMESPACE + +#endif // QHELPSEARCHINDEXWRITER_H diff --git a/src/assistant/help/qhelpsearchquerywidget.cpp b/src/assistant/help/qhelpsearchquerywidget.cpp index 8367eb983..d5e84bacd 100644 --- a/src/assistant/help/qhelpsearchquerywidget.cpp +++ b/src/assistant/help/qhelpsearchquerywidget.cpp @@ -1,75 +1,33 @@ -/**************************************************************************** -** -** Copyright (C) 2016 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$ -** -****************************************************************************/ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only #include "qhelpsearchquerywidget.h" -#include <QtCore/QAbstractListModel> -#include <QtCore/QObject> -#include <QtCore/QStringList> -#include <QtCore/QtGlobal> - -#include <QtWidgets/QCompleter> -#include <QtWidgets/QLabel> -#include <QtWidgets/QLayout> -#include <QtWidgets/QLineEdit> -#include <QtGui/QFocusEvent> -#include <QtWidgets/QPushButton> -#include <QtWidgets/QToolButton> +#include <QtCore/qabstractitemmodel.h> +#include <QtCore/qstringlist.h> +#include <QtGui/qevent.h> +#include <QtWidgets/qcompleter.h> +#include <QtWidgets/qlabel.h> +#include <QtWidgets/qlayout.h> +#include <QtWidgets/qlineedit.h> +#include <QtWidgets/qpushbutton.h> +#include <QtWidgets/qtoolbutton.h> QT_BEGIN_NAMESPACE class QHelpSearchQueryWidgetPrivate : public QObject { - Q_OBJECT - -private: +public: struct QueryHistory { explicit QueryHistory() : curQuery(-1) {} QStringList queries; - int curQuery; + int curQuery = 0; }; class CompleterModel : public QAbstractListModel { public: - explicit CompleterModel(QObject *parent) - : QAbstractListModel(parent) {} + explicit CompleterModel(QObject *parent) : QAbstractListModel(parent) { } int rowCount(const QModelIndex &parent = QModelIndex()) const override { @@ -78,9 +36,9 @@ private: QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override { - if (!index.isValid() || index.row() >= termList.count()|| + if (!index.isValid() || index.row() >= termList.size()|| (role != Qt::EditRole && role != Qt::DisplayRole)) - return QVariant(); + return {}; return termList.at(index.row()); } @@ -97,16 +55,7 @@ private: QStringList termList; }; - QHelpSearchQueryWidgetPrivate() - : QObject() - , m_searchCompleter(new CompleterModel(this), this) - { - } - - ~QHelpSearchQueryWidgetPrivate() override - { - // nothing todo - } + QHelpSearchQueryWidgetPrivate() : m_searchCompleter(new CompleterModel(this), this) {} void retranslate() { @@ -136,7 +85,7 @@ private: // Otherwise, the respective button would be disabled. Q_ASSERT(m_queries.curQuery != maxOrMinIndex); - m_queries.curQuery = qBound(0, m_queries.curQuery + addend, m_queries.queries.count() - 1); + m_queries.curQuery = qBound(0, m_queries.curQuery + addend, m_queries.queries.size() - 1); const QString &query = m_queries.queries.at(m_queries.curQuery); m_lineEdit->setText(query); @@ -148,11 +97,9 @@ private: void enableOrDisableToolButtons() { m_prevQueryButton->setEnabled(m_queries.curQuery > 0); - m_nextQueryButton->setEnabled(m_queries.curQuery - < m_queries.queries.size() - 1); + m_nextQueryButton->setEnabled(m_queries.curQuery < m_queries.queries.size() - 1); } -private slots: bool eventFilter(QObject *ob, QEvent *event) override { if (event->type() == QEvent::KeyPress) { @@ -167,7 +114,6 @@ private slots: prevQuery(); return true; } - } return QObject::eventFilter(ob, event); } @@ -183,17 +129,10 @@ private slots: void nextQuery() { - nextOrPrevQuery(m_queries.queries.size() - 1, 1, m_nextQueryButton, - m_prevQueryButton); + nextOrPrevQuery(m_queries.queries.size() - 1, 1, m_nextQueryButton, m_prevQueryButton); } - void prevQuery() - { - nextOrPrevQuery(0, -1, m_prevQueryButton, m_nextQueryButton); - } - -private: - friend class QHelpSearchQueryWidget; + void prevQuery() { nextOrPrevQuery(0, -1, m_prevQueryButton, m_nextQueryButton); } QLabel *m_searchLabel = nullptr; QPushButton *m_searchButton = nullptr; @@ -227,13 +166,12 @@ private: */ QHelpSearchQueryWidget::QHelpSearchQueryWidget(QWidget *parent) : QWidget(parent) + , d(new QHelpSearchQueryWidgetPrivate) { - d = new QHelpSearchQueryWidgetPrivate(); - QVBoxLayout *vLayout = new QVBoxLayout(this); - vLayout->setContentsMargins(QMargins()); + vLayout->setContentsMargins({}); - QHBoxLayout* hBoxLayout = new QHBoxLayout(); + QHBoxLayout* hBoxLayout = new QHBoxLayout; d->m_searchLabel = new QLabel(this); d->m_lineEdit = new QLineEdit(this); d->m_lineEdit->setClearButtonEnabled(true); @@ -254,18 +192,13 @@ QHelpSearchQueryWidget::QHelpSearchQueryWidget(QWidget *parent) vLayout->addLayout(hBoxLayout); - connect(d->m_prevQueryButton, &QAbstractButton::clicked, - d, &QHelpSearchQueryWidgetPrivate::prevQuery); - connect(d->m_nextQueryButton, &QAbstractButton::clicked, - d, &QHelpSearchQueryWidgetPrivate::nextQuery); - connect(d->m_searchButton, &QAbstractButton::clicked, - this, &QHelpSearchQueryWidget::search); - connect(d->m_lineEdit, &QLineEdit::returnPressed, - this, &QHelpSearchQueryWidget::search); + connect(d->m_prevQueryButton, &QAbstractButton::clicked, this, [this] { d->prevQuery(); }); + connect(d->m_nextQueryButton, &QAbstractButton::clicked, this, [this] { d->nextQuery(); }); + connect(d->m_searchButton, &QAbstractButton::clicked, this, &QHelpSearchQueryWidget::search); + connect(d->m_lineEdit, &QLineEdit::returnPressed, this, &QHelpSearchQueryWidget::search); d->retranslate(); - connect(this, &QHelpSearchQueryWidget::search, - d, &QHelpSearchQueryWidgetPrivate::searchRequested); + connect(this, &QHelpSearchQueryWidget::search, this, [this] { d->searchRequested(); }); setCompactMode(true); } @@ -294,6 +227,9 @@ void QHelpSearchQueryWidget::collapseExtendedSearch() // TODO: no extended search anymore, deprecate it? } +#if QT_DEPRECATED_SINCE(5, 9) +QT_WARNING_PUSH +QT_WARNING_DISABLE_DEPRECATED /*! \deprecated @@ -301,8 +237,7 @@ void QHelpSearchQueryWidget::collapseExtendedSearch() */ QList<QHelpSearchQuery> QHelpSearchQueryWidget::query() const { - return QList<QHelpSearchQuery>() << QHelpSearchQuery(QHelpSearchQuery::DEFAULT, - searchInput().split(QChar::Space, Qt::SkipEmptyParts)); + return {{QHelpSearchQuery::DEFAULT, searchInput().split(QChar::Space, Qt::SkipEmptyParts)}}; } /*! @@ -317,6 +252,8 @@ void QHelpSearchQueryWidget::setQuery(const QList<QHelpSearchQuery> &queryList) setSearchInput(queryList.first().wordList.join(QChar::Space)); } +QT_WARNING_POP +#endif // QT_DEPRECATED_SINCE(5, 9) /*! \since 5.9 @@ -327,7 +264,7 @@ void QHelpSearchQueryWidget::setQuery(const QList<QHelpSearchQuery> &queryList) QString QHelpSearchQueryWidget::searchInput() const { if (d->m_queries.queries.isEmpty()) - return QString(); + return {}; return d->m_queries.queries.last(); } @@ -343,9 +280,7 @@ QString QHelpSearchQueryWidget::searchInput() const void QHelpSearchQueryWidget::setSearchInput(const QString &searchInput) { d->m_lineEdit->clear(); - d->m_lineEdit->setText(searchInput); - d->searchRequested(); } @@ -387,5 +322,3 @@ void QHelpSearchQueryWidget::changeEvent(QEvent *event) } QT_END_NAMESPACE - -#include "qhelpsearchquerywidget.moc" diff --git a/src/assistant/help/qhelpsearchquerywidget.h b/src/assistant/help/qhelpsearchquerywidget.h index 52a137db1..148ae0f11 100644 --- a/src/assistant/help/qhelpsearchquerywidget.h +++ b/src/assistant/help/qhelpsearchquerywidget.h @@ -1,41 +1,5 @@ -/**************************************************************************** -** -** Copyright (C) 2016 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$ -** -****************************************************************************/ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only #ifndef QHELPSEARCHQUERYWIDGET_H #define QHELPSEARCHQUERYWIDGET_H @@ -43,15 +7,10 @@ #include <QtHelp/qhelp_global.h> #include <QtHelp/qhelpsearchengine.h> -#include <QtCore/QMap> -#include <QtCore/QString> -#include <QtCore/QStringList> - -#include <QtWidgets/QWidget> +#include <QtWidgets/qwidget.h> QT_BEGIN_NAMESPACE - class QFocusEvent; class QHelpSearchQueryWidgetPrivate; @@ -75,7 +34,9 @@ public: void setSearchInput(const QString &searchInput); bool isCompactMode() const; - Q_SLOT void setCompactMode(bool on); + +public Q_SLOTS: + void setCompactMode(bool on); Q_SIGNALS: void search(); @@ -90,4 +51,4 @@ private: QT_END_NAMESPACE -#endif // QHELPSEARCHQUERYWIDGET_H +#endif // QHELPSEARCHQUERYWIDGET_H diff --git a/src/assistant/help/qhelpsearchresult.cpp b/src/assistant/help/qhelpsearchresult.cpp new file mode 100644 index 000000000..a813249d7 --- /dev/null +++ b/src/assistant/help/qhelpsearchresult.cpp @@ -0,0 +1,90 @@ +// Copyright (C) 2024 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#include "qhelpsearchresult.h" + +#include <QtCore/qstring.h> +#include <QtCore/qurl.h> + +QT_BEGIN_NAMESPACE + +class QHelpSearchResultData : public QSharedData +{ +public: + QUrl m_url; + QString m_title; + QString m_snippet; +}; + +/*! + \class QHelpSearchResult + \since 5.9 + \inmodule QtHelp + \brief The QHelpSearchResult class provides the data associated with the + search result. + + The QHelpSearchResult object is a data object that describes a single search result. + The vector of search result objects is returned by QHelpSearchEngine::searchResults(). + The description of the search result contains the document title and URL + that the search input matched. It also contains the snippet from + the document content containing the best match of the search input. + \sa QHelpSearchEngine +*/ + +/*! + Constructs a new empty QHelpSearchResult. +*/ +QHelpSearchResult::QHelpSearchResult() : d(new QHelpSearchResultData) { } + +/*! + Constructs a copy of \a other. +*/ +QHelpSearchResult::QHelpSearchResult(const QHelpSearchResult &other) = default; + +/*! + Constructs the search result containing \a url, \a title and \a snippet + as the description of the result. +*/ +QHelpSearchResult::QHelpSearchResult(const QUrl &url, const QString &title, const QString &snippet) + : d(new QHelpSearchResultData) +{ + d->m_url = url; + d->m_title = title; + d->m_snippet = snippet; +} + +/*! + Destroys the search result. +*/ +QHelpSearchResult::~QHelpSearchResult() = default; + +/*! + Assigns \a other to this search result and returns a reference to this search result. +*/ +QHelpSearchResult &QHelpSearchResult::operator=(const QHelpSearchResult &other) = default; + +/*! + Returns the document title of the search result. +*/ +QString QHelpSearchResult::title() const +{ + return d->m_title; +} + +/*! + Returns the document URL of the search result. +*/ +QUrl QHelpSearchResult::url() const +{ + return d->m_url; +} + +/*! + Returns the document snippet containing the search phrase of the search result. +*/ +QString QHelpSearchResult::snippet() const +{ + return d->m_snippet; +} + +QT_END_NAMESPACE diff --git a/src/assistant/help/qhelpsearchresult.h b/src/assistant/help/qhelpsearchresult.h new file mode 100644 index 000000000..d8b42c158 --- /dev/null +++ b/src/assistant/help/qhelpsearchresult.h @@ -0,0 +1,37 @@ +// Copyright (C) 2024 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#ifndef QHELPSEARCHRESULT_H +#define QHELPSEARCHRESULT_H + +#include <QtHelp/qhelp_global.h> + +#include <QtCore/qshareddata.h> + +QT_BEGIN_NAMESPACE + +class QHelpSearchResultData; +class QString; +class QUrl; + +class QHELP_EXPORT QHelpSearchResult +{ +public: + QHelpSearchResult(); + QHelpSearchResult(const QHelpSearchResult &other); + QHelpSearchResult(const QUrl &url, const QString &title, const QString &snippet); + ~QHelpSearchResult(); + + QHelpSearchResult &operator=(const QHelpSearchResult &other); + + QString title() const; + QUrl url() const; + QString snippet() const; + +private: + QSharedDataPointer<QHelpSearchResultData> d; +}; + +QT_END_NAMESPACE + +#endif // QHELPSEARCHRESULT_H diff --git a/src/assistant/help/qhelpsearchresultwidget.cpp b/src/assistant/help/qhelpsearchresultwidget.cpp index 12d689dc6..3de64dd85 100644 --- a/src/assistant/help/qhelpsearchresultwidget.cpp +++ b/src/assistant/help/qhelpsearchresultwidget.cpp @@ -1,62 +1,22 @@ -/**************************************************************************** -** -** Copyright (C) 2016 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$ -** -****************************************************************************/ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only #include "qhelpsearchresultwidget.h" -#include <QtCore/QList> -#include <QtCore/QString> -#include <QtCore/QPointer> -#include <QtCore/QStringList> -#include <QtCore/QTextStream> - -#include <QtWidgets/QLabel> -#include <QtWidgets/QLayout> -#include <QtGui/QMouseEvent> -#include <QtWidgets/QHeaderView> -#include <QtWidgets/QSpacerItem> -#include <QtWidgets/QToolButton> -#include <QtWidgets/QTreeWidget> -#include <QtWidgets/QTextBrowser> -#include <QtWidgets/QTreeWidgetItem> +#include <QtCore/qcoreevent.h> +#include <QtCore/qlist.h> +#include <QtCore/qpointer.h> +#include <QtCore/qtextstream.h> +#include <QtWidgets/qlabel.h> +#include <QtWidgets/qlayout.h> +#include <QtWidgets/qlayoutitem.h> +#include <QtWidgets/qtoolbutton.h> +#include <QtWidgets/qtextbrowser.h> QT_BEGIN_NAMESPACE +static constexpr int ResultsRange = 20; + class QResultWidget : public QTextBrowser { Q_OBJECT @@ -66,8 +26,7 @@ public: QResultWidget(QWidget *parent = nullptr) : QTextBrowser(parent) { - connect(this, &QTextBrowser::anchorClicked, - this, &QResultWidget::requestShowLink); + connect(this, &QTextBrowser::anchorClicked, this, &QResultWidget::requestShowLink); setContextMenuPolicy(Qt::NoContextMenu); setLinkColor(palette().color(QPalette::Link)); } @@ -76,7 +35,8 @@ public: void setLinkColor(const QColor &color) { m_linkColor = color; - const QString sheet = QString::fromLatin1("a { text-decoration: underline; color: %1 }").arg(m_linkColor.name()); + const QString sheet = QString::fromLatin1("a { text-decoration: underline; color: %1 }") + .arg(m_linkColor.name()); document()->setDefaultStyleSheet(sheet); } @@ -86,7 +46,7 @@ public: QTextStream str(&htmlFile); str << "<html><head><title>" << tr("Search Results") << "</title></head><body>"; - const int count = results.count(); + const int count = results.size(); if (count != 0) { if (isIndexing) { str << "<div style=\"text-align:left;" @@ -115,7 +75,6 @@ public: } str << "</body></html>"; - setHtml(htmlFile); } @@ -129,80 +88,22 @@ private: QColor m_linkColor; }; - -class QHelpSearchResultWidgetPrivate : public QObject +class QHelpSearchResultWidgetPrivate { - Q_OBJECT - -private slots: - void showFirstResultPage() - { - if (!searchEngine.isNull()) - resultFirstToShow = 0; - updateHitRange(); - } - - void showLastResultPage() - { - if (!searchEngine.isNull()) - resultFirstToShow = (searchEngine->searchResultCount() - 1) / ResultsRange * ResultsRange; - updateHitRange(); - } - - void showPreviousResultPage() - { - if (!searchEngine.isNull()) { - resultFirstToShow -= ResultsRange; - if (resultFirstToShow < 0) - resultFirstToShow = 0; - } - updateHitRange(); - } - - void showNextResultPage() - { - if (!searchEngine.isNull() - && resultFirstToShow + ResultsRange < searchEngine->searchResultCount()) { - resultFirstToShow += ResultsRange; - } - updateHitRange(); - } - - void indexingStarted() - { - isIndexing = true; - } - - void indexingFinished() - { - isIndexing = false; - } - -private: - QHelpSearchResultWidgetPrivate(QHelpSearchEngine *engine) - : QObject() - , searchEngine(engine) - { - connect(searchEngine.data(), &QHelpSearchEngine::indexingStarted, - this, &QHelpSearchResultWidgetPrivate::indexingStarted); - connect(searchEngine.data(), &QHelpSearchEngine::indexingFinished, - this, &QHelpSearchResultWidgetPrivate::indexingFinished); - } - +public: ~QHelpSearchResultWidgetPrivate() { - delete searchEngine; + delete searchEngine; // TODO: This it probably wrong, why the widget owns the engine? } QToolButton* setupToolButton(const QString &iconPath) { - QToolButton *button = new QToolButton(); + QToolButton *button = new QToolButton; button->setEnabled(false); button->setAutoRaise(true); button->setIcon(QIcon(iconPath)); - button->setIconSize(QSize(12, 12)); - button->setMaximumSize(QSize(16, 16)); - + button->setIconSize({12, 12}); + button->setMaximumSize({16, 16}); return button; } @@ -218,26 +119,23 @@ private: last = qMin(resultFirstToShow + ResultsRange, count); first = resultFirstToShow + 1; } - resultTextBrowser->showResultPage(searchEngine->searchResults(resultFirstToShow, - last), isIndexing); + resultTextBrowser->showResultPage(searchEngine->searchResults(resultFirstToShow, last), + isIndexing); } - hitsLabel->setText(QHelpSearchResultWidget::tr("%1 - %2 of %n Hits", nullptr, count).arg(first).arg(last)); + hitsLabel->setText(QHelpSearchResultWidget::tr("%1 - %2 of %n Hits", nullptr, count) + .arg(first).arg(last)); firstResultPage->setEnabled(resultFirstToShow); previousResultPage->setEnabled(resultFirstToShow); lastResultPage->setEnabled(count - last); nextResultPage->setEnabled(count - last); } -private: - friend class QHelpSearchResultWidget; - + QHelpSearchResultWidget *q = nullptr; QPointer<QHelpSearchEngine> searchEngine; QResultWidget *resultTextBrowser = nullptr; - static const int ResultsRange = 20; - QToolButton *firstResultPage = nullptr; QToolButton *previousResultPage = nullptr; QToolButton *nextResultPage = nullptr; @@ -264,15 +162,21 @@ private: QHelpSearchResultWidget::QHelpSearchResultWidget(QHelpSearchEngine *engine) : QWidget(0) - , d(new QHelpSearchResultWidgetPrivate(engine)) + , d(new QHelpSearchResultWidgetPrivate) { + d->q = this; + d->searchEngine = engine; + + connect(engine, &QHelpSearchEngine::indexingStarted, this, [this] { d->isIndexing = true; }); + connect(engine, &QHelpSearchEngine::indexingFinished, this, [this] { d->isIndexing = false; }); + QVBoxLayout *vLayout = new QVBoxLayout(this); - vLayout->setContentsMargins(QMargins()); + vLayout->setContentsMargins({}); vLayout->setSpacing(0); QHBoxLayout *hBoxLayout = new QHBoxLayout(); #ifndef Q_OS_MAC - hBoxLayout->setContentsMargins(QMargins()); + hBoxLayout->setContentsMargins({}); hBoxLayout->setSpacing(0); #endif hBoxLayout->addWidget(d->firstResultPage = d->setupToolButton( @@ -303,17 +207,33 @@ QHelpSearchResultWidget::QHelpSearchResultWidget(QHelpSearchEngine *engine) connect(d->resultTextBrowser, &QResultWidget::requestShowLink, this, &QHelpSearchResultWidget::requestShowLink); - connect(d->nextResultPage, &QAbstractButton::clicked, - d, &QHelpSearchResultWidgetPrivate::showNextResultPage); - connect(d->lastResultPage, &QAbstractButton::clicked, - d, &QHelpSearchResultWidgetPrivate::showLastResultPage); - connect(d->firstResultPage, &QAbstractButton::clicked, - d, &QHelpSearchResultWidgetPrivate::showFirstResultPage); - connect(d->previousResultPage, &QAbstractButton::clicked, - d, &QHelpSearchResultWidgetPrivate::showPreviousResultPage); - - connect(engine, &QHelpSearchEngine::searchingFinished, - d, &QHelpSearchResultWidgetPrivate::showFirstResultPage); + connect(d->nextResultPage, &QAbstractButton::clicked, this, [this] { + if (!d->searchEngine.isNull() + && d->resultFirstToShow + ResultsRange < d->searchEngine->searchResultCount()) { + d->resultFirstToShow += ResultsRange; + } + d->updateHitRange(); + }); + connect(d->previousResultPage, &QAbstractButton::clicked, this, [this] { + if (!d->searchEngine.isNull()) { + d->resultFirstToShow -= ResultsRange; + if (d->resultFirstToShow < 0) + d->resultFirstToShow = 0; + } + d->updateHitRange(); + }); + connect(d->lastResultPage, &QAbstractButton::clicked, this, [this] { + if (!d->searchEngine.isNull()) + d->resultFirstToShow = (d->searchEngine->searchResultCount() - 1) / ResultsRange * ResultsRange; + d->updateHitRange(); + }); + const auto showFirstPage = [this] { + if (!d->searchEngine.isNull()) + d->resultFirstToShow = 0; + d->updateHitRange(); + }; + connect(d->firstResultPage, &QAbstractButton::clicked, this, showFirstPage); + connect(engine, &QHelpSearchEngine::searchingFinished, this, showFirstPage); } /*! \reimp @@ -340,7 +260,7 @@ QUrl QHelpSearchResultWidget::linkAt(const QPoint &point) { if (d->resultTextBrowser) return d->resultTextBrowser->anchorAt(point); - return QUrl(); + return {}; } QT_END_NAMESPACE diff --git a/src/assistant/help/qhelpsearchresultwidget.h b/src/assistant/help/qhelpsearchresultwidget.h index 4cb802527..859477eae 100644 --- a/src/assistant/help/qhelpsearchresultwidget.h +++ b/src/assistant/help/qhelpsearchresultwidget.h @@ -1,57 +1,19 @@ -/**************************************************************************** -** -** Copyright (C) 2016 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$ -** -****************************************************************************/ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only #ifndef QHELPSEARCHRESULTWIDGET_H #define QHELPSEARCHRESULTWIDGET_H -#include <QtHelp/qhelpsearchengine.h> #include <QtHelp/qhelp_global.h> +#include <QtHelp/qhelpsearchengine.h> -#include <QtCore/QUrl> -#include <QtCore/QPoint> -#include <QtCore/QObject> - -#include <QtWidgets/QWidget> +#include <QtWidgets/qwidget.h> QT_BEGIN_NAMESPACE class QHelpSearchResultWidgetPrivate; +class QPoint; +class QUrl; class QHELP_EXPORT QHelpSearchResultWidget : public QWidget { @@ -74,4 +36,4 @@ private: QT_END_NAMESPACE -#endif // QHELPSEARCHRESULTWIDGET_H +#endif // QHELPSEARCHRESULTWIDGET_H diff --git a/src/assistant/help/qoptionswidget.cpp b/src/assistant/help/qoptionswidget.cpp index 21fdfe07a..e529b65eb 100644 --- a/src/assistant/help/qoptionswidget.cpp +++ b/src/assistant/help/qoptionswidget.cpp @@ -1,47 +1,23 @@ -/**************************************************************************** -** -** 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:GPL-EXCEPT$ -** 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 General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** 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-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2020 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only #include "qoptionswidget_p.h" -#include <QtWidgets/QComboBox> -#include <QtWidgets/QItemDelegate> -#include <QtWidgets/QListWidget> -#include <QtWidgets/QVBoxLayout> +#include <QtWidgets/qitemdelegate.h> +#include <QtWidgets/qlayout.h> +#include <QtWidgets/qlistwidget.h> QT_BEGIN_NAMESPACE +using namespace Qt::StringLiterals; + class ListWidgetDelegate : public QItemDelegate { public: ListWidgetDelegate(QWidget *w) : QItemDelegate(w), m_widget(w) {} static bool isSeparator(const QModelIndex &index) { - return index.data(Qt::AccessibleDescriptionRole).toString() == QLatin1String("separator"); + return index.data(Qt::AccessibleDescriptionRole).toString() == "separator"_L1; } static void setSeparator(QListWidgetItem *item) { item->setData(Qt::AccessibleDescriptionRole, QString::fromLatin1("separator")); @@ -49,29 +25,31 @@ public: } protected: - void paint(QPainter *painter, - const QStyleOptionViewItem &option, - const QModelIndex &index) const override { + void paint(QPainter *painter, const QStyleOptionViewItem &option, + const QModelIndex &index) const override + { if (isSeparator(index)) { QRect rect = option.rect; if (const QAbstractItemView *view = qobject_cast<const QAbstractItemView*>(option.widget)) rect.setWidth(view->viewport()->width()); QStyleOption opt; opt.rect = rect; - m_widget->style()->drawPrimitive(QStyle::PE_IndicatorToolBarSeparator, &opt, painter, m_widget); + m_widget->style()->drawPrimitive(QStyle::PE_IndicatorToolBarSeparator, &opt, painter, + m_widget); } else { QItemDelegate::paint(painter, option, index); } } - QSize sizeHint(const QStyleOptionViewItem &option, - const QModelIndex &index) const override { + QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const override + { if (isSeparator(index)) { int pm = m_widget->style()->pixelMetric(QStyle::PM_DefaultFrameWidth, nullptr, m_widget); - return QSize(pm, pm); + return {pm, pm}; } return QItemDelegate::sizeHint(option, index); } + private: QWidget *m_widget; }; @@ -93,18 +71,11 @@ QOptionsWidget::QOptionsWidget(QWidget *parent) m_listWidget->setItemDelegate(new ListWidgetDelegate(m_listWidget)); QVBoxLayout *layout = new QVBoxLayout(this); layout->addWidget(m_listWidget); - layout->setContentsMargins(QMargins()); - + layout->setContentsMargins({}); connect(m_listWidget, &QListWidget::itemChanged, this, &QOptionsWidget::itemChanged); } -void QOptionsWidget::clear() -{ - setOptions(QStringList(), QStringList()); -} - -void QOptionsWidget::setOptions(const QStringList &validOptions, - const QStringList &selectedOptions) +void QOptionsWidget::setOptions(const QStringList &validOptions, const QStringList &selectedOptions) { m_listWidget->clear(); m_optionToItem.clear(); @@ -128,28 +99,16 @@ void QOptionsWidget::setOptions(const QStringList &validOptions, for (const QString &option : m_invalidOptions) appendItem(option, false, true); - if ((validSelectedOptions.count() + m_invalidOptions.count()) - && validUnselectedOptions.count()) { + if ((validSelectedOptions.size() + m_invalidOptions.size()) && validUnselectedOptions.size()) appendSeparator(); - } for (const QString &option : validUnselectedOptions) { appendItem(option, true, false); - if (option.isEmpty() && validUnselectedOptions.count() > 1) // special No Option item + if (option.isEmpty() && validUnselectedOptions.size() > 1) // special No Option item appendSeparator(); } } -QStringList QOptionsWidget::validOptions() const -{ - return m_validOptions; -} - -QStringList QOptionsWidget::selectedOptions() const -{ - return m_selectedOptions; -} - void QOptionsWidget::setNoOptionText(const QString &text) { if (m_noOptionText == text) @@ -182,9 +141,9 @@ QString QOptionsWidget::optionText(const QString &optionName, bool valid) const { QString text = optionName; if (optionName.isEmpty()) - text = QLatin1Char('[') + m_noOptionText + QLatin1Char(']'); + text = u'[' + m_noOptionText + u']'; if (!valid) - text += QLatin1String("\t[") + m_invalidOptionText + QLatin1Char(']'); + text += "\t["_L1 + m_invalidOptionText + u']'; return text; } @@ -192,7 +151,7 @@ QListWidgetItem *QOptionsWidget::appendItem(const QString &optionName, bool vali { QListWidgetItem *optionItem = new QListWidgetItem(optionText(optionName, valid), m_listWidget); optionItem->setCheckState(selected ? Qt::Checked : Qt::Unchecked); - m_listWidget->insertItem(m_listWidget->count(), optionItem); + m_listWidget->addItem(optionItem); m_optionToItem[optionName] = optionItem; m_itemToOption[optionItem] = optionName; return optionItem; @@ -202,7 +161,7 @@ void QOptionsWidget::appendSeparator() { QListWidgetItem *separatorItem = new QListWidgetItem(m_listWidget); ListWidgetDelegate::setSeparator(separatorItem); - m_listWidget->insertItem(m_listWidget->count(), separatorItem); + m_listWidget->addItem(separatorItem); } void QOptionsWidget::itemChanged(QListWidgetItem *item) @@ -221,9 +180,7 @@ void QOptionsWidget::itemChanged(QListWidgetItem *item) } else { return; } - emit optionSelectionChanged(m_selectedOptions); } - QT_END_NAMESPACE diff --git a/src/assistant/help/qoptionswidget_p.h b/src/assistant/help/qoptionswidget_p.h index a6700c1d7..a62fbe2c8 100644 --- a/src/assistant/help/qoptionswidget_p.h +++ b/src/assistant/help/qoptionswidget_p.h @@ -1,30 +1,5 @@ -/**************************************************************************** -** -** 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:GPL-EXCEPT$ -** 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 General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** 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-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2020 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only #ifndef QOPTIONSWIDGET_H #define QOPTIONSWIDGET_H @@ -40,8 +15,8 @@ // We mean it. // -#include <QtWidgets/QWidget> -#include <QtCore/QMap> +#include <QtCore/qhash.h> +#include <QtWidgets/qwidget.h> QT_BEGIN_NAMESPACE @@ -54,11 +29,10 @@ class QOptionsWidget : public QWidget public: QOptionsWidget(QWidget *parent = nullptr); - void clear(); - void setOptions(const QStringList &validOptions, - const QStringList &selectedOptions); - QStringList validOptions() const; - QStringList selectedOptions() const; + void clear() { setOptions({}, {}); } + void setOptions(const QStringList &validOptions, const QStringList &selectedOptions); + QStringList validOptions() const { return m_validOptions; } + QStringList selectedOptions() const { return m_selectedOptions; } void setNoOptionText(const QString &text); void setInvalidOptionText(const QString &text); @@ -78,10 +52,10 @@ private: QStringList m_validOptions; QStringList m_invalidOptions; QStringList m_selectedOptions; - QMap<QString, QListWidgetItem *> m_optionToItem; - QMap<QListWidgetItem *, QString> m_itemToOption; + QHash<QString, QListWidgetItem *> m_optionToItem; + QHash<QListWidgetItem *, QString> m_itemToOption; }; QT_END_NAMESPACE -#endif // OPTIONSWIDGET_H +#endif // QOPTIONSWIDGET_H |