From 80bdeb32edde7add833db5e6536c4c2eb414749e Mon Sep 17 00:00:00 2001 From: Nicolas Mailloux Date: Wed, 6 Jul 2022 14:24:23 -0400 Subject: [PATCH] localLibraryWidget: Implement book options dialog (WIP) This dialog will open if user keeps touch input active on a button from `bookBtnArray` for >= 500 ms. 'Pin' and 'More info' operations are currently not implemented. --- bookinfodialog.ui | 248 ++++++++++++++++++++++------------------- bookoptionsdialog.cpp | 43 +++++++ bookoptionsdialog.h | 30 +++++ bookoptionsdialog.ui | 111 ++++++++++++++++++ functions.h | 28 ++++- homepagewidget.cpp | 7 +- inkbox.pro | 3 + locallibrarywidget.cpp | 23 +++- locallibrarywidget.h | 4 + qclickablelabel.cpp | 10 +- qclickablelabel.h | 2 + userapps.cpp | 3 +- 12 files changed, 393 insertions(+), 119 deletions(-) create mode 100644 bookoptionsdialog.cpp create mode 100644 bookoptionsdialog.h create mode 100644 bookoptionsdialog.ui diff --git a/bookinfodialog.ui b/bookinfodialog.ui index 1146cfa..ed57eb1 100644 --- a/bookinfodialog.ui +++ b/bookinfodialog.ui @@ -42,125 +42,149 @@ - - - 18 + + + 0 - - - - Cover + + + + 0 - - Qt::AlignCenter + + 0 - - - - - - 18 + + 0 - - - - - 75 - true - + + 0 + + + + + 18 - - Book title - - - Qt::AlignCenter - - - true - - - - - - - - 75 - true - - - - GET - - - - - - - Qt::Vertical - - - - 20 - 40 - - - - - - - - Qt::Vertical - - - - 20 - 40 - - - + + + + Cover + + + Qt::AlignCenter + + + + + + + 18 + + + + + + 75 + true + + + + Book title + + + Qt::AlignCenter + + + true + + + + + + + + 75 + true + + + + GET + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - + + + diff --git a/bookoptionsdialog.cpp b/bookoptionsdialog.cpp new file mode 100644 index 0000000..56f1676 --- /dev/null +++ b/bookoptionsdialog.cpp @@ -0,0 +1,43 @@ +#include "bookoptionsdialog.h" +#include "ui_bookoptionsdialog.h" + +#include "functions.h" + +bookOptionsDialog::bookOptionsDialog(QWidget *parent) : + QDialog(parent), + ui(new Ui::bookOptionsDialog) +{ + ui->setupUi(this); + ui->pinBtn->setProperty("type", "borderless"); + ui->deleteBtn->setProperty("type", "borderless"); + ui->infoBtn->setProperty("type", "borderless"); + + bookPath = getBookMetadata(global::localLibrary::bookOptionsDialog::bookID)["BookPath"].toString(); +} + +bookOptionsDialog::~bookOptionsDialog() +{ + delete ui; +} + +void bookOptionsDialog::on_pinBtn_clicked() +{ + // TODO +} + +void bookOptionsDialog::on_deleteBtn_clicked() +{ + log("Deleting book '" + bookPath + "'", className); + QFile::remove(bookPath); + global::localLibrary::bookOptionsDialog::bookDeleted = true; + QFile::remove(global::localLibrary::databasePath); + ui->deleteBtn->setEnabled(false); + ui->deleteBtn->setStyleSheet("padding: 10px; color: lightGrey"); +} + + +void bookOptionsDialog::on_infoBtn_clicked() +{ + // TODO +} + diff --git a/bookoptionsdialog.h b/bookoptionsdialog.h new file mode 100644 index 0000000..2f0b0ed --- /dev/null +++ b/bookoptionsdialog.h @@ -0,0 +1,30 @@ +#ifndef BOOKOPTIONSDIALOG_H +#define BOOKOPTIONSDIALOG_H + +#include +#include + +namespace Ui { +class bookOptionsDialog; +} + +class bookOptionsDialog : public QDialog +{ + Q_OBJECT + +public: + QString className = this->metaObject()->className(); + explicit bookOptionsDialog(QWidget *parent = nullptr); + ~bookOptionsDialog(); + QString bookPath; + +private slots: + void on_pinBtn_clicked(); + void on_deleteBtn_clicked(); + void on_infoBtn_clicked(); + +private: + Ui::bookOptionsDialog *ui; +}; + +#endif // BOOKOPTIONSDIALOG_H diff --git a/bookoptionsdialog.ui b/bookoptionsdialog.ui new file mode 100644 index 0000000..96c3a56 --- /dev/null +++ b/bookoptionsdialog.ui @@ -0,0 +1,111 @@ + + + bookOptionsDialog + + + + 0 + 0 + 400 + 300 + + + + Dialog + + + + 18 + + + 22 + + + 18 + + + 22 + + + + + + + + 75 + true + + + + padding: 10px + + + More info + + + + + + + + 75 + true + + + + padding: 10px + + + Pin + + + + + + + QFrame::Plain + + + 4 + + + Qt::Horizontal + + + + + + + + 75 + true + + + + padding: 10px + + + Delete + + + + + + + QFrame::Plain + + + 4 + + + Qt::Horizontal + + + + + + + + + + diff --git a/functions.h b/functions.h index 1ddefd7..c0a6b23 100644 --- a/functions.h +++ b/functions.h @@ -128,9 +128,15 @@ namespace global { } namespace localLibrary { static inline QString rawDatabasePath = "/inkbox/LocalLibrary.db.raw"; - static inline QString databasePath = "/mnt/onboard/onboard/.inkbox/LocalLibrary.db"; - static inline QString recentBooksDatabasePath = "/mnt/onboard/onboard/.inkbox/RecentBooks.db"; + static inline QString databaseDirectoryPath = "/mnt/onboard/onboard/.database/"; + static inline QString databasePath = databaseDirectoryPath + "LocalLibrary.db"; + static inline QString recentBooksDatabasePath = databaseDirectoryPath + "RecentBooks.db"; + static inline QString pinnedBooksDatabasePath = databaseDirectoryPath + "PinnedBooks.db"; inline bool headless; + namespace bookOptionsDialog { + inline int bookID; + inline bool bookDeleted; + } } namespace localStorage { inline QStringList searchResultsPaths; @@ -977,6 +983,24 @@ namespace { } } } + QJsonObject getBookMetadata(int bookID) { + // Read library database from file + log("Reading database", "functions"); + QFile database(global::localLibrary::databasePath); + QByteArray data; + if(database.open(QIODevice::ReadOnly)) { + data = database.readAll(); + database.close(); + } + else { + QString function = __func__; log(function + ": Failed to open local library database file for reading at '" + database.fileName() + "'", "functions"); + } + + // Parse JSON data + QJsonObject jsonObject = QJsonDocument::fromJson(qUncompress(QByteArray::fromBase64(data))).object(); + QJsonArray jsonArrayList = jsonObject["database"].toArray(); + return jsonArrayList.at(bookID - 1).toObject(); + } } #endif // FUNCTIONS_H diff --git a/homepagewidget.cpp b/homepagewidget.cpp index e73405e..354c5e1 100644 --- a/homepagewidget.cpp +++ b/homepagewidget.cpp @@ -78,7 +78,12 @@ homePageWidget::~homePageWidget() } void homePageWidget::openBook(QString bookPath) { - emit openBookSignal(bookPath, false); + if(!bookPath.isEmpty()) { + emit openBookSignal(bookPath, false); + } + else { + showToast("Book not found"); + } } void homePageWidget::refreshScreenNative() { diff --git a/inkbox.pro b/inkbox.pro index 4451b2e..55463f0 100644 --- a/inkbox.pro +++ b/inkbox.pro @@ -27,6 +27,7 @@ SOURCES += \ alert.cpp \ apps.cpp \ bookinfodialog.cpp \ + bookoptionsdialog.cpp \ brightnessdialog.cpp \ calendarapp.cpp \ dictionarywidget.cpp \ @@ -61,6 +62,7 @@ HEADERS += \ alert.h \ apps.h \ bookinfodialog.h \ + bookoptionsdialog.h \ brightnessdialog.h \ calendarapp.h \ dictionarywidget.h \ @@ -95,6 +97,7 @@ FORMS += \ alert.ui \ apps.ui \ bookinfodialog.ui \ + bookoptionsdialog.ui \ brightnessdialog.ui \ calendarapp.ui \ dictionarywidget.ui \ diff --git a/locallibrarywidget.cpp b/locallibrarywidget.cpp index 24dec63..8823000 100644 --- a/locallibrarywidget.cpp +++ b/locallibrarywidget.cpp @@ -93,7 +93,8 @@ localLibraryWidget::localLibraryWidget(QWidget *parent) : // Book button bookBtnArray[i] = new QClickableLabel(this); bookBtnArray[i]->setObjectName(QString::number(i)); - connect(bookBtnArray[i], SIGNAL(bookID(int)), SLOT(btnOpenBook(int))); + QObject::connect(bookBtnArray[i], &QClickableLabel::bookID, this, &localLibraryWidget::btnOpenBook); + QObject::connect(bookBtnArray[i], &QClickableLabel::longPress, this, &localLibraryWidget::openBookOptionsDialog); bookBtnArray[i]->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding); bookBtnArray[i]->setStyleSheet("color: black; background-color: white; border-radius: 10px; padding: 10px"); bookBtnArray[i]->setFont(QFont("u001")); @@ -356,3 +357,23 @@ void localLibraryWidget::showToast(QString messageToDisplay) { toastWindow->setAttribute(Qt::WA_DeleteOnClose); toastWindow->show(); } + +void localLibraryWidget::openBookOptionsDialog(int bookID) { + log("Opening book options dialog for book with ID " + QString::number(bookID), className); + global::localLibrary::bookOptionsDialog::bookID = bookID; + bookOptionsDialog * bookOptionsDialogWindow = new bookOptionsDialog(this); + QObject::connect(bookOptionsDialogWindow, &bookOptionsDialog::destroyed, this, &localLibraryWidget::handlePossibleBookDeletion); + bookOptionsDialogWindow->setAttribute(Qt::WA_DeleteOnClose); + bookOptionsDialogWindow->setWindowFlags(Qt::FramelessWindowHint | Qt::Popup); + bookOptionsDialogWindow->show(); +} + +void localLibraryWidget::handlePossibleBookDeletion() { + if(global::localLibrary::bookOptionsDialog::bookDeleted == true) { + global::localLibrary::bookOptionsDialog::bookDeleted = false; + global::toast::modalToast = true; + global::toast::indefiniteToast = true; + showToast("Generating database"); + QTimer::singleShot(100, this, SLOT(setupDisplay())); + } +} diff --git a/locallibrarywidget.h b/locallibrarywidget.h index fb65128..47a5891 100644 --- a/locallibrarywidget.h +++ b/locallibrarywidget.h @@ -9,6 +9,7 @@ #include "qclickablelabel.h" #include "generaldialog.h" #include "toast.h" +#include "bookoptionsdialog.h" namespace Ui { class localLibraryWidget; @@ -52,10 +53,13 @@ private slots: void goToPage(int page); void setupDisplay(); void showToast(QString messageToDisplay); + void openBookOptionsDialog(int bookID); + void handlePossibleBookDeletion(); private: Ui::localLibraryWidget * ui; generalDialog * generalDialogWindow; + bookOptionsDialog * bookOptionsDialogWindow; toast * toastWindow; QVector horizontalLayoutArray; QVector bookIconArray; diff --git a/qclickablelabel.cpp b/qclickablelabel.cpp index bcba13b..118f499 100644 --- a/qclickablelabel.cpp +++ b/qclickablelabel.cpp @@ -11,6 +11,7 @@ QClickableLabel::QClickableLabel(QWidget* parent, Qt::WindowFlags f) QClickableLabel::~QClickableLabel() {} void QClickableLabel::mousePressEvent(QMouseEvent * event) { + timeAtClick = QDateTime::currentMSecsSinceEpoch(); emit clicked(); if(objectName() == "pageNumberLabel") { QClickableLabel::setStyleSheet("border-radius: 10px; padding-left: 10px; padding-right: 10px"); @@ -21,8 +22,13 @@ void QClickableLabel::mousePressEvent(QMouseEvent * event) { } void QClickableLabel::mouseReleaseEvent(QMouseEvent * event) { - emit unclicked(); - emit bookID(objectName().toInt()); + if(QDateTime::currentMSecsSinceEpoch() >= timeAtClick + 500) { + emit longPress(objectName().toInt()); + } + else { + emit unclicked(); + emit bookID(objectName().toInt()); + } emit bookPath(QJsonDocument::fromJson(qUncompress(QByteArray::fromBase64(objectName().toUtf8()))).object()["BookPath"].toString()); if(objectName() == "pageNumberLabel") { QClickableLabel::setStyleSheet("border-radius: 10px; padding-left: 10px; padding-right: 10px"); diff --git a/qclickablelabel.h b/qclickablelabel.h index 213884c..7d9a5c9 100644 --- a/qclickablelabel.h +++ b/qclickablelabel.h @@ -10,12 +10,14 @@ class QClickableLabel : public QLabel { public: explicit QClickableLabel(QWidget* parent = Q_NULLPTR, Qt::WindowFlags f = Qt::WindowFlags()); ~QClickableLabel(); + long long timeAtClick; signals: void clicked(); void unclicked(); void bookID(int id); void bookPath(QString path); + void longPress(int id); protected: void mousePressEvent(QMouseEvent * event); diff --git a/userapps.cpp b/userapps.cpp index 37b40f8..7559fd3 100644 --- a/userapps.cpp +++ b/userapps.cpp @@ -156,8 +156,9 @@ void userapps::on_launchBtn_clicked() if(manageRequiredFeatures() == true) { if(global::userApps::launchApp == true) { global::userApps::launchApp = false; - QString message = "Launching user application at: "; + QString message = "Launching user application at: '"; message.append("[" + appDir.path() + "]" + execPath.fileName()); + message.append("'"); log(message, className); // Tell the OS that we're not running anymore string_writeconfig("/tmp/inkbox_running", "false");