diff --git a/kiwix-desktop.pro b/kiwix-desktop.pro index ba0ae1c..4aa3d58 100644 --- a/kiwix-desktop.pro +++ b/kiwix-desktop.pro @@ -41,6 +41,7 @@ DEFINES += QT_DEPRECATED_WARNINGS SOURCES += \ + src/contenttypefilter.cpp \ src/findinpagebar.cpp \ src/translation.cpp \ src/main.cpp \ @@ -72,6 +73,7 @@ SOURCES += \ src/static_content.cpp HEADERS += \ + src/contenttypefilter.h \ src/findinpagebar.h \ src/translation.h \ src/mainwindow.h \ diff --git a/resources/css/style.css b/resources/css/style.css index 7b4ccc8..99acf4d 100644 --- a/resources/css/style.css +++ b/resources/css/style.css @@ -237,6 +237,10 @@ QTabBar::tab:last QToolButton::hover { show-decoration-selected: 0; } +#contentTypeSelector QCheckBox { + padding: 0; +} + #categorySelector QScrollBar, #languageSelector QScrollBar, #readinglistbar QScrollBar { @@ -258,6 +262,11 @@ QTabBar::tab:last QToolButton::hover { outline: none; } +#contentTypeAllButton, +ContentTypeFilter { + spacing: 10; +} + #readinglistbar QLabel { font-size: 24px; font: bold; diff --git a/resources/i18n/en.json b/resources/i18n/en.json index 904f810..813136f 100644 --- a/resources/i18n/en.json +++ b/resources/i18n/en.json @@ -104,5 +104,12 @@ "wikiversity":"Wikiversity", "wikivoyage":"Wikivoyage", "wiktionary":"Wiktionary", - "fulltext-search":"Fulltext search" + "fulltext-search":"Fulltext search", + "pictures":"Pictures", + "videos":"Videos", + "ftindex":"Fulltext index", + "details":"Full article", + "yes":"yes", + "no":"no", + "no-filter":"no filter" } diff --git a/src/contentmanager.cpp b/src/contentmanager.cpp index 6839157..5185d12 100644 --- a/src/contentmanager.cpp +++ b/src/contentmanager.cpp @@ -345,6 +345,12 @@ void ContentManager::setCurrentCategoryFilter(QString category) emit(filterParamsChanged()); } +void ContentManager::setCurrentContentTypeFilter(QList& contentTypeFilters) +{ + m_contentTypeFilters = contentTypeFilters; + emit(filterParamsChanged()); +} + void ContentManager::updateLibrary() { if (m_local) { emit(pendingRequest(false)); @@ -378,7 +384,6 @@ QStringList ContentManager::getBookIds() std::vector tags; if (m_categoryFilter != "all" && m_categoryFilter != "other") { tags.push_back("_category:"+m_categoryFilter.toStdString()); - filter.acceptTags(tags); } if (m_categoryFilter == "other") { for (auto& category: S_CATEGORIES) { @@ -388,6 +393,18 @@ QStringList ContentManager::getBookIds() } filter.rejectTags(tags); } + + for (auto &contentTypeFilter : m_contentTypeFilters) { + auto state = contentTypeFilter->checkState(); + auto filter = contentTypeFilter->getName(); + if (state == Qt::PartiallyChecked) { + tags.push_back("_" + filter.toStdString() +":yes"); + } else if (state == Qt::Checked) { + tags.push_back("_" + filter.toStdString() +":no"); + } + } + + filter.acceptTags(tags); filter.query(m_searchQuery.toStdString()); if (m_local) { diff --git a/src/contentmanager.h b/src/contentmanager.h index f778423..eac25e0 100644 --- a/src/contentmanager.h +++ b/src/contentmanager.h @@ -7,6 +7,7 @@ #include "contentmanagerview.h" #include #include "opdsrequestmanager.h" +#include "contenttypefilter.h" class ContentManager : public QObject { @@ -25,6 +26,7 @@ public: QStringList getDownloadIds(); void setCurrentLanguage(QString language); void setCurrentCategoryFilter(QString category); + void setCurrentContentTypeFilter(QList& contentTypeFilter); private: Library* mp_library; @@ -36,6 +38,7 @@ private: QString m_currentLanguage; QString m_searchQuery; QString m_categoryFilter = "all"; + QList m_contentTypeFilters; kiwix::supportedListSortBy m_sortBy = kiwix::UNSORTED; bool m_sortOrderAsc = true; diff --git a/src/contentmanagerside.cpp b/src/contentmanagerside.cpp index ce472db..e44fca8 100644 --- a/src/contentmanagerside.cpp +++ b/src/contentmanagerside.cpp @@ -28,15 +28,58 @@ ContentManagerSide::ContentManagerSide(QWidget *parent) : 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_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_ui->contentTypeButton->hide(); + + 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: bold}"); + connect(mp_ui->contentTypeAllButton, &QCheckBox::clicked, this, [=](bool checked) { + Q_UNUSED(checked); + mp_ui->contentTypeAllButton->setStyleSheet("*{font-weight: bold}"); + for (auto &contentTypeFilter : m_contentTypeFilters) { + contentTypeFilter->setCheckState(Qt::Unchecked); + } + mp_contentManager->setCurrentContentTypeFilter(m_contentTypeFilters); + }); + + ContentTypeFilter* videosFilter = new ContentTypeFilter("pictures", this); + ContentTypeFilter* picturesFilter = new ContentTypeFilter("videos", this); + ContentTypeFilter* detailsFilter = new ContentTypeFilter("details", this); + ContentTypeFilter* ftindexFilter = new ContentTypeFilter("ftindex", this); + m_contentTypeFilters.push_back(videosFilter); + m_contentTypeFilters.push_back(picturesFilter); + m_contentTypeFilters.push_back(detailsFilter); + m_contentTypeFilters.push_back(ftindexFilter); + + 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 ? "" : "*{font-weight: bold}"); + mp_contentManager->setCurrentContentTypeFilter(m_contentTypeFilters); + }); + } for(auto lang: S_LANGUAGES) { @@ -71,7 +114,6 @@ ContentManagerSide::ContentManagerSide(QWidget *parent) : item->setSelected(true); } } - } ContentManagerSide::~ContentManagerSide() @@ -79,7 +121,6 @@ ContentManagerSide::~ContentManagerSide() delete mp_ui; } - void ContentManagerSide::setContentManager(ContentManager *contentManager) { mp_contentManager = contentManager; diff --git a/src/contentmanagerside.h b/src/contentmanagerside.h index 9cfd911..da8dcff 100644 --- a/src/contentmanagerside.h +++ b/src/contentmanagerside.h @@ -5,6 +5,7 @@ #include #include #include "contentmanager.h" +#include "contenttypefilter.h" namespace Ui { class contentmanagerside; @@ -27,6 +28,8 @@ private: QListWidget* mp_languageSelector; QCheckBox* mp_categoryButton; QListWidget* mp_categorySelector; + QCheckBox* mp_contentTypeButton; + QList m_contentTypeFilters; }; #endif // CONTENTMANAGERSIDE_H diff --git a/src/contentmanagerside.ui b/src/contentmanagerside.ui index 74d705f..62346b0 100644 --- a/src/contentmanagerside.ui +++ b/src/contentmanagerside.ui @@ -7,7 +7,7 @@ 0 0 197 - 366 + 368 @@ -23,6 +23,9 @@ 0 + + QLayout::SetMaximumSize + 0 @@ -43,7 +46,7 @@ true - + 0 @@ -64,6 +67,12 @@ + + + 0 + 0 + + All Files @@ -71,6 +80,12 @@ + + + 0 + 0 + + Local Files @@ -81,6 +96,12 @@ + + + 0 + 0 + + Browse By Language @@ -91,7 +112,7 @@ 0 - 1 + 0 @@ -119,6 +140,12 @@ true + + + 0 + 0 + + Browse By Category @@ -129,7 +156,7 @@ 0 - 1 + 0 @@ -151,14 +178,63 @@ - - false + + + 0 + 0 + Content Type + + + + + 0 + 0 + + + + QFrame::NoFrame + + + QFrame::Sunken + + + 0 + + + + 0 + + + 0 + + + 0 + + + + + + 0 + 0 + + + + All + + + false + + + + + + diff --git a/src/contenttypefilter.cpp b/src/contenttypefilter.cpp new file mode 100644 index 0000000..4a10f77 --- /dev/null +++ b/src/contenttypefilter.cpp @@ -0,0 +1,21 @@ +#include "contenttypefilter.h" +#include "kiwixapp.h" + +ContentTypeFilter::ContentTypeFilter(QString name, QWidget *parent) +: QCheckBox(parent), + m_name(name) +{ + setTristate(true); + + m_states[Qt::Unchecked] = gt("no-filter"); + m_states[Qt::PartiallyChecked] = gt("yes"); + m_states[Qt::Checked] = gt("no"); + setText(gt(m_name) + " : " + m_states[checkState()]); + 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 diff --git a/src/contenttypefilter.h b/src/contenttypefilter.h new file mode 100644 index 0000000..ede75b9 --- /dev/null +++ b/src/contenttypefilter.h @@ -0,0 +1,25 @@ +#ifndef CONTENTTYPEFILTER_H +#define CONTENTTYPEFILTER_H + +#include +#include + +class ContentTypeFilter : public QCheckBox +{ + Q_OBJECT + +public: + explicit ContentTypeFilter(QString name, QWidget *parent = nullptr); + virtual ~ContentTypeFilter() {} + + QString getName() { return m_name; } + +public slots: + void onStateChanged(int state); + +private: + QString m_name; + QMap m_states; +}; + +#endif // CONTENTTYPEFILTER_H