From e6cb442dc6124dc62aef0b07a8b1bf62f31c6886 Mon Sep 17 00:00:00 2001 From: Nikhil Tanwar <2002nikhiltanwar@gmail.com> Date: Thu, 20 Jul 2023 19:18:11 +0530 Subject: [PATCH 01/17] New widget: KiwixChoiceBox This change adds a new widget called KiwixChoiceBox The design inspiration is taken from here: https://harvesthq.github.io/chosen/#multiple-select setType() takes a string to put on the label We can add possible choices using the setSelections() method --- kiwix-desktop.pro | 10 + resources/css/_contentManager.css | 15 +- resources/css/choiceBox.css | 71 +++++++ resources/css/contentmanagerside.css | 10 + resources/i18n/en.json | 9 +- resources/icons/xmark-solid.svg | 1 + resources/kiwix.qrc | 1 + resources/style.qrc | 1 + src/choiceitem.cpp | 23 +++ src/choiceitem.h | 29 +++ src/choiceitem.ui | 143 ++++++++++++++ src/contentmanager.cpp | 2 - src/contentmanagerside.h | 2 + src/contentmanagerside.ui | 275 ++++++++++++++++++++------- src/contenttypefilter.cpp | 5 +- src/flowlayout.cpp | 230 ++++++++++++++++++++++ src/flowlayout.h | 89 +++++++++ src/kiwixchoicebox.cpp | 205 ++++++++++++++++++++ src/kiwixchoicebox.h | 58 ++++++ src/kiwixlineedit.cpp | 27 +++ src/kiwixlineedit.h | 20 ++ src/klistwidgetitem.cpp | 3 + src/klistwidgetitem.h | 3 + ui/kiwixchoicebox.ui | 103 ++++++++++ 24 files changed, 1245 insertions(+), 90 deletions(-) create mode 100644 resources/css/choiceBox.css create mode 100644 resources/css/contentmanagerside.css create mode 100644 resources/icons/xmark-solid.svg create mode 100644 src/choiceitem.cpp create mode 100644 src/choiceitem.h create mode 100644 src/choiceitem.ui create mode 100644 src/flowlayout.cpp create mode 100644 src/flowlayout.h create mode 100644 src/kiwixchoicebox.cpp create mode 100644 src/kiwixchoicebox.h create mode 100644 src/kiwixlineedit.cpp create mode 100644 src/kiwixlineedit.h create mode 100644 ui/kiwixchoicebox.ui diff --git a/kiwix-desktop.pro b/kiwix-desktop.pro index 1e993414..e9a148ce 100644 --- a/kiwix-desktop.pro +++ b/kiwix-desktop.pro @@ -34,13 +34,17 @@ DEFINES += QT_DEPRECATED_WARNINGS SOURCES += \ + src/choiceitem.cpp \ src/contentmanagerdelegate.cpp \ src/contentmanagerheader.cpp \ src/contentmanagermodel.cpp \ src/contenttypefilter.cpp \ src/descriptionnode.cpp \ src/findinpagebar.cpp \ + src/flowlayout.cpp \ + src/kiwixchoicebox.cpp \ src/kiwixconfirmbox.cpp \ + src/kiwixlineedit.cpp \ src/kiwixloader.cpp \ src/rownode.cpp \ src/suggestionlistworker.cpp \ @@ -74,6 +78,7 @@ SOURCES += \ src/zimview.cpp \ HEADERS += \ + src/choiceitem.h \ src/contentmanagerdelegate.h \ src/contentmanagerheader.h \ src/contentmanagermodel.h \ @@ -81,7 +86,10 @@ HEADERS += \ src/contenttypefilter.h \ src/descriptionnode.h \ src/findinpagebar.h \ + src/flowlayout.h \ + src/kiwixchoicebox.h \ src/kiwixconfirmbox.h \ + src/kiwixlineedit.h \ src/kiwixloader.h \ src/node.h \ src/rownode.h \ @@ -116,8 +124,10 @@ HEADERS += \ src/zimview.h \ FORMS += \ + src/choiceitem.ui \ src/contentmanagerview.ui \ src/findinpagebar.ui \ + ui/kiwixchoicebox.ui \ ui/kiwixconfirmbox.ui \ ui/mainwindow.ui \ ui/about.ui \ diff --git a/resources/css/_contentManager.css b/resources/css/_contentManager.css index 93e31adc..f2e2a3bb 100644 --- a/resources/css/_contentManager.css +++ b/resources/css/_contentManager.css @@ -1,3 +1,7 @@ +#contentmanagerside { + background-color: red; +} + QTreeView::branch:open:has-children { image: url(:/icons/caret-down-solid.svg); padding: 6px; @@ -64,14 +68,3 @@ QMenu::item { QMenu::item:selected { background-color: #cccccc; } - -QLineEdit { - font-family: 'Selawik'; - padding: 4px; - border: none; - border-bottom: 1px solid #cccccc; - color: #666666; - font-size: 16px; - height: 32px; - line-height: 24px; -} diff --git a/resources/css/choiceBox.css b/resources/css/choiceBox.css new file mode 100644 index 00000000..20d85dea --- /dev/null +++ b/resources/css/choiceBox.css @@ -0,0 +1,71 @@ +QListWidget::item { + padding: 0; + padding-top: 6px; + padding-bottom: 6px; + padding-left: 2px; +} + +QListWidget { + padding: 0; + border: 1px solid #ccc; +} + +QListWidget::item::selected { + color: #444444; + background-color: transparent; +} + +QLineEdit { + padding: 4px; + border: 0; +} + +#choiceLabel { + font-size: 16px; +} + +#currentChoices { + margin: 0; + padding: 0; + border: 1px solid #ccc; + border-radius: 1px; +} + +#closeButton { + margin: 0; + background: transparent; + color: #eaecf0; + font-size: 12px; +} + +ChoiceItem > QFrame { + border: 1px solid #ccc; + border-radius: 2px; + padding: 0; + background-color: #666; + padding-left: 2px; + padding-right: 2px; + margin:0; +} + +#itemLabel { + margin: 0; + height: 6px; + background-color: #666; + color: #eaecf0; + font-size: 13px; +} + +#clearButton { + background-color: white; + color: #3366cc; + padding: 4px; + font: bold; + font-size: 14px; + border-radius: 4px; +} + +#clearButton:hover { + background-color: #3366cc; + color: white; +} diff --git a/resources/css/contentmanagerside.css b/resources/css/contentmanagerside.css new file mode 100644 index 00000000..fc848645 --- /dev/null +++ b/resources/css/contentmanagerside.css @@ -0,0 +1,10 @@ +#searcher { + font-family: 'Selawik'; + padding: 4px; + border: none; + border-bottom: 1px solid #cccccc; + color: #666666; + font-size: 16px; + height: 32px; + line-height: 24px; +} diff --git a/resources/i18n/en.json b/resources/i18n/en.json index bcae634b..8f441fe9 100644 --- a/resources/i18n/en.json +++ b/resources/i18n/en.json @@ -90,8 +90,8 @@ "fullscreen-notification":"You are now in full screen mode. Press ESC to quit!", "online-files":"Online Files", "local-files":"Local Files", - "browse-by-category":"Browse By Category", - "browse-by-language":"Browse By Language", + "category":"Category", + "language":"Language", "hide":"Hide", "open-in-browser":"Open in browser", "start-kiwix-server":"Start Kiwix Server", @@ -154,5 +154,8 @@ "couldnt-open-location-text": "Kiwix is not able to open folder {{FOLDER}}", "move-files-to-trash": "Move deleted files to trash", "move-files-to-trash-text": "This action will move the file to trash.", - "perma-delete-files-text": "This action will permanently delete the file." + "perma-delete-files-text": "This action will permanently delete the file.", + "clear-filter": "Clear the currently set filters", + "search-language": "Search language", + "search-category": "Search category" } diff --git a/resources/icons/xmark-solid.svg b/resources/icons/xmark-solid.svg new file mode 100644 index 00000000..c693bd00 --- /dev/null +++ b/resources/icons/xmark-solid.svg @@ -0,0 +1 @@ + diff --git a/resources/kiwix.qrc b/resources/kiwix.qrc index c25bd435..05a2e32c 100644 --- a/resources/kiwix.qrc +++ b/resources/kiwix.qrc @@ -61,5 +61,6 @@ icons/caret-up-solid.svg icons/kiwix-logo.svg icons/check-solid.svg + icons/xmark-solid.svg diff --git a/resources/style.qrc b/resources/style.qrc index 565b93fa..1dfa31e4 100644 --- a/resources/style.qrc +++ b/resources/style.qrc @@ -4,5 +4,6 @@ css/popup.css css/localServer.css css/confirmBox.css + css/contentmanagerside.css diff --git a/src/choiceitem.cpp b/src/choiceitem.cpp new file mode 100644 index 00000000..755eae19 --- /dev/null +++ b/src/choiceitem.cpp @@ -0,0 +1,23 @@ +#include "choiceitem.h" +#include "ui_choiceitem.h" +#include + +ChoiceItem::ChoiceItem(QString key, QString value, QWidget *parent) : + QWidget(parent), + ui(new Ui::ChoiceItem), + m_key(key), + m_value(value) +{ + ui->setupUi(this); + ui->itemLabel->setText(key); + ui->itemLabel->setToolTip(key); + connect(ui->closeButton, &QPushButton::clicked, [=](){ + emit(closeButtonClicked(ui->itemLabel->text())); + }); + ui->closeButton->setCursor(Qt::PointingHandCursor); +} + +ChoiceItem::~ChoiceItem() +{ + delete ui; +} diff --git a/src/choiceitem.h b/src/choiceitem.h new file mode 100644 index 00000000..76ea4772 --- /dev/null +++ b/src/choiceitem.h @@ -0,0 +1,29 @@ +#ifndef CHOICEITEM_H +#define CHOICEITEM_H + +#include + +namespace Ui { +class ChoiceItem; +} + +class ChoiceItem : public QWidget +{ + Q_OBJECT + +public: + explicit ChoiceItem(QString key, QString value, QWidget *parent = nullptr); + ~ChoiceItem(); + QString getKey() { return m_key; } + QString getValue() { return m_value; } + +private: + Ui::ChoiceItem *ui; + QString m_key; + QString m_value; + +signals: + void closeButtonClicked(QString); +}; + +#endif // CHOICEITEM_H diff --git a/src/choiceitem.ui b/src/choiceitem.ui new file mode 100644 index 00000000..19aae85c --- /dev/null +++ b/src/choiceitem.ui @@ -0,0 +1,143 @@ + + + ChoiceItem + + + + 0 + 0 + 119 + 35 + + + + + 0 + 0 + + + + + 0 + 30 + + + + Form + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + 0 + 0 + + + + + 16777215 + 16777215 + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + 3 + + + 3 + + + 3 + + + 3 + + + + + + 0 + 0 + + + + + 16777215 + 16777215 + + + + TextLabel + + + + + + + true + + + + 0 + 0 + + + + + 0 + 0 + + + + + 10 + 16777215 + + + + + + + + :/icons/xmark-solid.svg:/icons/xmark-solid.svg + + + + 10 + 20 + + + + true + + + + + + + + + + + + + diff --git a/src/contentmanager.cpp b/src/contentmanager.cpp index 1c454676..c601340c 100644 --- a/src/contentmanager.cpp +++ b/src/contentmanager.cpp @@ -184,7 +184,6 @@ void ContentManager::setCategories() QStringList categories; if (m_local) { auto categoryData = mp_library->getKiwixLibrary().getBooksCategories(); - categories.push_back("all"); for (auto category : categoryData) { auto categoryName = QString::fromStdString(category); categories.push_back(categoryName); @@ -686,7 +685,6 @@ void ContentManager::updateLanguages(const QString& content) { void ContentManager::updateCategories(const QString& content) {; auto categories = kiwix::readCategoriesFromFeed(content.toStdString()); QStringList tempCategories; - tempCategories.push_back("all"); for (auto catg : categories) { tempCategories.push_back(QString::fromStdString(catg)); } diff --git a/src/contentmanagerside.h b/src/contentmanagerside.h index 5af981d9..1e7cdd58 100644 --- a/src/contentmanagerside.h +++ b/src/contentmanagerside.h @@ -11,6 +11,8 @@ namespace Ui { class contentmanagerside; } +class KiwixChoiceBox; + class ContentManagerSide : public QWidget { Q_OBJECT diff --git a/src/contentmanagerside.ui b/src/contentmanagerside.ui index 9dfd13b4..ff71833c 100644 --- a/src/contentmanagerside.ui +++ b/src/contentmanagerside.ui @@ -6,8 +6,8 @@ 0 0 - 197 - 368 + 199 + 370 @@ -16,47 +16,194 @@ 0 + + + 0 + 0 + + Form - - - 0 - - - QLayout::SetMaximumSize - - - 0 - - - 0 + + true + + + + + 0 + 0 + 197 + 368 + - - 0 + + - - 0 + + true - - - - - - - true - - - + + + 0 + + + QLayout::SetMinimumSize + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + + + + 0 + 0 + + + + All Files + + + + + + + + 0 + 0 + + + + Local Files + + + true + + + + + + + + 0 + 0 + + + + Browse By Language + + + + + + + + 0 + 0 + + + + QFrame::NoFrame + + + QFrame::Plain + + 0 - - QLayout::SetMinimumSize + + Qt::ScrollBarAlwaysOn + + + Qt::ScrollBarAlwaysOff + + + QAbstractScrollArea::AdjustToContents + + + + + + + true + + + + 0 + 0 + + + + Browse By Category + + + + + + + + 0 + 0 + - + + QFrame::NoFrame + + + QFrame::Plain + + 0 - + + Qt::ScrollBarAlwaysOff + + + QAbstractScrollArea::AdjustToContents + + + + + + + + 0 + 0 + + + + Content Type + + + + + + + + 0 + 0 + + + + QFrame::NoFrame + + + QFrame::Sunken + + 0 @@ -219,48 +366,32 @@ 0 - - 0 + + All - - 0 + + false - - - - - 0 - 0 - - - - All - - - false - - - - - - - - - - Qt::Vertical - - - - 20 - 40 - - - - - - - - + + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + diff --git a/src/contenttypefilter.cpp b/src/contenttypefilter.cpp index 4a10f77d..97612c3c 100644 --- a/src/contenttypefilter.cpp +++ b/src/contenttypefilter.cpp @@ -11,11 +11,12 @@ ContentTypeFilter::ContentTypeFilter(QString name, QWidget *parent) m_states[Qt::PartiallyChecked] = gt("yes"); m_states[Qt::Checked] = gt("no"); setText(gt(m_name) + " : " + m_states[checkState()]); + setStyleSheet("* { color: #666666; }"); connect(this, &QCheckBox::stateChanged, this, &ContentTypeFilter::onStateChanged); } void ContentTypeFilter::onStateChanged(int state) { setText(gt(m_name) + " : " + m_states[static_cast(state)]); - setStyleSheet((state == 0) ? "" : "*{font-weight: bold}"); -} \ No newline at end of file + setStyleSheet((state == 0) ? "*{color: #666666;}" : "*{font-weight: bold; color: black;}"); +} diff --git a/src/flowlayout.cpp b/src/flowlayout.cpp new file mode 100644 index 00000000..caea2849 --- /dev/null +++ b/src/flowlayout.cpp @@ -0,0 +1,230 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the examples 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$ +** +****************************************************************************/ + +#include + +#include "flowlayout.h" +//! [1] +FlowLayout::FlowLayout(QWidget *parent, int margin, int hSpacing, int vSpacing) + : QLayout(parent), m_hSpace(hSpacing), m_vSpace(vSpacing) +{ + setContentsMargins(margin, margin, margin, margin); +} + +FlowLayout::FlowLayout(int margin, int hSpacing, int vSpacing) + : m_hSpace(hSpacing), m_vSpace(vSpacing) +{ + setContentsMargins(margin, margin, margin, margin); +} +//! [1] + +//! [2] +FlowLayout::~FlowLayout() +{ + QLayoutItem *item; + while ((item = takeAt(0))) + delete item; +} +//! [2] + +//! [3] +void FlowLayout::addItem(QLayoutItem *item) +{ + itemList.append(item); +} +//! [3] + +//! [4] +int FlowLayout::horizontalSpacing() const +{ + if (m_hSpace >= 0) { + return m_hSpace; + } else { + return smartSpacing(QStyle::PM_LayoutHorizontalSpacing); + } +} + +int FlowLayout::verticalSpacing() const +{ + if (m_vSpace >= 0) { + return m_vSpace; + } else { + return smartSpacing(QStyle::PM_LayoutVerticalSpacing); + } +} +//! [4] + +//! [5] +int FlowLayout::count() const +{ + return itemList.size(); +} + +QLayoutItem *FlowLayout::itemAt(int index) const +{ + return itemList.value(index); +} + +QLayoutItem *FlowLayout::takeAt(int index) +{ + if (index >= 0 && index < itemList.size()) + return itemList.takeAt(index); + return nullptr; +} +//! [5] + +//! [6] +Qt::Orientations FlowLayout::expandingDirections() const +{ + return { }; +} +//! [6] + +//! [7] +bool FlowLayout::hasHeightForWidth() const +{ + return true; +} + +int FlowLayout::heightForWidth(int width) const +{ + int height = doLayout(QRect(0, 0, width, 0), true); + return height; +} +//! [7] + +//! [8] +void FlowLayout::setGeometry(const QRect &rect) +{ + QLayout::setGeometry(rect); + doLayout(rect, false); +} + +QSize FlowLayout::sizeHint() const +{ + return minimumSize(); +} + +QSize FlowLayout::minimumSize() const +{ + QSize size; + for (const QLayoutItem *item : qAsConst(itemList)) + size = size.expandedTo(item->minimumSize()); + + const QMargins margins = contentsMargins(); + size += QSize(margins.left() + margins.right(), margins.top() + margins.bottom()); + return size; +} +//! [8] + +//! [9] +int FlowLayout::doLayout(const QRect &rect, bool testOnly) const +{ + int left, top, right, bottom; + getContentsMargins(&left, &top, &right, &bottom); + QRect effectiveRect = rect.adjusted(+left, +top, -right, -bottom); + int x = effectiveRect.x(); + int y = effectiveRect.y(); + int lineHeight = 0; +//! [9] + +//! [10] + for (QLayoutItem *item : qAsConst(itemList)) { + const QWidget *wid = item->widget(); + int spaceX = horizontalSpacing(); + if (spaceX == -1) + spaceX = wid->style()->layoutSpacing( + QSizePolicy::PushButton, QSizePolicy::PushButton, Qt::Horizontal); + int spaceY = verticalSpacing(); + if (spaceY == -1) + spaceY = wid->style()->layoutSpacing( + QSizePolicy::PushButton, QSizePolicy::PushButton, Qt::Vertical); +//! [10] +//! [11] + int nextX = x + item->sizeHint().width() + spaceX; + if (nextX - spaceX > effectiveRect.right() && lineHeight > 0) { + x = effectiveRect.x(); + y = y + lineHeight + spaceY; + nextX = x + item->sizeHint().width() + spaceX; + lineHeight = 0; + } + + if (!testOnly) + item->setGeometry(QRect(QPoint(x, y), item->sizeHint())); + + x = nextX; + lineHeight = qMax(lineHeight, item->sizeHint().height()); + } + return y + lineHeight - rect.y() + bottom; +} +//! [11] +//! [12] +int FlowLayout::smartSpacing(QStyle::PixelMetric pm) const +{ + QObject *parent = this->parent(); + if (!parent) { + return -1; + } else if (parent->isWidgetType()) { + QWidget *pw = static_cast(parent); + return pw->style()->pixelMetric(pm, nullptr, pw); + } else { + return static_cast(parent)->spacing(); + } +} +//! [12] + +void FlowLayout::insertWidget(int index, QWidget *w) { + addWidget(w); + if (index < 0) + index = 0; + if (index >= itemList.size()) + index = itemList.size() - 1; + itemList.move(indexOf(w), index); +} diff --git a/src/flowlayout.h b/src/flowlayout.h new file mode 100644 index 00000000..d98defca --- /dev/null +++ b/src/flowlayout.h @@ -0,0 +1,89 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the examples 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$ +** +****************************************************************************/ + +#ifndef FLOWLAYOUT_H +#define FLOWLAYOUT_H + +#include +#include +#include +//! [0] +class FlowLayout : public QLayout +{ +public: + explicit FlowLayout(QWidget *parent, int margin = -1, int hSpacing = -1, int vSpacing = -1); + explicit FlowLayout(int margin = -1, int hSpacing = -1, int vSpacing = -1); + ~FlowLayout(); + + void addItem(QLayoutItem *item) override; + int horizontalSpacing() const; + int verticalSpacing() const; + Qt::Orientations expandingDirections() const override; + bool hasHeightForWidth() const override; + int heightForWidth(int) const override; + int count() const override; + QLayoutItem *itemAt(int index) const override; + QSize minimumSize() const override; + void setGeometry(const QRect &rect) override; + QSize sizeHint() const override; + QLayoutItem *takeAt(int index) override; + void insertWidget(int index, QWidget *w); + +private: + int doLayout(const QRect &rect, bool testOnly) const; + int smartSpacing(QStyle::PixelMetric pm) const; + + QList itemList; + int m_hSpace; + int m_vSpace; +}; +//! [0] + +#endif // FLOWLAYOUT_H diff --git a/src/kiwixchoicebox.cpp b/src/kiwixchoicebox.cpp new file mode 100644 index 00000000..fd2ff39d --- /dev/null +++ b/src/kiwixchoicebox.cpp @@ -0,0 +1,205 @@ +#include "kiwixchoicebox.h" +#include "ui_kiwixchoicebox.h" +#include "klistwidgetitem.h" +#include "kiwixapp.h" +#include "choiceitem.h" +#include +#include "choiceitem.h" +#include "kiwixapp.h" +#include +#include +#include +#include +#include "kiwixlineedit.h" + +KiwixChoiceBox::KiwixChoiceBox(QWidget *parent) : + QWidget(parent), + ui(new Ui::kiwixchoicebox) +{ + m_defaultItem = nullptr; + ui->setupUi(this); + ui->clearButton->setText(gt("clear")); + ui->clearButton->setToolTip(gt("clear-filter")); + + choiceLabel = ui->choiceLabel; + choiceLabel->setText(gt("undefined")); + + choiceSelector = new QListWidget(parent); + choiceSelector->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Minimum); + choiceSelector->setMaximumWidth(250); + choiceSelector->setMaximumHeight(200); + choiceSelector->setCursor(Qt::PointingHandCursor); + choiceSelector->setVerticalScrollMode(QAbstractItemView::ScrollMode::ScrollPerPixel); + choiceSelector->setFocusPolicy(Qt::FocusPolicy::NoFocus); + choiceSelector->setVerticalScrollBarPolicy(Qt::ScrollBarPolicy::ScrollBarAlwaysOff); + choiceSelector->setSelectionMode(QAbstractItemView::SelectionMode::MultiSelection); + + currentChoicesLayout = new FlowLayout(ui->currentChoices, 2, 2, 2); + searcher = new KiwixLineEdit(); + searcher->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Preferred); + currentChoicesLayout->addWidget(searcher); + connect(choiceSelector, &QListWidget::itemPressed, this, [=](QListWidgetItem *item) { + searcher->clear(); + if (item->isSelected()) { + addSelection(item->text(), item->data(Qt::UserRole).toString()); + } else { + removeSelection(item->text()); + } + }); + + connect(searcher, &QLineEdit::textChanged, [=](QString search) { + searcher->setStyleSheet("QLineEdit{color: #666;}"); + int visibleItems = 0; + for (auto i = 0; i < choiceSelector->count(); i++) { + auto itemAtRow = choiceSelector->item(i); + itemAtRow->setHidden(!itemAtRow->text().contains(search, Qt::CaseSensitivity::CaseInsensitive)); + visibleItems += !(itemAtRow->isHidden()); + } + choiceSelector->setGeometry(this->x() + ui->currentChoices->x(), + this->y() + ui->currentChoices->y() + ui->currentChoices->height(), + choiceSelector->width(), + visibleItems * KListWidgetItem::getItemHeight() + 2); + choiceSelector->setVisible(true); + }); + + connect(searcher, &KiwixLineEdit::clicked, [=]() { + choiceSelector->setVisible(true); + adjustSize(); + }); + + choiceSelector->setVisible(false); + searcher->setStyleSheet("QLineEdit{color: #999;}"); + + connect(searcher, &KiwixLineEdit::focusedOut, [=]() { + searcher->setPlaceholderText(gt("search-" + m_type.toLower())); + searcher->setStyleSheet("QLineEdit{color: #999;}"); + choiceSelector->setVisible(false); + ui->currentChoices->setStyleSheet("#currentChoices{border: 1px solid #ccc;}"); + }); + + connect(searcher, &KiwixLineEdit::focusedIn, [=]() { + ui->currentChoices->setStyleSheet("#currentChoices{border: 2px solid #4e63ad;}"); + adjustSize(); + choiceSelector->setVisible(true); + choiceSelector->raise(); + searcher->setPlaceholderText(""); + }); + + ui->clearButton->setCursor(Qt::PointingHandCursor); + connect(ui->clearButton, &QPushButton::clicked, [=]() { + clearSelections(); + emit(choiceUpdated(getCurrentSelected())); + }); + + connect(this, &KiwixChoiceBox::choiceUpdated, [=]() { + choiceSelector->setVisible(false); + }); +} + +KiwixChoiceBox::~KiwixChoiceBox() +{ + delete ui; +} + +void KiwixChoiceBox::keyPressEvent(QKeyEvent *event) +{ + if (event->key() == Qt::Key_Escape) { + searcher->clearFocus(); + } +} + +bool KiwixChoiceBox::addSelection(QString key, QString value) +{ + auto chItem = new ChoiceItem(key, value); + connect(chItem, &ChoiceItem::closeButtonClicked, [=](QString text) { + removeSelection(text); + }); + chItem->setObjectName(key); + currentChoicesLayout->insertWidget(ui->currentChoices->children().count() - 2, chItem); + searcher->setFixedWidth(20); + searcher->setFocus(); + emit(choiceUpdated(getCurrentSelected())); + return true; +} + +bool KiwixChoiceBox::removeSelection(QString selection) +{ + auto chItem = ui->currentChoices->findChild(selection); + chItem->deleteLater(); + emit(choiceUpdated(getCurrentSelected())); + return true; +} + +void KiwixChoiceBox::clearSelections() +{ + for (auto &item : choiceSelector->selectedItems()) { + item->setSelected(false); + auto chItem = ui->currentChoices->findChild(item->text()); + ui->currentChoices->layout()->removeWidget(chItem); + delete chItem; + } +} + +QString beautifyString(QString word) +{ + word = word.replace("_", " "); + word[0] = word[0].toUpper(); + return word; +} + +void KiwixChoiceBox::setSelections(QStringList selections, QString defaultSelection) +{ + SelectionList sList; + for (const auto &sel : selections) { + sList.append({sel, sel}); + } + setSelections(sList, defaultSelection); +} + +void KiwixChoiceBox::setSelections(SelectionList selections, QString defaultSelection) +{ + choiceSelector->clear(); + for (const auto &selection: selections) + { + auto item = new KListWidgetItem(beautifyString(selection.second)); + item->setData(Qt::UserRole, selection.first); + choiceSelector->addItem(item); + if (selection.second == defaultSelection) + { + m_defaultItem = item; + } + } + if (choiceSelector->selectedItems().isEmpty() && m_defaultItem) { + m_defaultItem->setSelected(true); + addSelection(m_defaultItem->text(), m_defaultItem->data(Qt::UserRole).toString()); + } + adjustSize(); +} + +void KiwixChoiceBox::adjustSize() +{ + QWidget::adjustSize(); + choiceSelector->adjustSize(); + choiceSelector->setGeometry(this->x() + ui->currentChoices->x(), + this->y() + ui->currentChoices->y() + ui->currentChoices->height(), + choiceSelector->width(), + choiceSelector->count() * KListWidgetItem::getItemHeight() + 2); // 2 is for the border so that all elements are visible +} + +void KiwixChoiceBox::setType(QString type) +{ + ui->choiceLabel->setText(type); + m_type = type; + searcher->setPlaceholderText(gt("search-" + type.toLower())); +} + +QStringList KiwixChoiceBox::getCurrentSelected() +{ + if (choiceSelector->selectedItems().isEmpty()) + return {"all"}; + QStringList selections; + for (auto &item : choiceSelector->selectedItems()) { + selections.append(item->data(Qt::UserRole).toString()); + } + return selections; +} diff --git a/src/kiwixchoicebox.h b/src/kiwixchoicebox.h new file mode 100644 index 00000000..2c9d49e2 --- /dev/null +++ b/src/kiwixchoicebox.h @@ -0,0 +1,58 @@ +#ifndef KIWIXCHOICEBOX_H +#define KIWIXCHOICEBOX_H + +#include +#include +#include +#include +#include +#include +#include +#include "flowlayout.h" +#include +#include + +class ChoiceItem; +class KiwixLineEdit; + +namespace Ui { +class kiwixchoicebox; +} + +class KiwixChoiceBox : public QWidget +{ + Q_OBJECT + + typedef QList> SelectionList; + +public: + explicit KiwixChoiceBox(QWidget *parent = nullptr); + void setType(QString type); + void setSelections(SelectionList selections, QString defaultSelection); + void setSelections(QStringList selections, QString defaultSelection); + ~KiwixChoiceBox(); + void adjustSize(); + +protected: + void keyPressEvent(QKeyEvent* event) override; + +signals: + void choiceUpdated(QStringList); + +private: + Ui::kiwixchoicebox *ui; + QLabel *choiceLabel; + QLineEdit *choiceSearch; + QListWidget *choiceSelector; + QListWidgetItem *m_defaultItem; + FlowLayout *currentChoicesLayout; + KiwixLineEdit *searcher; + QStringList getCurrentSelected(); + bool removeSelection(QString selection); + void clearSelections(); + bool addSelection(QString key, QString value); + QString m_type; + bool m_sliderMoved = false; +}; + +#endif // KIWIXCHOICEBOX_H diff --git a/src/kiwixlineedit.cpp b/src/kiwixlineedit.cpp new file mode 100644 index 00000000..ca5ca1e4 --- /dev/null +++ b/src/kiwixlineedit.cpp @@ -0,0 +1,27 @@ +#include "kiwixlineedit.h" + +KiwixLineEdit::KiwixLineEdit(QWidget *parent) : QLineEdit(parent) +{ + installEventFilter(this); +} + +KiwixLineEdit::~KiwixLineEdit() +{ +} + +void KiwixLineEdit::resizeEvent(QResizeEvent *event) +{ + QLineEdit::resizeEvent(event); + adjustSize(); +} +bool KiwixLineEdit::eventFilter(QObject* object, QEvent* event) +{ + if (event->type() == QEvent::MouseButtonPress) { + emit(clicked()); + } else if (event->type() == QEvent::FocusIn) { + emit(focusedIn()); + } else if (event->type() == QEvent::FocusOut) { + emit(focusedOut()); + } + return false; +} diff --git a/src/kiwixlineedit.h b/src/kiwixlineedit.h new file mode 100644 index 00000000..6b25b859 --- /dev/null +++ b/src/kiwixlineedit.h @@ -0,0 +1,20 @@ +#ifndef KIWIXLINEEDIT_H +#define KIWIXLINEEDIT_H + +#include +#include + +class KiwixLineEdit : public QLineEdit { + Q_OBJECT; +public: + KiwixLineEdit(QWidget *parent = nullptr); + ~KiwixLineEdit(); +protected: + void resizeEvent(QResizeEvent *event) override; + bool eventFilter(QObject* object, QEvent* event) override; +signals: + void clicked(); + void focusedIn(); + void focusedOut(); +}; +#endif // KIWIXLINEEDIT_H diff --git a/src/klistwidgetitem.cpp b/src/klistwidgetitem.cpp index 574626a4..6891394f 100644 --- a/src/klistwidgetitem.cpp +++ b/src/klistwidgetitem.cpp @@ -1,8 +1,11 @@ #include "klistwidgetitem.h" +int KListWidgetItem::m_itemHeight = 35; + KListWidgetItem::KListWidgetItem(QString text) : QListWidgetItem (text) { + setSizeHint(QSize(200, m_itemHeight)); } QVariant KListWidgetItem::data(int role) const diff --git a/src/klistwidgetitem.h b/src/klistwidgetitem.h index 2208c20d..66bdd1ef 100644 --- a/src/klistwidgetitem.h +++ b/src/klistwidgetitem.h @@ -8,6 +8,9 @@ class KListWidgetItem : public QListWidgetItem public: KListWidgetItem(QString text); QVariant data(int role) const; + static int getItemHeight() { return m_itemHeight; }; +private: + static int m_itemHeight; }; #endif // KLISTWIDGETITEM_H diff --git a/ui/kiwixchoicebox.ui b/ui/kiwixchoicebox.ui new file mode 100644 index 00000000..302bdce5 --- /dev/null +++ b/ui/kiwixchoicebox.ui @@ -0,0 +1,103 @@ + + + kiwixchoicebox + + + + 0 + 0 + 274 + 325 + + + + + 0 + 0 + + + + Form + + + + + + QFrame::NoFrame + + + QFrame::Plain + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + TextLabel + + + + + + + + 50 + 16777215 + + + + Clear + + + + + + + + + + + 0 + 0 + + + + + 250 + 0 + + + + + + + + Qt::Vertical + + + QSizePolicy::Expanding + + + + 20 + 5 + + + + + + + + + From 22aa0ec56aae8e24df2aedd477367c3bc887e252 Mon Sep 17 00:00:00 2001 From: Nikhil Tanwar <2002nikhiltanwar@gmail.com> Date: Tue, 15 Aug 2023 11:00:22 +0530 Subject: [PATCH 02/17] Categories and Languages now use KiwixChoiceBox Replaced the old Categories and Languages with KiwixChoiceBox --- src/contentmanagerside.cpp | 95 +++---- src/contentmanagerside.h | 6 +- src/contentmanagerside.ui | 549 +++++++++++++------------------------ 3 files changed, 227 insertions(+), 423 deletions(-) diff --git a/src/contentmanagerside.cpp b/src/contentmanagerside.cpp index d2da4bc5..7e633a8b 100644 --- a/src/contentmanagerside.cpp +++ b/src/contentmanagerside.cpp @@ -1,6 +1,7 @@ #include "contentmanagerside.h" #include "ui_contentmanagerside.h" #include "kiwixapp.h" +#include "kiwixchoicebox.h" #include #include @@ -11,7 +12,13 @@ ContentManagerSide::ContentManagerSide(QWidget *parent) : QWidget(parent), mp_ui(new Ui::contentmanagerside) { + setFocusPolicy(Qt::FocusPolicy::StrongFocus); mp_ui->setupUi(this); + QFile file(QString::fromUtf8(":/css/contentmanagerside.css")); + file.open(QFile::ReadOnly); + QString styleSheet = QString(file.readAll()); + this->setStyleSheet(styleSheet); + mp_ui->buttonGroup->setId(mp_ui->allFileButton, CatalogButtonId::ALL); mp_ui->buttonGroup->setId(mp_ui->localFileButton, CatalogButtonId::LOCAL); connect(mp_ui->buttonGroup, QOverload::of(&QButtonGroup::buttonClicked), [=](QAbstractButton *btn) { @@ -19,6 +26,8 @@ ContentManagerSide::ContentManagerSide(QWidget *parent) : mp_contentManager->setLocal(id == CatalogButtonId::LOCAL); }); + mp_ui->contentTypeButton->setIcon(QIcon(":/icons/caret-right-solid.svg")); + mp_ui->contentTypeButton->setIconSize(QSize(12, 12)); connect(mp_ui->allFileButton, &QRadioButton::toggled, this, [=](bool checked) { mp_ui->allFileButton->setStyleSheet( checked ? "*{font-weight: bold}" : "");}); @@ -28,29 +37,29 @@ ContentManagerSide::ContentManagerSide(QWidget *parent) : mp_ui->allFileButton->setText(gt("online-files")); mp_ui->localFileButton ->setText(gt("local-files")); - mp_ui->languageButton->setText(gt("browse-by-language")); - mp_ui->categoryButton->setText(gt("browse-by-category")); mp_ui->contentTypeButton->setText(gt("content-type")); - mp_languageButton = mp_ui->languageButton; - mp_languageSelector = mp_ui->languageSelector; - connect(mp_languageButton, &QCheckBox::toggled, this, [=](bool checked) { mp_languageSelector->setHidden(!checked); }); - mp_languageSelector->setHidden(true); + mp_categories = mp_ui->categories; + mp_categories->setType(gt("category")); - mp_categoryButton = mp_ui->categoryButton; - mp_categorySelector = mp_ui->categorySelector; - connect(mp_categoryButton, &QCheckBox::toggled, this, [=](bool checked) { mp_categorySelector->setHidden(!checked); }); - mp_categorySelector->setHidden(true); + mp_languages = mp_ui->languages; + mp_languages->setType(gt("language")); mp_contentTypeButton = mp_ui->contentTypeButton; - connect(mp_contentTypeButton, &QCheckBox::toggled, this, [=](bool checked) { mp_ui->contentTypeSelector->setHidden(!checked); }); + + + connect(mp_contentTypeButton, &QCheckBox::toggled, this, [=](bool checked) { + mp_ui->contentTypeSelector->setHidden(!checked); + mp_ui->contentTypeButton->setIcon(checked ? QIcon(":/icons/caret-down-solid.svg") : QIcon(":/icons/caret-right-solid.svg")); + + }); mp_ui->contentTypeSelector->setHidden(true); mp_ui->contentTypeAllButton->setText(gt("all")); - mp_ui->contentTypeAllButton->setStyleSheet("*{font-weight: bold}"); + mp_ui->contentTypeAllButton->setStyleSheet("*{font-weight: 500;}"); connect(mp_ui->contentTypeAllButton, &QCheckBox::clicked, this, [=](bool checked) { Q_UNUSED(checked); - mp_ui->contentTypeAllButton->setStyleSheet("*{font-weight: bold}"); + mp_ui->contentTypeAllButton->setStyleSheet("*{font-weight: 500;}"); for (auto &contentTypeFilter : m_contentTypeFilters) { contentTypeFilter->setCheckState(Qt::Unchecked); } @@ -59,11 +68,8 @@ ContentManagerSide::ContentManagerSide(QWidget *parent) : auto searcher = mp_ui->searcher; searcher->setPlaceholderText(gt("search-files")); - QFile file(QString::fromUtf8(":/css/_contentManager.css")); - file.open(QFile::ReadOnly); - QString styleSheet = QString(file.readAll()); - searcher->setStyleSheet(styleSheet); QIcon searchIcon = QIcon(":/icons/search.svg"); + searcher->addAction(searchIcon, QLineEdit::LeadingPosition); connect(searcher, &QLineEdit::textChanged, [searcher](){ KiwixApp::instance()->getContentManager()->setSearch(searcher->text()); @@ -88,7 +94,7 @@ ContentManagerSide::ContentManagerSide(QWidget *parent) : break; } } - mp_ui->contentTypeAllButton->setStyleSheet(activeFilter ? "" : "*{font-weight: bold}"); + mp_ui->contentTypeAllButton->setStyleSheet(activeFilter ? " * {color : #666666;} " : "*{font-weight: 500; color: black;}"); mp_contentManager->setCurrentContentTypeFilter(m_contentTypeFilters); }); } @@ -111,23 +117,16 @@ void ContentManagerSide::setContentManager(ContentManager *contentManager) const auto checkedButton = mp_ui->buttonGroup->button(isLocal == CatalogButtonId::LOCAL); checkedButton->setChecked(true); checkedButton->setStyleSheet("*{font-weight: bold}"); - connect(mp_languageSelector, &QListWidget::itemSelectionChanged, - this, [=]() { - auto item = mp_languageSelector->selectedItems().at(0); - if (!item) return; - auto lang = item->data(Qt::UserRole).toString(); - if (lang == "all") { + connect(mp_languages, &KiwixChoiceBox::choiceUpdated, + this, [=](QStringList values) { + if (values[0] == "all") { mp_contentManager->setCurrentLanguage("*"); return; } - mp_contentManager->setCurrentLanguage(lang); + mp_contentManager->setCurrentLanguage(values.join(",")); }); - connect(mp_categorySelector, &QListWidget::itemSelectionChanged, - this, [=]() { - auto item = mp_categorySelector->selectedItems().at(0); - if (!item) return; - auto category = item->data(Qt::UserRole).toString(); - mp_contentManager->setCurrentCategoryFilter(category); + connect(mp_categories, &KiwixChoiceBox::choiceUpdated, this, [=](QStringList values) { + mp_contentManager->setCurrentCategoryFilter(values.join(",")); }); } @@ -140,40 +139,10 @@ QString beautify(QString word) void ContentManagerSide::setCategories(QStringList categories) { - mp_categorySelector->blockSignals(true); - mp_categorySelector->setHidden(true); - mp_categorySelector->clear(); - mp_categorySelector->blockSignals(false); - for (auto category: categories) - { - auto item = new KListWidgetItem(beautify(category)); - item->setData(Qt::UserRole, category); - mp_categorySelector->addItem(item); - if (category == "all") - { - item->setSelected(true); - } - } + mp_categories->setSelections(categories, gt("all")); } void ContentManagerSide::setLanguages(ContentManager::LanguageList langList) { - mp_languageSelector->blockSignals(true); - mp_languageSelector->setHidden(true); - mp_languageSelector->clear(); - mp_languageSelector->blockSignals(false); - for(auto lang: langList) - { - auto currentLang = QLocale().language(); - auto item = new KListWidgetItem(lang.second); - item->setData(Qt::UserRole, lang.first); - mp_languageSelector->addItem(item); - if (lang.second == QLocale::languageToString(currentLang)) { - item->setSelected(true); - } - } - mp_languageSelector->sortItems(); - auto item = new KListWidgetItem("All"); - item->setData(Qt::UserRole, "all"); - mp_languageSelector->insertItem(0, item); + mp_languages->setSelections(langList, QLocale::languageToString(QLocale().language())); } diff --git a/src/contentmanagerside.h b/src/contentmanagerside.h index 1e7cdd58..b6162699 100644 --- a/src/contentmanagerside.h +++ b/src/contentmanagerside.h @@ -30,10 +30,8 @@ class ContentManagerSide : public QWidget private: Ui::contentmanagerside *mp_ui; ContentManager* mp_contentManager; - QCheckBox* mp_languageButton; - QListWidget* mp_languageSelector; - QCheckBox* mp_categoryButton; - QListWidget* mp_categorySelector; + KiwixChoiceBox *mp_categories; + KiwixChoiceBox *mp_languages; QCheckBox* mp_contentTypeButton; QList m_contentTypeFilters; diff --git a/src/contentmanagerside.ui b/src/contentmanagerside.ui index ff71833c..90d65be4 100644 --- a/src/contentmanagerside.ui +++ b/src/contentmanagerside.ui @@ -6,8 +6,8 @@ 0 0 - 199 - 370 + 300 + 386 @@ -18,7 +18,7 @@ - 0 + 250 0 @@ -28,371 +28,208 @@ true - - - - 0 - 0 - 197 - 368 - + + + QLayout::SetNoConstraint - - + + 0 - - true + + 0 - - - 0 - - - QLayout::SetMinimumSize - - - 0 - - - 0 - - - 0 - - - 0 - - - - - - - - - 0 - 0 - - - - All Files - - - - - - - - 0 - 0 - - - - Local Files - - - true - - - - - - - - 0 - 0 - - - - Browse By Language - - - - - - - - 0 - 0 - - - - QFrame::NoFrame - - - QFrame::Plain - - - 0 - - - Qt::ScrollBarAlwaysOn - - - Qt::ScrollBarAlwaysOff - - - QAbstractScrollArea::AdjustToContents - - - - - - - true - - - - 0 - 0 - - - - Browse By Category - - - - - - - - 0 - 0 - - - - QFrame::NoFrame - - - QFrame::Plain - - - 0 - - - Qt::ScrollBarAlwaysOff - - - QAbstractScrollArea::AdjustToContents - - - - - - - - 0 - 0 - - - - Content Type - - - - - - - - 0 - 0 - - - - QFrame::NoFrame - - - QFrame::Sunken - - - 0 - - - 0 - - - 0 - - - - - - - - - 0 - 0 - - - - All Files - - - buttonGroup - - - - - - - - 0 - 0 - - - - Local Files - - - true - - - buttonGroup - - - - - - - - 0 - 0 - - - - Browse By Language - - - - - - - - 0 - 0 - - - - QFrame::NoFrame - - - QFrame::Plain - - - 0 - - - Qt::ScrollBarAlwaysOn - - - Qt::ScrollBarAlwaysOff - - - QAbstractScrollArea::AdjustToContents - - - - - - - true - - - - 0 - 0 - - - - Browse By Category - - - - - - - - 0 - 0 - - - - QFrame::NoFrame - - - QFrame::Plain - - - 0 - - - Qt::ScrollBarAlwaysOff - - - QAbstractScrollArea::AdjustToContents - - - - - - - - 0 - 0 - - - - Content Type - - - - - - - - 0 - 0 - - - - QFrame::NoFrame - - - QFrame::Sunken - - - 0 - - - - 0 + + 0 + + + 0 + + + + + true + + + true + + + + + 0 + 0 + 298 + 384 + + + + + + + + + + + 0 + 0 + + + + PointingHandCursor + + + All Files + + + buttonGroup + + + + + + + + 0 + 0 + + + + PointingHandCursor + + + Local Files + + + true + + + buttonGroup + + + + + + + + 0 + 0 + + + + true + + + + + + + + 0 + 0 + + + + true + + + + + + + + 0 + 0 + - All + Content Type + + + + + + + + 0 + 0 + + + + + 0 + 0 + + + + PointingHandCursor - - false + + QFrame::NoFrame + + QFrame::Sunken + + + 0 + + + + 0 + + + 0 + + + 0 + + + + + + 0 + 0 + + + + All + + + false + + + + + + + + Qt::Vertical + + + QSizePolicy::Expanding + + + + 20 + 0 + + + + - - - - - Qt::Vertical - - - - 20 - 40 - - - - - - + + + + + + KiwixChoiceBox + QWidget +
src/kiwixchoicebox.h
+ 1 +
+
From bca0bb3a7adf87bd64dce4b449f06623a9fbed2a Mon Sep 17 00:00:00 2001 From: Nikhil Tanwar <2002nikhiltanwar@gmail.com> Date: Sun, 23 Jul 2023 19:07:13 +0530 Subject: [PATCH 03/17] Multiple category support This removes the previous method of filtering books by category, which filtered using tags. Now, we move to a more generic way (similar to library) using the category filter. --- src/contentmanager.cpp | 12 ++---------- src/opdsrequestmanager.cpp | 14 ++------------ 2 files changed, 4 insertions(+), 22 deletions(-) diff --git a/src/contentmanager.cpp b/src/contentmanager.cpp index c601340c..ea27035d 100644 --- a/src/contentmanager.cpp +++ b/src/contentmanager.cpp @@ -702,16 +702,6 @@ QStringList ContentManager::getBookIds() { kiwix::Filter filter; std::vector acceptTags, rejectTags; - if (m_categoryFilter != "all" && m_categoryFilter != "other") { - acceptTags.push_back("_category:"+m_categoryFilter.toStdString()); - } - if (m_categoryFilter == "other") { - for (auto& category: m_categories) { - if (category != "other" && category != "all") { - rejectTags.push_back("_category:"+category.toStdString()); - } - } - } for (auto &contentTypeFilter : m_contentTypeFilters) { auto state = contentTypeFilter->checkState(); @@ -728,6 +718,8 @@ QStringList ContentManager::getBookIds() filter.query(m_searchQuery.toStdString()); if (m_currentLanguage != "*") filter.lang(m_currentLanguage.toStdString()); + if (m_categoryFilter != "all") + filter.category(m_categoryFilter.toStdString()); if (m_local) { filter.local(true); diff --git a/src/opdsrequestmanager.cpp b/src/opdsrequestmanager.cpp index 209ee3bf..afcc0f38 100644 --- a/src/opdsrequestmanager.cpp +++ b/src/opdsrequestmanager.cpp @@ -23,20 +23,10 @@ void OpdsRequestManager::doUpdate(const QString& currentLanguage, const QString& query.addQueryItem("count", QString::number(-1)); // Add filter by category (if necessary) - if (categoryFilter != "all" && categoryFilter != "other") { - query.addQueryItem("tag", "_category:"+categoryFilter); + if (categoryFilter != "all") { + query.addQueryItem("category", categoryFilter); } - // Add "special negative" filter for "other" category (if necessary) - if (categoryFilter == "other") { - for (auto& category: KiwixApp::instance()->getContentManager()->getCategories()) { - if (category != "other" && category != "all") { - excludeTags += "_category:"+category; - } - } - } - query.addQueryItem("notag", excludeTags.join(";")); - auto mp_reply = opdsResponseFromPath("/catalog/search", query); connect(mp_reply, &QNetworkReply::finished, this, [=]() { receiveContent(mp_reply); From fd371d2a47fa152cd70cecec97aae403834b5531 Mon Sep 17 00:00:00 2001 From: Nikhil Tanwar <2002nikhiltanwar@gmail.com> Date: Tue, 15 Aug 2023 10:41:51 +0530 Subject: [PATCH 04/17] Add styles for KiwixChoiceBox Added styles for KiwixChoiceBox to make it match the model. Also moved everything in contentmanagerside more to the left. --- resources/css/choiceBox.css | 6 ++++++ resources/css/contentmanagerside.css | 13 +++++++++++++ resources/style.qrc | 1 + src/choiceitem.cpp | 4 ++++ src/contentmanagerside.cpp | 2 -- src/contentmanagerside.ui | 9 +++++++++ src/kiwixchoicebox.cpp | 6 ++++++ ui/kiwixchoicebox.ui | 6 ++++++ 8 files changed, 45 insertions(+), 2 deletions(-) diff --git a/resources/css/choiceBox.css b/resources/css/choiceBox.css index 20d85dea..0c6b180c 100644 --- a/resources/css/choiceBox.css +++ b/resources/css/choiceBox.css @@ -1,4 +1,5 @@ QListWidget::item { + color: #666666; padding: 0; padding-top: 6px; padding-bottom: 6px; @@ -15,6 +16,11 @@ QListWidget::item::selected { background-color: transparent; } +QListWidget::item::hover { + color: white; + background-color: #4e63ad; +} + QLineEdit { padding: 4px; border: 0; diff --git a/resources/css/contentmanagerside.css b/resources/css/contentmanagerside.css index fc848645..df16f702 100644 --- a/resources/css/contentmanagerside.css +++ b/resources/css/contentmanagerside.css @@ -8,3 +8,16 @@ height: 32px; line-height: 24px; } + +QScrollArea { + border: 0; +} + +#allFileButton, #localFileButton, #contentTypeButton { + padding-left: 2px; +} + +#allFileButton::indicator, #localFileButton::indicator, #contentTypeButton::indicator { + height: 0; + width: 0; +} diff --git a/resources/style.qrc b/resources/style.qrc index 1dfa31e4..bb0bef4f 100644 --- a/resources/style.qrc +++ b/resources/style.qrc @@ -5,5 +5,6 @@ css/localServer.css css/confirmBox.css css/contentmanagerside.css + css/choiceBox.css diff --git a/src/choiceitem.cpp b/src/choiceitem.cpp index 755eae19..8748527b 100644 --- a/src/choiceitem.cpp +++ b/src/choiceitem.cpp @@ -9,6 +9,10 @@ ChoiceItem::ChoiceItem(QString key, QString value, QWidget *parent) : m_value(value) { ui->setupUi(this); + QFile file(QString::fromUtf8(":/css/choiceBox.css")); + file.open(QFile::ReadOnly); + QString styleSheet = QString(file.readAll()); + this->setStyleSheet(styleSheet); ui->itemLabel->setText(key); ui->itemLabel->setToolTip(key); connect(ui->closeButton, &QPushButton::clicked, [=](){ diff --git a/src/contentmanagerside.cpp b/src/contentmanagerside.cpp index 7e633a8b..b84d48ab 100644 --- a/src/contentmanagerside.cpp +++ b/src/contentmanagerside.cpp @@ -50,8 +50,6 @@ ContentManagerSide::ContentManagerSide(QWidget *parent) : connect(mp_contentTypeButton, &QCheckBox::toggled, this, [=](bool checked) { mp_ui->contentTypeSelector->setHidden(!checked); - mp_ui->contentTypeButton->setIcon(checked ? QIcon(":/icons/caret-down-solid.svg") : QIcon(":/icons/caret-right-solid.svg")); - }); mp_ui->contentTypeSelector->setHidden(true); diff --git a/src/contentmanagerside.ui b/src/contentmanagerside.ui index 90d65be4..a7fa509c 100644 --- a/src/contentmanagerside.ui +++ b/src/contentmanagerside.ui @@ -62,6 +62,9 @@ + + 9 + @@ -82,6 +85,12 @@ buttonGroup + + + 0 + 0 + + diff --git a/src/kiwixchoicebox.cpp b/src/kiwixchoicebox.cpp index fd2ff39d..0191854d 100644 --- a/src/kiwixchoicebox.cpp +++ b/src/kiwixchoicebox.cpp @@ -18,6 +18,11 @@ KiwixChoiceBox::KiwixChoiceBox(QWidget *parent) : { m_defaultItem = nullptr; ui->setupUi(this); + + QFile file(QString::fromUtf8(":/css/choiceBox.css")); + file.open(QFile::ReadOnly); + QString styleSheet = QString(file.readAll()); + this->setStyleSheet(styleSheet); ui->clearButton->setText(gt("clear")); ui->clearButton->setToolTip(gt("clear-filter")); @@ -32,6 +37,7 @@ KiwixChoiceBox::KiwixChoiceBox(QWidget *parent) : choiceSelector->setVerticalScrollMode(QAbstractItemView::ScrollMode::ScrollPerPixel); choiceSelector->setFocusPolicy(Qt::FocusPolicy::NoFocus); choiceSelector->setVerticalScrollBarPolicy(Qt::ScrollBarPolicy::ScrollBarAlwaysOff); + choiceSelector->setStyleSheet(styleSheet); choiceSelector->setSelectionMode(QAbstractItemView::SelectionMode::MultiSelection); currentChoicesLayout = new FlowLayout(ui->currentChoices, 2, 2, 2); diff --git a/ui/kiwixchoicebox.ui b/ui/kiwixchoicebox.ui index 302bdce5..140154b2 100644 --- a/ui/kiwixchoicebox.ui +++ b/ui/kiwixchoicebox.ui @@ -16,6 +16,12 @@ 0 + + + 0 + 0 + + Form From ccf1e505a182f0b4acdc6ee34b9d4ae801164509 Mon Sep 17 00:00:00 2001 From: Nikhil Tanwar <2002nikhiltanwar@gmail.com> Date: Tue, 15 Aug 2023 17:55:57 +0530 Subject: [PATCH 05/17] Remember language and category values Language and category values are now a setting --- src/contentmanager.cpp | 34 ++++++++++++++++++++++------------ src/contentmanager.h | 5 ++--- src/contentmanagerside.cpp | 12 +++++------- src/kiwixchoicebox.cpp | 15 +++++---------- src/kiwixchoicebox.h | 5 ++--- src/settingsmanager.cpp | 18 ++++++++++++++++++ src/settingsmanager.h | 8 ++++++++ 7 files changed, 62 insertions(+), 35 deletions(-) diff --git a/src/contentmanager.cpp b/src/contentmanager.cpp index ea27035d..1a51d877 100644 --- a/src/contentmanager.cpp +++ b/src/contentmanager.cpp @@ -56,7 +56,6 @@ ContentManager::ContentManager(Library* library, kiwix::Downloader* downloader, treeView->setColumnWidth(5, 120); // TODO: set width for all columns based on viewport - setCurrentLanguage(QLocale().name().split("_").at(0)); connect(mp_library, &Library::booksChanged, this, [=]() {emit(this->booksChanged());}); connect(this, &ContentManager::filterParamsChanged, this, &ContentManager::updateLibrary); connect(this, &ContentManager::booksChanged, this, [=]() { @@ -72,6 +71,8 @@ ContentManager::ContentManager(Library* library, kiwix::Downloader* downloader, connect(&m_remoteLibraryManager, &OpdsRequestManager::categoriesReceived, this, &ContentManager::updateCategories); setCategories(); setLanguages(); + setCurrentLanguage(KiwixApp::instance()->getSettingsManager()->getLanguageList()); + setCurrentCategoryFilter(KiwixApp::instance()->getSettingsManager()->getCategoryList()); } QList> ContentManager::getBooksList() @@ -617,26 +618,35 @@ QStringList ContentManager::getDownloadIds() return list; } -void ContentManager::setCurrentLanguage(QString language) +void ContentManager::setCurrentLanguage(QStringList languageList) { - if (language.length() == 2) { - try { - language = QString::fromStdString( - kiwix::converta2toa3(language.toStdString())); - } catch (std::out_of_range&) {} + languageList.sort(); + for (auto &language : languageList) { + if (language.length() == 2) { + try { + language = QString::fromStdString( + kiwix::converta2toa3(language.toStdString())); + } catch (std::out_of_range&) {} + } } - if (m_currentLanguage == language) + if (languageList.empty()) + languageList.append("*"); + auto newLanguage = languageList.join(","); + if (m_currentLanguage == newLanguage) return; - m_currentLanguage = language; + m_currentLanguage = newLanguage; + KiwixApp::instance()->getSettingsManager()->setLanguage(languageList); emit(currentLangChanged()); emit(filterParamsChanged()); } -void ContentManager::setCurrentCategoryFilter(QString category) +void ContentManager::setCurrentCategoryFilter(QStringList categoryList) { - if (m_categoryFilter == category) + categoryList.sort(); + if (m_categoryFilter == categoryList.join(",")) return; - m_categoryFilter = category.toLower(); + m_categoryFilter = categoryList.join(","); + KiwixApp::instance()->getSettingsManager()->setCategory(categoryList); emit(filterParamsChanged()); } diff --git a/src/contentmanager.h b/src/contentmanager.h index ae283a2e..cbdb6aaa 100644 --- a/src/contentmanager.h +++ b/src/contentmanager.h @@ -15,7 +15,6 @@ class ContentManager : public QObject Q_OBJECT Q_PROPERTY(QStringList bookIds READ getBookIds NOTIFY booksChanged) Q_PROPERTY(QStringList downloadIds READ getDownloadIds NOTIFY downloadsChanged) - Q_PROPERTY(QString currentLanguage MEMBER m_currentLanguage WRITE setCurrentLanguage NOTIFY currentLangChanged) Q_PROPERTY(bool isLocal MEMBER m_local READ isLocal WRITE setLocal NOTIFY localChanged) public: @@ -26,8 +25,8 @@ class ContentManager : public QObject ContentManagerView* getView() { return mp_view; } void setLocal(bool local); QStringList getDownloadIds(); - void setCurrentLanguage(QString language); - void setCurrentCategoryFilter(QString category); + void setCurrentLanguage(QStringList languageList); + void setCurrentCategoryFilter(QStringList category); void setCurrentContentTypeFilter(QList& contentTypeFilter); bool isLocal() const { return m_local; } QStringList getCategories() const { return m_categories; } diff --git a/src/contentmanagerside.cpp b/src/contentmanagerside.cpp index b84d48ab..1dce3c85 100644 --- a/src/contentmanagerside.cpp +++ b/src/contentmanagerside.cpp @@ -2,7 +2,6 @@ #include "ui_contentmanagerside.h" #include "kiwixapp.h" #include "kiwixchoicebox.h" - #include #include @@ -118,13 +117,12 @@ void ContentManagerSide::setContentManager(ContentManager *contentManager) connect(mp_languages, &KiwixChoiceBox::choiceUpdated, this, [=](QStringList values) { if (values[0] == "all") { - mp_contentManager->setCurrentLanguage("*"); - return; + values = QStringList(); } - mp_contentManager->setCurrentLanguage(values.join(",")); + mp_contentManager->setCurrentLanguage(values); }); connect(mp_categories, &KiwixChoiceBox::choiceUpdated, this, [=](QStringList values) { - mp_contentManager->setCurrentCategoryFilter(values.join(",")); + mp_contentManager->setCurrentCategoryFilter(values); }); } @@ -137,10 +135,10 @@ QString beautify(QString word) void ContentManagerSide::setCategories(QStringList categories) { - mp_categories->setSelections(categories, gt("all")); + mp_categories->setSelections(categories, KiwixApp::instance()->getSettingsManager()->getCategoryList()); } void ContentManagerSide::setLanguages(ContentManager::LanguageList langList) { - mp_languages->setSelections(langList, QLocale::languageToString(QLocale().language())); + mp_languages->setSelections(langList, KiwixApp::instance()->getSettingsManager()->getLanguageList()); } diff --git a/src/kiwixchoicebox.cpp b/src/kiwixchoicebox.cpp index 0191854d..0cea2c88 100644 --- a/src/kiwixchoicebox.cpp +++ b/src/kiwixchoicebox.cpp @@ -16,7 +16,6 @@ KiwixChoiceBox::KiwixChoiceBox(QWidget *parent) : QWidget(parent), ui(new Ui::kiwixchoicebox) { - m_defaultItem = nullptr; ui->setupUi(this); QFile file(QString::fromUtf8(":/css/choiceBox.css")); @@ -153,7 +152,7 @@ QString beautifyString(QString word) return word; } -void KiwixChoiceBox::setSelections(QStringList selections, QString defaultSelection) +void KiwixChoiceBox::setSelections(QStringList selections, QStringList defaultSelection) { SelectionList sList; for (const auto &sel : selections) { @@ -162,7 +161,7 @@ void KiwixChoiceBox::setSelections(QStringList selections, QString defaultSelect setSelections(sList, defaultSelection); } -void KiwixChoiceBox::setSelections(SelectionList selections, QString defaultSelection) +void KiwixChoiceBox::setSelections(SelectionList selections, QStringList defaultSelection) { choiceSelector->clear(); for (const auto &selection: selections) @@ -170,15 +169,11 @@ void KiwixChoiceBox::setSelections(SelectionList selections, QString defaultSele auto item = new KListWidgetItem(beautifyString(selection.second)); item->setData(Qt::UserRole, selection.first); choiceSelector->addItem(item); - if (selection.second == defaultSelection) - { - m_defaultItem = item; + if (defaultSelection.contains(selection.first)) { + item->setSelected(true); + addSelection(item->text(), item->data(Qt::UserRole).toString()); } } - if (choiceSelector->selectedItems().isEmpty() && m_defaultItem) { - m_defaultItem->setSelected(true); - addSelection(m_defaultItem->text(), m_defaultItem->data(Qt::UserRole).toString()); - } adjustSize(); } diff --git a/src/kiwixchoicebox.h b/src/kiwixchoicebox.h index 2c9d49e2..b788a155 100644 --- a/src/kiwixchoicebox.h +++ b/src/kiwixchoicebox.h @@ -28,8 +28,8 @@ class KiwixChoiceBox : public QWidget public: explicit KiwixChoiceBox(QWidget *parent = nullptr); void setType(QString type); - void setSelections(SelectionList selections, QString defaultSelection); - void setSelections(QStringList selections, QString defaultSelection); + void setSelections(SelectionList selections, QStringList defaultSelection); + void setSelections(QStringList selections, QStringList defaultSelection); ~KiwixChoiceBox(); void adjustSize(); @@ -44,7 +44,6 @@ class KiwixChoiceBox : public QWidget QLabel *choiceLabel; QLineEdit *choiceSearch; QListWidget *choiceSelector; - QListWidgetItem *m_defaultItem; FlowLayout *currentChoicesLayout; KiwixLineEdit *searcher; QStringList getCurrentSelected(); diff --git a/src/settingsmanager.cpp b/src/settingsmanager.cpp index a0a7605c..84322992 100644 --- a/src/settingsmanager.cpp +++ b/src/settingsmanager.cpp @@ -4,6 +4,8 @@ #include #include #include +#include + SettingsManager::SettingsManager(QObject *parent) : QObject(parent), m_settings("Kiwix", "Kiwix-desktop"), @@ -96,6 +98,20 @@ void SettingsManager::setMoveToTrash(bool moveToTrash) emit(moveToTrashChanged(m_moveToTrash)); } +void SettingsManager::setLanguage(QStringList langList) +{ + m_langList = langList; + setSettings("language", m_langList); + emit(languageChanged(m_langList)); +} + +void SettingsManager::setCategory(QStringList categoryList) +{ + m_categoryList = categoryList; + setSettings("category", m_categoryList); + emit(categoryChanged(m_categoryList)); +} + void SettingsManager::initSettings() { m_kiwixServerPort = m_settings.value("localKiwixServer/port", 8080).toInt(); @@ -104,4 +120,6 @@ void SettingsManager::initSettings() m_kiwixServerIpAddress = m_settings.value("localKiwixServer/ipAddress", QString("0.0.0.0")).toString(); m_monitorDir = m_settings.value("monitor/dir", QString("")).toString(); m_moveToTrash = m_settings.value("moveToTrash", true).toBool(); + m_langList = m_settings.value("language", QLocale::languageToString(QLocale().language())).toStringList(); + m_categoryList = m_settings.value("category", {"all"}).toStringList(); } diff --git a/src/settingsmanager.h b/src/settingsmanager.h index 501fe7eb..a07c1788 100644 --- a/src/settingsmanager.h +++ b/src/settingsmanager.h @@ -28,6 +28,8 @@ class SettingsManager : public QObject QString getDownloadDir() const { return m_downloadDir; } QString getMonitorDir() const { return m_monitorDir; } bool getMoveToTrash() const { return m_moveToTrash; } + QStringList getLanguageList() const { return m_langList; } + QStringList getCategoryList() const { return m_categoryList; } public slots: void setKiwixServerPort(int port); @@ -36,6 +38,8 @@ public slots: void setDownloadDir(QString downloadDir); void setMonitorDir(QString monitorDir); void setMoveToTrash(bool moveToTrash); + void setLanguage(QStringList langList); + void setCategory(QStringList categoryList); private: void initSettings(); @@ -45,6 +49,8 @@ public slots: void downloadDirChanged(QString downloadDir); void monitorDirChanged(QString monitorDir); void moveToTrashChanged(bool moveToTrash); + void languageChanged(QStringList langList); + void categoryChanged(QStringList categoryList); private: QSettings m_settings; @@ -55,6 +61,8 @@ public slots: QString m_downloadDir; QString m_monitorDir; bool m_moveToTrash; + QStringList m_langList; + QStringList m_categoryList; }; #endif // SETTINGSMANAGER_H From 146705ba931e6801214b23d6ea65b6764ce0a07f Mon Sep 17 00:00:00 2001 From: Nikhil Tanwar <2002nikhiltanwar@gmail.com> Date: Tue, 15 Aug 2023 19:36:12 +0530 Subject: [PATCH 06/17] Content type now uses KiwixChoiceBox Replaced the old content type filters with KiwixChoiceBox Previously, the content type was a tri state checkbox having yes, no & no-filter values. This changes that to add the values in the following format: Pictures (_pictures:yes) No Pictures (_pictures:no) "no-filter" is simulated by not having any of the above 2 selected. --- resources/i18n/en.json | 8 +++- src/contentmanager.cpp | 16 +++----- src/contentmanager.h | 4 +- src/contentmanagerside.cpp | 75 +++++++++++--------------------------- src/contentmanagerside.h | 3 +- src/contentmanagerside.ui | 32 ++-------------- src/kiwixchoicebox.cpp | 11 ++++-- src/settingsmanager.cpp | 8 ++++ src/settingsmanager.h | 4 ++ 9 files changed, 60 insertions(+), 101 deletions(-) diff --git a/resources/i18n/en.json b/resources/i18n/en.json index 8f441fe9..6f493455 100644 --- a/resources/i18n/en.json +++ b/resources/i18n/en.json @@ -156,6 +156,10 @@ "move-files-to-trash-text": "This action will move the file to trash.", "perma-delete-files-text": "This action will permanently delete the file.", "clear-filter": "Clear the currently set filters", - "search-language": "Search language", - "search-category": "Search category" + "language-searcher-placeholder": "Filter language", + "category-searcher-placeholder": "Filter category", + "content-type-searcher-placeholder": "Filter content type", + "no-details": "Introduction only", + "no-pictures": "No Pictures", + "no-videos": "No Videos" } diff --git a/src/contentmanager.cpp b/src/contentmanager.cpp index 1a51d877..6f4f8e48 100644 --- a/src/contentmanager.cpp +++ b/src/contentmanager.cpp @@ -56,6 +56,9 @@ ContentManager::ContentManager(Library* library, kiwix::Downloader* downloader, treeView->setColumnWidth(5, 120); // TODO: set width for all columns based on viewport + setCurrentLanguage(KiwixApp::instance()->getSettingsManager()->getLanguageList()); + setCurrentCategoryFilter(KiwixApp::instance()->getSettingsManager()->getCategoryList()); + setCurrentContentTypeFilter(KiwixApp::instance()->getSettingsManager()->getContentType()); connect(mp_library, &Library::booksChanged, this, [=]() {emit(this->booksChanged());}); connect(this, &ContentManager::filterParamsChanged, this, &ContentManager::updateLibrary); connect(this, &ContentManager::booksChanged, this, [=]() { @@ -71,8 +74,6 @@ ContentManager::ContentManager(Library* library, kiwix::Downloader* downloader, connect(&m_remoteLibraryManager, &OpdsRequestManager::categoriesReceived, this, &ContentManager::updateCategories); setCategories(); setLanguages(); - setCurrentLanguage(KiwixApp::instance()->getSettingsManager()->getLanguageList()); - setCurrentCategoryFilter(KiwixApp::instance()->getSettingsManager()->getCategoryList()); } QList> ContentManager::getBooksList() @@ -650,9 +651,10 @@ void ContentManager::setCurrentCategoryFilter(QStringList categoryList) emit(filterParamsChanged()); } -void ContentManager::setCurrentContentTypeFilter(QList& contentTypeFilters) +void ContentManager::setCurrentContentTypeFilter(QStringList contentTypeFilters) { m_contentTypeFilters = contentTypeFilters; + KiwixApp::instance()->getSettingsManager()->setContentType(m_contentTypeFilters); emit(filterParamsChanged()); } @@ -714,13 +716,7 @@ QStringList ContentManager::getBookIds() std::vector acceptTags, rejectTags; for (auto &contentTypeFilter : m_contentTypeFilters) { - auto state = contentTypeFilter->checkState(); - auto filter = contentTypeFilter->getName(); - if (state == Qt::PartiallyChecked) { - acceptTags.push_back("_" + filter.toStdString() +":yes"); - } else if (state == Qt::Checked) { - acceptTags.push_back("_" + filter.toStdString() +":no"); - } + acceptTags.push_back(contentTypeFilter.toStdString()); } filter.acceptTags(acceptTags); diff --git a/src/contentmanager.h b/src/contentmanager.h index cbdb6aaa..2fbd87d2 100644 --- a/src/contentmanager.h +++ b/src/contentmanager.h @@ -27,7 +27,7 @@ class ContentManager : public QObject QStringList getDownloadIds(); void setCurrentLanguage(QStringList languageList); void setCurrentCategoryFilter(QStringList category); - void setCurrentContentTypeFilter(QList& contentTypeFilter); + void setCurrentContentTypeFilter(QStringList contentTypeFilter); bool isLocal() const { return m_local; } QStringList getCategories() const { return m_categories; } LanguageList getLanguages() const { return m_languages; } @@ -42,7 +42,7 @@ class ContentManager : public QObject QString m_currentLanguage; QString m_searchQuery; QString m_categoryFilter = "all"; - QList m_contentTypeFilters; + QStringList m_contentTypeFilters; kiwix::supportedListSortBy m_sortBy = kiwix::UNSORTED; bool m_sortOrderAsc = true; LanguageList m_languages; diff --git a/src/contentmanagerside.cpp b/src/contentmanagerside.cpp index 1dce3c85..9c1f2379 100644 --- a/src/contentmanagerside.cpp +++ b/src/contentmanagerside.cpp @@ -25,8 +25,6 @@ ContentManagerSide::ContentManagerSide(QWidget *parent) : mp_contentManager->setLocal(id == CatalogButtonId::LOCAL); }); - mp_ui->contentTypeButton->setIcon(QIcon(":/icons/caret-right-solid.svg")); - mp_ui->contentTypeButton->setIconSize(QSize(12, 12)); connect(mp_ui->allFileButton, &QRadioButton::toggled, this, [=](bool checked) { mp_ui->allFileButton->setStyleSheet( checked ? "*{font-weight: bold}" : "");}); @@ -36,32 +34,15 @@ ContentManagerSide::ContentManagerSide(QWidget *parent) : mp_ui->allFileButton->setText(gt("online-files")); mp_ui->localFileButton ->setText(gt("local-files")); - mp_ui->contentTypeButton->setText(gt("content-type")); mp_categories = mp_ui->categories; - mp_categories->setType(gt("category")); + mp_categories->setType("category"); mp_languages = mp_ui->languages; - mp_languages->setType(gt("language")); + mp_languages->setType("language"); - mp_contentTypeButton = mp_ui->contentTypeButton; - - - connect(mp_contentTypeButton, &QCheckBox::toggled, this, [=](bool checked) { - mp_ui->contentTypeSelector->setHidden(!checked); - }); - mp_ui->contentTypeSelector->setHidden(true); - - mp_ui->contentTypeAllButton->setText(gt("all")); - mp_ui->contentTypeAllButton->setStyleSheet("*{font-weight: 500;}"); - connect(mp_ui->contentTypeAllButton, &QCheckBox::clicked, this, [=](bool checked) { - Q_UNUSED(checked); - mp_ui->contentTypeAllButton->setStyleSheet("*{font-weight: 500;}"); - for (auto &contentTypeFilter : m_contentTypeFilters) { - contentTypeFilter->setCheckState(Qt::Unchecked); - } - mp_contentManager->setCurrentContentTypeFilter(m_contentTypeFilters); - }); + mp_contentType = mp_ui->contentType; + mp_contentType->setType("content-type"); auto searcher = mp_ui->searcher; searcher->setPlaceholderText(gt("search-files")); @@ -71,30 +52,17 @@ ContentManagerSide::ContentManagerSide(QWidget *parent) : connect(searcher, &QLineEdit::textChanged, [searcher](){ KiwixApp::instance()->getContentManager()->setSearch(searcher->text()); }); - - ContentTypeFilter* videosFilter = new ContentTypeFilter("pictures", this); - ContentTypeFilter* picturesFilter = new ContentTypeFilter("videos", this); - ContentTypeFilter* detailsFilter = new ContentTypeFilter("details", this); - m_contentTypeFilters.push_back(videosFilter); - m_contentTypeFilters.push_back(picturesFilter); - m_contentTypeFilters.push_back(detailsFilter); - - auto layout = static_cast(mp_ui->contentTypeSelector->layout()); - for (auto &contentTypeFilter : m_contentTypeFilters) { - layout->addWidget(contentTypeFilter, 0, Qt::AlignTop); - connect(contentTypeFilter, &QCheckBox::clicked, this, [=](bool checked) { - Q_UNUSED(checked); - bool activeFilter = false; - for (auto &contentTypeFilter : m_contentTypeFilters) { - if (contentTypeFilter->checkState() != Qt::Unchecked) { - activeFilter = true; - break; - } - } - mp_ui->contentTypeAllButton->setStyleSheet(activeFilter ? " * {color : #666666;} " : "*{font-weight: 500; color: black;}"); - mp_contentManager->setCurrentContentTypeFilter(m_contentTypeFilters); - }); - } + + QList> contentTypeList = { + {"_pictures:yes", gt("pictures")}, + {"_pictures:no", gt("no-pictures")}, + {"_videos:yes", gt("videos")}, + {"_videos:no", gt("no-videos")}, + {"_details:yes", gt("details")}, + {"_details:no", gt("no-details")} + }; + + mp_contentType->setSelections(contentTypeList, KiwixApp::instance()->getSettingsManager()->getContentType()); setCategories(KiwixApp::instance()->getContentManager()->getCategories()); setLanguages(KiwixApp::instance()->getContentManager()->getLanguages()); @@ -124,13 +92,12 @@ void ContentManagerSide::setContentManager(ContentManager *contentManager) connect(mp_categories, &KiwixChoiceBox::choiceUpdated, this, [=](QStringList values) { mp_contentManager->setCurrentCategoryFilter(values); }); -} - -QString beautify(QString word) -{ - word = word.replace("_", " "); - word[0] = word[0].toUpper(); - return word; + connect(mp_contentType, &KiwixChoiceBox::choiceUpdated, this, [=](QStringList values) { + if (values[0] == "all") { + values = QStringList(); + } + mp_contentManager->setCurrentContentTypeFilter(values); + }); } void ContentManagerSide::setCategories(QStringList categories) diff --git a/src/contentmanagerside.h b/src/contentmanagerside.h index b6162699..69c9ced0 100644 --- a/src/contentmanagerside.h +++ b/src/contentmanagerside.h @@ -32,8 +32,9 @@ class ContentManagerSide : public QWidget ContentManager* mp_contentManager; KiwixChoiceBox *mp_categories; KiwixChoiceBox *mp_languages; + KiwixChoiceBox *mp_contentType; QCheckBox* mp_contentTypeButton; - QList m_contentTypeFilters; + QStringList m_contentTypeFilters; public slots: void setCategories(QStringList); diff --git a/src/contentmanagerside.ui b/src/contentmanagerside.ui index a7fa509c..9eda6754 100644 --- a/src/contentmanagerside.ui +++ b/src/contentmanagerside.ui @@ -141,19 +141,6 @@ - - - - - 0 - 0 - - - - Content Type - - - @@ -190,25 +177,12 @@ 0 - - - - - 0 - 0 - - - - All - - - false - - - + + + diff --git a/src/kiwixchoicebox.cpp b/src/kiwixchoicebox.cpp index 0cea2c88..acb00e41 100644 --- a/src/kiwixchoicebox.cpp +++ b/src/kiwixchoicebox.cpp @@ -76,7 +76,7 @@ KiwixChoiceBox::KiwixChoiceBox(QWidget *parent) : searcher->setStyleSheet("QLineEdit{color: #999;}"); connect(searcher, &KiwixLineEdit::focusedOut, [=]() { - searcher->setPlaceholderText(gt("search-" + m_type.toLower())); + searcher->setPlaceholderText(gt(m_type.toLower() + "-searcher-placeholder")); searcher->setStyleSheet("QLineEdit{color: #999;}"); choiceSelector->setVisible(false); ui->currentChoices->setStyleSheet("#currentChoices{border: 1px solid #ccc;}"); @@ -189,9 +189,14 @@ void KiwixChoiceBox::adjustSize() void KiwixChoiceBox::setType(QString type) { - ui->choiceLabel->setText(type); + ui->choiceLabel->setText(gt(type)); m_type = type; - searcher->setPlaceholderText(gt("search-" + type.toLower())); + searcher->setPlaceholderText(gt(type + "-searcher-placeholder")); + + // Putting width based on placeholder contents + QFontMetrics fm = searcher->fontMetrics(); + auto w = fm.boundingRect(gt(type + "-searcher-placeholder")).width(); + searcher->setMinimumWidth(w + 20); } QStringList KiwixChoiceBox::getCurrentSelected() diff --git a/src/settingsmanager.cpp b/src/settingsmanager.cpp index 84322992..1f4f1ad4 100644 --- a/src/settingsmanager.cpp +++ b/src/settingsmanager.cpp @@ -112,6 +112,13 @@ void SettingsManager::setCategory(QStringList categoryList) emit(categoryChanged(m_categoryList)); } +void SettingsManager::setContentType(QStringList contentTypeList) +{ + m_contentTypeList = contentTypeList; + setSettings("contentType", m_contentTypeList); + emit(contentTypeChanged(m_contentTypeList)); +} + void SettingsManager::initSettings() { m_kiwixServerPort = m_settings.value("localKiwixServer/port", 8080).toInt(); @@ -122,4 +129,5 @@ void SettingsManager::initSettings() m_moveToTrash = m_settings.value("moveToTrash", true).toBool(); m_langList = m_settings.value("language", QLocale::languageToString(QLocale().language())).toStringList(); m_categoryList = m_settings.value("category", {"all"}).toStringList(); + m_contentTypeList = m_settings.value("contentType", {}).toStringList(); } diff --git a/src/settingsmanager.h b/src/settingsmanager.h index a07c1788..5f18f345 100644 --- a/src/settingsmanager.h +++ b/src/settingsmanager.h @@ -30,6 +30,7 @@ class SettingsManager : public QObject bool getMoveToTrash() const { return m_moveToTrash; } QStringList getLanguageList() const { return m_langList; } QStringList getCategoryList() const { return m_categoryList; } + QStringList getContentType() const { return m_contentTypeList; } public slots: void setKiwixServerPort(int port); @@ -40,6 +41,7 @@ public slots: void setMoveToTrash(bool moveToTrash); void setLanguage(QStringList langList); void setCategory(QStringList categoryList); + void setContentType(QStringList contentTypeList); private: void initSettings(); @@ -51,6 +53,7 @@ public slots: void moveToTrashChanged(bool moveToTrash); void languageChanged(QStringList langList); void categoryChanged(QStringList categoryList); + void contentTypeChanged(QStringList contentTypeList); private: QSettings m_settings; @@ -63,6 +66,7 @@ public slots: bool m_moveToTrash; QStringList m_langList; QStringList m_categoryList; + QStringList m_contentTypeList; }; #endif // SETTINGSMANAGER_H From b3a0542ba75632eea93112bfbd813442f8b6ace0 Mon Sep 17 00:00:00 2001 From: Nikhil Tanwar <2002nikhiltanwar@gmail.com> Date: Sat, 19 Aug 2023 12:21:41 +0530 Subject: [PATCH 07/17] Navigate through choices using up,down keys This change allows one to navigate through the choices using up and down arrow keys from keyboard Enter/Return key can be pressed to select the current item --- kiwix-desktop.pro | 2 + resources/css/choiceBox.css | 6 -- src/kiwixchoicebox.cpp | 9 ++- src/kiwixchoicebox.h | 3 +- src/kiwixlistwidget.cpp | 108 ++++++++++++++++++++++++++++++++++++ src/kiwixlistwidget.h | 36 ++++++++++++ src/klistwidgetitem.cpp | 30 ++++++++-- src/klistwidgetitem.h | 3 + 8 files changed, 184 insertions(+), 13 deletions(-) create mode 100644 src/kiwixlistwidget.cpp create mode 100644 src/kiwixlistwidget.h diff --git a/kiwix-desktop.pro b/kiwix-desktop.pro index e9a148ce..32903431 100644 --- a/kiwix-desktop.pro +++ b/kiwix-desktop.pro @@ -45,6 +45,7 @@ SOURCES += \ src/kiwixchoicebox.cpp \ src/kiwixconfirmbox.cpp \ src/kiwixlineedit.cpp \ + src/kiwixlistwidget.cpp \ src/kiwixloader.cpp \ src/rownode.cpp \ src/suggestionlistworker.cpp \ @@ -90,6 +91,7 @@ HEADERS += \ src/kiwixchoicebox.h \ src/kiwixconfirmbox.h \ src/kiwixlineedit.h \ + src/kiwixlistwidget.h \ src/kiwixloader.h \ src/node.h \ src/rownode.h \ diff --git a/resources/css/choiceBox.css b/resources/css/choiceBox.css index 0c6b180c..20d85dea 100644 --- a/resources/css/choiceBox.css +++ b/resources/css/choiceBox.css @@ -1,5 +1,4 @@ QListWidget::item { - color: #666666; padding: 0; padding-top: 6px; padding-bottom: 6px; @@ -16,11 +15,6 @@ QListWidget::item::selected { background-color: transparent; } -QListWidget::item::hover { - color: white; - background-color: #4e63ad; -} - QLineEdit { padding: 4px; border: 0; diff --git a/src/kiwixchoicebox.cpp b/src/kiwixchoicebox.cpp index acb00e41..e6d6cb7b 100644 --- a/src/kiwixchoicebox.cpp +++ b/src/kiwixchoicebox.cpp @@ -11,6 +11,7 @@ #include #include #include "kiwixlineedit.h" +#include "kiwixlistwidget.h" KiwixChoiceBox::KiwixChoiceBox(QWidget *parent) : QWidget(parent), @@ -28,7 +29,7 @@ KiwixChoiceBox::KiwixChoiceBox(QWidget *parent) : choiceLabel = ui->choiceLabel; choiceLabel->setText(gt("undefined")); - choiceSelector = new QListWidget(parent); + choiceSelector = new KiwixListWidget(parent); choiceSelector->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Minimum); choiceSelector->setMaximumWidth(250); choiceSelector->setMaximumHeight(200); @@ -110,6 +111,12 @@ void KiwixChoiceBox::keyPressEvent(QKeyEvent *event) { if (event->key() == Qt::Key_Escape) { searcher->clearFocus(); + } else if (event->key() == Qt::Key_Down) { + choiceSelector->moveDown(); + } else if (event->key() == Qt::Key_Up) { + choiceSelector->moveUp(); + } else if ((event->key() == Qt::Key_Enter) || (event->key() == Qt::Key_Return)) { + choiceSelector->selectCurrent(); } } diff --git a/src/kiwixchoicebox.h b/src/kiwixchoicebox.h index b788a155..313c0dd7 100644 --- a/src/kiwixchoicebox.h +++ b/src/kiwixchoicebox.h @@ -14,6 +14,7 @@ class ChoiceItem; class KiwixLineEdit; +class KiwixListWidget; namespace Ui { class kiwixchoicebox; @@ -43,7 +44,7 @@ class KiwixChoiceBox : public QWidget Ui::kiwixchoicebox *ui; QLabel *choiceLabel; QLineEdit *choiceSearch; - QListWidget *choiceSelector; + KiwixListWidget *choiceSelector; FlowLayout *currentChoicesLayout; KiwixLineEdit *searcher; QStringList getCurrentSelected(); diff --git a/src/kiwixlistwidget.cpp b/src/kiwixlistwidget.cpp new file mode 100644 index 00000000..0d1f58bc --- /dev/null +++ b/src/kiwixlistwidget.cpp @@ -0,0 +1,108 @@ +#include "kiwixlistwidget.h" +#include +#include +#include +#include +#include "kiwixapp.h" +#include "klistwidgetitem.h" + +KiwixListWidget::KiwixListWidget(QWidget *parent) + : QListWidget(parent), currRow(0), m_visibleItems(count()) +{ + connect(this, &KiwixListWidget::currRowChanged, this, &KiwixListWidget::handleCurrRowChange); + setMouseTracking(true); +} + +void KiwixListWidget::mousePressEvent(QMouseEvent *event) +{ + if (event->button() == Qt::LeftButton) { + selectCurrent(item(m_mouseIndex)); + } +} + +void KiwixListWidget::mouseMoveEvent(QMouseEvent *event) +{ + int oldRow = currRow; + m_mouseIndex = row(itemAt(event->pos())); + currRow = m_mouseIndex; + emit(currRowChanged(oldRow, currRow)); +} + +void KiwixListWidget::hideEvent(QHideEvent *event) +{ + auto currItem = dynamic_cast(item(currRow)); + if (currItem) + currItem->disableHighlight(); + QListWidget::hideEvent(event); +} + +void KiwixListWidget::resizeEvent(QResizeEvent *e) +{ + int oldRow = currRow; + for (auto i = 0; i < count(); i++) { + auto itemAtRow = item(i); + if (!itemAtRow->isHidden() && !itemAtRow->isSelected()) { + currRow = i; + break; + } + } + emit(currRowChanged(oldRow, currRow)); + QListWidget::resizeEvent(e); +} + +void KiwixListWidget::handleCurrRowChange(int oldRow, int newRow) +{ + auto prevItem = dynamic_cast(item(oldRow)); + if (prevItem) { + prevItem->disableHighlight(); + } + auto currItem = dynamic_cast(item(newRow)); + if (currItem) { + currItem->enableHighlight(); + scrollToItem(currItem, QAbstractItemView::EnsureVisible); + } + emit(dataChanged(QModelIndex(), QModelIndex())); +} + +void KiwixListWidget::moveUp() +{ + if (selectedItems().size() == count()) + return; + KListWidgetItem *currItem = dynamic_cast(item(currRow)); + int oldRow = currRow; + do { + currRow--; + if (currRow < 0) currRow = count() - 1; + currItem = dynamic_cast(item(currRow)); + } while (currItem->isSelected() || currItem->isHidden()); + emit(currRowChanged(oldRow, currRow)); +} + +void KiwixListWidget::moveDown() +{ + if (selectedItems().size() == count()) + return; + KListWidgetItem *currItem = dynamic_cast(item(currRow)); + int oldRow = currRow; + do { + currRow++; + if (currRow == count()) currRow = 0; + currItem = dynamic_cast(item(currRow)); + } while (currItem->isSelected() || currItem->isHidden()); + emit(currRowChanged(oldRow, currRow)); +} + +void KiwixListWidget::selectCurrent() +{ + selectCurrent(item(currRow)); +} + +void KiwixListWidget::selectCurrent(QListWidgetItem *item) +{ + auto currItem = dynamic_cast(item); + if (currItem && !currItem->isSelected() && !currItem->isHidden()) { + currItem->disableHighlight(); + currItem->setSelected(!currItem->isSelected()); + emit(itemPressed(currItem)); + } +} diff --git a/src/kiwixlistwidget.h b/src/kiwixlistwidget.h new file mode 100644 index 00000000..0f4cd078 --- /dev/null +++ b/src/kiwixlistwidget.h @@ -0,0 +1,36 @@ +#ifndef KIWIXLISTWIDGET_H +#define KIWIXLISTWIDGET_H + +#include + +class KiwixListWidget : public QListWidget { + Q_OBJECT + +public: + KiwixListWidget(QWidget *parent = nullptr); + void moveUp(); + void moveDown(); + void selectCurrent(); + void selectCurrent(QListWidgetItem *item); + void setVisibleItems(int visibleItems) { m_visibleItems = visibleItems; } + int getVisibleItems() { return m_visibleItems; } + +protected: + void hideEvent(QHideEvent *event) override; + void resizeEvent(QResizeEvent *event) override; + void mousePressEvent(QMouseEvent *event) override; + void mouseMoveEvent(QMouseEvent *event) override; + +signals: + void currRowChanged(int oldRow, int newRow); + +private slots: + void handleCurrRowChange(int oldRow, int newRow); + +private: + int currRow; + int m_visibleItems; + int m_mouseIndex; +}; + +#endif // KIWIXLISTWIDGET_H diff --git a/src/klistwidgetitem.cpp b/src/klistwidgetitem.cpp index 6891394f..b77ef607 100644 --- a/src/klistwidgetitem.cpp +++ b/src/klistwidgetitem.cpp @@ -6,16 +6,36 @@ KListWidgetItem::KListWidgetItem(QString text) : QListWidgetItem (text) { setSizeHint(QSize(200, m_itemHeight)); + setBackground(QColor("white")); + setForeground(QColor("#666666")); +} + +void KListWidgetItem::disableHighlight() +{ + isHighlighted = false; +} + +void KListWidgetItem::enableHighlight() +{ + isHighlighted = true; } QVariant KListWidgetItem::data(int role) const { QVariant v = QListWidgetItem::data(role); - if( isSelected() && role == Qt::FontRole ) - { - QFont font = v.value(); - font.setBold( true ); - v = QVariant::fromValue( font ); + if( isSelected()) { + if (role == Qt::FontRole) { + QFont font = v.value(); + font.setBold( true ); + v = QVariant::fromValue( font ); + } + } + if (isHighlighted) { + if (role == Qt::BackgroundRole) { + v = QVariant::fromValue(QColor("#4e63ad")); + } else if (role == Qt::ForegroundRole) { + v = QVariant::fromValue(QColor("white")); + } } return v; } diff --git a/src/klistwidgetitem.h b/src/klistwidgetitem.h index 66bdd1ef..493fe073 100644 --- a/src/klistwidgetitem.h +++ b/src/klistwidgetitem.h @@ -9,8 +9,11 @@ class KListWidgetItem : public QListWidgetItem KListWidgetItem(QString text); QVariant data(int role) const; static int getItemHeight() { return m_itemHeight; }; + void disableHighlight(); + void enableHighlight(); private: static int m_itemHeight; + bool isHighlighted = false; }; #endif // KLISTWIDGETITEM_H From 00392aebfdf48dc83da06e07759cba0ec9896d9f Mon Sep 17 00:00:00 2001 From: Nikhil Tanwar <2002nikhiltanwar@gmail.com> Date: Sat, 19 Aug 2023 12:40:17 +0530 Subject: [PATCH 08/17] Minor style fixes Fixed the height of selector to show 6 elements maximum Reduced distance between filters Increased margin between choiceItem and container box All of the choicebox is now clickable and shows up the list on click --- src/kiwixchoicebox.cpp | 16 ++++++++++++++-- src/kiwixchoicebox.h | 2 ++ ui/kiwixchoicebox.ui | 10 ++++++++-- 3 files changed, 24 insertions(+), 4 deletions(-) diff --git a/src/kiwixchoicebox.cpp b/src/kiwixchoicebox.cpp index e6d6cb7b..6d3d15d6 100644 --- a/src/kiwixchoicebox.cpp +++ b/src/kiwixchoicebox.cpp @@ -32,7 +32,8 @@ KiwixChoiceBox::KiwixChoiceBox(QWidget *parent) : choiceSelector = new KiwixListWidget(parent); choiceSelector->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Minimum); choiceSelector->setMaximumWidth(250); - choiceSelector->setMaximumHeight(200); + // allow maximum 6 elements + choiceSelector->setMaximumHeight(KListWidgetItem::getItemHeight() * 6); choiceSelector->setCursor(Qt::PointingHandCursor); choiceSelector->setVerticalScrollMode(QAbstractItemView::ScrollMode::ScrollPerPixel); choiceSelector->setFocusPolicy(Qt::FocusPolicy::NoFocus); @@ -40,7 +41,7 @@ KiwixChoiceBox::KiwixChoiceBox(QWidget *parent) : choiceSelector->setStyleSheet(styleSheet); choiceSelector->setSelectionMode(QAbstractItemView::SelectionMode::MultiSelection); - currentChoicesLayout = new FlowLayout(ui->currentChoices, 2, 2, 2); + currentChoicesLayout = new FlowLayout(ui->currentChoices, 4, 2, 2); searcher = new KiwixLineEdit(); searcher->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Preferred); currentChoicesLayout->addWidget(searcher); @@ -100,6 +101,10 @@ KiwixChoiceBox::KiwixChoiceBox(QWidget *parent) : connect(this, &KiwixChoiceBox::choiceUpdated, [=]() { choiceSelector->setVisible(false); }); + + connect(this, &KiwixChoiceBox::clicked, [=]() { + searcher->setFocus(); + }); } KiwixChoiceBox::~KiwixChoiceBox() @@ -107,6 +112,13 @@ KiwixChoiceBox::~KiwixChoiceBox() delete ui; } +void KiwixChoiceBox::mouseReleaseEvent(QMouseEvent *event) +{ + if (event->button() == Qt::LeftButton) { + emit(clicked()); + } +} + void KiwixChoiceBox::keyPressEvent(QKeyEvent *event) { if (event->key() == Qt::Key_Escape) { diff --git a/src/kiwixchoicebox.h b/src/kiwixchoicebox.h index 313c0dd7..3a49df71 100644 --- a/src/kiwixchoicebox.h +++ b/src/kiwixchoicebox.h @@ -36,9 +36,11 @@ class KiwixChoiceBox : public QWidget protected: void keyPressEvent(QKeyEvent* event) override; + void mouseReleaseEvent(QMouseEvent *event) override; signals: void choiceUpdated(QStringList); + void clicked(); private: Ui::kiwixchoicebox *ui; diff --git a/ui/kiwixchoicebox.ui b/ui/kiwixchoicebox.ui index 140154b2..e70b1933 100644 --- a/ui/kiwixchoicebox.ui +++ b/ui/kiwixchoicebox.ui @@ -6,8 +6,8 @@ 0 0 - 274 - 325 + 268 + 50 @@ -26,6 +26,12 @@ Form + + 0 + + + 0 + From 907a225abdaf014c95027b2bd05c18affe8ef9e2 Mon Sep 17 00:00:00 2001 From: Nikhil Tanwar <2002nikhiltanwar@gmail.com> Date: Sun, 27 Aug 2023 18:22:51 +0530 Subject: [PATCH 09/17] Move Search-files between Local-files and language filter This change puts the file-search option after Catalog buttons (Online and local files) putting all filters on catalog in one place. First suggested in https://github.com/kiwix/kiwix-desktop/pull/965#pullrequestreview-1585813810 --- src/contentmanagerside.ui | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/contentmanagerside.ui b/src/contentmanagerside.ui index 9eda6754..b06e1595 100644 --- a/src/contentmanagerside.ui +++ b/src/contentmanagerside.ui @@ -65,9 +65,6 @@ 9 - - - @@ -115,6 +112,9 @@ + + + From 877352d3bd575107cb836f595e27406a3d3392d0 Mon Sep 17 00:00:00 2001 From: Nikhil Tanwar <2002nikhiltanwar@gmail.com> Date: Sun, 27 Aug 2023 19:10:07 +0530 Subject: [PATCH 10/17] Cosmetic changes related to showing options menu Options menu shows up on pressing down arrow Clicking kiwixchoicebox when options is shown doesn't result in flashing now Display placeholder only if there are no options selected. --- src/kiwixchoicebox.cpp | 54 ++++++++++++++++++++++++++++++------------ src/kiwixchoicebox.h | 4 +++- 2 files changed, 42 insertions(+), 16 deletions(-) diff --git a/src/kiwixchoicebox.cpp b/src/kiwixchoicebox.cpp index 6d3d15d6..fb296ceb 100644 --- a/src/kiwixchoicebox.cpp +++ b/src/kiwixchoicebox.cpp @@ -70,32 +70,25 @@ KiwixChoiceBox::KiwixChoiceBox(QWidget *parent) : }); connect(searcher, &KiwixLineEdit::clicked, [=]() { - choiceSelector->setVisible(true); - adjustSize(); + showOptions(); }); choiceSelector->setVisible(false); searcher->setStyleSheet("QLineEdit{color: #999;}"); connect(searcher, &KiwixLineEdit::focusedOut, [=]() { - searcher->setPlaceholderText(gt(m_type.toLower() + "-searcher-placeholder")); - searcher->setStyleSheet("QLineEdit{color: #999;}"); - choiceSelector->setVisible(false); - ui->currentChoices->setStyleSheet("#currentChoices{border: 1px solid #ccc;}"); + hideOptions(); }); connect(searcher, &KiwixLineEdit::focusedIn, [=]() { - ui->currentChoices->setStyleSheet("#currentChoices{border: 2px solid #4e63ad;}"); - adjustSize(); - choiceSelector->setVisible(true); - choiceSelector->raise(); - searcher->setPlaceholderText(""); + showOptions(); }); ui->clearButton->setCursor(Qt::PointingHandCursor); connect(ui->clearButton, &QPushButton::clicked, [=]() { clearSelections(); emit(choiceUpdated(getCurrentSelected())); + hideOptions(); }); connect(this, &KiwixChoiceBox::choiceUpdated, [=]() { @@ -103,7 +96,7 @@ KiwixChoiceBox::KiwixChoiceBox(QWidget *parent) : }); connect(this, &KiwixChoiceBox::clicked, [=]() { - searcher->setFocus(); + showOptions(); }); } @@ -112,18 +105,48 @@ KiwixChoiceBox::~KiwixChoiceBox() delete ui; } -void KiwixChoiceBox::mouseReleaseEvent(QMouseEvent *event) +/* +When the lineEdit is currently focused, +if the outer widget is pressed, lineEdit loses focus and hides the options. +When mouseRelease event is called, it will create a flicker effect: + - Clicking and holding causes the lineEdit to lose focus and hide the options + - Release causes the options to show up again. +Showing the options on a mousePress doesn't allow this +*/ +void KiwixChoiceBox::mousePressEvent(QMouseEvent *event) { if (event->button() == Qt::LeftButton) { emit(clicked()); } } +void KiwixChoiceBox::hideOptions() +{ + if (choiceSelector->selectedItems().isEmpty()) { + searcher->setPlaceholderText(gt(m_type.toLower() + "-searcher-placeholder")); + } + searcher->setStyleSheet("QLineEdit{color: #999;}"); + choiceSelector->setVisible(false); + ui->currentChoices->setStyleSheet("#currentChoices{border: 1px solid #ccc;}"); + searcher->clearFocus(); +} + +void KiwixChoiceBox::showOptions() +{ + ui->currentChoices->setStyleSheet("#currentChoices{border: 2px solid #4e63ad;}"); + adjustSize(); + choiceSelector->setVisible(true); + choiceSelector->raise(); + searcher->setPlaceholderText(""); + searcher->setFocus(); +} + void KiwixChoiceBox::keyPressEvent(QKeyEvent *event) { if (event->key() == Qt::Key_Escape) { - searcher->clearFocus(); + hideOptions(); } else if (event->key() == Qt::Key_Down) { + showOptions(); choiceSelector->moveDown(); } else if (event->key() == Qt::Key_Up) { choiceSelector->moveUp(); @@ -193,6 +216,8 @@ void KiwixChoiceBox::setSelections(SelectionList selections, QStringList default addSelection(item->text(), item->data(Qt::UserRole).toString()); } } + if (choiceSelector->selectedItems().isEmpty()) + searcher->setPlaceholderText(gt(m_type + "-searcher-placeholder")); adjustSize(); } @@ -210,7 +235,6 @@ void KiwixChoiceBox::setType(QString type) { ui->choiceLabel->setText(gt(type)); m_type = type; - searcher->setPlaceholderText(gt(type + "-searcher-placeholder")); // Putting width based on placeholder contents QFontMetrics fm = searcher->fontMetrics(); diff --git a/src/kiwixchoicebox.h b/src/kiwixchoicebox.h index 3a49df71..053f0a56 100644 --- a/src/kiwixchoicebox.h +++ b/src/kiwixchoicebox.h @@ -36,7 +36,7 @@ class KiwixChoiceBox : public QWidget protected: void keyPressEvent(QKeyEvent* event) override; - void mouseReleaseEvent(QMouseEvent *event) override; + void mousePressEvent(QMouseEvent *event) override; signals: void choiceUpdated(QStringList); @@ -53,6 +53,8 @@ class KiwixChoiceBox : public QWidget bool removeSelection(QString selection); void clearSelections(); bool addSelection(QString key, QString value); + void showOptions(); + void hideOptions(); QString m_type; bool m_sliderMoved = false; }; From fce5b004b48ef94845b6a3c3e329cc450e7f031f Mon Sep 17 00:00:00 2001 From: Nikhil Tanwar <2002nikhiltanwar@gmail.com> Date: Sun, 27 Aug 2023 21:03:58 +0530 Subject: [PATCH 11/17] Put newly selected item on top of options menu When a new item is selected, it is not kept on top of options menu --- src/kiwixchoicebox.cpp | 29 +++++++++++++++++++++-------- src/kiwixchoicebox.h | 4 ++-- 2 files changed, 23 insertions(+), 10 deletions(-) diff --git a/src/kiwixchoicebox.cpp b/src/kiwixchoicebox.cpp index fb296ceb..c36d44ee 100644 --- a/src/kiwixchoicebox.cpp +++ b/src/kiwixchoicebox.cpp @@ -48,9 +48,9 @@ KiwixChoiceBox::KiwixChoiceBox(QWidget *parent) : connect(choiceSelector, &QListWidget::itemPressed, this, [=](QListWidgetItem *item) { searcher->clear(); if (item->isSelected()) { - addSelection(item->text(), item->data(Qt::UserRole).toString()); + addSelection(item); } else { - removeSelection(item->text()); + removeSelection(item); } }); @@ -155,24 +155,38 @@ void KiwixChoiceBox::keyPressEvent(QKeyEvent *event) } } -bool KiwixChoiceBox::addSelection(QString key, QString value) +bool KiwixChoiceBox::addSelection(QListWidgetItem *item) { + auto key = item->text(); + auto value = item->data(Qt::UserRole).toString(); auto chItem = new ChoiceItem(key, value); connect(chItem, &ChoiceItem::closeButtonClicked, [=](QString text) { - removeSelection(text); + auto selectionItems = choiceSelector->findItems(text, Qt::MatchExactly); + if (selectionItems.size() != 1) return; + removeSelection(selectionItems[0]); }); chItem->setObjectName(key); currentChoicesLayout->insertWidget(ui->currentChoices->children().count() - 2, chItem); searcher->setFixedWidth(20); + // put on top of list + item = choiceSelector->takeItem(choiceSelector->row(item)); + choiceSelector->insertItem(0, item); + item->setSelected(true); + searcher->setFocus(); emit(choiceUpdated(getCurrentSelected())); return true; } -bool KiwixChoiceBox::removeSelection(QString selection) +bool KiwixChoiceBox::removeSelection(QListWidgetItem *item) { - auto chItem = ui->currentChoices->findChild(selection); + auto chItem = ui->currentChoices->findChild(item->text()); chItem->deleteLater(); + // selected items are always shown at top, put it after the last selected item + item->setSelected(false); + auto selItems = choiceSelector->selectedItems(); + item = choiceSelector->takeItem(choiceSelector->row(item)); + choiceSelector->insertItem(selItems.size(), item); emit(choiceUpdated(getCurrentSelected())); return true; } @@ -212,8 +226,7 @@ void KiwixChoiceBox::setSelections(SelectionList selections, QStringList default item->setData(Qt::UserRole, selection.first); choiceSelector->addItem(item); if (defaultSelection.contains(selection.first)) { - item->setSelected(true); - addSelection(item->text(), item->data(Qt::UserRole).toString()); + addSelection(item); } } if (choiceSelector->selectedItems().isEmpty()) diff --git a/src/kiwixchoicebox.h b/src/kiwixchoicebox.h index 053f0a56..eb7aa882 100644 --- a/src/kiwixchoicebox.h +++ b/src/kiwixchoicebox.h @@ -50,9 +50,9 @@ class KiwixChoiceBox : public QWidget FlowLayout *currentChoicesLayout; KiwixLineEdit *searcher; QStringList getCurrentSelected(); - bool removeSelection(QString selection); + bool removeSelection(QListWidgetItem *item); void clearSelections(); - bool addSelection(QString key, QString value); + bool addSelection(QListWidgetItem *item); void showOptions(); void hideOptions(); QString m_type; From 1c5bb8345e11dec589fd45a700a2a3bd6186f8fc Mon Sep 17 00:00:00 2001 From: Nikhil Tanwar <2002nikhiltanwar@gmail.com> Date: Sun, 27 Aug 2023 22:05:34 +0530 Subject: [PATCH 12/17] Don't set focus/show options menu if choiceItem is clicked --- src/choiceitem.cpp | 7 +++++++ src/choiceitem.h | 3 +++ 2 files changed, 10 insertions(+) diff --git a/src/choiceitem.cpp b/src/choiceitem.cpp index 8748527b..8f0ba0d4 100644 --- a/src/choiceitem.cpp +++ b/src/choiceitem.cpp @@ -1,6 +1,7 @@ #include "choiceitem.h" #include "ui_choiceitem.h" #include +#include ChoiceItem::ChoiceItem(QString key, QString value, QWidget *parent) : QWidget(parent), @@ -25,3 +26,9 @@ ChoiceItem::~ChoiceItem() { delete ui; } + +void ChoiceItem::mousePressEvent(QMouseEvent *event) +{ + Q_UNUSED(event); + return; +} diff --git a/src/choiceitem.h b/src/choiceitem.h index 76ea4772..b03b11db 100644 --- a/src/choiceitem.h +++ b/src/choiceitem.h @@ -17,6 +17,9 @@ class ChoiceItem : public QWidget QString getKey() { return m_key; } QString getValue() { return m_value; } +protected: + void mousePressEvent(QMouseEvent *event) override; + private: Ui::ChoiceItem *ui; QString m_key; From 3c16f795d48aa33529f0cbd2967592a50cd46787 Mon Sep 17 00:00:00 2001 From: Nikhil Tanwar <2002nikhiltanwar@gmail.com> Date: Thu, 31 Aug 2023 12:08:41 +0530 Subject: [PATCH 13/17] Increase searcher width based on entered text The searcher doesn't have a predefined width now. It increases based on text entered. --- src/kiwixchoicebox.cpp | 49 +++++++++++++++++++++++++++--------------- src/kiwixchoicebox.h | 1 + ui/kiwixchoicebox.ui | 4 ++-- 3 files changed, 35 insertions(+), 19 deletions(-) diff --git a/src/kiwixchoicebox.cpp b/src/kiwixchoicebox.cpp index c36d44ee..15c1ae28 100644 --- a/src/kiwixchoicebox.cpp +++ b/src/kiwixchoicebox.cpp @@ -43,7 +43,8 @@ KiwixChoiceBox::KiwixChoiceBox(QWidget *parent) : currentChoicesLayout = new FlowLayout(ui->currentChoices, 4, 2, 2); searcher = new KiwixLineEdit(); - searcher->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Preferred); + searcher->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed); + searcher->setFixedWidth(20); currentChoicesLayout->addWidget(searcher); connect(choiceSelector, &QListWidget::itemPressed, this, [=](QListWidgetItem *item) { searcher->clear(); @@ -56,16 +57,20 @@ KiwixChoiceBox::KiwixChoiceBox(QWidget *parent) : connect(searcher, &QLineEdit::textChanged, [=](QString search) { searcher->setStyleSheet("QLineEdit{color: #666;}"); + QFontMetrics fm = searcher->fontMetrics(); + auto w = fm.horizontalAdvance(search) + 20; + if (w + 4 < ui->currentChoices->width()) { + searcher->setFixedWidth(w); + ui->currentChoices->resize(ui->currentChoices->width(), currentChoicesLayout->minimumHeightForWidth(ui->currentChoices->width())); + } int visibleItems = 0; for (auto i = 0; i < choiceSelector->count(); i++) { auto itemAtRow = choiceSelector->item(i); itemAtRow->setHidden(!itemAtRow->text().contains(search, Qt::CaseSensitivity::CaseInsensitive)); visibleItems += !(itemAtRow->isHidden()); } - choiceSelector->setGeometry(this->x() + ui->currentChoices->x(), - this->y() + ui->currentChoices->y() + ui->currentChoices->height(), - choiceSelector->width(), - visibleItems * KListWidgetItem::getItemHeight() + 2); + choiceSelector->setVisibleItems(visibleItems); + adjustSize(); choiceSelector->setVisible(true); }); @@ -86,12 +91,14 @@ KiwixChoiceBox::KiwixChoiceBox(QWidget *parent) : ui->clearButton->setCursor(Qt::PointingHandCursor); connect(ui->clearButton, &QPushButton::clicked, [=]() { - clearSelections(); - emit(choiceUpdated(getCurrentSelected())); - hideOptions(); + clearSelections(); + emit(choiceUpdated(getCurrentSelected())); + hideOptions(); }); connect(this, &KiwixChoiceBox::choiceUpdated, [=]() { + if (choiceSelector->selectedItems().isEmpty()) + showPlaceholder(); choiceSelector->setVisible(false); }); @@ -123,7 +130,7 @@ void KiwixChoiceBox::mousePressEvent(QMouseEvent *event) void KiwixChoiceBox::hideOptions() { if (choiceSelector->selectedItems().isEmpty()) { - searcher->setPlaceholderText(gt(m_type.toLower() + "-searcher-placeholder")); + showPlaceholder(); } searcher->setStyleSheet("QLineEdit{color: #999;}"); choiceSelector->setVisible(false); @@ -146,7 +153,8 @@ void KiwixChoiceBox::keyPressEvent(QKeyEvent *event) if (event->key() == Qt::Key_Escape) { hideOptions(); } else if (event->key() == Qt::Key_Down) { - showOptions(); + if (!choiceSelector->isVisible()) + showOptions(); choiceSelector->moveDown(); } else if (event->key() == Qt::Key_Up) { choiceSelector->moveUp(); @@ -173,6 +181,7 @@ bool KiwixChoiceBox::addSelection(QListWidgetItem *item) choiceSelector->insertItem(0, item); item->setSelected(true); + searcher->setFixedWidth(20); searcher->setFocus(); emit(choiceUpdated(getCurrentSelected())); return true; @@ -201,6 +210,16 @@ void KiwixChoiceBox::clearSelections() } } +void KiwixChoiceBox::showPlaceholder() +{ + searcher->clear(); + searcher->setPlaceholderText(gt(m_type + "-searcher-placeholder")); + // Putting width based on placeholder contents + QFontMetrics fm = searcher->fontMetrics(); + auto w = fm.boundingRect(gt(m_type + "-searcher-placeholder")).width(); + searcher->setFixedWidth(w + 20); +} + QString beautifyString(QString word) { word = word.replace("_", " "); @@ -230,7 +249,8 @@ void KiwixChoiceBox::setSelections(SelectionList selections, QStringList default } } if (choiceSelector->selectedItems().isEmpty()) - searcher->setPlaceholderText(gt(m_type + "-searcher-placeholder")); + showPlaceholder(); + choiceSelector->setVisibleItems(choiceSelector->count()); adjustSize(); } @@ -241,18 +261,13 @@ void KiwixChoiceBox::adjustSize() choiceSelector->setGeometry(this->x() + ui->currentChoices->x(), this->y() + ui->currentChoices->y() + ui->currentChoices->height(), choiceSelector->width(), - choiceSelector->count() * KListWidgetItem::getItemHeight() + 2); // 2 is for the border so that all elements are visible + choiceSelector->getVisibleItems() * KListWidgetItem::getItemHeight() + 2); // 2 is for the border so that all elements are visible } void KiwixChoiceBox::setType(QString type) { ui->choiceLabel->setText(gt(type)); m_type = type; - - // Putting width based on placeholder contents - QFontMetrics fm = searcher->fontMetrics(); - auto w = fm.boundingRect(gt(type + "-searcher-placeholder")).width(); - searcher->setMinimumWidth(w + 20); } QStringList KiwixChoiceBox::getCurrentSelected() diff --git a/src/kiwixchoicebox.h b/src/kiwixchoicebox.h index eb7aa882..d5ff0906 100644 --- a/src/kiwixchoicebox.h +++ b/src/kiwixchoicebox.h @@ -55,6 +55,7 @@ class KiwixChoiceBox : public QWidget bool addSelection(QListWidgetItem *item); void showOptions(); void hideOptions(); + void showPlaceholder(); QString m_type; bool m_sliderMoved = false; }; diff --git a/ui/kiwixchoicebox.ui b/ui/kiwixchoicebox.ui index e70b1933..4d78a3a7 100644 --- a/ui/kiwixchoicebox.ui +++ b/ui/kiwixchoicebox.ui @@ -7,7 +7,7 @@ 0 0 268 - 50 + 54 @@ -79,7 +79,7 @@ - + 0 0 From cadac0a1e9c215a0b40369cff63d39bdc506aeb9 Mon Sep 17 00:00:00 2001 From: Nikhil Tanwar <2002nikhiltanwar@gmail.com> Date: Tue, 12 Sep 2023 22:44:07 +0530 Subject: [PATCH 14/17] Use empty string to signify no filter values consistently Earlier we used, "*" to signify all languages and "all" for all categories. This change removes these inconsistencies. Now, if the filter value is empty, it should signify that no filter is set (show all values) --- src/contentmanager.cpp | 6 ++---- src/contentmanagerside.cpp | 13 +++---------- src/kiwixchoicebox.cpp | 2 -- src/opdsrequestmanager.cpp | 4 ++-- src/settingsmanager.cpp | 2 +- 5 files changed, 8 insertions(+), 19 deletions(-) diff --git a/src/contentmanager.cpp b/src/contentmanager.cpp index 6f4f8e48..4a83d7cc 100644 --- a/src/contentmanager.cpp +++ b/src/contentmanager.cpp @@ -630,8 +630,6 @@ void ContentManager::setCurrentLanguage(QStringList languageList) } catch (std::out_of_range&) {} } } - if (languageList.empty()) - languageList.append("*"); auto newLanguage = languageList.join(","); if (m_currentLanguage == newLanguage) return; @@ -722,9 +720,9 @@ QStringList ContentManager::getBookIds() filter.acceptTags(acceptTags); filter.rejectTags(rejectTags); filter.query(m_searchQuery.toStdString()); - if (m_currentLanguage != "*") + if (m_currentLanguage != "") filter.lang(m_currentLanguage.toStdString()); - if (m_categoryFilter != "all") + if (m_categoryFilter != "") filter.category(m_categoryFilter.toStdString()); if (m_local) { diff --git a/src/contentmanagerside.cpp b/src/contentmanagerside.cpp index 9c1f2379..4666ebee 100644 --- a/src/contentmanagerside.cpp +++ b/src/contentmanagerside.cpp @@ -82,21 +82,14 @@ void ContentManagerSide::setContentManager(ContentManager *contentManager) const auto checkedButton = mp_ui->buttonGroup->button(isLocal == CatalogButtonId::LOCAL); checkedButton->setChecked(true); checkedButton->setStyleSheet("*{font-weight: bold}"); - connect(mp_languages, &KiwixChoiceBox::choiceUpdated, - this, [=](QStringList values) { - if (values[0] == "all") { - values = QStringList(); - } - mp_contentManager->setCurrentLanguage(values); + connect(mp_languages, &KiwixChoiceBox::choiceUpdated, this, [=](QStringList values) { + mp_contentManager->setCurrentLanguage(values); }); connect(mp_categories, &KiwixChoiceBox::choiceUpdated, this, [=](QStringList values) { mp_contentManager->setCurrentCategoryFilter(values); }); connect(mp_contentType, &KiwixChoiceBox::choiceUpdated, this, [=](QStringList values) { - if (values[0] == "all") { - values = QStringList(); - } - mp_contentManager->setCurrentContentTypeFilter(values); + mp_contentManager->setCurrentContentTypeFilter(values); }); } diff --git a/src/kiwixchoicebox.cpp b/src/kiwixchoicebox.cpp index 15c1ae28..8f13cf86 100644 --- a/src/kiwixchoicebox.cpp +++ b/src/kiwixchoicebox.cpp @@ -272,8 +272,6 @@ void KiwixChoiceBox::setType(QString type) QStringList KiwixChoiceBox::getCurrentSelected() { - if (choiceSelector->selectedItems().isEmpty()) - return {"all"}; QStringList selections; for (auto &item : choiceSelector->selectedItems()) { selections.append(item->data(Qt::UserRole).toString()); diff --git a/src/opdsrequestmanager.cpp b/src/opdsrequestmanager.cpp index afcc0f38..8a243028 100644 --- a/src/opdsrequestmanager.cpp +++ b/src/opdsrequestmanager.cpp @@ -15,7 +15,7 @@ void OpdsRequestManager::doUpdate(const QString& currentLanguage, const QString& QStringList excludeTags("_sw:yes"); // Add filter by language (if necessary) - if (currentLanguage != "*") { + if (currentLanguage != "") { query.addQueryItem("lang", currentLanguage); } @@ -23,7 +23,7 @@ void OpdsRequestManager::doUpdate(const QString& currentLanguage, const QString& query.addQueryItem("count", QString::number(-1)); // Add filter by category (if necessary) - if (categoryFilter != "all") { + if (categoryFilter != "") { query.addQueryItem("category", categoryFilter); } diff --git a/src/settingsmanager.cpp b/src/settingsmanager.cpp index 1f4f1ad4..4e5e5642 100644 --- a/src/settingsmanager.cpp +++ b/src/settingsmanager.cpp @@ -128,6 +128,6 @@ void SettingsManager::initSettings() m_monitorDir = m_settings.value("monitor/dir", QString("")).toString(); m_moveToTrash = m_settings.value("moveToTrash", true).toBool(); m_langList = m_settings.value("language", QLocale::languageToString(QLocale().language())).toStringList(); - m_categoryList = m_settings.value("category", {"all"}).toStringList(); + m_categoryList = m_settings.value("category", {}).toStringList(); m_contentTypeList = m_settings.value("contentType", {}).toStringList(); } From a50f1e73be799fbcd48dcf17e43c568f9237a7ba Mon Sep 17 00:00:00 2001 From: Nikhil Tanwar <2002nikhiltanwar@gmail.com> Date: Tue, 12 Sep 2023 22:46:34 +0530 Subject: [PATCH 15/17] Keep selected values when changing catalog If a filter which is available in remote catalog but not in local catalog (or vice versa) is selected, then we keep that filter applied even after the catalog is switched. --- src/kiwixchoicebox.cpp | 18 ++++++++++++++---- src/kiwixchoicebox.h | 2 +- 2 files changed, 15 insertions(+), 5 deletions(-) diff --git a/src/kiwixchoicebox.cpp b/src/kiwixchoicebox.cpp index 8f13cf86..9fa4c65b 100644 --- a/src/kiwixchoicebox.cpp +++ b/src/kiwixchoicebox.cpp @@ -163,7 +163,7 @@ void KiwixChoiceBox::keyPressEvent(QKeyEvent *event) } } -bool KiwixChoiceBox::addSelection(QListWidgetItem *item) +bool KiwixChoiceBox::addSelection(QListWidgetItem *item, bool updateRequired) { auto key = item->text(); auto value = item->data(Qt::UserRole).toString(); @@ -182,8 +182,10 @@ bool KiwixChoiceBox::addSelection(QListWidgetItem *item) item->setSelected(true); searcher->setFixedWidth(20); - searcher->setFocus(); - emit(choiceUpdated(getCurrentSelected())); + if (updateRequired) { + searcher->setFocus(); + emit(choiceUpdated(getCurrentSelected())); + } return true; } @@ -238,6 +240,14 @@ void KiwixChoiceBox::setSelections(QStringList selections, QStringList defaultSe void KiwixChoiceBox::setSelections(SelectionList selections, QStringList defaultSelection) { + auto prevSelections = choiceSelector->selectedItems(); + for (auto prev : prevSelections) { + QPair prevPair = {prev->data(Qt::UserRole).toString(), prev->text()}; + if (!selections.contains(prevPair)) { + selections.append(prevPair); + } + } + clearSelections(); choiceSelector->clear(); for (const auto &selection: selections) { @@ -245,7 +255,7 @@ void KiwixChoiceBox::setSelections(SelectionList selections, QStringList default item->setData(Qt::UserRole, selection.first); choiceSelector->addItem(item); if (defaultSelection.contains(selection.first)) { - addSelection(item); + addSelection(item, false); } } if (choiceSelector->selectedItems().isEmpty()) diff --git a/src/kiwixchoicebox.h b/src/kiwixchoicebox.h index d5ff0906..25a35886 100644 --- a/src/kiwixchoicebox.h +++ b/src/kiwixchoicebox.h @@ -52,7 +52,7 @@ class KiwixChoiceBox : public QWidget QStringList getCurrentSelected(); bool removeSelection(QListWidgetItem *item); void clearSelections(); - bool addSelection(QListWidgetItem *item); + bool addSelection(QListWidgetItem *item, bool updateRequired = true); void showOptions(); void hideOptions(); void showPlaceholder(); From d2a6098eca733fbc19da2a5a968ba607a5520e9d Mon Sep 17 00:00:00 2001 From: Nikhil Tanwar <2002nikhiltanwar@gmail.com> Date: Tue, 12 Sep 2023 19:20:37 +0530 Subject: [PATCH 16/17] Introduce KiwixApp::parseStyleFromFile() This change adds a new function parseStyleFromFile(QString filePath) It takes a file path, reads it and returns the string --- src/choiceitem.cpp | 6 ++---- src/contentmanagerside.cpp | 5 +---- src/contentmanagerview.cpp | 5 +---- src/kiwixapp.cpp | 17 ++++++++++------- src/kiwixapp.h | 1 + src/kiwixchoicebox.cpp | 5 +---- src/kiwixconfirmbox.cpp | 8 +------- src/searchbar.cpp | 7 +------ src/settingsview.cpp | 5 +---- 9 files changed, 19 insertions(+), 40 deletions(-) diff --git a/src/choiceitem.cpp b/src/choiceitem.cpp index 8f0ba0d4..e6346458 100644 --- a/src/choiceitem.cpp +++ b/src/choiceitem.cpp @@ -2,6 +2,7 @@ #include "ui_choiceitem.h" #include #include +#include "kiwixapp.h" ChoiceItem::ChoiceItem(QString key, QString value, QWidget *parent) : QWidget(parent), @@ -10,10 +11,7 @@ ChoiceItem::ChoiceItem(QString key, QString value, QWidget *parent) : m_value(value) { ui->setupUi(this); - QFile file(QString::fromUtf8(":/css/choiceBox.css")); - file.open(QFile::ReadOnly); - QString styleSheet = QString(file.readAll()); - this->setStyleSheet(styleSheet); + this->setStyleSheet(KiwixApp::instance()->parseStyleFromFile(":/css/choiceBox.css")); ui->itemLabel->setText(key); ui->itemLabel->setToolTip(key); connect(ui->closeButton, &QPushButton::clicked, [=](){ diff --git a/src/contentmanagerside.cpp b/src/contentmanagerside.cpp index 4666ebee..3b6fb5f4 100644 --- a/src/contentmanagerside.cpp +++ b/src/contentmanagerside.cpp @@ -13,10 +13,7 @@ ContentManagerSide::ContentManagerSide(QWidget *parent) : { setFocusPolicy(Qt::FocusPolicy::StrongFocus); mp_ui->setupUi(this); - QFile file(QString::fromUtf8(":/css/contentmanagerside.css")); - file.open(QFile::ReadOnly); - QString styleSheet = QString(file.readAll()); - this->setStyleSheet(styleSheet); + this->setStyleSheet(KiwixApp::instance()->parseStyleFromFile(":/css/contentmanagerside.css")); mp_ui->buttonGroup->setId(mp_ui->allFileButton, CatalogButtonId::ALL); mp_ui->buttonGroup->setId(mp_ui->localFileButton, CatalogButtonId::LOCAL); diff --git a/src/contentmanagerview.cpp b/src/contentmanagerview.cpp index f3281eea..24ba1f9b 100644 --- a/src/contentmanagerview.cpp +++ b/src/contentmanagerview.cpp @@ -10,10 +10,7 @@ ContentManagerView::ContentManagerView(QWidget *parent) { mp_ui->setupUi(this); mp_ui->m_view->setSortingEnabled(true); - QFile file(QString::fromUtf8(":/css/_contentManager.css")); - file.open(QFile::ReadOnly); - QString styleSheet = QString(file.readAll()); - mp_ui->m_view->setStyleSheet(styleSheet); + mp_ui->m_view->setStyleSheet(KiwixApp::instance()->parseStyleFromFile(":/css/_contentManager.css")); mp_ui->m_view->setContextMenuPolicy(Qt::CustomContextMenu); auto managerDelegate = new ContentManagerDelegate(); mp_ui->m_view->setItemDelegate(managerDelegate); diff --git a/src/kiwixapp.cpp b/src/kiwixapp.cpp index eff5b07c..a47274bc 100644 --- a/src/kiwixapp.cpp +++ b/src/kiwixapp.cpp @@ -72,13 +72,7 @@ void KiwixApp::init() setApplicationName("Kiwix"); setDesktopFileName("kiwix.desktop"); - - QFile styleFile(":/css/style.css"); - styleFile.open(QIODevice::ReadOnly); - auto byteContent = styleFile.readAll(); - QString style(byteContent); - setStyleSheet(style); - + setStyleSheet(parseStyleFromFile(":/css/style.css")); createAction(); mp_mainWindow = new MainWindow; @@ -474,3 +468,12 @@ void KiwixApp::printVersions(std::ostream& out) { out << std::endl; zim::printVersions(out); } + +QString KiwixApp::parseStyleFromFile(QString filePath) +{ + QFile file(filePath); + file.open(QFile::ReadOnly); + QString styleSheet = QString(file.readAll()); + file.close(); + return styleSheet; +} diff --git a/src/kiwixapp.h b/src/kiwixapp.h index 212f1680..4a4befbb 100644 --- a/src/kiwixapp.h +++ b/src/kiwixapp.h @@ -86,6 +86,7 @@ class KiwixApp : public QtSingleApplication QString getText(const QString &key) { return m_translation.getText(key); }; void setMonitorDir(const QString &dir); bool isCurrentArticleBookmarked(); + QString parseStyleFromFile(QString filePath); public slots: void openZimFile(const QString& zimfile=""); diff --git a/src/kiwixchoicebox.cpp b/src/kiwixchoicebox.cpp index 9fa4c65b..8e6b2248 100644 --- a/src/kiwixchoicebox.cpp +++ b/src/kiwixchoicebox.cpp @@ -18,10 +18,7 @@ KiwixChoiceBox::KiwixChoiceBox(QWidget *parent) : ui(new Ui::kiwixchoicebox) { ui->setupUi(this); - - QFile file(QString::fromUtf8(":/css/choiceBox.css")); - file.open(QFile::ReadOnly); - QString styleSheet = QString(file.readAll()); + auto styleSheet = KiwixApp::instance()->parseStyleFromFile(":/css/choiceBox.css"); this->setStyleSheet(styleSheet); ui->clearButton->setText(gt("clear")); ui->clearButton->setToolTip(gt("clear-filter")); diff --git a/src/kiwixconfirmbox.cpp b/src/kiwixconfirmbox.cpp index 094339a1..d855669e 100644 --- a/src/kiwixconfirmbox.cpp +++ b/src/kiwixconfirmbox.cpp @@ -9,13 +9,7 @@ KiwixConfirmBox::KiwixConfirmBox(QString confirmTitle, QString confirmText, bool { ui->setupUi(this); setWindowFlag(Qt::FramelessWindowHint, true); - - QFile styleFile(":/css/confirmBox.css"); - styleFile.open(QIODevice::ReadOnly); - auto byteContent = styleFile.readAll(); - styleFile.close(); - QString style(byteContent); - setStyleSheet(style); + setStyleSheet(KiwixApp::instance()->parseStyleFromFile(":/css/confirmBox.css")); connect(ui->yesButton, &QPushButton::clicked, [=]() { emit yesClicked(); }); diff --git a/src/searchbar.cpp b/src/searchbar.cpp index d82a688e..c7a643c0 100644 --- a/src/searchbar.cpp +++ b/src/searchbar.cpp @@ -71,12 +71,7 @@ SearchBar::SearchBar(QWidget *parent) : m_completer.setMaxVisibleItems(16); setCompleter(&m_completer); - QFile styleFile(":/css/popup.css"); - styleFile.open(QIODevice::ReadOnly); - auto byteContent = styleFile.readAll(); - styleFile.close(); - QString style(byteContent); - m_completer.popup()->setStyleSheet(style); + m_completer.popup()->setStyleSheet(KiwixApp::instance()->parseStyleFromFile(":/css/popup.css")); qRegisterMetaType>("QVector"); connect(mp_typingTimer, &QTimer::timeout, this, &SearchBar::updateCompletion); diff --git a/src/settingsview.cpp b/src/settingsview.cpp index 30f608b0..7b59b1a0 100644 --- a/src/settingsview.cpp +++ b/src/settingsview.cpp @@ -9,10 +9,7 @@ SettingsView::SettingsView(QWidget *parent) , ui(new Ui::Settings) { ui->setupUi(this); - QFile file(QString::fromUtf8(":/css/_settingsManager.css")); - file.open(QFile::ReadOnly); - QString styleSheet = QString(file.readAll()); - ui->widget->setStyleSheet(styleSheet); + ui->widget->setStyleSheet(KiwixApp::instance()->parseStyleFromFile(":/css/_settingsManager.css")); connect(ui->zoomPercentSpinBox, QOverload::of(&QSpinBox::valueChanged), this, &SettingsView::setZoom); connect(ui->moveToTrashToggle, &QCheckBox::clicked, this, &SettingsView::setMoveToTrash); connect(ui->browseButton, &QPushButton::clicked, this, &SettingsView::browseDownloadDir); From f61635e7ca10133d7e4673659d64f1e13fab2bb7 Mon Sep 17 00:00:00 2001 From: Nikhil Tanwar <2002nikhiltanwar@gmail.com> Date: Sun, 1 Oct 2023 12:06:12 +0530 Subject: [PATCH 17/17] Save filter settings with their keys Now, the filter settings (language, category and content type) are saved as: keys|values in QSettings. --- src/contentmanager.cpp | 24 +++++++++++++++++------ src/contentmanager.h | 7 ++++--- src/contentmanagerside.cpp | 8 ++++---- src/contentmanagerside.h | 1 + src/kiwixchoicebox.cpp | 29 +++++++++++++++------------- src/kiwixchoicebox.h | 8 ++++---- src/settingsmanager.cpp | 39 +++++++++++++++++++++++++++++--------- src/settingsmanager.h | 27 ++++++++++++++------------ 8 files changed, 92 insertions(+), 51 deletions(-) diff --git a/src/contentmanager.cpp b/src/contentmanager.cpp index 4a83d7cc..c71ef8e2 100644 --- a/src/contentmanager.cpp +++ b/src/contentmanager.cpp @@ -619,8 +619,12 @@ QStringList ContentManager::getDownloadIds() return list; } -void ContentManager::setCurrentLanguage(QStringList languageList) +void ContentManager::setCurrentLanguage(FilterList langPairList) { + QStringList languageList; + for (auto &langPair : langPairList) { + languageList.append(langPair.second); + } languageList.sort(); for (auto &language : languageList) { if (language.length() == 2) { @@ -634,25 +638,33 @@ void ContentManager::setCurrentLanguage(QStringList languageList) if (m_currentLanguage == newLanguage) return; m_currentLanguage = newLanguage; - KiwixApp::instance()->getSettingsManager()->setLanguage(languageList); + KiwixApp::instance()->getSettingsManager()->setLanguage(langPairList); emit(currentLangChanged()); emit(filterParamsChanged()); } -void ContentManager::setCurrentCategoryFilter(QStringList categoryList) +void ContentManager::setCurrentCategoryFilter(FilterList categoryPairList) { + QStringList categoryList; + for (auto &catPair : categoryPairList) { + categoryList.append(catPair.second); + } categoryList.sort(); if (m_categoryFilter == categoryList.join(",")) return; m_categoryFilter = categoryList.join(","); - KiwixApp::instance()->getSettingsManager()->setCategory(categoryList); + KiwixApp::instance()->getSettingsManager()->setCategory(categoryPairList); emit(filterParamsChanged()); } -void ContentManager::setCurrentContentTypeFilter(QStringList contentTypeFilters) +void ContentManager::setCurrentContentTypeFilter(FilterList contentTypeFiltersPairList) { + QStringList contentTypeFilters; + for (auto &ctfPair : contentTypeFiltersPairList) { + contentTypeFilters.append(ctfPair.second); + } m_contentTypeFilters = contentTypeFilters; - KiwixApp::instance()->getSettingsManager()->setContentType(m_contentTypeFilters); + KiwixApp::instance()->getSettingsManager()->setContentType(contentTypeFiltersPairList); emit(filterParamsChanged()); } diff --git a/src/contentmanager.h b/src/contentmanager.h index 2fbd87d2..b7f1051d 100644 --- a/src/contentmanager.h +++ b/src/contentmanager.h @@ -19,15 +19,16 @@ class ContentManager : public QObject public: typedef QList> LanguageList; + typedef QList> FilterList; explicit ContentManager(Library* library, kiwix::Downloader *downloader, QObject *parent = nullptr); virtual ~ContentManager() {} ContentManagerView* getView() { return mp_view; } void setLocal(bool local); QStringList getDownloadIds(); - void setCurrentLanguage(QStringList languageList); - void setCurrentCategoryFilter(QStringList category); - void setCurrentContentTypeFilter(QStringList contentTypeFilter); + void setCurrentLanguage(FilterList languageList); + void setCurrentCategoryFilter(FilterList category); + void setCurrentContentTypeFilter(FilterList contentTypeFilter); bool isLocal() const { return m_local; } QStringList getCategories() const { return m_categories; } LanguageList getLanguages() const { return m_languages; } diff --git a/src/contentmanagerside.cpp b/src/contentmanagerside.cpp index 3b6fb5f4..0bde3a96 100644 --- a/src/contentmanagerside.cpp +++ b/src/contentmanagerside.cpp @@ -50,7 +50,7 @@ ContentManagerSide::ContentManagerSide(QWidget *parent) : KiwixApp::instance()->getContentManager()->setSearch(searcher->text()); }); - QList> contentTypeList = { + FilterList contentTypeList = { {"_pictures:yes", gt("pictures")}, {"_pictures:no", gt("no-pictures")}, {"_videos:yes", gt("videos")}, @@ -79,13 +79,13 @@ void ContentManagerSide::setContentManager(ContentManager *contentManager) const auto checkedButton = mp_ui->buttonGroup->button(isLocal == CatalogButtonId::LOCAL); checkedButton->setChecked(true); checkedButton->setStyleSheet("*{font-weight: bold}"); - connect(mp_languages, &KiwixChoiceBox::choiceUpdated, this, [=](QStringList values) { + connect(mp_languages, &KiwixChoiceBox::choiceUpdated, this, [=](FilterList values) { mp_contentManager->setCurrentLanguage(values); }); - connect(mp_categories, &KiwixChoiceBox::choiceUpdated, this, [=](QStringList values) { + connect(mp_categories, &KiwixChoiceBox::choiceUpdated, this, [=](FilterList values) { mp_contentManager->setCurrentCategoryFilter(values); }); - connect(mp_contentType, &KiwixChoiceBox::choiceUpdated, this, [=](QStringList values) { + connect(mp_contentType, &KiwixChoiceBox::choiceUpdated, this, [=](FilterList values) { mp_contentManager->setCurrentContentTypeFilter(values); }); } diff --git a/src/contentmanagerside.h b/src/contentmanagerside.h index 69c9ced0..a751f616 100644 --- a/src/contentmanagerside.h +++ b/src/contentmanagerside.h @@ -12,6 +12,7 @@ class contentmanagerside; } class KiwixChoiceBox; +using FilterList = ContentManager::FilterList; class ContentManagerSide : public QWidget { diff --git a/src/kiwixchoicebox.cpp b/src/kiwixchoicebox.cpp index 8e6b2248..68841837 100644 --- a/src/kiwixchoicebox.cpp +++ b/src/kiwixchoicebox.cpp @@ -226,7 +226,7 @@ QString beautifyString(QString word) return word; } -void KiwixChoiceBox::setSelections(QStringList selections, QStringList defaultSelection) +void KiwixChoiceBox::setSelections(QStringList selections, SelectionList defaultSelection) { SelectionList sList; for (const auto &sel : selections) { @@ -235,15 +235,8 @@ void KiwixChoiceBox::setSelections(QStringList selections, QStringList defaultSe setSelections(sList, defaultSelection); } -void KiwixChoiceBox::setSelections(SelectionList selections, QStringList defaultSelection) +void KiwixChoiceBox::setSelections(SelectionList selections, SelectionList defaultSelection) { - auto prevSelections = choiceSelector->selectedItems(); - for (auto prev : prevSelections) { - QPair prevPair = {prev->data(Qt::UserRole).toString(), prev->text()}; - if (!selections.contains(prevPair)) { - selections.append(prevPair); - } - } clearSelections(); choiceSelector->clear(); for (const auto &selection: selections) @@ -251,10 +244,20 @@ void KiwixChoiceBox::setSelections(SelectionList selections, QStringList default auto item = new KListWidgetItem(beautifyString(selection.second)); item->setData(Qt::UserRole, selection.first); choiceSelector->addItem(item); - if (defaultSelection.contains(selection.first)) { + } + + for (const auto &defSel : defaultSelection) { + auto itemList = choiceSelector->findItems(defSel.first, Qt::MatchExactly); + if (itemList.isEmpty()) { + auto item = new KListWidgetItem(defSel.first); + item->setData(Qt::UserRole, defSel.second); + choiceSelector->addItem(item); addSelection(item, false); + } else { + addSelection(itemList[0], false); } } + if (choiceSelector->selectedItems().isEmpty()) showPlaceholder(); choiceSelector->setVisibleItems(choiceSelector->count()); @@ -277,11 +280,11 @@ void KiwixChoiceBox::setType(QString type) m_type = type; } -QStringList KiwixChoiceBox::getCurrentSelected() +KiwixChoiceBox::SelectionList KiwixChoiceBox::getCurrentSelected() { - QStringList selections; + SelectionList selections; for (auto &item : choiceSelector->selectedItems()) { - selections.append(item->data(Qt::UserRole).toString()); + selections.append({item->text(), item->data(Qt::UserRole).toString()}); } return selections; } diff --git a/src/kiwixchoicebox.h b/src/kiwixchoicebox.h index 25a35886..18cc8cb0 100644 --- a/src/kiwixchoicebox.h +++ b/src/kiwixchoicebox.h @@ -29,8 +29,8 @@ class KiwixChoiceBox : public QWidget public: explicit KiwixChoiceBox(QWidget *parent = nullptr); void setType(QString type); - void setSelections(SelectionList selections, QStringList defaultSelection); - void setSelections(QStringList selections, QStringList defaultSelection); + void setSelections(SelectionList selections, SelectionList defaultSelection); + void setSelections(QStringList selections, SelectionList defaultSelection); ~KiwixChoiceBox(); void adjustSize(); @@ -39,7 +39,7 @@ class KiwixChoiceBox : public QWidget void mousePressEvent(QMouseEvent *event) override; signals: - void choiceUpdated(QStringList); + void choiceUpdated(SelectionList); void clicked(); private: @@ -49,7 +49,7 @@ class KiwixChoiceBox : public QWidget KiwixListWidget *choiceSelector; FlowLayout *currentChoicesLayout; KiwixLineEdit *searcher; - QStringList getCurrentSelected(); + SelectionList getCurrentSelected(); bool removeSelection(QListWidgetItem *item); void clearSelections(); bool addSelection(QListWidgetItem *item, bool updateRequired = true); diff --git a/src/settingsmanager.cpp b/src/settingsmanager.cpp index 4e5e5642..b77657e6 100644 --- a/src/settingsmanager.cpp +++ b/src/settingsmanager.cpp @@ -98,23 +98,43 @@ void SettingsManager::setMoveToTrash(bool moveToTrash) emit(moveToTrashChanged(m_moveToTrash)); } -void SettingsManager::setLanguage(QStringList langList) +QList SettingsManager::flattenPair(FilterList pairList) { - m_langList = langList; + QList res; + for (auto &pair : pairList) { + res.push_back(pair.first+"|"+pair.second); + } + return res; +} + +SettingsManager::FilterList SettingsManager::deducePair(QList variantList) +{ + FilterList pairList; + for (auto &variant : variantList) { + QString str = variant.toString(); + auto pairs = str.split('|'); + pairList.push_back({pairs[0], pairs[1]}); + } + return pairList; +} + +void SettingsManager::setLanguage(FilterList langList) +{ + m_langList = flattenPair(langList); setSettings("language", m_langList); emit(languageChanged(m_langList)); } -void SettingsManager::setCategory(QStringList categoryList) +void SettingsManager::setCategory(FilterList categoryList) { - m_categoryList = categoryList; + m_categoryList = flattenPair(categoryList); setSettings("category", m_categoryList); emit(categoryChanged(m_categoryList)); } -void SettingsManager::setContentType(QStringList contentTypeList) +void SettingsManager::setContentType(FilterList contentTypeList) { - m_contentTypeList = contentTypeList; + m_contentTypeList = flattenPair(contentTypeList); setSettings("contentType", m_contentTypeList); emit(contentTypeChanged(m_contentTypeList)); } @@ -127,7 +147,8 @@ void SettingsManager::initSettings() m_kiwixServerIpAddress = m_settings.value("localKiwixServer/ipAddress", QString("0.0.0.0")).toString(); m_monitorDir = m_settings.value("monitor/dir", QString("")).toString(); m_moveToTrash = m_settings.value("moveToTrash", true).toBool(); - m_langList = m_settings.value("language", QLocale::languageToString(QLocale().language())).toStringList(); - m_categoryList = m_settings.value("category", {}).toStringList(); - m_contentTypeList = m_settings.value("contentType", {}).toStringList(); + QVariant defaultLang = QVariant::fromValue(QLocale::languageToString(QLocale().language()) + '|' + QLocale().name().split("_").at(0)); + m_langList = m_settings.value("language", {defaultLang}).toList(); + m_categoryList = m_settings.value("category", {}).toList(); + m_contentTypeList = m_settings.value("contentType", {}).toList(); } diff --git a/src/settingsmanager.h b/src/settingsmanager.h index 5f18f345..5646008d 100644 --- a/src/settingsmanager.h +++ b/src/settingsmanager.h @@ -13,6 +13,7 @@ class SettingsManager : public QObject Q_PROPERTY(QString downloadDir MEMBER m_downloadDir WRITE setDownloadDir NOTIFY downloadDirChanged) public: + typedef QList> FilterList; explicit SettingsManager(QObject *parent = nullptr); virtual ~SettingsManager() {}; @@ -28,9 +29,9 @@ class SettingsManager : public QObject QString getDownloadDir() const { return m_downloadDir; } QString getMonitorDir() const { return m_monitorDir; } bool getMoveToTrash() const { return m_moveToTrash; } - QStringList getLanguageList() const { return m_langList; } - QStringList getCategoryList() const { return m_categoryList; } - QStringList getContentType() const { return m_contentTypeList; } + FilterList getLanguageList() { return deducePair(m_langList); } + FilterList getCategoryList() { return deducePair(m_categoryList); } + FilterList getContentType() { return deducePair(m_contentTypeList); } public slots: void setKiwixServerPort(int port); @@ -39,11 +40,13 @@ public slots: void setDownloadDir(QString downloadDir); void setMonitorDir(QString monitorDir); void setMoveToTrash(bool moveToTrash); - void setLanguage(QStringList langList); - void setCategory(QStringList categoryList); - void setContentType(QStringList contentTypeList); + void setLanguage(FilterList langList); + void setCategory(FilterList categoryList); + void setContentType(FilterList contentTypeList); private: void initSettings(); + QList flattenPair(FilterList pairList); + FilterList deducePair(QList); signals: void portChanged(int port); @@ -51,9 +54,9 @@ public slots: void downloadDirChanged(QString downloadDir); void monitorDirChanged(QString monitorDir); void moveToTrashChanged(bool moveToTrash); - void languageChanged(QStringList langList); - void categoryChanged(QStringList categoryList); - void contentTypeChanged(QStringList contentTypeList); + void languageChanged(QList langList); + void categoryChanged(QList categoryList); + void contentTypeChanged(QList contentTypeList); private: QSettings m_settings; @@ -64,9 +67,9 @@ public slots: QString m_downloadDir; QString m_monitorDir; bool m_moveToTrash; - QStringList m_langList; - QStringList m_categoryList; - QStringList m_contentTypeList; + QList m_langList; + QList m_categoryList; + QList m_contentTypeList; }; #endif // SETTINGSMANAGER_H