mirror of
https://github.com/kiwix/kiwix-desktop.git
synced 2025-09-22 11:37:56 -04:00
Merge pull request #1098 from kiwix/united_states_of_books
Declaration of USB (Unified States of Books)
This commit is contained in:
commit
18456eb9c4
@ -218,26 +218,40 @@ void ContentManager::onCustomContextMenu(const QPoint &point)
|
||||
QAction menuCancelBook(gt("cancel-download"), this);
|
||||
QAction menuOpenFolder(gt("open-folder"), this);
|
||||
|
||||
if (const auto download = bookNode->getDownloadState()) {
|
||||
if (download->paused) {
|
||||
contextMenu.addAction(&menuResumeBook);
|
||||
} else {
|
||||
contextMenu.addAction(&menuPauseBook);
|
||||
}
|
||||
const auto bookState = getBookState(id);
|
||||
switch ( bookState ) {
|
||||
case BookState::DOWNLOAD_PAUSED:
|
||||
contextMenu.addAction(&menuResumeBook);
|
||||
contextMenu.addAction(&menuCancelBook);
|
||||
} else {
|
||||
try {
|
||||
break;
|
||||
|
||||
case BookState::DOWNLOADING:
|
||||
contextMenu.addAction(&menuPauseBook);
|
||||
contextMenu.addAction(&menuCancelBook);
|
||||
break;
|
||||
|
||||
case BookState::AVAILABLE_LOCALLY_AND_HEALTHY:
|
||||
case BookState::ERROR_MISSING_ZIM_FILE:
|
||||
case BookState::ERROR_CORRUPTED_ZIM_FILE:
|
||||
{
|
||||
const auto book = mp_library->getBookById(id);
|
||||
auto bookPath = QString::fromStdString(book.getPath());
|
||||
contextMenu.addAction(&menuOpenBook);
|
||||
if ( bookState == BookState::AVAILABLE_LOCALLY_AND_HEALTHY ) {
|
||||
contextMenu.addAction(&menuOpenBook);
|
||||
}
|
||||
contextMenu.addAction(&menuDeleteBook);
|
||||
contextMenu.addAction(&menuOpenFolder);
|
||||
connect(&menuOpenFolder, &QAction::triggered, [=]() {
|
||||
openFileLocation(bookPath, mp_view);
|
||||
});
|
||||
} catch (...) {
|
||||
contextMenu.addAction(&menuDownloadBook);
|
||||
break;
|
||||
}
|
||||
|
||||
case BookState::AVAILABLE_ONLINE:
|
||||
contextMenu.addAction(&menuDownloadBook);
|
||||
break;
|
||||
|
||||
default: break;
|
||||
}
|
||||
|
||||
connect(&menuDeleteBook, &QAction::triggered, [=]() {
|
||||
@ -390,6 +404,19 @@ QVariant getBookAttribute(const kiwix::Book& b, const QString& a)
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
ContentManager::BookState getStateOfLocalBook(const kiwix::Book& book)
|
||||
{
|
||||
if ( !book.isPathValid() ) {
|
||||
return ContentManager::BookState::ERROR_MISSING_ZIM_FILE;
|
||||
}
|
||||
|
||||
// XXX: When a book is detected to be corrupted, information about that
|
||||
// XXX: has to be recorded somewhere so that we can return
|
||||
// XXX: ERROR_CORRUPTED_ZIM_FILE here
|
||||
|
||||
return ContentManager::BookState::AVAILABLE_LOCALLY_AND_HEALTHY;
|
||||
}
|
||||
|
||||
} // unnamed namespace
|
||||
|
||||
ContentManager::BookInfo ContentManager::getBookInfos(QString id, const QStringList &keys)
|
||||
@ -420,17 +447,40 @@ ContentManager::BookInfo ContentManager::getBookInfos(QString id, const QStringL
|
||||
return values;
|
||||
}
|
||||
|
||||
ContentManager::BookState ContentManager::getBookState(QString bookId)
|
||||
{
|
||||
if ( const auto downloadState = m_downloads.value(bookId) ) {
|
||||
return downloadState->paused
|
||||
? BookState::DOWNLOAD_PAUSED
|
||||
: BookState::DOWNLOADING;
|
||||
// TODO: a download may be in error state
|
||||
}
|
||||
|
||||
try {
|
||||
const kiwix::Book& b = mp_library->getBookById(bookId);
|
||||
return b.getDownloadId().empty()
|
||||
? getStateOfLocalBook(b)
|
||||
: BookState::DOWNLOADING;
|
||||
} catch (...) {}
|
||||
|
||||
try {
|
||||
QMutexLocker locker(&remoteLibraryLocker);
|
||||
const kiwix::Book& b = mp_remoteLibrary->getBookById(bookId.toStdString());
|
||||
return !b.getUrl().empty()
|
||||
? BookState::AVAILABLE_ONLINE
|
||||
: BookState::METADATA_ONLY;
|
||||
} catch (...) {}
|
||||
|
||||
return BookState::INVALID;
|
||||
}
|
||||
|
||||
void ContentManager::openBookWithIndex(const QModelIndex &index)
|
||||
{
|
||||
try {
|
||||
auto bookNode = static_cast<Node*>(index.internalPointer());
|
||||
const QString bookId = bookNode->getBookId();
|
||||
// throws std::out_of_range if the book isn't available in local library
|
||||
const kiwix::Book& book = mp_library->getBookById(bookId);
|
||||
if ( !book.getDownloadId().empty() )
|
||||
return;
|
||||
auto bookNode = static_cast<Node*>(index.internalPointer());
|
||||
const QString bookId = bookNode->getBookId();
|
||||
if ( getBookState(bookId) == BookState::AVAILABLE_LOCALLY_AND_HEALTHY ) {
|
||||
openBook(bookId);
|
||||
} catch (std::out_of_range &e) {}
|
||||
}
|
||||
}
|
||||
|
||||
void ContentManager::openBook(const QString &id)
|
||||
|
@ -20,6 +20,43 @@ public: // types
|
||||
typedef ContentManagerModel::BookInfo BookInfo;
|
||||
typedef ContentManagerModel::BookInfoList BookInfoList;
|
||||
|
||||
enum class BookState
|
||||
{
|
||||
// Nothing known about a book with that id
|
||||
INVALID,
|
||||
|
||||
// Only (some) metadata is available for the book, however neither a
|
||||
// ZIM-file nor a URL is associated with it.
|
||||
METADATA_ONLY,
|
||||
|
||||
// No ZIM file is associated with the book but a URL is provided.
|
||||
AVAILABLE_ONLINE,
|
||||
|
||||
// The book is being downloaded.
|
||||
DOWNLOADING,
|
||||
|
||||
// The book started downloading, but the download is currently paused.
|
||||
DOWNLOAD_PAUSED,
|
||||
|
||||
// The book started downloading but the download was stopped due to
|
||||
// errors.
|
||||
DOWNLOAD_ERROR,
|
||||
|
||||
// A valid ZIM file path is associated with the book and no evidence
|
||||
// about any issues with that ZIM file has so far been obtained.
|
||||
AVAILABLE_LOCALLY_AND_HEALTHY,
|
||||
|
||||
// A ZIM file path is associated with the book but no such file seems
|
||||
// to exist (may be caused by missing read permissions for the directory
|
||||
// containing the ZIM file).
|
||||
ERROR_MISSING_ZIM_FILE,
|
||||
|
||||
// A ZIM file is associated with the book but it cannot be opened
|
||||
// due to issues with its content.
|
||||
ERROR_CORRUPTED_ZIM_FILE
|
||||
};
|
||||
|
||||
|
||||
public: // functions
|
||||
explicit ContentManager(Library* library, kiwix::Downloader *downloader, QObject *parent = nullptr);
|
||||
virtual ~ContentManager();
|
||||
@ -49,6 +86,7 @@ signals:
|
||||
public slots:
|
||||
QStringList getTranslations(const QStringList &keys);
|
||||
BookInfo getBookInfos(QString id, const QStringList &keys);
|
||||
BookState getBookState(QString id);
|
||||
void openBook(const QString& id);
|
||||
void downloadBook(const QString& id);
|
||||
void downloadBook(const QString& id, QModelIndex index);
|
||||
|
@ -146,17 +146,39 @@ void showDownloadProgress(QPainter *painter, QRect box, const DownloadState& dow
|
||||
createArc(painter, startAngle, spanAngle, rectangle, pen);
|
||||
}
|
||||
|
||||
void ContentManagerDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
|
||||
void ContentManagerDelegate::paintButton(QPainter *p, const QRect &r, QString t) const
|
||||
{
|
||||
QStyleOptionButton button;
|
||||
QRect r = option.rect;
|
||||
int x,y,w,h;
|
||||
x = r.left();
|
||||
y = r.top();
|
||||
w = r.width();
|
||||
h = r.height();
|
||||
button.rect = QRect(x,y,w,h);
|
||||
button.rect = r;
|
||||
button.state = QStyle::State_Enabled;
|
||||
button.text = t;
|
||||
baseButton->style()->drawControl( QStyle::CE_PushButton, &button, p, baseButton.data());
|
||||
}
|
||||
|
||||
void ContentManagerDelegate::paintBookState(QPainter *p, QRect r, const QModelIndex &index) const
|
||||
{
|
||||
const auto node = static_cast<RowNode*>(index.internalPointer());
|
||||
const auto id = node->getBookId();
|
||||
switch ( KiwixApp::instance()->getContentManager()->getBookState(id) ) {
|
||||
case ContentManager::BookState::AVAILABLE_LOCALLY_AND_HEALTHY:
|
||||
return paintButton(p, r, gt("open"));
|
||||
|
||||
case ContentManager::BookState::AVAILABLE_ONLINE:
|
||||
return paintButton(p, r, gt("download"));
|
||||
|
||||
case ContentManager::BookState::DOWNLOADING:
|
||||
case ContentManager::BookState::DOWNLOAD_PAUSED:
|
||||
case ContentManager::BookState::DOWNLOAD_ERROR:
|
||||
return showDownloadProgress(p, r, *node->getDownloadState());
|
||||
|
||||
default:
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void ContentManagerDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
|
||||
{
|
||||
QRect r = option.rect;
|
||||
if (index.parent().isValid()) {
|
||||
// additional info
|
||||
QRect nRect = r;
|
||||
@ -165,24 +187,9 @@ void ContentManagerDelegate::paint(QPainter *painter, const QStyleOptionViewItem
|
||||
painter->drawText(nRect, Qt::AlignLeft | Qt::AlignVCenter, index.data(Qt::UserRole+1).toString());
|
||||
return;
|
||||
}
|
||||
auto node = static_cast<RowNode*>(index.internalPointer());
|
||||
try {
|
||||
const auto id = node->getBookId();
|
||||
const auto book = KiwixApp::instance()->getLibrary()->getBookById(id);
|
||||
if ( book.getDownloadId().empty() ) {
|
||||
button.text = gt("open");
|
||||
}
|
||||
} catch (std::out_of_range& e) {
|
||||
button.text = gt("download");
|
||||
}
|
||||
QStyleOptionViewItem eOpt = option;
|
||||
if (index.column() == 5) {
|
||||
if (const auto downloadState = node->getDownloadState()) {
|
||||
showDownloadProgress(painter, r, *downloadState);
|
||||
}
|
||||
else {
|
||||
baseButton->style()->drawControl( QStyle::CE_PushButton, &button, painter, baseButton.data());
|
||||
}
|
||||
paintBookState(painter, option.rect, index);
|
||||
return;
|
||||
}
|
||||
if (index.column() == 0) {
|
||||
@ -192,7 +199,7 @@ void ContentManagerDelegate::paint(QPainter *painter, const QStyleOptionViewItem
|
||||
QPixmap pix;
|
||||
pix.loadFromData(iconData);
|
||||
QIcon icon(pix);
|
||||
icon.paint(painter, QRect(x+10, y+10, 30, 50));
|
||||
icon.paint(painter, QRect(r.left()+10, r.top()+10, 30, 50));
|
||||
return;
|
||||
}
|
||||
if (index.column() == 1) {
|
||||
@ -249,24 +256,25 @@ void ContentManagerDelegate::handleLastColumnClicked(const QModelIndex& index, Q
|
||||
int x = r.left();
|
||||
int w = r.width();
|
||||
|
||||
if (const auto downloadState = node->getDownloadState()) {
|
||||
if (downloadState->paused) {
|
||||
if (clickX < (x + w/2)) {
|
||||
KiwixApp::instance()->getContentManager()->cancelBook(id);
|
||||
} else {
|
||||
KiwixApp::instance()->getContentManager()->resumeBook(id, index);
|
||||
}
|
||||
} else {
|
||||
KiwixApp::instance()->getContentManager()->pauseBook(id, index);
|
||||
}
|
||||
} else {
|
||||
try {
|
||||
const auto book = KiwixApp::instance()->getLibrary()->getBookById(id);
|
||||
KiwixApp::instance()->getContentManager()->openBook(id);
|
||||
} catch (std::out_of_range& e) {
|
||||
KiwixApp::instance()->getContentManager()->downloadBook(id, index);
|
||||
}
|
||||
}
|
||||
ContentManager& contentMgr = *KiwixApp::instance()->getContentManager();
|
||||
switch ( contentMgr.getBookState(id) ) {
|
||||
case ContentManager::BookState::AVAILABLE_LOCALLY_AND_HEALTHY:
|
||||
return contentMgr.openBook(id);
|
||||
|
||||
case ContentManager::BookState::AVAILABLE_ONLINE:
|
||||
return contentMgr.downloadBook(id, index);
|
||||
|
||||
case ContentManager::BookState::DOWNLOADING:
|
||||
return contentMgr.pauseBook(id, index);
|
||||
|
||||
case ContentManager::BookState::DOWNLOAD_PAUSED:
|
||||
return clickX < (x + w/2)
|
||||
? contentMgr.cancelBook(id)
|
||||
: contentMgr.resumeBook(id, index);
|
||||
|
||||
default:
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
QSize ContentManagerDelegate::sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const
|
||||
|
@ -15,6 +15,10 @@ public:
|
||||
bool editorEvent(QEvent *event, QAbstractItemModel *model, const QStyleOptionViewItem &option, const QModelIndex &index) override;
|
||||
QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const override;
|
||||
|
||||
private: // functions
|
||||
void paintBookState(QPainter *p, QRect r, const QModelIndex &index) const;
|
||||
void paintButton(QPainter *p, const QRect &r, QString t) const;
|
||||
|
||||
private:
|
||||
QScopedPointer<QPushButton> baseButton;
|
||||
QByteArray placeholderIcon;
|
||||
|
Loading…
x
Reference in New Issue
Block a user