From bf1c317f10d61ac8b6da4e686fd62e2e6da2d514 Mon Sep 17 00:00:00 2001 From: Nikhil Tanwar <2002nikhiltanwar@gmail.com> Date: Wed, 19 Jul 2023 02:43:18 +0530 Subject: [PATCH] Split view nodes into RowNode and DescriptionNode Splitted the views into RowNode and DescriptionNode for consistency RowNode represents one row with thumbnail, name, data, size, etc. DescriptionNode shows the description --- kiwix-desktop.pro | 5 ++- src/contentmanager.cpp | 19 +++++++---- src/contentmanagerdelegate.cpp | 25 +++++++------- src/contentmanagermodel.cpp | 59 ++++++++++++---------------------- src/contentmanagermodel.h | 3 +- src/descriptionnode.cpp | 41 +++++++++++++++++++++++ src/descriptionnode.h | 26 +++++++++++++++ src/node.cpp | 54 ------------------------------- src/node.h | 43 ++++--------------------- src/rownode.cpp | 35 ++++++++------------ src/rownode.h | 48 +++++++++++++++++++++++++++ 11 files changed, 186 insertions(+), 172 deletions(-) create mode 100644 src/descriptionnode.cpp create mode 100644 src/descriptionnode.h delete mode 100644 src/node.cpp create mode 100644 src/rownode.h diff --git a/kiwix-desktop.pro b/kiwix-desktop.pro index 444d40c..6f0467d 100644 --- a/kiwix-desktop.pro +++ b/kiwix-desktop.pro @@ -38,10 +38,11 @@ SOURCES += \ src/contentmanagerheader.cpp \ src/contentmanagermodel.cpp \ src/contenttypefilter.cpp \ + src/descriptionnode.cpp \ src/findinpagebar.cpp \ src/kiwixconfirmbox.cpp \ src/kiwixloader.cpp \ - src/node.cpp \ + src/rownode.cpp \ src/suggestionlistworker.cpp \ src/thumbnaildownloader.cpp \ src/translation.cpp \ @@ -79,10 +80,12 @@ HEADERS += \ src/contentmanagermodel.h \ src/contentmanagerview.h \ src/contenttypefilter.h \ + src/descriptionnode.h \ src/findinpagebar.h \ src/kiwixconfirmbox.h \ src/kiwixloader.h \ src/node.h \ + src/rownode.h \ src/suggestionlistworker.h \ src/thumbnaildownloader.h \ src/translation.h \ diff --git a/src/contentmanager.cpp b/src/contentmanager.cpp index f41b503..7cb0a99 100644 --- a/src/contentmanager.cpp +++ b/src/contentmanager.cpp @@ -16,7 +16,8 @@ #include #include #include "contentmanagerdelegate.h" -#include "node.h" +#include "rownode.h" +#include "descriptionnode.h" #include "kiwixconfirmbox.h" #include #include "contentmanagerheader.h" @@ -85,7 +86,7 @@ void ContentManager::onCustomContextMenu(const QPoint &point) { QModelIndex index = mp_view->getView()->indexAt(point); QMenu contextMenu("optionsMenu", mp_view->getView()); - Node* bookNode = static_cast(index.internalPointer()); + auto bookNode = static_cast(index.internalPointer()); const auto id = bookNode->getBookId(); QAction menuDeleteBook("Delete book", this); @@ -234,10 +235,14 @@ QMap ContentManager::getBookInfos(QString id, const QStringLi void ContentManager::openBookWithIndex(const QModelIndex &index) { try { - Node* bookNode = static_cast(index.internalPointer()); - auto bookId = bookNode->getBookId(); - if (bookNode->isAdditonal()) - bookId = bookNode->parentItem()->getBookId(); + QString bookId; + if (index.parent().isValid()) { + auto bookNode = static_cast(index.internalPointer()); + bookId = bookNode->getBookId(); + } else { + auto bookNode = static_cast(index.internalPointer()); + bookId = bookNode->getBookId(); + } // check if the book is available in local library, will throw std::out_of_range if it isn't. KiwixApp::instance()->getLibrary()->getBookById(bookId); if (getBookInfos(bookId, {"downloadId"})["downloadId"] != "") @@ -367,7 +372,7 @@ QString ContentManager::downloadBook(const QString &id, QModelIndex index) emit managerModel->startDownload(index); return downloadStatus; } - KiwixConfirmBox *dialog = new KiwixConfirmBox(dialogHeader, dialogText, mp_view, true); + KiwixConfirmBox *dialog = new KiwixConfirmBox(dialogHeader, dialogText, true, mp_view); dialog->show(); connect(dialog, &KiwixConfirmBox::okClicked, [=]() { dialog->deleteLater(); diff --git a/src/contentmanagerdelegate.cpp b/src/contentmanagerdelegate.cpp index f1de60b..4d7583a 100644 --- a/src/contentmanagerdelegate.cpp +++ b/src/contentmanagerdelegate.cpp @@ -5,7 +5,8 @@ #include #include "kiwixapp.h" #include -#include "node.h" +#include "rownode.h" +#include "descriptionnode.h" ContentManagerDelegate::ContentManagerDelegate(QObject *parent) : QStyledItemDelegate(parent), baseButton(new QPushButton) @@ -155,7 +156,15 @@ void ContentManagerDelegate::paint(QPainter *painter, const QStyleOptionViewItem h = r.height(); button.rect = QRect(x,y,w,h); button.state = QStyle::State_Enabled; - auto node = static_cast(index.internalPointer()); + if (index.parent().isValid()) { + // additional info + QRect nRect = r; + auto viewWidth = KiwixApp::instance()->getContentManager()->getView()->getView()->width(); + nRect.setWidth(viewWidth); + painter->drawText(nRect, Qt::AlignLeft | Qt::AlignVCenter, index.data(Qt::UserRole+1).toString()); + return; + } + auto node = static_cast(index.internalPointer()); try { const auto id = node->getBookId(); const auto book = KiwixApp::instance()->getLibrary()->getBookById(id); @@ -167,14 +176,6 @@ void ContentManagerDelegate::paint(QPainter *painter, const QStyleOptionViewItem button.text = gt("download"); } QStyleOptionViewItem eOpt = option; - if (index.data(Qt::UserRole+1) != QVariant()) { - // additional info role - QRect nRect = r; - auto viewWidth = KiwixApp::instance()->getContentManager()->getView()->getView()->width(); - nRect.setWidth(viewWidth); - painter->drawText(nRect, Qt::AlignLeft | Qt::AlignVCenter, index.data(Qt::UserRole+1).toString()); - return; - } if (index.column() == 5) { if (node->isDownloading()) { auto downloadInfo = node->getDownloadInfo(); @@ -235,7 +236,7 @@ bool ContentManagerDelegate::editorEvent(QEvent *event, QAbstractItemModel *mode void ContentManagerDelegate::handleLastColumnClicked(const QModelIndex& index, QMouseEvent *mouseEvent, const QStyleOptionViewItem &option) { - const auto node = static_cast(index.internalPointer()); + const auto node = static_cast(index.internalPointer()); const auto id = node->getBookId(); int clickX = mouseEvent->x(); @@ -265,7 +266,7 @@ void ContentManagerDelegate::handleLastColumnClicked(const QModelIndex& index, Q QSize ContentManagerDelegate::sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const { - if (index.data(Qt::UserRole+1) != QVariant()) { + if (index.parent().isValid()) { return QSize(300, 70); } return QSize(50, 70); diff --git a/src/contentmanagermodel.cpp b/src/contentmanagermodel.cpp index 28971ec..c83b04b 100644 --- a/src/contentmanagermodel.cpp +++ b/src/contentmanagermodel.cpp @@ -1,5 +1,7 @@ #include "contentmanagermodel.h" #include "node.h" +#include "rownode.h" +#include "descriptionnode.h" #include #include #include @@ -35,7 +37,7 @@ QVariant ContentManagerModel::data(const QModelIndex& index, int role) const Node *item = static_cast(index.internalPointer()); const auto displayRole = role == Qt::DisplayRole; - const auto additionalInfoRole = role == Qt::UserRole+1 && item->isAdditonal(); + const auto additionalInfoRole = role == Qt::UserRole+1; if (displayRole || additionalInfoRole) return item->data(index.column()); @@ -56,16 +58,18 @@ QModelIndex ContentManagerModel::index(int row, int column, const QModelIndex &p if (!hasIndex(row, column, parent)) return QModelIndex(); - Node *parentItem; + RowNode* parentItem; - if (!parent.isValid()) + if (!parent.isValid()) { parentItem = rootNode; - else - parentItem = static_cast(parent.internalPointer()); - - Node *childItem = parentItem->child(row); + } + else { + parentItem = static_cast(parent.internalPointer()); + } + auto childItem = parentItem->child(row); if (childItem) return createIndex(row, column, childItem); + return QModelIndex(); } @@ -107,7 +111,7 @@ QVariant ContentManagerModel::headerData(int section, Qt::Orientation orientatio void ContentManagerModel::setBooksData(const QList>& data) { m_data = data; - rootNode = new Node({tr("Icon"), tr("Name"), tr("Date"), tr("Size"), tr("Content Type"), tr("Download")}); + rootNode = new RowNode({tr("Icon"), tr("Name"), tr("Date"), tr("Size"), tr("Content Type"), tr("Download")}, "", nullptr); setupNodes(); emit dataChanged(QModelIndex(), QModelIndex()); } @@ -128,32 +132,9 @@ QString convertToUnits(QString size) void ContentManagerModel::setupNodes() { - QByteArray bookIcon; beginResetModel(); for (auto bookItem : m_data) { - auto name = bookItem["title"].toString(); - auto date = bookItem["date"].toString(); - auto size = convertToUnits(bookItem["size"].toString()); - auto content = bookItem["tags"].toString(); - auto id = bookItem["id"].toString(); - auto description = bookItem["description"].toString(); - auto faviconUrl = "https://" + bookItem["faviconUrl"].toString(); - try { - auto book = KiwixApp::instance()->getLibrary()->getBookById(id); - std::string favicon; - auto item = book.getIllustration(48); - favicon = item->getData(); - bookIcon = QByteArray::fromRawData(reinterpret_cast(favicon.data()), favicon.size()); - bookIcon.detach(); // deep copy - } catch (std::out_of_range &e) { - if (iconMap.contains(faviconUrl)) { - bookIcon = iconMap[faviconUrl]; - } - } - const auto temp = new Node({bookIcon, name, date, size, content, id}, rootNode, id); - const auto tempsTemp = new Node({"", description, "", "", "", ""}, temp, "", true); - temp->appendChild(tempsTemp); - rootNode->appendChild(temp); + rootNode->appendChild(RowNode::createNode(bookItem, iconMap, rootNode)); } endResetModel(); } @@ -171,7 +152,7 @@ void ContentManagerModel::refreshIcons() try { auto book = app->getLibrary()->getBookById(id); auto item = book.getIllustration(48); - } catch (std::out_of_range &e) { + } catch (...) { if (faviconUrl != "" && !iconMap.contains(faviconUrl)) { td.addDownload(faviconUrl, index(i, 0)); } @@ -183,7 +164,7 @@ bool ContentManagerModel::hasChildren(const QModelIndex &parent) const { Node *item = static_cast(parent.internalPointer()); if (item) - return !item->isAdditonal(); + return item->childCount() > 0; return true; } @@ -230,7 +211,7 @@ void ContentManagerModel::sort(int column, Qt::SortOrder order) void ContentManagerModel::updateImage(QModelIndex index, QString url, QByteArray imageData) { - Node *item = static_cast(index.internalPointer()); + RowNode *item = static_cast(index.internalPointer()); item->setIconData(imageData); iconMap[url] = imageData; emit dataChanged(index, index); @@ -238,7 +219,7 @@ void ContentManagerModel::updateImage(QModelIndex index, QString url, QByteArray void ContentManagerModel::startDownload(QModelIndex index) { - auto node = static_cast(index.internalPointer()); + auto node = static_cast(index.internalPointer()); node->setIsDownloading(true); auto id = node->getBookId(); QTimer *timer = new QTimer(this); @@ -263,7 +244,7 @@ void ContentManagerModel::startDownload(QModelIndex index) void ContentManagerModel::pauseDownload(QModelIndex index) { - auto node = static_cast(index.internalPointer()); + auto node = static_cast(index.internalPointer()); auto id = node->getBookId(); auto prevDownloadInfo = node->getDownloadInfo(); prevDownloadInfo.paused = true; @@ -274,7 +255,7 @@ void ContentManagerModel::pauseDownload(QModelIndex index) void ContentManagerModel::resumeDownload(QModelIndex index) { - auto node = static_cast(index.internalPointer()); + auto node = static_cast(index.internalPointer()); auto id = node->getBookId(); auto prevDownloadInfo = node->getDownloadInfo(); prevDownloadInfo.paused = false; @@ -285,7 +266,7 @@ void ContentManagerModel::resumeDownload(QModelIndex index) void ContentManagerModel::cancelDownload(QModelIndex index) { - auto node = static_cast(index.internalPointer()); + auto node = static_cast(index.internalPointer()); auto id = node->getBookId(); node->setIsDownloading(false); node->setDownloadInfo({0, "", "", false}); diff --git a/src/contentmanagermodel.h b/src/contentmanagermodel.h index 678b833..c91b8fd 100644 --- a/src/contentmanagermodel.h +++ b/src/contentmanagermodel.h @@ -7,6 +7,7 @@ #include #include "thumbnaildownloader.h" +class RowNode; class Node; class ContentManagerModel : public QAbstractItemModel @@ -45,7 +46,7 @@ protected: private: QList> m_data; - Node *rootNode; + RowNode *rootNode; int zimCount = 0; ThumbnailDownloader td; QMap iconMap; diff --git a/src/descriptionnode.cpp b/src/descriptionnode.cpp new file mode 100644 index 0000000..36f0cc8 --- /dev/null +++ b/src/descriptionnode.cpp @@ -0,0 +1,41 @@ +#include "descriptionnode.h" +#include "rownode.h" + +DescriptionNode::DescriptionNode(QString desc, RowNode *parent) + : m_desc(desc), m_parentItem(parent) +{} + +DescriptionNode::~DescriptionNode() +{} + +Node* DescriptionNode::parentItem() +{ + return m_parentItem; +} + +QString DescriptionNode::getBookId() const +{ + return m_parentItem->getBookId(); +} + +int DescriptionNode::childCount() const +{ + return 0; +} + +int DescriptionNode::columnCount() const +{ + return 1; +} + +QVariant DescriptionNode::data(int column) +{ + if (column == 1) + return m_desc; + return QVariant(); +} + +int DescriptionNode::row() const +{ + return m_parentItem->row(); +} diff --git a/src/descriptionnode.h b/src/descriptionnode.h new file mode 100644 index 0000000..557a21f --- /dev/null +++ b/src/descriptionnode.h @@ -0,0 +1,26 @@ +#ifndef DESCRIPTIONNODE_H +#define DESCRIPTIONNODE_H + +#include +#include "node.h" + +class RowNode; + +class DescriptionNode : public Node +{ +public: + DescriptionNode(QString desc, RowNode *parent); + ~DescriptionNode(); + Node *parentItem() override; + int childCount() const override; + int columnCount() const override; + QVariant data(int column) override; + int row() const override; + QString getBookId() const override; + +private: + QString m_desc; + RowNode *m_parentItem; +}; + +#endif // DESCRIPTIONNODE_H diff --git a/src/node.cpp b/src/node.cpp deleted file mode 100644 index 5cf2dac..0000000 --- a/src/node.cpp +++ /dev/null @@ -1,54 +0,0 @@ -#include "node.h" - -Node::Node(const QList &data, Node *parent, QString bookId, bool isAdditional) - : m_itemData(data), m_parentItem(parent), m_isAdditonal(isAdditional), m_bookId(bookId) -{ - m_downloadInfo = {0, "", "", false}; -} - -Node::~Node() -{ - qDeleteAll(m_childItems); -} - -void Node::appendChild(Node *item) -{ - m_childItems.append(item); -} - -Node *Node::child(int row) -{ - if (row < 0 || row >= m_childItems.size()) - return nullptr; - return m_childItems.at(row); -} - -int Node::childCount() const -{ - return m_childItems.count(); -} - -int Node::columnCount() const -{ - return m_itemData.count(); -} - -QVariant Node::data(int column) const -{ - if (column < 0 || column >= m_itemData.size()) - return QVariant(); - return m_itemData.at(column); -} - -Node *Node::parentItem() -{ - return m_parentItem; -} - -int Node::row() const -{ - if (m_parentItem) - return m_parentItem->m_childItems.indexOf(const_cast(this)); - - return 0; -} diff --git a/src/node.h b/src/node.h index a25844b..dc008ba 100644 --- a/src/node.h +++ b/src/node.h @@ -2,46 +2,17 @@ #define NODE_H #include -#include -#include "contentmanagermodel.h" -#include - -struct DownloadInfo -{ - double progress; - QString completedLength; - QString downloadSpeed; - bool paused; -}; class Node { public: - explicit Node(const QList &data, Node *parentItem = nullptr, QString bookId = "", bool isAdditional = false); - ~Node(); - void appendChild(Node *child); - Node *child(int row); - int childCount() const; - int columnCount() const; - QVariant data(int column) const; - int row() const; - Node *parentItem(); - bool isAdditonal() const { return m_isAdditonal; } - QString getBookId() const { return m_bookId; } - void setIconData(QByteArray iconData) { m_itemData[0] = iconData; } - bool isDownloading() const { return m_isDownloading; } - void setDownloadInfo(DownloadInfo downloadInfo) { m_downloadInfo = downloadInfo; } - DownloadInfo getDownloadInfo() const { return m_downloadInfo; } - void setIsDownloading(bool val) { m_isDownloading = val; } - -private: - QList m_itemData; - Node *m_parentItem; - QList m_childItems; - bool m_isAdditonal; - QString m_bookId; - bool m_isDownloading = false; - DownloadInfo m_downloadInfo; + virtual ~Node() = default; + virtual Node *parentItem() = 0; + virtual int childCount() const = 0; + virtual int columnCount() const = 0; + virtual QVariant data(int column) = 0; + virtual int row() const = 0; + virtual QString getBookId() const = 0; }; diff --git a/src/rownode.cpp b/src/rownode.cpp index 957c5cd..25fe7f5 100644 --- a/src/rownode.cpp +++ b/src/rownode.cpp @@ -4,7 +4,7 @@ #include "descriptionnode.h" #include "kiwix/tools.h" -RowNode::RowNode(QList itemData, QString bookId, std::weak_ptr parent) +RowNode::RowNode(QList itemData, QString bookId, RowNode *parent) : m_itemData(itemData), m_parentItem(parent), m_bookId(bookId) { m_downloadInfo = {0, "", "", false}; @@ -13,12 +13,12 @@ RowNode::RowNode(QList itemData, QString bookId, std::weak_ptr item) +void RowNode::appendChild(Node *item) { m_childItems.append(item); } -std::shared_ptr RowNode::child(int row) +Node *RowNode::child(int row) { if (row < 0 || row >= m_childItems.size()) return nullptr; @@ -35,10 +35,9 @@ int RowNode::columnCount() const return 6; } -std::shared_ptr RowNode::parentItem() +Node* RowNode::parentItem() { - std::shared_ptr temp = m_parentItem.lock(); - return temp; + return m_parentItem; } QVariant RowNode::data(int column) @@ -50,17 +49,13 @@ QVariant RowNode::data(int column) int RowNode::row() const { - try { - std::shared_ptr temp = m_parentItem.lock(); - return temp->m_childItems.indexOf(std::const_pointer_cast(shared_from_this())); - } catch(...) { - return 0; - } + if (m_parentItem) + return m_parentItem->m_childItems.indexOf(const_cast(this)); return 0; } -std::shared_ptr RowNode::createNode(QMap bookItem, QMap iconMap, std::shared_ptr rootNode) +RowNode* RowNode::createNode(QMap bookItem, QMap iconMap, RowNode *rootNode) { auto faviconUrl = "https://" + bookItem["faviconUrl"].toString(); QString id = bookItem["id"].toString(); @@ -73,20 +68,16 @@ std::shared_ptr RowNode::createNode(QMap bookItem, Q bookIcon = QByteArray::fromRawData(reinterpret_cast(favicon.data()), favicon.size()); bookIcon.detach(); // deep copy } catch (...) { - bookIcon = QByteArray(); if (iconMap.contains(faviconUrl)) { bookIcon = iconMap[faviconUrl]; } } - std::weak_ptr weakRoot = rootNode; - auto rowNodePtr = std::make_shared( - RowNode({bookIcon, bookItem["title"], + auto temp = new RowNode({bookIcon, bookItem["title"], bookItem["date"], QString::fromStdString(kiwix::beautifyFileSize(bookItem["size"].toULongLong())), bookItem["tags"] - }, id, weakRoot)); - std::weak_ptr weakRowNodePtr = rowNodePtr; - const auto descNodePtr = std::make_shared(DescriptionNode(bookItem["description"].toString(), weakRowNodePtr)); - rowNodePtr->appendChild(descNodePtr); - return rowNodePtr; + }, id, rootNode); + auto tempsTemp = new DescriptionNode(bookItem["description"].toString(), temp); + temp->appendChild(tempsTemp); + return temp; } diff --git a/src/rownode.h b/src/rownode.h new file mode 100644 index 0000000..f9ef7ab --- /dev/null +++ b/src/rownode.h @@ -0,0 +1,48 @@ +#ifndef ROWNODE_H +#define ROWNODE_H + +#include "node.h" +#include +#include "contentmanagermodel.h" +#include +#include "kiwix/book.h" + +struct DownloadInfo +{ + double progress; + QString completedLength; + QString downloadSpeed; + bool paused; +}; + +class RowNode : public Node +{ +public: + explicit RowNode(QList itemData, QString bookId, RowNode *parentItem); + ~RowNode(); + Node *parentItem() override; + Node *child(int row); + void appendChild(Node *child); + int childCount() const override; + int columnCount() const override; + QVariant data(int column) override; + int row() const override; + QString getBookId() const { return m_bookId; } + void setIconData(QByteArray iconData) { m_itemData[0] = iconData; } + bool isDownloading() const { return m_isDownloading; } + void setDownloadInfo(DownloadInfo downloadInfo) { m_downloadInfo = downloadInfo; } + DownloadInfo getDownloadInfo() const { return m_downloadInfo; } + void setIsDownloading(bool val) { m_isDownloading = val; } + static RowNode* createNode(QMap bookItem, QMap iconMap, RowNode *rootNode); + +private: + QList m_itemData; + QList m_childItems; + RowNode *m_parentItem; + QString m_bookId; + bool m_isDownloading = false; + DownloadInfo m_downloadInfo; +}; + + +#endif // ROWNODE_H