mirror of
https://github.com/kiwix/kiwix-desktop.git
synced 2025-09-23 03:58:56 -04:00
Add a basic support for bookmarks.
This commit is contained in:
parent
67d56f1d03
commit
b1b0c1d2c3
@ -57,7 +57,8 @@ SOURCES += \
|
||||
src/contentmanager.cpp \
|
||||
src/contentmanagerview.cpp \
|
||||
src/tabbar.cpp \
|
||||
src/contentmanagerside.cpp
|
||||
src/contentmanagerside.cpp \
|
||||
src/readinglistbar.cpp
|
||||
|
||||
HEADERS += \
|
||||
src/mainwindow.h \
|
||||
@ -76,13 +77,15 @@ HEADERS += \
|
||||
src/contentmanager.h \
|
||||
src/contentmanagerview.h \
|
||||
src/tabbar.h \
|
||||
src/contentmanagerside.h
|
||||
src/contentmanagerside.h \
|
||||
src/readinglistbar.h
|
||||
|
||||
FORMS += \
|
||||
ui/mainwindow.ui \
|
||||
ui/about.ui \
|
||||
src/tocsidebar.ui \
|
||||
src/contentmanagerside.ui
|
||||
src/contentmanagerside.ui \
|
||||
src/readinglistbar.ui
|
||||
|
||||
TRANSLATIONS = "resources/i18n/kiwix-desktop_fr.ts"
|
||||
CODECFORSRC = UTF-8
|
||||
|
@ -193,7 +193,8 @@ QTabBar::close-button {
|
||||
background-color: white;
|
||||
}
|
||||
|
||||
#contentmanagerside QWidget{
|
||||
#contentmanagerside QWidget,
|
||||
#readinglistbar QWidget{
|
||||
background-color: white;
|
||||
outline: none;
|
||||
}
|
||||
@ -210,3 +211,12 @@ QTabBar::close-button {
|
||||
#contentmanagerside QCheckBox::indicator {
|
||||
image: none;
|
||||
}
|
||||
|
||||
#readinglistbar QListWidget {
|
||||
border: none;
|
||||
}
|
||||
|
||||
#readinglistbar QListWidget::item {
|
||||
font-size: 16px;
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
|
@ -173,6 +173,7 @@ void KiwixApp::setSideBar(KiwixApp::SideBarType type)
|
||||
switch(type) {
|
||||
case SEARCH_BAR:
|
||||
case CONTENTMANAGER_BAR:
|
||||
case READINGLIST_BAR:
|
||||
sideDockWidget->setCurrentIndex(type);
|
||||
sideDockWidget->show();
|
||||
break;
|
||||
@ -208,6 +209,20 @@ QAction *KiwixApp::getAction(KiwixApp::Actions action)
|
||||
return mpa_actions[action];
|
||||
}
|
||||
|
||||
bool KiwixApp::isCurrentArticleBookmarked()
|
||||
{
|
||||
auto zimId = getTabWidget()->currentZimId().toStdString();
|
||||
zimId.resize(zimId.length()-4);
|
||||
auto url = getTabWidget()->currentArticleUrl().toStdString();
|
||||
|
||||
for (auto& bookmark: getLibrary()->getBookmarks()) {
|
||||
if (bookmark.getBookId() == zimId && bookmark.getUrl() == url) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
#define CREATE_ACTION_ICON(ID, ICON, TEXT) \
|
||||
mpa_actions[ID] = new QAction(QIcon(":/icons/" ICON ".svg"), TEXT)
|
||||
#define CREATE_ACTION(ID, TEXT) \
|
||||
@ -286,9 +301,17 @@ void KiwixApp::createAction()
|
||||
SET_SHORTCUT(ToggleTOCAction, QKeySequence(Qt::CTRL+Qt::SHIFT+Qt::Key_1));
|
||||
HIDE_ACTION(ToggleTOCAction);
|
||||
|
||||
CREATE_ACTION(ToggleReadingListAction, tr("Reading list"));
|
||||
CREATE_ACTION_ICON(ToggleReadingListAction, "reading-list" ,tr("Reading list"));
|
||||
SET_SHORTCUT(ToggleReadingListAction, QKeySequence(Qt::CTRL+Qt::SHIFT+Qt::Key_2));
|
||||
HIDE_ACTION(ToggleReadingListAction);
|
||||
connect(mpa_actions[ToggleReadingListAction], &QAction::toggled,
|
||||
this, [=](bool checked) {
|
||||
auto action = mpa_actions[ToggleReadingListAction];
|
||||
action->setIcon(
|
||||
QIcon(checked ? ":/icons/reading-list-active.svg" : ":/icons/reading-list.svg"));
|
||||
setSideBar(checked ? READINGLIST_BAR : NONE);
|
||||
});
|
||||
mpa_actions[ToggleReadingListAction]->setCheckable(true);
|
||||
|
||||
|
||||
CREATE_ACTION(ZoomInAction, tr("Zoom in"));
|
||||
SET_SHORTCUT(ZoomInAction, QKeySequence::ZoomIn);
|
||||
|
@ -51,6 +51,7 @@ public:
|
||||
enum SideBarType {
|
||||
SEARCH_BAR,
|
||||
CONTENTMANAGER_BAR,
|
||||
READINGLIST_BAR,
|
||||
NONE
|
||||
};
|
||||
|
||||
@ -69,6 +70,8 @@ public:
|
||||
TabBar* getTabWidget() { return mp_tabWidget; }
|
||||
QAction* getAction(Actions action);
|
||||
|
||||
bool isCurrentArticleBookmarked();
|
||||
|
||||
signals:
|
||||
void currentTitleChanged(const QString& title);
|
||||
|
||||
|
@ -9,11 +9,15 @@ class LibraryManipulator: public kiwix::LibraryManipulator {
|
||||
public:
|
||||
LibraryManipulator(Library* p_library)
|
||||
: mp_library(p_library) {}
|
||||
virtual ~LibraryManipulator() {}
|
||||
bool addBookToLibrary(kiwix::Book book) {
|
||||
auto ret = mp_library->m_library.addBook(book);
|
||||
emit(mp_library->booksChanged());
|
||||
return ret;
|
||||
}
|
||||
void addBookmarkToLibrary(kiwix::Bookmark bookmark) {
|
||||
mp_library->m_library.addBookmark(bookmark);
|
||||
}
|
||||
Library* mp_library;
|
||||
};
|
||||
|
||||
@ -23,6 +27,7 @@ Library::Library()
|
||||
auto manager = kiwix::Manager(&manipulator);
|
||||
qInfo() << QString::fromStdString(getDataDirectory());
|
||||
manager.readFile(appendToDirectory(getDataDirectory(),"library.xml"), false);
|
||||
manager.readBookmarkFile(appendToDirectory(getDataDirectory(),"library.bookmarks.xml"));
|
||||
qInfo() << getBookIds().length();
|
||||
emit(booksChanged());
|
||||
}
|
||||
@ -93,9 +98,22 @@ void Library::addBookToLibrary(kiwix::Book &book)
|
||||
m_library.addBook(book);
|
||||
}
|
||||
|
||||
void Library::addBookmark(kiwix::Bookmark &bookmark)
|
||||
{
|
||||
m_library.addBookmark(bookmark);
|
||||
emit bookmarksChanged();
|
||||
}
|
||||
|
||||
void Library::removeBookmark(const QString &zimId, const QString &url)
|
||||
{
|
||||
m_library.removeBookmark(zimId.toStdString(), url.toStdString());
|
||||
emit bookmarksChanged();
|
||||
}
|
||||
|
||||
void Library::save()
|
||||
{
|
||||
m_library.writeToFile(appendToDirectory(getDataDirectory(),"library.xml"));
|
||||
m_library.writeBookmarksToFile(appendToDirectory(getDataDirectory(), "library.bookmarks.xml"));
|
||||
}
|
||||
|
||||
kiwix::Book &Library::getBookById(QString id)
|
||||
|
@ -29,7 +29,10 @@ public:
|
||||
QString openBookFromPath(const QString& zimPath);
|
||||
std::shared_ptr<kiwix::Reader> getReader(const QString& zimId);
|
||||
QStringList getBookIds();
|
||||
const std::vector<kiwix::Bookmark>& getBookmarks() { return m_library.getBookmarks(); }
|
||||
void addBookToLibrary(kiwix::Book& book);
|
||||
void addBookmark(kiwix::Bookmark& bookmark);
|
||||
void removeBookmark(const QString& zimId, const QString& url);
|
||||
void save();
|
||||
public slots:
|
||||
QString openBookById(const QString& _id);
|
||||
@ -37,6 +40,7 @@ public slots:
|
||||
|
||||
signals:
|
||||
void booksChanged();
|
||||
void bookmarksChanged();
|
||||
|
||||
private:
|
||||
kiwix::Library m_library;
|
||||
|
59
src/readinglistbar.cpp
Normal file
59
src/readinglistbar.cpp
Normal file
@ -0,0 +1,59 @@
|
||||
#include "readinglistbar.h"
|
||||
#include "ui_readinglistbar.h"
|
||||
#include "kiwixapp.h"
|
||||
|
||||
#include <QListWidgetItem>
|
||||
|
||||
ReadingListBar::ReadingListBar(QWidget *parent) :
|
||||
QWidget(parent),
|
||||
ui(new Ui::readinglistbar)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
connect(KiwixApp::instance()->getLibrary(), &Library::bookmarksChanged,
|
||||
this, &ReadingListBar::setupList);
|
||||
connect(ui->listWidget, &QListWidget::itemActivated,
|
||||
this, &ReadingListBar::on_itemActivated);
|
||||
setupList();
|
||||
|
||||
}
|
||||
|
||||
ReadingListBar::~ReadingListBar()
|
||||
{
|
||||
delete ui;
|
||||
}
|
||||
|
||||
|
||||
void ReadingListBar::setupList()
|
||||
{
|
||||
auto library = KiwixApp::instance()->getLibrary();
|
||||
auto bookmarks = library->getBookmarks();
|
||||
auto listWidget = ui->listWidget;
|
||||
listWidget->clear();
|
||||
for(auto& bookmark:bookmarks) {
|
||||
auto reader = library->getReader(QString::fromStdString(bookmark.getBookId()) + ".zim");
|
||||
if (reader == nullptr)
|
||||
continue;
|
||||
std::string content;
|
||||
std::string mimeType;
|
||||
reader->getFavicon(content, mimeType);
|
||||
QPixmap pixmap;
|
||||
pixmap.loadFromData(reinterpret_cast<const uchar*>(content.data()), content.size());
|
||||
auto icon = QIcon(pixmap);
|
||||
auto item = new QListWidgetItem(
|
||||
icon,
|
||||
QString::fromStdString(bookmark.getTitle()),
|
||||
listWidget);
|
||||
item->setTextAlignment(Qt::TextWordWrap);
|
||||
}
|
||||
}
|
||||
|
||||
void ReadingListBar::on_itemActivated(QListWidgetItem* item)
|
||||
{
|
||||
int index = ui->listWidget->row(item);
|
||||
auto bookmark = KiwixApp::instance()->getLibrary()->getBookmarks().at(index);
|
||||
QUrl url;
|
||||
url.setScheme("zim");
|
||||
url.setHost(QString::fromStdString(bookmark.getBookId())+".zim");
|
||||
url.setPath(QString::fromStdString(bookmark.getUrl()));
|
||||
KiwixApp::instance()->openUrl(url);
|
||||
}
|
26
src/readinglistbar.h
Normal file
26
src/readinglistbar.h
Normal file
@ -0,0 +1,26 @@
|
||||
#ifndef READINGLISTBAR_H
|
||||
#define READINGLISTBAR_H
|
||||
|
||||
#include <QWidget>
|
||||
#include <QListWidgetItem>
|
||||
|
||||
namespace Ui {
|
||||
class readinglistbar;
|
||||
}
|
||||
|
||||
class ReadingListBar : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit ReadingListBar(QWidget *parent = nullptr);
|
||||
~ReadingListBar();
|
||||
|
||||
public slots:
|
||||
void setupList();
|
||||
void on_itemActivated(QListWidgetItem *item);
|
||||
private:
|
||||
Ui::readinglistbar *ui;
|
||||
};
|
||||
|
||||
#endif // READINGLISTBAR_H
|
73
src/readinglistbar.ui
Normal file
73
src/readinglistbar.ui
Normal file
@ -0,0 +1,73 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>readinglistbar</class>
|
||||
<widget class="QWidget" name="readinglistbar">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>400</width>
|
||||
<height>300</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Form</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="font">
|
||||
<font>
|
||||
<pointsize>16</pointsize>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Reading List</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QListWidget" name="listWidget">
|
||||
<property name="frameShape">
|
||||
<enum>QFrame::NoFrame</enum>
|
||||
</property>
|
||||
<property name="lineWidth">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="horizontalScrollBarPolicy">
|
||||
<enum>Qt::ScrollBarAlwaysOff</enum>
|
||||
</property>
|
||||
<property name="sizeAdjustPolicy">
|
||||
<enum>QAbstractScrollArea::AdjustToContents</enum>
|
||||
</property>
|
||||
<property name="textElideMode">
|
||||
<enum>Qt::ElideNone</enum>
|
||||
</property>
|
||||
<property name="isWrapping" stdset="0">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="uniformItemSizes">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
@ -11,21 +11,51 @@ SearchButton::SearchButton(QWidget *parent) :
|
||||
{
|
||||
setFlat(true);
|
||||
setIcon(QIcon(":/icons/search.svg"));
|
||||
connect(this, &QPushButton::clicked, this, &SearchButton::on_buttonClicked);
|
||||
}
|
||||
|
||||
void SearchButton::set_searchMode(bool searchMode)
|
||||
{
|
||||
if (searchMode == m_searchMode)
|
||||
return;
|
||||
|
||||
m_searchMode = searchMode;
|
||||
if (m_searchMode) {
|
||||
setIcon(QIcon(":/icons/search.svg"));
|
||||
} else {
|
||||
setIcon(QIcon(":/icons/reading-list.svg"));
|
||||
auto kiwixApp = KiwixApp::instance();
|
||||
if (kiwixApp->isCurrentArticleBookmarked()) {
|
||||
setIcon(QIcon(":/icons/reading-list-active.svg"));
|
||||
} else {
|
||||
setIcon(QIcon(":/icons/reading-list.svg"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SearchButton::on_buttonClicked()
|
||||
{
|
||||
if (m_searchMode)
|
||||
return;
|
||||
|
||||
auto kiwixApp = KiwixApp::instance();
|
||||
auto library = kiwixApp->getLibrary();
|
||||
auto tabWidget = kiwixApp->getTabWidget();
|
||||
if (kiwixApp->isCurrentArticleBookmarked()) {
|
||||
auto zimid = tabWidget->currentZimId();
|
||||
zimid.resize(zimid.length()-4);
|
||||
library->removeBookmark(
|
||||
zimid, tabWidget->currentArticleUrl()
|
||||
);
|
||||
} else {
|
||||
kiwix::Bookmark bookmark;
|
||||
auto zimid = tabWidget->currentZimId().toStdString();
|
||||
zimid.resize(zimid.length()-4);
|
||||
bookmark.setBookId(zimid);
|
||||
bookmark.setUrl(tabWidget->currentArticleUrl().toStdString());
|
||||
bookmark.setTitle(tabWidget->currentArticleTitle().toStdString());
|
||||
library->addBookmark(bookmark);
|
||||
}
|
||||
set_searchMode(false);
|
||||
library->save();
|
||||
}
|
||||
|
||||
SearchBar::SearchBar(QWidget *parent) :
|
||||
QLineEdit(parent),
|
||||
m_completer(&m_completionModel, this),
|
||||
@ -42,13 +72,15 @@ SearchBar::SearchBar(QWidget *parent) :
|
||||
#else
|
||||
connect(this, &QLineEdit::returnPressed, this, &SearchBar::openTitle);
|
||||
#endif
|
||||
connect(KiwixApp::instance(), &KiwixApp::currentTitleChanged, this,
|
||||
[=](const QString& title) {
|
||||
setText(title);
|
||||
m_button.set_searchMode(false);
|
||||
});
|
||||
connect(KiwixApp::instance(), &KiwixApp::currentTitleChanged,
|
||||
this, &SearchBar::on_currentTitleChanged);
|
||||
}
|
||||
|
||||
void SearchBar::on_currentTitleChanged(const QString& title)
|
||||
{
|
||||
setText(title);
|
||||
m_button.set_searchMode(false);
|
||||
}
|
||||
|
||||
void SearchBar::focusInEvent( QFocusEvent* event)
|
||||
{
|
||||
|
@ -14,6 +14,8 @@ public:
|
||||
|
||||
public slots:
|
||||
void set_searchMode(bool searchMode);
|
||||
void on_buttonClicked();
|
||||
|
||||
protected:
|
||||
bool m_searchMode;
|
||||
};
|
||||
@ -24,6 +26,8 @@ class SearchBar : public QLineEdit
|
||||
public:
|
||||
SearchBar(QWidget *parent = nullptr);
|
||||
|
||||
public slots:
|
||||
void on_currentTitleChanged(const QString &title);
|
||||
protected:
|
||||
virtual void focusInEvent(QFocusEvent *);
|
||||
private:
|
||||
|
@ -137,6 +137,20 @@ QString TabBar::currentZimId()
|
||||
return currentWidget()->zimId();
|
||||
}
|
||||
|
||||
QString TabBar::currentArticleUrl()
|
||||
{
|
||||
if(!currentWidget())
|
||||
return "";
|
||||
return currentWidget()->url().path();
|
||||
}
|
||||
|
||||
QString TabBar::currentArticleTitle()
|
||||
{
|
||||
if(!currentWidget())
|
||||
return "";
|
||||
return currentWidget()->title();
|
||||
}
|
||||
|
||||
void TabBar::triggerWebPageAction(QWebEnginePage::WebAction action, WebView *webView)
|
||||
{
|
||||
CURRENTIFNULL(webView);
|
||||
|
@ -11,6 +11,7 @@ class TabBar : public QTabBar
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_PROPERTY(QString currentZimId READ currentZimId NOTIFY currentZimIdChanged)
|
||||
|
||||
public:
|
||||
TabBar(QWidget* parent=nullptr);
|
||||
void setStackedWidget(QStackedWidget* widget);
|
||||
@ -30,6 +31,8 @@ public:
|
||||
QString currentZimId();
|
||||
|
||||
void triggerWebPageAction(QWebEnginePage::WebAction action, WebView* webView=nullptr);
|
||||
QString currentArticleUrl();
|
||||
QString currentArticleTitle();
|
||||
signals:
|
||||
void webActionEnabledChanged(QWebEnginePage::WebAction action, bool enabled);
|
||||
void currentZimIdChanged(const QString& zimId);
|
||||
|
@ -14,7 +14,7 @@ TopWidget::TopWidget(QWidget *parent) :
|
||||
mp_historyBackAction->setIcon(QIcon(":/icons/back.svg"));
|
||||
mp_historyBackAction->setText(tr("back"));
|
||||
mp_historyBackAction->setToolTip(tr("back"));
|
||||
connect(mp_historyBackAction, &QAction::triggered, [this](){
|
||||
connect(mp_historyBackAction, &QAction::triggered, [](){
|
||||
KiwixApp::instance()->getTabWidget()->triggerWebPageAction(QWebEnginePage::Back);
|
||||
});
|
||||
addAction(mp_historyBackAction);
|
||||
@ -22,13 +22,14 @@ TopWidget::TopWidget(QWidget *parent) :
|
||||
mp_historyForwardAction->setIcon(QIcon(":/icons/forward.svg"));
|
||||
mp_historyForwardAction->setText(tr("forward"));
|
||||
mp_historyForwardAction->setToolTip(tr("forward"));
|
||||
connect(mp_historyForwardAction, &QAction::triggered, [this](){
|
||||
connect(mp_historyForwardAction, &QAction::triggered, [](){
|
||||
KiwixApp::instance()->getTabWidget()->triggerWebPageAction(QWebEnginePage::Forward);
|
||||
});
|
||||
addAction(mp_historyForwardAction);
|
||||
addSeparator();
|
||||
|
||||
addWidget(&m_searchEntry);
|
||||
addAction(KiwixApp::instance()->getAction(KiwixApp::ToggleReadingListAction));
|
||||
|
||||
addSeparator();
|
||||
|
||||
|
@ -9,7 +9,7 @@
|
||||
class WebView : public QWebEngineView
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_PROPERTY(const QIcon icon READ icon NOTIFY iconChanged);
|
||||
Q_PROPERTY(const QIcon icon READ icon NOTIFY iconChanged)
|
||||
Q_PROPERTY(QString zimId READ zimId NOTIFY zimIdChanged)
|
||||
|
||||
public:
|
||||
|
@ -76,6 +76,7 @@
|
||||
</sizepolicy>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="ReadingListBar" name="readinglistbar"/>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
@ -126,6 +127,12 @@
|
||||
<header>src/contentmanagerside.h</header>
|
||||
<container>1</container>
|
||||
</customwidget>
|
||||
<customwidget>
|
||||
<class>ReadingListBar</class>
|
||||
<extends>QWidget</extends>
|
||||
<header>src/readinglistbar.h</header>
|
||||
<container>1</container>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<resources/>
|
||||
<connections/>
|
||||
|
Loading…
x
Reference in New Issue
Block a user