mirror of
https://github.com/YACReader/yacreader
synced 2025-05-28 03:10:27 -04:00
a?adida b?squeda por directorios
falta resetear adecuadamente el modelo interno cuando se cambia de base de datos falta hacer scroll automatico al hacer click en uno de los resultados de b?squeda falta a?adir soporte a la b?squeda con nombres de c?mics
This commit is contained in:
parent
c3ed550793
commit
b551c9484a
@ -139,3 +139,9 @@ int TreeItem::row() const
|
||||
return 0;
|
||||
}
|
||||
//! [8]
|
||||
|
||||
|
||||
QList<QVariant> TreeItem::getData() const
|
||||
{
|
||||
return itemData;
|
||||
}
|
@ -57,15 +57,20 @@ public:
|
||||
int childCount() const;
|
||||
int columnCount() const;
|
||||
QVariant data(int column) const;
|
||||
QList<QVariant> getData() const;
|
||||
int row() const;
|
||||
TreeItem *parent();
|
||||
TreeItem *parentItem;
|
||||
unsigned long long int id;
|
||||
QList<QString> comicNames;
|
||||
int originalRow; //usado en los TreeItem filtrados //TODO crear clase específica.....
|
||||
int originalColumn; //usado en los TreeItem filtrados //TODO crear clase específica.....
|
||||
int column;
|
||||
private:
|
||||
QList<TreeItem*> childItems;
|
||||
QList<QVariant> itemData;
|
||||
|
||||
|
||||
|
||||
|
||||
};
|
||||
|
@ -53,7 +53,7 @@
|
||||
#include "data_base_management.h"
|
||||
|
||||
TreeModel::TreeModel(QObject *parent)
|
||||
: QAbstractItemModel(parent)
|
||||
: QAbstractItemModel(parent),rootItem(0),rootBeforeFilter(0),filterEnabled(false),includeComics(false)
|
||||
{
|
||||
connect(this,SIGNAL(beforeReset()),this,SIGNAL(modelAboutToBeReset()));
|
||||
connect(this,SIGNAL(reset()),this,SIGNAL(modelReset()));
|
||||
@ -61,7 +61,7 @@ TreeModel::TreeModel(QObject *parent)
|
||||
|
||||
//! [0]
|
||||
TreeModel::TreeModel( QSqlQuery &sqlquery, QObject *parent)
|
||||
: QAbstractItemModel(parent),rootItem(0)
|
||||
: QAbstractItemModel(parent),rootItem(0),rootBeforeFilter(0),filterEnabled(false),includeComics(false)
|
||||
{
|
||||
//lo más probable es que el nodo raíz no necesite tener información
|
||||
QList<QVariant> rootData;
|
||||
@ -144,7 +144,10 @@ QModelIndex TreeModel::index(int row, int column, const QModelIndex &parent)
|
||||
|
||||
TreeItem *childItem = parentItem->child(row);
|
||||
if (childItem)
|
||||
{
|
||||
childItem->column = column;
|
||||
return createIndex(row, column, childItem);
|
||||
}
|
||||
else
|
||||
return QModelIndex();
|
||||
}
|
||||
@ -207,11 +210,11 @@ void TreeModel::setupModelData(QString path)
|
||||
|
||||
}
|
||||
|
||||
|
||||
void TreeModel::setupModelData(QSqlQuery &sqlquery, TreeItem *parent)
|
||||
{
|
||||
//64 bits para la primary key, es decir la misma precisión que soporta sqlit 2^64
|
||||
//el diccionario permitirá encontrar cualquier nodo del árbol rápidamente, de forma que añadir un hijo a un padre sea O(1)
|
||||
QMap<unsigned long long int, TreeItem *> items;
|
||||
|
||||
//se añade el nodo 0
|
||||
items.insert(parent->id,parent);
|
||||
@ -222,21 +225,117 @@ void TreeModel::setupModelData(QSqlQuery &sqlquery, TreeItem *parent)
|
||||
data << sqlquery.value(3).toString();
|
||||
TreeItem * item = new TreeItem(data);
|
||||
|
||||
/*QSqlQuery selectQuery(_database); //TODO check
|
||||
selectQuery.prepare("select fileName from comic where parentId = :parentId");
|
||||
selectQuery.bindValue(":parentId", sqlquery.value(0).toLongLong());
|
||||
selectQuery.exec();
|
||||
while (selectQuery.next()) {
|
||||
item->comicNames.append(sqlquery.value(0).toString());
|
||||
}*/
|
||||
|
||||
item->id = sqlquery.value(0).toLongLong();
|
||||
//la inserción de hijos se hace de forma ordenada
|
||||
items.value(sqlquery.value(1).toLongLong())->appendChild(item);
|
||||
//se añade el item al map, de forma que se pueda encontrar como padre en siguientes iteraciones
|
||||
items.insert(item->id,item);
|
||||
}
|
||||
}
|
||||
|
||||
void TreeModel::setupFilteredModelData()
|
||||
{
|
||||
emit(beforeReset());
|
||||
|
||||
//TODO hay que liberar memoria de anteriores filtrados
|
||||
|
||||
//inicializar el nodo raíz
|
||||
|
||||
if(rootBeforeFilter == 0)
|
||||
rootBeforeFilter = rootItem;
|
||||
|
||||
QList<QVariant> rootData;
|
||||
rootData << "root"; //id 0, padre 0, title "root" (el id, y el id del padre van a ir en la clase TreeItem)
|
||||
rootItem = new TreeItem(rootData);
|
||||
rootItem->id = 0;
|
||||
|
||||
//cargar la base de datos
|
||||
if(_database.isValid())
|
||||
_database.open();
|
||||
//crear la consulta
|
||||
QSqlQuery selectQuery(_database); //TODO check
|
||||
selectQuery.prepare("select * from folder where upper(name) like upper(:filter) order by parentId,name ");
|
||||
selectQuery.bindValue(":filter", "%%"+filter+"%%");
|
||||
selectQuery.exec();
|
||||
setupFilteredModelData(selectQuery,rootItem);
|
||||
_database.close();
|
||||
emit(reset());
|
||||
}
|
||||
|
||||
void TreeModel::setupFilteredModelData(QSqlQuery &sqlquery, TreeItem *parent)
|
||||
{
|
||||
//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);
|
||||
|
||||
while (sqlquery.next()) { //se procesan todos los folders que cumplen con el filtro
|
||||
//datos de la base de datos
|
||||
QList<QVariant> data;
|
||||
data << sqlquery.value(2).toString();
|
||||
data << sqlquery.value(3).toString();
|
||||
TreeItem * item = new TreeItem(data);
|
||||
item->id = sqlquery.value(0).toLongLong();
|
||||
|
||||
//id del padre
|
||||
quint64 parentId = sqlquery.value(1).toLongLong();
|
||||
|
||||
//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->originalRow = items.value(item->id)->row();
|
||||
item->originalColumn = items.value(item->id)->column;
|
||||
|
||||
//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 !=0 )
|
||||
{
|
||||
//el padre no estaba en el modelo filtrado, así que se rescata del modelo original
|
||||
TreeItem * parentItem = items.value(parentId);
|
||||
//se debe crear un nuevo nodo (para no compartir los hijos con el nodo original)
|
||||
TreeItem * newparentItem = new TreeItem(parentItem->getData()); //padre que se añadirá a la estructura de directorios filtrados
|
||||
newparentItem->id = parentId;
|
||||
|
||||
//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 hijo de 0, no había sido previamente insertado como hijo, se añade como tal
|
||||
if(!parentPreviousInserted)
|
||||
filteredItems.value(0)->appendChild(item);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
QSqlDatabase & TreeModel::getDatabase()
|
||||
{
|
||||
return _database;
|
||||
@ -245,4 +344,24 @@ QSqlDatabase & TreeModel::getDatabase()
|
||||
QString TreeModel::getFolderPath(const QModelIndex &folder)
|
||||
{
|
||||
return static_cast<TreeItem*>(folder.internalPointer())->data(1).toString();
|
||||
}
|
||||
|
||||
void TreeModel::setFilter(QString filter, bool includeComics)
|
||||
{
|
||||
this->filter = filter;
|
||||
this->includeComics = includeComics;
|
||||
filterEnabled = true;
|
||||
setupFilteredModelData();
|
||||
}
|
||||
|
||||
void TreeModel::resetFilter()
|
||||
{
|
||||
emit(beforeReset());
|
||||
filter = "";
|
||||
includeComics = false;
|
||||
//TODO hay que liberar la memoria reservada para el filtrado
|
||||
rootItem = rootBeforeFilter; //TODO si no se aplica el filtro previamente, esto invalidaría en modelo
|
||||
filterEnabled = false;
|
||||
emit(reset());
|
||||
|
||||
}
|
@ -73,12 +73,26 @@ public:
|
||||
|
||||
//Métodos de conveniencia
|
||||
QString getFolderPath(const QModelIndex &folder);
|
||||
|
||||
void setFilter(QString filter, bool includeComics);
|
||||
void resetFilter();
|
||||
bool isFilterEnabled(){return filterEnabled;};
|
||||
private:
|
||||
void setupModelData( QSqlQuery &sqlquery, TreeItem *parent);
|
||||
void setupFilteredModelData( QSqlQuery &sqlquery, TreeItem *parent);
|
||||
void setupFilteredModelData();
|
||||
|
||||
TreeItem *rootItem; //el árbol
|
||||
QMap<unsigned long long int, TreeItem *> items; //relación entre folders
|
||||
|
||||
TreeItem *rootBeforeFilter;
|
||||
QMap<unsigned long long int, TreeItem *> filteredItems; //relación entre folders
|
||||
|
||||
QSqlDatabase _database;
|
||||
|
||||
bool includeComics;
|
||||
QString filter;
|
||||
bool filterEnabled;
|
||||
signals:
|
||||
void beforeReset();
|
||||
void reset();
|
||||
|
@ -32,8 +32,8 @@ void LibraryWindow::setupUI()
|
||||
packageManager = new PackageManager();
|
||||
|
||||
doModels();
|
||||
doLayout();
|
||||
doDialogs();
|
||||
doLayout();
|
||||
createActions();
|
||||
createToolBars();
|
||||
createMenus();
|
||||
@ -72,7 +72,7 @@ void LibraryWindow::doLayout()
|
||||
foldersView = new QTreeView;
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
//CONFIG FLOW/COMICS-------------------------------------------------------
|
||||
//CONFIG FOLDERS/COMICS-------------------------------------------------------
|
||||
/*sVertical->setStretchFactor(0,1);
|
||||
sVertical->setStretchFactor(1,0);
|
||||
*/
|
||||
@ -586,7 +586,9 @@ void LibraryWindow::loadCovers(const QModelIndex & mi)
|
||||
{
|
||||
if(foldersFilter->text()!="")
|
||||
{
|
||||
setFoldersFilter("");
|
||||
//setFoldersFilter("");
|
||||
row = static_cast<TreeItem *>(mi.internalPointer())->originalRow;
|
||||
column = static_cast<TreeItem *>(mi.internalPointer())->originalColumn;
|
||||
foldersFilter->clear();
|
||||
}
|
||||
unsigned long long int folderId = 0;
|
||||
@ -991,6 +993,20 @@ void LibraryWindow::setFoldersFilter(QString filter)
|
||||
foldersView->scrollTo(foldersView->currentIndex(),QAbstractItemView::PositionAtTop);
|
||||
foldersView->collapseAll();
|
||||
}*/
|
||||
if(filter.isEmpty() && dm->isFilterEnabled())
|
||||
{
|
||||
dm->resetFilter();
|
||||
foldersView->collapseAll();
|
||||
foldersView->scrollTo(dm->index(row,column),QAbstractItemView::PositionAtTop);
|
||||
}
|
||||
else
|
||||
{
|
||||
if(!filter.isEmpty())
|
||||
{
|
||||
dm->setFilter(filter, false);
|
||||
foldersView->expandAll();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void LibraryWindow::showProperties()
|
||||
|
@ -51,6 +51,8 @@ private:
|
||||
QSize slideSizeF;
|
||||
//search filter
|
||||
QLineEdit * foldersFilter;
|
||||
int row; //row a la que hay que hacer scroll automático después de limpiar el filtro
|
||||
int column; //column a la que hay que hacer scroll automático después de limpiar el filtro
|
||||
QString previousFilter;
|
||||
QPushButton * clearFoldersFilter;
|
||||
QCheckBox * includeComicsCheckBox;
|
||||
|
Loading…
Reference in New Issue
Block a user