Merge pull request #110 from kiwix/language_filtering

Language filtering
This commit is contained in:
Matthieu Gautier 2019-03-06 18:48:56 +01:00 committed by GitHub
commit 0824c86c91
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 403 additions and 67 deletions

View File

@ -58,7 +58,8 @@ SOURCES += \
src/contentmanagerview.cpp \
src/tabbar.cpp \
src/contentmanagerside.cpp \
src/readinglistbar.cpp
src/readinglistbar.cpp \
src/klistwidgetitem.cpp
HEADERS += \
src/mainwindow.h \
@ -78,7 +79,8 @@ HEADERS += \
src/contentmanagerview.h \
src/tabbar.h \
src/contentmanagerside.h \
src/readinglistbar.h
src/readinglistbar.h \
src/klistwidgetitem.h
FORMS += \
ui/mainwindow.ui \

View File

@ -200,7 +200,6 @@ QTabBar::close-button {
border: none;
}
#contentmanagerside QRadioButton::indicator {
image: none;
}
@ -209,6 +208,28 @@ QTabBar::close-button {
image: none;
}
#contentmanagerside QListWidget {
border: none;
padding-left: 30px;
show-decoration-selected: 0;
}
#languageSelector QScrollBar {
width: 5px;
border: none;
outline: none;
}
#languageSelector QScrollBar::handle {
background-color: grey;
}
#languageSelector::item:selected {
background-color: white;
color: black;
outline: none;
}
#readinglistbar QListWidget {
border: none;
}

View File

@ -34,6 +34,7 @@ function onBooksChanged () {
var id = contentManager.bookIds[i];
contentManager.getBookInfos(id, BOOK_KEYS, addBook);
}
app.displayedBooksNb = 20;
}
downloadUpdaters = {}
@ -59,6 +60,7 @@ function init() {
el: "#app",
data: {
contentManager: contentManager,
displayedBooksNb: 20,
books: [],
downloads: {}
},
@ -72,6 +74,10 @@ function init() {
downloadUpdaters[book.id] = setInterval(function() { getDownloadInfo(book.id); }, 1000);
});
},
displayedBooks : function(books, nb) {
var a = books.slice(0, nb);
return a;
},
niceBytes : niceBytes
}
});
@ -85,11 +91,25 @@ function setSearch(value) {
clearTimeout(futurCall);
futurCall = setTimeout(function(){contentManager.setSearch(value)}, 100);
}
function scrolled(e) {
if (e.offsetHeight + e.scrollTop >= e.scrollHeight) {
app.displayedBooksNb = Math.min(app.displayedBooksNb+20, app.books.length);
}
}
</script>
<style>
body {
padding: 0;
html, body {
padding: 0;
margin: 0;
height: 100%;
position: relative;
width: 100%;
overflow: hidden;
}
#app {
height: 100%;
position: relative;
}
*:focus {
outline: none;
@ -106,9 +126,21 @@ padding: 0;
width: 90%;
border: 1px solid #EEE;
}
#bookList {
width:100%;
#bookTable {
position: relative;
height: calc(100% - 42px); /* 42px = 40px(height of #searchInput) + 2px(border) */
width: 100%;
}
#bookList {
height: calc(100% - 19px - 20px); /*19px the header size, 20px the header margin-top */
overflow-y:scroll;
overflow-x:hidden;
position: relative;
width: 100%
}
.tablerow,
.header {
display: flex;
@ -181,7 +213,7 @@ details:hover {
<input id="searchInput" type="text" placeholder="Search files" oninput="setSearch(this.value)"/>
</form>
</div>
<div id="bookList">
<div id="bookTable">
<div class="header">
<span class="tablecell cell0"></span>
<span class="tablecell cell1">File name</span>
@ -190,38 +222,40 @@ details:hover {
<span class="tablecell cell4">Content type</span>
<span class="tablecell cell5"></span>
</div>
<details v-for="book in books" class="book">
<summary class="tablerow">
<span class="tablecell cell0">
<img v-if="book.faviconUrl" v-bind:src="'http://' + book.faviconUrl" />
<img v-else-if="book.faviconMimeType" v-bind:src="'zim://' + book.id + '.favicon.meta'" />
</span>
<span class="tablecell cell1">
{{ book.title }}
</span>
<span class="tablecell cell2">
{{ niceBytes(book.size) }}
</span>
<span class="tablecell cell3">
{{ book.date }}
</span>
<span class="tablecell cell4">
{{ book.tags }}
</span>
<span class="tablecell cell5">
<template v-if="book.downloadId">
<span v-if="downloads[book.id]">
{{ niceBytes(downloads[book.id].completedLength) }} / {{ niceBytes(downloads[book.id].totalLength) }}
</span>
</template>
<button v-else-if="book.path" v-on:click="openBook(book)">Open</button>
<button v-else v-on:click="downloadBook(book)">Download</button>
</span>
</summary>
<p class="content">
{{ book.description }}
</p>
</details>
<div id="bookList" onscroll=scrolled(this)>
<details v-for="book in displayedBooks(books, displayedBooksNb)" class="book">
<summary class="tablerow">
<span class="tablecell cell0">
<img v-if="book.faviconUrl" v-bind:src="'http://' + book.faviconUrl" />
<img v-else-if="book.faviconMimeType" v-bind:src="'zim://' + book.id + '.favicon.meta'" />
</span>
<span class="tablecell cell1">
{{ book.title }}
</span>
<span class="tablecell cell2">
{{ niceBytes(book.size) }}
</span>
<span class="tablecell cell3">
{{ book.date }}
</span>
<span class="tablecell cell4">
{{ book.tags }}
</span>
<span class="tablecell cell5">
<template v-if="book.downloadId">
<span v-if="downloads[book.id]">
{{ niceBytes(downloads[book.id].completedLength) }} / {{ niceBytes(downloads[book.id].totalLength) }}
</span>
</template>
<button v-else-if="book.path" v-on:click="openBook(book)">Open</button>
<button v-else v-on:click="downloadBook(book)">Download</button>
</span>
</summary>
<p class="content">
{{ book.description }}
</p>
</details>
</div>
</div>
</div>
</body></html>

View File

@ -212,13 +212,16 @@ void ContentManager::setCurrentLanguage(QString language)
}
m_currentLanguage = language;
emit(currentLangChanged());
emit(remoteParamsChanged());
}
#define CATALOG_HOST "library.kiwix.org"
#define CATALOG_PORT 80
void ContentManager::updateRemoteLibrary() {
QUrlQuery query;
query.addQueryItem("lang", m_currentLanguage);
if (m_currentLanguage != "*") {
query.addQueryItem("lang", m_currentLanguage);
}
query.addQueryItem("count", QString::number(0));
QUrl url;
url.setScheme("http");

View File

@ -22,6 +22,7 @@ public:
ContentManagerView* getView() { return mp_view; }
void setLocal(bool local);
QStringList getDownloadIds();
void setCurrentLanguage(QString language);
private:
Library* mp_library;
kiwix::Library m_remoteLibrary;
@ -30,7 +31,7 @@ private:
bool m_local = true;
QString m_currentLanguage;
QString m_searchQuery;
void setCurrentLanguage(QString language);
QStringList getBookIds();

View File

@ -1,6 +1,10 @@
#include "contentmanagerside.h"
#include "ui_contentmanagerside.h"
#include <QLocale>
#include "klistwidgetitem.h"
ContentManagerSide::ContentManagerSide(QWidget *parent) :
QWidget(parent),
mp_ui(new Ui::contentmanagerside)
@ -17,9 +21,201 @@ ContentManagerSide::ContentManagerSide(QWidget *parent) :
this, [=](bool checked) { mp_ui->localFileButton->setStyleSheet(
checked ?"*{font-weight: bold}" : "");});
mp_ui->localFileButton->setStyleSheet("*{font-weight: bold}");
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);
for (auto lang:
{
QLocale::AnyLanguage,
QLocale::Afar,
QLocale::Afrikaans,
QLocale::Akan,
QLocale::Amharic,
QLocale::Arabic,
QLocale::Assamese,
QLocale::Azerbaijani,
QLocale::Bashkir,
QLocale::Belarusian,
QLocale::Bulgarian,
QLocale::Bambara,
QLocale::Bengali,
QLocale::Tibetan,
QLocale::Breton,
QLocale::Bosnian,
QLocale::Catalan,
QLocale::Chechen,
QLocale::Corsican,
QLocale::Czech,
QLocale::Church,
QLocale::Chuvash,
QLocale::Welsh,
QLocale::Danish,
QLocale::German,
QLocale::Divehi,
QLocale::Dzongkha,
QLocale::Ewe,
QLocale::Greek,
QLocale::English,
QLocale::Spanish,
QLocale::Estonian,
QLocale::Basque,
QLocale::Persian,
QLocale::Fulah,
QLocale::Finnish,
QLocale::Faroese,
QLocale::French,
QLocale::WesternFrisian,
QLocale::Irish,
QLocale::Gaelic,
QLocale::Galician,
QLocale::Guarani,
QLocale::Gujarati,
QLocale::Manx,
QLocale::Hausa,
QLocale::Hebrew,
QLocale::Hindi,
QLocale::Croatian,
QLocale::Hungarian,
QLocale::Armenian,
QLocale::Interlingua,
QLocale::Indonesian,
QLocale::Igbo,
QLocale::Icelandic,
QLocale::Italian,
QLocale::Inuktitut,
QLocale::Japanese,
QLocale::Javanese,
QLocale::Georgian,
QLocale::Kikuyu,
QLocale::Kazakh,
QLocale::Greenlandic,
QLocale::Khmer,
QLocale::Kannada,
QLocale::Korean,
QLocale::Kashmiri,
QLocale::Kurdish,
QLocale::Cornish,
QLocale::Kirghiz,
QLocale::Luxembourgish,
QLocale::Ganda,
QLocale::Lingala,
QLocale::Lao,
QLocale::Lithuanian,
QLocale::Latvian,
QLocale::Malagasy,
QLocale::Maori,
QLocale::Maori,
QLocale::Macedonian,
QLocale::Malayalam,
QLocale::Mongolian,
QLocale::Marathi,
QLocale::Malay,
QLocale::Maltese,
QLocale::Burmese,
QLocale::Nepali,
QLocale::Dutch,
QLocale::NorwegianNynorsk,
QLocale::NorwegianBokmal,
QLocale::Nyanja,
QLocale::Occitan,
QLocale::Oromo,
QLocale::Oriya,
QLocale::Ossetic,
QLocale::Punjabi,
QLocale::Polish,
QLocale::Pashto,
QLocale::Portuguese,
QLocale::Quechua,
QLocale::Romansh,
QLocale::Rundi,
QLocale::Romanian,
QLocale::Russian,
QLocale::Kinyarwanda,
QLocale::Sanskrit,
QLocale::Sindhi,
QLocale::NorthernSami,
QLocale::Sango,
QLocale::Sinhala,
QLocale::Slovak,
QLocale::Slovenian,
QLocale::Shona,
QLocale::Somali,
QLocale::Albanian,
QLocale::Serbian,
QLocale::Swati,
QLocale::SouthernSotho,
QLocale::Swedish,
QLocale::Swahili,
QLocale::Tamil,
QLocale::Telugu,
QLocale::Tajik,
QLocale::Thai,
QLocale::Tigrinya,
QLocale::Turkmen,
QLocale::Filipino,
QLocale::Tswana,
QLocale::Tongan,
QLocale::Turkish,
QLocale::Tsonga,
QLocale::Tatar,
QLocale::Uighur,
QLocale::Ukrainian,
QLocale::Urdu,
QLocale::Uzbek,
QLocale::Venda,
QLocale::Vietnamese,
QLocale::Walloon,
QLocale::Wolof,
QLocale::Xhosa,
QLocale::Yoruba,
QLocale::Chinese,
QLocale::Zulu,
})
{
auto currentLang = QLocale().language();
if (lang == QLocale::AnyLanguage) {
auto item = new KListWidgetItem("All");
item->setData(Qt::UserRole, lang);
mp_languageSelector->addItem(item);
continue;
}
auto locale = QLocale(lang);
if (locale.language() != lang) {
// Qt may not find the locale for the lang :/
// In this case, Qt return the current locale
// So we must be sure that the locale found correspond to the lang we want to add,
// else we may add several time the current language.
continue;
}
auto item = new KListWidgetItem(QLocale::languageToString(locale.language()));
item->setData(Qt::UserRole, lang);
mp_languageSelector->addItem(item);
if (lang == currentLang) {
item->setSelected(true);
}
}
}
ContentManagerSide::~ContentManagerSide()
{
delete mp_ui;
}
void ContentManagerSide::setContentManager(ContentManager *contentManager)
{
mp_contentManager = contentManager;
connect(mp_languageSelector, &QListWidget::itemSelectionChanged,
this, [=]() {
auto item = mp_languageSelector->selectedItems().at(0);
if (!item) return;
auto lang = QLocale::Language(item->data(Qt::UserRole).toInt());
if (lang == QLocale::AnyLanguage) {
mp_contentManager->setCurrentLanguage("*");
return;
}
auto locale = QLocale(QLocale::Language(item->data(Qt::UserRole).toInt()));
mp_contentManager->setCurrentLanguage(locale.name().split("_").at(0));});
}

View File

@ -2,6 +2,8 @@
#define CONTENTMANAGERSIDE_H
#include <QWidget>
#include <QListWidget>
#include <QCheckBox>
#include "contentmanager.h"
namespace Ui {
@ -16,11 +18,13 @@ public:
explicit ContentManagerSide(QWidget *parent = 0);
~ContentManagerSide();
void setContentManager(ContentManager* contentManager) { mp_contentManager = contentManager; }
void setContentManager(ContentManager* contentManager);
private:
Ui::contentmanagerside *mp_ui;
ContentManager* mp_contentManager;
QCheckBox* mp_languageButton;
QListWidget* mp_languageSelector;
};
#endif // CONTENTMANAGERSIDE_H

View File

@ -10,6 +10,12 @@
<height>366</height>
</rect>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="windowTitle">
<string>Form</string>
</property>
@ -37,10 +43,13 @@
<property name="flat">
<bool>true</bool>
</property>
<layout class="QVBoxLayout" name="verticalLayout_2">
<layout class="QVBoxLayout" name="verticalLayout_2" stretch="0,0,0,0,0,0,1">
<property name="spacing">
<number>0</number>
</property>
<property name="sizeConstraint">
<enum>QLayout::SetMinimumSize</enum>
</property>
<property name="leftMargin">
<number>0</number>
</property>
@ -70,6 +79,50 @@
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="languageButton">
<property name="text">
<string>Browse By Language</string>
</property>
</widget>
</item>
<item>
<widget class="QListWidget" name="languageSelector">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>1</verstretch>
</sizepolicy>
</property>
<property name="cursor" stdset="0">
<cursorShape>ArrowCursor</cursorShape>
</property>
<property name="frameShape">
<enum>QFrame::NoFrame</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Plain</enum>
</property>
<property name="lineWidth">
<number>0</number>
</property>
<property name="verticalScrollBarPolicy">
<enum>Qt::ScrollBarAlwaysOn</enum>
</property>
<property name="horizontalScrollBarPolicy">
<enum>Qt::ScrollBarAlwaysOff</enum>
</property>
<property name="sizeAdjustPolicy">
<enum>QAbstractScrollArea::AdjustToContents</enum>
</property>
<property name="selectionBehavior">
<enum>QAbstractItemView::SelectItems</enum>
</property>
<property name="verticalScrollMode">
<enum>QAbstractItemView::ScrollPerPixel</enum>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="categoryButton">
<property name="enabled">
@ -80,16 +133,6 @@
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="languageButton">
<property name="enabled">
<bool>false</bool>
</property>
<property name="text">
<string>Language</string>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="contentTypeButton">
<property name="enabled">
@ -100,22 +143,22 @@
</property>
</widget>
</item>
<item>
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
</item>
<item>
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
<resources/>

19
src/klistwidgetitem.cpp Normal file
View File

@ -0,0 +1,19 @@
#include "klistwidgetitem.h"
KListWidgetItem::KListWidgetItem(QString text)
: QListWidgetItem (text)
{
}
QVariant KListWidgetItem::data(int role) const
{
QVariant v = QListWidgetItem::data(role);
if( isSelected() && role == Qt::FontRole )
{
QFont font = v.value<QFont>();
font.setBold( true );
v = QVariant::fromValue<QFont>( font );
}
return v;
}

13
src/klistwidgetitem.h Normal file
View File

@ -0,0 +1,13 @@
#ifndef KLISTWIDGETITEM_H
#define KLISTWIDGETITEM_H
#include <QListWidgetItem>
class KListWidgetItem : public QListWidgetItem
{
public:
KListWidgetItem(QString text);
QVariant data(int role) const;
};
#endif // KLISTWIDGETITEM_H