mirror of
https://github.com/YACReader/yacreader
synced 2025-07-19 05:24:57 -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:
@ -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<65>fica.....
|
||||
int originalColumn; //usado en los TreeItem filtrados //TODO crear clase espec<65>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<72>z no necesite tener informaci<63>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<73>n que soporta sqlit 2^64
|
||||
//el diccionario permitir<69> encontrar cualquier nodo del <20>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<63>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<72>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<73>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<6F>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 <20>l y todos los padres hasta el nodo ra<72>z
|
||||
{
|
||||
//comprobamos con esta variable si el <20>ltimo de los padres (antes del nodo ra<72>z) ya exist<73>a en el modelo
|
||||
bool parentPreviousInserted = false;
|
||||
|
||||
//mientras no se alcance el nodo ra<72>z se procesan todos los padres (de abajo a arriba)
|
||||
while(parentId !=0 )
|
||||
{
|
||||
//el padre no estaba en el modelo filtrado, as<61> 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<69> 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<61>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<61>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 <20>rbol
|
||||
QMap<unsigned long long int, TreeItem *> items; //relaci<63>n entre folders
|
||||
|
||||
TreeItem *rootBeforeFilter;
|
||||
QMap<unsigned long long int, TreeItem *> filteredItems; //relaci<63>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<6F>tico despu<70>s de limpiar el filtro
|
||||
int column; //column a la que hay que hacer scroll autom<6F>tico despu<70>s de limpiar el filtro
|
||||
QString previousFilter;
|
||||
QPushButton * clearFoldersFilter;
|
||||
QCheckBox * includeComicsCheckBox;
|
||||
|
Reference in New Issue
Block a user