From 2289e24602dff38ad8fffd024f236eb9634ad3a2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luis=20=C3=81ngel=20San=20Mart=C3=ADn?= Date: Fri, 21 Nov 2014 18:54:07 +0100 Subject: [PATCH] added label content loading --- YACReaderLibrary/YACReaderLibrary.pro | 6 +- YACReaderLibrary/db/comic_model.cpp | 70 +++++++++++------- YACReaderLibrary/db/comic_model.h | 3 +- YACReaderLibrary/db/reading_list_model.cpp | 3 + YACReaderLibrary/db/reading_list_model.h | 1 + YACReaderLibrary/empty_label_widget.cpp | 49 ++++++++++++ YACReaderLibrary/empty_label_widget.h | 26 +++++++ YACReaderLibrary/images_osx.qrc | 1 + YACReaderLibrary/images_win.qrc | 1 + YACReaderLibrary/library_window.cpp | 7 ++ YACReaderLibrary/library_window.h | 3 + .../yacreader_navigation_controller.cpp | 51 ++++++++++++- .../yacreader_navigation_controller.h | 4 + images/empty_label.png | Bin 0 -> 2715 bytes images/empty_label_osx.png | Bin 0 -> 2637 bytes 15 files changed, 193 insertions(+), 32 deletions(-) create mode 100644 YACReaderLibrary/empty_label_widget.cpp create mode 100644 YACReaderLibrary/empty_label_widget.h create mode 100644 images/empty_label.png create mode 100644 images/empty_label_osx.png diff --git a/YACReaderLibrary/YACReaderLibrary.pro b/YACReaderLibrary/YACReaderLibrary.pro index f389c213..81f8d6b2 100644 --- a/YACReaderLibrary/YACReaderLibrary.pro +++ b/YACReaderLibrary/YACReaderLibrary.pro @@ -127,7 +127,8 @@ HEADERS += comic_flow.h \ yacreader_reading_lists_view.h \ add_label_dialog.h \ yacreader_history_controller.h \ - yacreader_navigation_controller.h + yacreader_navigation_controller.h \ + empty_label_widget.h SOURCES += comic_flow.cpp \ @@ -183,7 +184,8 @@ SOURCES += comic_flow.cpp \ yacreader_reading_lists_view.cpp \ add_label_dialog.cpp \ yacreader_history_controller.cpp \ - yacreader_navigation_controller.cpp + yacreader_navigation_controller.cpp \ + empty_label_widget.cpp include(./server/server.pri) diff --git a/YACReaderLibrary/db/comic_model.cpp b/YACReaderLibrary/db/comic_model.cpp index a2027c46..07c56c1a 100644 --- a/YACReaderLibrary/db/comic_model.cpp +++ b/YACReaderLibrary/db/comic_model.cpp @@ -274,36 +274,50 @@ QStringList ComicModel::getPaths(const QString & _source) return paths; } -void ComicModel::setupModelData(unsigned long long int folderId,const QString & databasePath) +void ComicModel::setupFolderModelData(unsigned long long int folderId,const QString & databasePath) { - //QFile f(QCoreApplication::applicationDirPath()+"/performance.txt"); - //f.open(QIODevice::Append); - beginResetModel(); - //QElapsedTimer timer; - //timer.start(); - qDeleteAll(_data); - _data.clear(); + beginResetModel(); + qDeleteAll(_data); + _data.clear(); - //QTextStream txtS(&f); - //txtS << "TABLEMODEL: Tiempo de borrado: " << timer.elapsed() << "ms\r\n"; - _databasePath = databasePath; - QSqlDatabase db = DataBaseManagement::loadDatabase(databasePath); - { - //crear la consulta - //timer.restart(); - QSqlQuery selectQuery(db); - selectQuery.prepare("select ci.number,ci.title,c.fileName,ci.numPages,c.id,c.parentId,c.path,ci.hash,ci.read,ci.isBis,ci.currentPage,ci.rating,ci.hasBeenOpened from comic c inner join comic_info ci on (c.comicInfoId = ci.id) where c.parentId = :parentId"); - selectQuery.bindValue(":parentId", folderId); - selectQuery.exec(); - //txtS << "TABLEMODEL: Tiempo de consulta: " << timer.elapsed() << "ms\r\n"; - //timer.restart(); - setupModelData(selectQuery); - //txtS << "TABLEMODEL: Tiempo de creaci�n del modelo: " << timer.elapsed() << "ms\r\n"; - //selectQuery.finish(); - } - db.close(); - QSqlDatabase::removeDatabase(_databasePath); - endResetModel(); + _databasePath = databasePath; + QSqlDatabase db = DataBaseManagement::loadDatabase(databasePath); + { + QSqlQuery selectQuery(db); + selectQuery.prepare("select ci.number,ci.title,c.fileName,ci.numPages,c.id,c.parentId,c.path,ci.hash,ci.read,ci.isBis,ci.currentPage,ci.rating,ci.hasBeenOpened from comic c inner join comic_info ci on (c.comicInfoId = ci.id) where c.parentId = :parentId"); + selectQuery.bindValue(":parentId", folderId); + selectQuery.exec(); + setupModelData(selectQuery); + } + db.close(); + QSqlDatabase::removeDatabase(_databasePath); + endResetModel(); + + if(_data.length()==0) + emit isEmpty(); +} + +void ComicModel::setupLabelModelData(unsigned long long parentLabel, const QString &databasePath) +{ + beginResetModel(); + qDeleteAll(_data); + _data.clear(); + + _databasePath = databasePath; + QSqlDatabase db = DataBaseManagement::loadDatabase(databasePath); + { + QSqlQuery selectQuery(db); + selectQuery.prepare("SELECT ci.number,ci.title,c.fileName,ci.numPages,c.id,c.parentId,c.path,ci.hash,ci.read,ci.isBis,ci.currentPage,ci.rating,ci.hasBeenOpened " + "FROM comic c INNER JOIN comic_info ci ON (c.comicInfoId = ci.id) " + "INNER JOIN comic_label cl ON (c.id == cl.comic_id) " + "WHERE cl.label_id = :parentLabelId"); + selectQuery.bindValue(":parentLabelId", parentLabel); + selectQuery.exec(); + setupModelData(selectQuery); + } + db.close(); + QSqlDatabase::removeDatabase(_databasePath); + endResetModel(); if(_data.length()==0) emit isEmpty(); diff --git a/YACReaderLibrary/db/comic_model.h b/YACReaderLibrary/db/comic_model.h index 48d9ac65..3e808c3f 100644 --- a/YACReaderLibrary/db/comic_model.h +++ b/YACReaderLibrary/db/comic_model.h @@ -34,7 +34,8 @@ public: QModelIndex parent(const QModelIndex &index) const; int rowCount(const QModelIndex &parent = QModelIndex()) const; int columnCount(const QModelIndex &parent = QModelIndex()) const; - void setupModelData(unsigned long long int parentFolder,const QString & databasePath); + void setupFolderModelData(unsigned long long int parentFolder,const QString & databasePath); + void setupLabelModelData(unsigned long long int parentLabel, const QString & databasePath); //configures the model for showing the comics matching the filter criteria. void setupModelData(const SearchModifiers modifier, const QString & filter, const QString & databasePath); diff --git a/YACReaderLibrary/db/reading_list_model.cpp b/YACReaderLibrary/db/reading_list_model.cpp index 6057a106..9f7185be 100644 --- a/YACReaderLibrary/db/reading_list_model.cpp +++ b/YACReaderLibrary/db/reading_list_model.cpp @@ -73,6 +73,9 @@ QVariant ReadingListModel::data(const QModelIndex &index, int role) const return QVariant(ReadingListModel::Separator); } + if (role == ReadingListModel::IDRole) + return item->getId(); + if(typeid(*item) == typeid(ReadingListSeparatorItem)) return QVariant(); diff --git a/YACReaderLibrary/db/reading_list_model.h b/YACReaderLibrary/db/reading_list_model.h index ee50bef7..fb801d3c 100644 --- a/YACReaderLibrary/db/reading_list_model.h +++ b/YACReaderLibrary/db/reading_list_model.h @@ -52,6 +52,7 @@ public: enum Roles { TypeListsRole = Qt::UserRole + 1, + IDRole }; enum TypeList { diff --git a/YACReaderLibrary/empty_label_widget.cpp b/YACReaderLibrary/empty_label_widget.cpp new file mode 100644 index 00000000..35d2fe9d --- /dev/null +++ b/YACReaderLibrary/empty_label_widget.cpp @@ -0,0 +1,49 @@ +#include "empty_label_widget.h" + +EmptyLabelWidget::EmptyLabelWidget(QWidget *parent) : + QWidget(parent) +{ +#ifdef Q_OS_MAC + backgroundColor = "#FFFFFF"; +#else + backgroundColor = "#2A2A2A"; +#endif + + QVBoxLayout * layout = new QVBoxLayout; + + iconLabel = new QLabel(); + iconLabel->setPixmap(QPixmap(":/images/empty_label.png")); + iconLabel->setAlignment(Qt::AlignCenter); + + //titleLabel->setText(tr("This label doesn't contain comics yet") + QString("

%1

").arg(tr("Drag and drop folders and comics here"))); + titleLabel = new QLabel(("This label doesn't contain comics yet")); + titleLabel->setAlignment(Qt::AlignCenter); + +#ifdef Q_OS_MAC + titleLabel->setStyleSheet("QLabel {color:#888888; font-size:24px;font-family:Arial;font-weight:bold;}"); +#else + titleLabel->setStyleSheet("QLabel {color:#CCCCCC; font-size:24px;font-family:Arial;font-weight:bold;}"); +#endif + + layout->addSpacing(100); + layout->addWidget(iconLabel); + layout->addSpacing(30); + layout->addWidget(titleLabel); + layout->addStretch(); + + setLayout(layout); +} + +void EmptyLabelWidget::setColor(YACReader::LabelColors color) +{ + //TODO tint the widget depending on color + //backgroundColor = "#FF0000"; + + //repaint(); +} + +void EmptyLabelWidget::paintEvent(QPaintEvent * event) +{ + QPainter painter (this); + painter.fillRect(0,0,width(),height(),QColor(backgroundColor)); +} diff --git a/YACReaderLibrary/empty_label_widget.h b/YACReaderLibrary/empty_label_widget.h new file mode 100644 index 00000000..ac76f722 --- /dev/null +++ b/YACReaderLibrary/empty_label_widget.h @@ -0,0 +1,26 @@ +#ifndef EMPTY_LABEL_WIDGET_H +#define EMPTY_LABEL_WIDGET_H + +#include +#include "yacreader_global.h" + +class EmptyLabelWidget : public QWidget +{ + Q_OBJECT +public: + explicit EmptyLabelWidget(QWidget *parent = 0); + void setColor(YACReader::LabelColors color); + void paintEvent(QPaintEvent *event); + +signals: + +public slots: + +protected: + QLabel * iconLabel; + QLabel * titleLabel; + QString backgroundColor; + +}; + +#endif // EMPTY_LABEL_WIDGET_H diff --git a/YACReaderLibrary/images_osx.qrc b/YACReaderLibrary/images_osx.qrc index 65aed99b..9d873f1a 100644 --- a/YACReaderLibrary/images_osx.qrc +++ b/YACReaderLibrary/images_osx.qrc @@ -25,6 +25,7 @@ ../images/flow_to_grid.gif ../images/grid_to_flow.gif ../images/empty_folder_osx.png + ../images/empty_label_osx.png ../images/empty_search_osx.png ../images/iconSearch.png ../images/clearSearch.png diff --git a/YACReaderLibrary/images_win.qrc b/YACReaderLibrary/images_win.qrc index f0f62517..40f2f769 100644 --- a/YACReaderLibrary/images_win.qrc +++ b/YACReaderLibrary/images_win.qrc @@ -19,6 +19,7 @@ ../images/flow_to_grid.gif ../images/grid_to_flow.gif ../images/empty_folder.png + ../images/empty_label.png ../images/empty_search.png ../images/addNew_sidebar.png ../images/delete_sidebar.png diff --git a/YACReaderLibrary/library_window.cpp b/YACReaderLibrary/library_window.cpp index 3a5f7e22..246fccc1 100644 --- a/YACReaderLibrary/library_window.cpp +++ b/YACReaderLibrary/library_window.cpp @@ -65,6 +65,7 @@ #include "grid_comics_view.h" #include "comics_view_transition.h" #include "empty_folder_widget.h" +#include "empty_label_widget.h" #include "edit_shortcuts_dialog.h" #include "shortcuts_manager.h" @@ -240,6 +241,7 @@ void LibraryWindow::doLayout() comicsView->setToolBar(editInfoToolBar); comicsViewStack->addWidget(comicsViewTransition = new ComicsViewTransition()); comicsViewStack->addWidget(emptyFolderWidget = new EmptyFolderWidget()); + comicsViewStack->addWidget(emptyLabelWidget = new EmptyLabelWidget()); comicsViewStack->addWidget(noSearchResultsWidget = new NoSearchResultsWidget()); comicsViewStack->addWidget(comicsView); @@ -2153,6 +2155,11 @@ void LibraryWindow::showEmptyFolderView() comicsViewStack->setCurrentWidget(emptyFolderWidget); } +void LibraryWindow::showEmptyLabelView() +{ + comicsViewStack->setCurrentWidget(emptyLabelWidget); +} + void LibraryWindow::showNoSearchResultsView() { comicsViewStack->setCurrentWidget(noSearchResultsWidget); diff --git a/YACReaderLibrary/library_window.h b/YACReaderLibrary/library_window.h index 7d81bb4f..8602d517 100644 --- a/YACReaderLibrary/library_window.h +++ b/YACReaderLibrary/library_window.h @@ -68,6 +68,7 @@ class ReadingListModel; class ReadingListModelProxy; class YACReaderReadingListsView; class YACReaderHistoryController; +class EmptyLabelWidget; #include "comic_db.h" @@ -121,6 +122,7 @@ private: QStackedWidget * comicsViewStack; ComicsViewTransition * comicsViewTransition; EmptyFolderWidget * emptyFolderWidget; + EmptyLabelWidget * emptyLabelWidget; NoSearchResultsWidget * noSearchResultsWidget; YACReaderFoldersView * foldersView; @@ -358,6 +360,7 @@ public slots: void toggleComicsView_delayed();//used in orther to avoid flickering; void showComicsView(); void showEmptyFolderView(); + void showEmptyLabelView(); void showNoSearchResultsView(); void toggleComicsView(); void checkSearchNumResults(int numResults); diff --git a/YACReaderLibrary/yacreader_navigation_controller.cpp b/YACReaderLibrary/yacreader_navigation_controller.cpp index 35a85a13..71543346 100644 --- a/YACReaderLibrary/yacreader_navigation_controller.cpp +++ b/YACReaderLibrary/yacreader_navigation_controller.cpp @@ -13,6 +13,8 @@ #include "comics_view.h" #include "empty_folder_widget.h" #include "yacreader_search_line_edit.h" +#include "yacreader_global.h" +#include "empty_label_widget.h" #include "QsLog.h" @@ -56,7 +58,7 @@ void YACReaderNavigationController::loadFolderInfo(const QModelIndex &modelIndex qulonglong folderId = folderModelIndexToID(modelIndex); //check comics in folder with id = folderId - libraryWindow->comicsModel->setupModelData(folderId,libraryWindow->foldersModel->getDatabase()); + libraryWindow->comicsModel->setupFolderModelData(folderId,libraryWindow->foldersModel->getDatabase()); libraryWindow->comicsView->setModel(libraryWindow->comicsModel); //configure views @@ -77,6 +79,53 @@ void YACReaderNavigationController::loadFolderInfo(const QModelIndex &modelIndex } void YACReaderNavigationController::loadListInfo(const QModelIndex &modelIndex) +{ + qulonglong id = modelIndex.data(ReadingListModel::IDRole).toULongLong(); + + switch(modelIndex.data(ReadingListModel::TypeListsRole).toInt()) + { + case ReadingListModel::SpecialList: + loadSpecialListInfo(id); + break; + + case ReadingListModel::Label: + loadLabelInfo(id); + break; + + case ReadingListModel::ReadingList: + loadReadingListInfo(id); + break; + } +} + +void YACReaderNavigationController::loadSpecialListInfo(const qulonglong id) +{ + +} + +void YACReaderNavigationController::loadLabelInfo(const qulonglong id) +{ + //check comics in folder with id = folderId + libraryWindow->comicsModel->setupLabelModelData(id,libraryWindow->foldersModel->getDatabase()); + libraryWindow->comicsView->setModel(libraryWindow->comicsModel); + + //configure views + if(libraryWindow->comicsModel->rowCount() > 0) + { + //updateView + libraryWindow->showComicsView(); + libraryWindow->disableComicsActions(false); + } + else{ + //showEmptyFolder + //loadEmptyLabelInfo(); //there is no info in an empty label by now, TODO design something + //TODO libraryWindow->emptyLabelWidget->setColor(YACReader::YRed); + libraryWindow->showEmptyLabelView(); + libraryWindow->disableComicsActions(true); + } +} + +void YACReaderNavigationController::loadReadingListInfo(const qulonglong id) { } diff --git a/YACReaderLibrary/yacreader_navigation_controller.h b/YACReaderLibrary/yacreader_navigation_controller.h index 5375adce..98bdb66f 100644 --- a/YACReaderLibrary/yacreader_navigation_controller.h +++ b/YACReaderLibrary/yacreader_navigation_controller.h @@ -30,6 +30,10 @@ public slots: void loadFolderInfo(const QModelIndex & modelIndex); void loadListInfo(const QModelIndex & modelIndex); + void loadSpecialListInfo(const qulonglong id); + void loadLabelInfo(const qulonglong id); + void loadReadingListInfo(const qulonglong id); + void loadPreviousStatus(); private: diff --git a/images/empty_label.png b/images/empty_label.png new file mode 100644 index 0000000000000000000000000000000000000000..58ea44bca7a6bf94d0b385f36d9194c2c6ce0a2b GIT binary patch literal 2715 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 kA=;=x_Vm4DLlF>TDhv(v-^T&}4