diff --git a/YACReaderLibrary/YACReaderLibrary.pro b/YACReaderLibrary/YACReaderLibrary.pro index 4162cb36..d0f0f0d3 100644 --- a/YACReaderLibrary/YACReaderLibrary.pro +++ b/YACReaderLibrary/YACReaderLibrary.pro @@ -79,6 +79,7 @@ HEADERS += comic_flow.h \ ../common/concurrent_queue.h \ create_library_dialog.h \ db/comic_query_result_procesor.h \ + db/folder_query_result_processor.h \ db/query_lexer.h \ library_creator.h \ library_window.h \ @@ -156,6 +157,7 @@ HEADERS += comic_flow.h \ SOURCES += comic_flow.cpp \ create_library_dialog.cpp \ db/comic_query_result_procesor.cpp \ + db/folder_query_result_processor.cpp \ db/query_lexer.cpp \ library_creator.cpp \ library_window.cpp \ diff --git a/YACReaderLibrary/db/folder_model.cpp b/YACReaderLibrary/db/folder_model.cpp index 1944e1e1..b20ff402 100644 --- a/YACReaderLibrary/db/folder_model.cpp +++ b/YACReaderLibrary/db/folder_model.cpp @@ -1,54 +1,6 @@ -/**************************************************************************** -** -** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the examples of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:BSD$ -** You may use this file under the terms of the BSD license as follows: -** -** "Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions are -** met: -** * Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** * Redistributions in binary form must reproduce the above copyright -** notice, this list of conditions and the following disclaimer in -** the documentation and/or other materials provided with the -** distribution. -** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor -** the names of its contributors may be used to endorse or promote -** products derived from this software without specific prior written -** permission. -** -** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." -** $QT_END_LICENSE$ -** -****************************************************************************/ - -/* - treemodel.cpp - - Provides a simple tree model to show how to create and use hierarchical - models. -*/ - -#include +#include "folder_model.h" #include "folder_item.h" -#include "folder_model.h" #include "data_base_management.h" #include "folder.h" #include "db_helper.h" @@ -57,6 +9,8 @@ #include "QsLog.h" #include "query_parser.h" +#include + #ifdef Q_OS_MAC #include QIcon finishedFolderIcon; @@ -104,7 +58,6 @@ FolderModel::FolderModel(QObject *parent) connect(this, SIGNAL(reset()), this, SIGNAL(modelReset())); } -//! [0] FolderModel::FolderModel(QSqlQuery &sqlquery, QObject *parent) : QAbstractItemModel(parent), rootItem(0) { @@ -117,17 +70,13 @@ FolderModel::FolderModel(QSqlQuery &sqlquery, QObject *parent) setupModelData(sqlquery, rootItem); //sqlquery.finish(); } -//! [0] -//! [1] FolderModel::~FolderModel() { if (rootItem != 0) delete rootItem; } -//! [1] -//! [2] int FolderModel::columnCount(const QModelIndex &parent) const { if (parent.isValid()) @@ -135,9 +84,7 @@ int FolderModel::columnCount(const QModelIndex &parent) const else return rootItem->columnCount(); } -//! [2] -//! [3] QVariant FolderModel::data(const QModelIndex &index, int role) const { if (!index.isValid()) @@ -188,9 +135,7 @@ QVariant FolderModel::data(const QModelIndex &index, int role) const return item->data(index.column()); } -//! [3] -//! [4] Qt::ItemFlags FolderModel::flags(const QModelIndex &index) const { if (!index.isValid()) @@ -198,9 +143,7 @@ Qt::ItemFlags FolderModel::flags(const QModelIndex &index) const return Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsDropEnabled | Qt::ItemIsDragEnabled; } -//! [4] -//! [5] QVariant FolderModel::headerData(int section, Qt::Orientation orientation, int role) const { @@ -209,9 +152,7 @@ QVariant FolderModel::headerData(int section, Qt::Orientation orientation, return QVariant(); } -//! [5] -//! [6] QModelIndex FolderModel::index(int row, int column, const QModelIndex &parent) const { @@ -231,9 +172,7 @@ QModelIndex FolderModel::index(int row, int column, const QModelIndex &parent) else return QModelIndex(); } -//! [6] -//! [7] QModelIndex FolderModel::parent(const QModelIndex &index) const { if (!index.isValid()) @@ -247,19 +186,7 @@ QModelIndex FolderModel::parent(const QModelIndex &index) const return createIndex(parentItem->row(), 0, parentItem); } -//! [7] -/* -QModelIndex FolderModel::indexFromItem(FolderItem * item,int column) -{ - //if(item->parent() != 0) - // return index(item->row(),column,parent(indexFromItem(item->parent(),column-1))); - //else - // return index(item->row(),0,QModelIndex()); - return createIndex(item->row(), column, item); -}*/ - -//! [8] int FolderModel::rowCount(const QModelIndex &parent) const { FolderItem *parentItem; @@ -273,7 +200,6 @@ int FolderModel::rowCount(const QModelIndex &parent) const return parentItem->childCount(); } -//! [8] void FolderModel::setupModelData(QString path) { @@ -386,27 +312,6 @@ QString FolderModel::getFolderPath(const QModelIndex &folder) return static_cast(folder.internalPointer())->data(FolderModel::Path).toString(); } -/* -void FolderModel::resetFilter() -{ - beginResetModel(); - filter = ""; - includeComics = false; - //TODO hay que liberar la memoria reservada para el filtrado - //items.clear(); - filteredItems.clear(); - FolderItem * root = rootItem; - rootItem = rootBeforeFilter; //TODO si no se aplica el filtro previamente, esto invalidar�a en modelo - if(root !=0) - delete root; - - rootBeforeFilter = 0; - filterEnabled = false; - endResetModel(); - - -}*/ - void FolderModel::updateFolderCompletedStatus(const QModelIndexList &list, bool status) { QString connectionName = ""; @@ -626,7 +531,7 @@ void FolderModel::updateFolderChildrenInfo(qulonglong folderId) //PROXY FolderModelProxy::FolderModelProxy(QObject *parent) - : QSortFilterProxyModel(parent), rootItem(0), includeComics(true), filter(""), filterEnabled(false) + : QSortFilterProxyModel(parent), rootItem(0), filterEnabled(false) { } @@ -649,93 +554,23 @@ bool FolderModelProxy::filterAcceptsRow(int source_row, const QModelIndex &sourc return filteredItems.contains(item->id); } -void FolderModelProxy::setFilter(const YACReader::SearchModifiers modifier, QString filter, bool includeComics) +void FolderModelProxy::setFilterData(QMap *filteredItems, FolderItem *root) { clear(); - this->filter = filter; - this->includeComics = includeComics; - this->modifier = modifier; filterEnabled = true; - setupFilteredModelData(); -} -void FolderModelProxy::setupFilteredModelData() -{ beginResetModel(); - //TODO hay que liberar memoria de anteriores filtrados - - //inicializar el nodo ra�z - if (rootItem != 0) delete rootItem; //TODO comprobar que se libera bien la memoria - rootItem = 0; + rootItem = root; - //inicializar el nodo ra�z - QList rootData; - rootData << "root"; - rootItem = new FolderItem(rootData); - rootItem->id = ROOT; - rootItem->parentItem = 0; + this->filteredItems.insert(*filteredItems); - auto model = static_cast(sourceModel()); + endResetModel(); - QString connectionName = ""; - { - QSqlDatabase db = DataBaseManagement::loadDatabase(model->_databasePath); - - QSqlQuery selectQuery(db); //TODO check - if (!includeComics) { - selectQuery.prepare("select * from folder where id <> 1 and upper(name) like upper(:filter) order by parentId,name "); - selectQuery.bindValue(":filter", "%%" + filter + "%%"); - } else { - std::string queryString("SELECT DISTINCT f.id, f.parentId, f.name, f.path, f.finished, f.completed " - "FROM folder f LEFT JOIN comic c ON (f.id = c.parentId) " - "INNER JOIN comic_info ci ON (c.comicInfoId = ci.id) WHERE "); - - try { - QueryParser parser; - auto result = parser.parse(filter.toStdString()); - result.buildSqlString(queryString); - - switch (modifier) { - case YACReader::NoModifiers: - queryString += " AND f.id <> 1 ORDER BY f.parentId,f.name"; - break; - - case YACReader::OnlyRead: - queryString += " AND f.id <> 1 AND ci.read = 1 ORDER BY f.parentId,f.name"; - break; - - case YACReader::OnlyUnread: - queryString += " AND f.id <> 1 AND ci.read = 0 ORDER BY f.parentId,f.name"; - break; - - default: - queryString += " AND f.id <> 1 ORDER BY f.parentId,f.name"; - QLOG_ERROR() << "not implemented"; - break; - } - - selectQuery.prepare(queryString.c_str()); - result.bindValues(selectQuery); - - selectQuery.exec(); - QLOG_DEBUG() << selectQuery.lastError() << "--"; - - setupFilteredModelData(selectQuery, rootItem); - } catch (const std::exception &e) { - QLOG_ERROR() << "Unable to parse query: " << e.what(); - } - } - - connectionName = db.connectionName(); - - endResetModel(); - } - - QSqlDatabase::removeDatabase(connectionName); + delete filteredItems; } void FolderModelProxy::clear() @@ -746,88 +581,3 @@ void FolderModelProxy::clear() QSortFilterProxyModel::clear(); } - -void FolderModelProxy::setupFilteredModelData(QSqlQuery &sqlquery, FolderItem *parent) -{ - auto model = static_cast(sourceModel()); - - //64 bits para la primary key, es decir la misma precisi�n que soporta sqlit 2^64 - filteredItems.clear(); - - //se a�ade el nodo 0 al modelo que representa el arbol de elementos que cumplen con el filtro - filteredItems.insert(parent->id, parent); - - QSqlRecord record = sqlquery.record(); - - int name = record.indexOf("name"); - int path = record.indexOf("path"); - int finished = record.indexOf("finished"); - int completed = record.indexOf("completed"); - int parentIdIndex = record.indexOf("parentId"); - - while (sqlquery.next()) { //se procesan todos los folders que cumplen con el filtro - //datos de la base de datos - QList data; - - data << sqlquery.value(name).toString(); - data << sqlquery.value(path).toString(); - data << sqlquery.value(finished).toBool(); - data << sqlquery.value(completed).toBool(); - - auto item = new FolderItem(data); - item->id = sqlquery.value(0).toULongLong(); - - //id del padre - quint64 parentId = sqlquery.value(parentIdIndex).toULongLong(); - - //se a�ade el item al map, de forma que se pueda encontrar como padre en siguientes iteraciones - if (!filteredItems.contains(item->id)) - filteredItems.insert(item->id, item); - - //es necesario conocer las coordenadas de origen para poder realizar scroll autom�tico en la vista - item->originalItem = model->items.value(item->id); - - //si el padre ya existe en el modelo, el item se a�ade como hijo - if (filteredItems.contains(parentId)) - filteredItems.value(parentId)->appendChild(item); - else //si el padre a�n no se ha a�adido, hay que a�adirlo a �l y todos los padres hasta el nodo ra�z - { - //comprobamos con esta variable si el �ltimo de los padres (antes del nodo ra�z) ya exist�a en el modelo - bool parentPreviousInserted = false; - - //mientras no se alcance el nodo ra�z se procesan todos los padres (de abajo a arriba) - while (parentId != ROOT) { - //el padre no estaba en el modelo filtrado, as� que se rescata del modelo original - FolderItem *parentItem = model->items.value(parentId); - //se debe crear un nuevo nodo (para no compartir los hijos con el nodo original) - FolderItem *newparentItem = new FolderItem(parentItem->getData()); //padre que se a�adir� a la estructura de directorios filtrados - newparentItem->id = parentId; - - newparentItem->originalItem = parentItem; - - //si el modelo contiene al padre, se a�ade el item actual como hijo - if (filteredItems.contains(parentId)) { - filteredItems.value(parentId)->appendChild(item); - parentPreviousInserted = true; - } - //sino se registra el nodo para poder encontrarlo con posterioridad y se a�ade el item actual como hijo - else { - newparentItem->appendChild(item); - filteredItems.insert(newparentItem->id, newparentItem); - parentPreviousInserted = false; - } - - //variables de control del bucle, se avanza hacia el nodo padre - item = newparentItem; - parentId = parentItem->parentItem->id; - } - - //si el nodo es hijo de 1 y no hab�a sido previamente insertado como hijo, se a�ade como tal - if (!parentPreviousInserted) { - filteredItems.value(ROOT)->appendChild(item); - } else { - delete item; - } - } - } -} diff --git a/YACReaderLibrary/db/folder_model.h b/YACReaderLibrary/db/folder_model.h index ecac40ee..9597d07c 100644 --- a/YACReaderLibrary/db/folder_model.h +++ b/YACReaderLibrary/db/folder_model.h @@ -1,43 +1,3 @@ -/**************************************************************************** -** -** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the examples of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:BSD$ -** You may use this file under the terms of the BSD license as follows: -** -** "Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions are -** met: -** * Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** * Redistributions in binary form must reproduce the above copyright -** notice, this list of conditions and the following disclaimer in -** the documentation and/or other materials provided with the -** distribution. -** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor -** the names of its contributors may be used to endorse or promote -** products derived from this software without specific prior written -** permission. -** -** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." -** $QT_END_LICENSE$ -** -****************************************************************************/ - #ifndef TREEMODEL_H #define TREEMODEL_H @@ -49,6 +9,7 @@ #include #include "yacreader_global.h" +#include "folder_query_result_processor.h" class FolderItem; @@ -59,9 +20,7 @@ public: explicit FolderModelProxy(QObject *parent = 0); ~FolderModelProxy() override; - void setFilter(const YACReader::SearchModifiers modifier, QString filter, bool includeComics); - void setupFilteredModelData(QSqlQuery &sqlquery, FolderItem *parent); - void setupFilteredModelData(); + void setFilterData(QMap *filteredItems, FolderItem *root); void clear(); bool filterAcceptsRow(int source_row, const QModelIndex &source_parent) const override; @@ -70,8 +29,6 @@ protected: FolderItem *rootItem; QMap filteredItems; //relación entre folders - bool includeComics; - QString filter; bool filterEnabled; YACReader::SearchModifiers modifier; @@ -79,10 +36,10 @@ protected: class FolderModel : public QAbstractItemModel { - Q_OBJECT friend class FolderModelProxy; + friend class YACReader::FolderQueryResultProcessor; public: FolderModel(QObject *parent = 0); @@ -147,6 +104,5 @@ signals: void beforeReset(); void reset(); }; -//! [0] #endif diff --git a/YACReaderLibrary/db/folder_query_result_processor.cpp b/YACReaderLibrary/db/folder_query_result_processor.cpp new file mode 100644 index 00000000..e0b6050d --- /dev/null +++ b/YACReaderLibrary/db/folder_query_result_processor.cpp @@ -0,0 +1,176 @@ +#include "folder_query_result_processor.h" + +#include "folder_item.h" +#include "qnaturalsorting.h" +#include "yacreader_global_gui.h" +#include "query_parser.h" +#include "folder_model.h" +#include "data_base_management.h" + +#include "QsLog.h" + +#include +#include + +//Copy/pasted from "folder_model.cpp" +#define ROOT 1 + +YACReader::FolderQueryResultProcessor::FolderQueryResultProcessor(FolderModel *model) + : querySearchQueue(1), model(model) +{ +} + +void YACReader::FolderQueryResultProcessor::createModelData(const YACReader::SearchModifiers modifier, const QString &filter, bool includeComics) +{ + querySearchQueue.cancellPending(); + + QString connectionName = ""; + { + QSqlDatabase db = DataBaseManagement::loadDatabase(model->getDatabase()); + + QSqlQuery selectQuery(db); //TODO check + if (!includeComics) { + selectQuery.prepare("select * from folder where id <> 1 and upper(name) like upper(:filter) order by parentId,name "); + selectQuery.bindValue(":filter", "%%" + filter + "%%"); + } else { + std::string queryString("SELECT DISTINCT f.id, f.parentId, f.name, f.path, f.finished, f.completed " + "FROM folder f LEFT JOIN comic c ON (f.id = c.parentId) " + "INNER JOIN comic_info ci ON (c.comicInfoId = ci.id) WHERE "); + + try { + QueryParser parser; + auto result = parser.parse(filter.toStdString()); + result.buildSqlString(queryString); + + switch (modifier) { + case YACReader::NoModifiers: + queryString += " AND f.id <> 1 ORDER BY f.parentId,f.name"; + break; + + case YACReader::OnlyRead: + queryString += " AND f.id <> 1 AND ci.read = 1 ORDER BY f.parentId,f.name"; + break; + + case YACReader::OnlyUnread: + queryString += " AND f.id <> 1 AND ci.read = 0 ORDER BY f.parentId,f.name"; + break; + + default: + queryString += " AND f.id <> 1 ORDER BY f.parentId,f.name"; + QLOG_ERROR() << "not implemented"; + break; + } + + selectQuery.prepare(queryString.c_str()); + result.bindValues(selectQuery); + + selectQuery.exec(); + QLOG_DEBUG() << selectQuery.lastError() << "--"; + + setupFilteredModelData(selectQuery); + } catch (const std::exception &e) { + //Do nothing, uncomplete search string will end here and it is part of how the QueryParser works + //I don't like the idea of using exceptions for this though + } + } + + connectionName = db.connectionName(); + } + + QSqlDatabase::removeDatabase(connectionName); +} + +void YACReader::FolderQueryResultProcessor::setupFilteredModelData(QSqlQuery &sqlquery) +{ + FolderItem *rootItem = 0; + + //inicializar el nodo ra�z + QList rootData; + rootData << "root"; + rootItem = new FolderItem(rootData); + rootItem->id = ROOT; + rootItem->parentItem = 0; + + FolderItem *parent = rootItem; + + QMap *filteredItems = new QMap(); + + //add tree root node + filteredItems->insert(parent->id, parent); + + QSqlRecord record = sqlquery.record(); + + int name = record.indexOf("name"); + int path = record.indexOf("path"); + int finished = record.indexOf("finished"); + int completed = record.indexOf("completed"); + int parentIdIndex = record.indexOf("parentId"); + + while (sqlquery.next()) { //se procesan todos los folders que cumplen con el filtro + //datos de la base de datos + QList data; + + data << sqlquery.value(name).toString(); + data << sqlquery.value(path).toString(); + data << sqlquery.value(finished).toBool(); + data << sqlquery.value(completed).toBool(); + + auto item = new FolderItem(data); + item->id = sqlquery.value(0).toULongLong(); + + //id del padre + quint64 parentId = sqlquery.value(parentIdIndex).toULongLong(); + + //se a�ade el item al map, de forma que se pueda encontrar como padre en siguientes iteraciones + if (!filteredItems->contains(item->id)) + filteredItems->insert(item->id, item); + + //es necesario conocer las coordenadas de origen para poder realizar scroll autom�tico en la vista + item->originalItem = model->items.value(item->id); + + //si el padre ya existe en el modelo, el item se a�ade como hijo + if (filteredItems->contains(parentId)) + filteredItems->value(parentId)->appendChild(item); + else //si el padre a�n no se ha a�adido, hay que a�adirlo a �l y todos los padres hasta el nodo ra�z + { + //comprobamos con esta variable si el �ltimo de los padres (antes del nodo ra�z) ya exist�a en el modelo + bool parentPreviousInserted = false; + + //mientras no se alcance el nodo ra�z se procesan todos los padres (de abajo a arriba) + while (parentId != ROOT) { + //el padre no estaba en el modelo filtrado, as� que se rescata del modelo original + FolderItem *parentItem = model->items.value(parentId); + //se debe crear un nuevo nodo (para no compartir los hijos con el nodo original) + FolderItem *newparentItem = new FolderItem(parentItem->getData()); //padre que se a�adir� a la estructura de directorios filtrados + newparentItem->id = parentId; + + newparentItem->originalItem = parentItem; + + //si el modelo contiene al padre, se a�ade el item actual como hijo + if (filteredItems->contains(parentId)) { + filteredItems->value(parentId)->appendChild(item); + parentPreviousInserted = true; + } + //sino se registra el nodo para poder encontrarlo con posterioridad y se a�ade el item actual como hijo + else { + newparentItem->appendChild(item); + filteredItems->insert(newparentItem->id, newparentItem); + parentPreviousInserted = false; + } + + //variables de control del bucle, se avanza hacia el nodo padre + item = newparentItem; + parentId = parentItem->parentItem->id; + } + + //si el nodo es hijo de 1 y no hab�a sido previamente insertado como hijo, se a�ade como tal + if (!parentPreviousInserted) { + filteredItems->value(ROOT)->appendChild(item); + } else { + delete item; + } + } + } + + emit newData(filteredItems, rootItem); +} diff --git a/YACReaderLibrary/db/folder_query_result_processor.h b/YACReaderLibrary/db/folder_query_result_processor.h new file mode 100644 index 00000000..a5612080 --- /dev/null +++ b/YACReaderLibrary/db/folder_query_result_processor.h @@ -0,0 +1,36 @@ +#ifndef FOLDER_QUERY_RESULT_PROCESSOR_H +#define FOLDER_QUERY_RESULT_PROCESSOR_H + +#include + +#include "yacreader_global_gui.h" +#include "concurrent_queue.h" + +class FolderItem; +class FolderModel; +class QSqlQuery; + +namespace YACReader { + +class FolderQueryResultProcessor : public QObject +{ + Q_OBJECT +public: + FolderQueryResultProcessor(FolderModel *model); + +public slots: + void createModelData(const SearchModifiers modifier, const QString &filter, bool includeComics); + +signals: + void newData(QMap *filteredItems, FolderItem *root); + +private: + ConcurrentQueue querySearchQueue; + + FolderModel *model; + + void setupFilteredModelData(QSqlQuery &sqlquery); +}; +}; + +#endif // FOLDER_QUERY_RESULT_PROCESSOR_H diff --git a/YACReaderLibrary/library_window.cpp b/YACReaderLibrary/library_window.cpp index aad471a7..65f66b61 100644 --- a/YACReaderLibrary/library_window.cpp +++ b/YACReaderLibrary/library_window.cpp @@ -400,6 +400,7 @@ void LibraryWindow::doModels() //folders foldersModel = new FolderModel(); foldersModelProxy = new FolderModelProxy(); + folderQueryResultProcessor = new FolderQueryResultProcessor(foldersModel); //foldersModelProxy->setSourceModel(foldersModel); //comics comicsModel = new ComicModel(this); @@ -1056,6 +1057,7 @@ void LibraryWindow::createConnections() //Search filter connect(searchEdit, SIGNAL(filterChanged(YACReader::SearchModifiers, QString)), this, SLOT(setSearchFilter(YACReader::SearchModifiers, QString))); connect(&comicQueryResultProcesor, &ComicQueryResultProcesor::newData, this, &LibraryWindow::setComicSearchFilterData); + connect(folderQueryResultProcessor, &FolderQueryResultProcessor::newData, this, &LibraryWindow::setFolderSearchFilterData); //ContextMenus connect(openContainingFolderComicAction, SIGNAL(triggered()), this, SLOT(openContainingFolderComic())); @@ -2069,8 +2071,7 @@ void LibraryWindow::toNormal() void LibraryWindow::setSearchFilter(const YACReader::SearchModifiers modifier, QString filter) { if (!filter.isEmpty()) { - //TODO move search query for folders to its own async processor - foldersModelProxy->setFilter(modifier, filter, true); //includeComicsCheckBox->isChecked()); + folderQueryResultProcessor->createModelData(modifier, filter, true); comicQueryResultProcesor.createModelData(modifier, filter, foldersModel->getDatabase()); } else if (status == LibraryWindow::Searching) { //if no searching, then ignore this clearSearchFilter(); @@ -2085,7 +2086,6 @@ void LibraryWindow::setComicSearchFilterData(QList *data, const QSt comicsModel->setModelData(data, databasePath); comicsViewsManager->comicsView->enableFilterMode(true); comicsViewsManager->comicsView->setModel(comicsModel); //TODO, columns are messed up after ResetModel some times, this shouldn't be necesary - foldersView->expandAll(); if (comicsModel->rowCount() == 0) comicsViewsManager->showNoSearchResultsView(); @@ -2093,6 +2093,12 @@ void LibraryWindow::setComicSearchFilterData(QList *data, const QSt comicsViewsManager->showComicsView(); } +void LibraryWindow::setFolderSearchFilterData(QMap *filteredItems, FolderItem *root) +{ + foldersModelProxy->setFilterData(filteredItems, root); + foldersView->expandAll(); +} + void LibraryWindow::clearSearchFilter() { foldersModelProxy->clear(); diff --git a/YACReaderLibrary/library_window.h b/YACReaderLibrary/library_window.h index e4ebeda7..4e626cf3 100644 --- a/YACReaderLibrary/library_window.h +++ b/YACReaderLibrary/library_window.h @@ -11,6 +11,7 @@ #include "yacreader_navigation_controller.h" #include "comic_query_result_procesor.h" +#include "folder_query_result_processor.h" #include @@ -329,6 +330,7 @@ public slots: void toFullScreen(); void setSearchFilter(const YACReader::SearchModifiers modifier, QString filter); void setComicSearchFilterData(QList *, const QString &); + void setFolderSearchFilterData(QMap *filteredItems, FolderItem *root); void clearSearchFilter(); void showProperties(); void exportLibrary(QString destPath); @@ -402,6 +404,7 @@ private: TrayIconController *trayIconController; ComicQueryResultProcesor comicQueryResultProcesor; + FolderQueryResultProcessor *folderQueryResultProcessor; }; #endif