fixed basic functionality of RsCollectionModel

This commit is contained in:
csoler 2024-02-28 21:56:38 +01:00
parent 885eb640dc
commit 2ed72a146b
4 changed files with 141 additions and 44 deletions

View File

@ -307,9 +307,9 @@ RsCollectionDialog::~RsCollectionDialog()
* @param event: event occured
* @return If we don't have to process event in parent.
*/
#ifdef TODO_COLLECTION
bool RsCollectionDialog::eventFilter(QObject *obj, QEvent *event)
{
#ifdef TODO_COLLECTION
if (obj == ui._fileEntriesTW) {
if (event->type() == QEvent::KeyPress) {
QKeyEvent *keyEvent = static_cast<QKeyEvent*>(event);
@ -367,9 +367,8 @@ bool RsCollectionDialog::eventFilter(QObject *obj, QEvent *event)
// pass the event on to the parent class
return QDialog::eventFilter(obj, event);
#endif
return true;
}
#endif
/**
* @brief RsCollectionDialog::processSettings

View File

@ -40,7 +40,7 @@ public:
static bool openExistingCollection(const QString& fileName, bool readOnly = false, bool showError = true);
protected:
bool eventFilter(QObject *obj, QEvent *ev);
//bool eventFilter(QObject *obj, QEvent *ev);
RsCollectionDialog(const QString& filename, const bool& creation, const bool& readOnly = false) ;

View File

@ -2,10 +2,28 @@
#include "RsCollectionModel.h"
// #define DEBUG_COLLECTION_MODEL 1
static const int COLLECTION_MODEL_NB_COLUMN = 4;
RsCollectionModel::RsCollectionModel(const RsCollection& col, QObject *parent)
: QAbstractItemModel(parent),mCollection(col)
{}
{
postMods();
}
#ifdef DEBUG_COLLECTION_MODEL
static std::ostream& operator<<(std::ostream& o,const RsCollectionModel::EntryIndex& i)
{
return o << ((i.is_file)?("File"):"Dir") << " with index " << (int)i.index ;
}
static std::ostream& operator<<(std::ostream& o,const QModelIndex& i)
{
return o << "QModelIndex (row " << i.row() << ", of ref " << i.internalId() << ")" ;
}
#endif
// Indernal Id is always a quintptr_t (basically a uint with the size of a pointer). Depending on the
// Indernal Id is always a quintptr_t (basically a uint with the size of a pointer). Depending on the
// architecture, the pointer may have 4 or 8 bytes. We use the low-level bit for type (0=dir, 1=file) and
// the remaining bits for the index (which will be accordingly understood as a FileIndex or a DirIndex)
@ -13,7 +31,7 @@ RsCollectionModel::RsCollectionModel(const RsCollection& col, QObject *parent)
bool RsCollectionModel::convertIndexToInternalId(const EntryIndex& e,quintptr& ref)
{
ref = (e.index << 1) || e.is_file;
ref = (e.index << 1) | e.is_file;
return true;
}
@ -26,56 +44,95 @@ bool RsCollectionModel::convertInternalIdToIndex(quintptr ref, EntryIndex& e)
int RsCollectionModel::rowCount(const QModelIndex& parent) const
{
#ifdef DEBUG_COLLECTION_MODEL
std::cerr << "Asking rowCount of " << parent << std::endl;
#endif
if(parent.column() >= COLLECTION_MODEL_NB_COLUMN)
return 0;
if(!parent.isValid())
return mCollection.fileTree().root();
{
#ifdef DEBUG_COLLECTION_MODEL
std::cerr << " root! returning " << mCollection.fileTree().directoryData(0).subdirs.size()
+ mCollection.fileTree().directoryData(0).subfiles.size() << std::endl;
#endif
return mCollection.fileTree().directoryData(0).subdirs.size()
+ mCollection.fileTree().directoryData(0).subfiles.size();
}
EntryIndex i;
if(!convertInternalIdToIndex(parent.internalId(),i))
return 0;
if(i.is_file)
{
#ifdef DEBUG_COLLECTION_MODEL
std::cerr << " file: returning 0" << std::endl;
#endif
return 0;
}
else
{
#ifdef DEBUG_COLLECTION_MODEL
std::cerr << " dir: returning " << mCollection.fileTree().directoryData(i.index).subdirs.size() + mCollection.fileTree().directoryData(i.index).subfiles.size()
<< std::endl;
#endif
return mCollection.fileTree().directoryData(i.index).subdirs.size() + mCollection.fileTree().directoryData(i.index).subfiles.size();
}
}
bool RsCollectionModel::hasChildren(const QModelIndex & parent) const
{
if(!parent.isValid())
return mCollection.fileTree().root();
return true;
EntryIndex i;
if(!convertInternalIdToIndex(parent.internalId(),i))
return 0;
return false;
if(i.is_file)
return false;
else if(mCollection.fileTree().directoryData(i.index).subdirs.size() + mCollection.fileTree().directoryData(i.index).subfiles.size() > 0)
return true;
else
return mCollection.fileTree().directoryData(i.index).subdirs.size() + mCollection.fileTree().directoryData(i.index).subfiles.size() > 0;
return false;
}
int RsCollectionModel::columnCount(const QModelIndex&) const
{
return 4;
return COLLECTION_MODEL_NB_COLUMN;
}
QVariant RsCollectionModel::headerData(int section, Qt::Orientation,int) const
QVariant RsCollectionModel::headerData(int section, Qt::Orientation,int role) const
{
switch(section)
{
case 0: return tr("File");
case 1: return tr("Size");
case 2: return tr("Hash");
case 3: return tr("Count");
default:
return QVariant();
}
if(role == Qt::DisplayRole)
switch(section)
{
case 0: return tr("File");
case 1: return tr("Size");
case 2: return tr("Hash");
case 3: return tr("Count");
default:
return QVariant();
}
return QVariant();
}
QModelIndex RsCollectionModel::index(int row, int column, const QModelIndex & parent) const
{
if(row < 0 || column < 0 || column >= columnCount(parent) || row >= rowCount(parent))
return QModelIndex();
EntryIndex i;
if(!convertInternalIdToIndex(parent.internalId(),i))
if(!parent.isValid()) // root
{
i.is_file = false;
i.index = 0;
}
else if(!convertInternalIdToIndex(parent.internalId(),i))
return QModelIndex();
if(i.is_file || i.index >= mCollection.fileTree().numDirs())
@ -83,9 +140,6 @@ QModelIndex RsCollectionModel::index(int row, int column, const QModelIndex & pa
const auto& parentData(mCollection.fileTree().directoryData(i.index));
if(row < 0)
return QModelIndex();
if((size_t)row < parentData.subdirs.size())
{
EntryIndex e;
@ -94,6 +148,10 @@ QModelIndex RsCollectionModel::index(int row, int column, const QModelIndex & pa
quintptr ref;
convertIndexToInternalId(e,ref);
#ifdef DEBUG_COLLECTION_MODEL
std::cerr << "creating index for row " << row << " of parent " << parent << ". result is " << createIndex(row,column,ref) << std::endl;
#endif
return createIndex(row,column,ref);
}
@ -105,6 +163,9 @@ QModelIndex RsCollectionModel::index(int row, int column, const QModelIndex & pa
quintptr ref;
convertIndexToInternalId(e,ref);
#ifdef DEBUG_COLLECTION_MODEL
std::cerr << "creating index for row " << row << " of parent " << parent << ". result is " << createIndex(row,column,ref) << std::endl;
#endif
return createIndex(row,column,ref);
}
@ -113,12 +174,16 @@ QModelIndex RsCollectionModel::index(int row, int column, const QModelIndex & pa
QModelIndex RsCollectionModel::parent(const QModelIndex & index) const
{
if(!index.isValid())
return QModelIndex();
EntryIndex i;
if(!convertInternalIdToIndex(index.internalId(),i))
if(!convertInternalIdToIndex(index.internalId(),i) || i.index==0)
return QModelIndex();
EntryIndex p;
p.is_file = false; // all parents are directories
int row;
if(i.is_file)
{
@ -128,7 +193,8 @@ QModelIndex RsCollectionModel::parent(const QModelIndex & index) const
RsErr() << "Error: parent not found for index " << index.row() << ", " << index.column();
return QModelIndex();
}
p.index = it->second;
p.index = it->second.parent_index;
row = it->second.parent_row;
}
else
{
@ -138,12 +204,14 @@ QModelIndex RsCollectionModel::parent(const QModelIndex & index) const
RsErr() << "Error: parent not found for index " << index.row() << ", " << index.column();
return QModelIndex();
}
p.index = it->second;
p.index = it->second.parent_index;
row = it->second.parent_row;
}
quintptr ref;
convertIndexToInternalId(p,ref);
return createIndex(0,index.column(),ref);
return createIndex(row,0,ref);
}
QVariant RsCollectionModel::data(const QModelIndex& index, int role) const
@ -152,6 +220,9 @@ QVariant RsCollectionModel::data(const QModelIndex& index, int role) const
if(!convertInternalIdToIndex(index.internalId(),i))
return QVariant();
#ifdef DEBUG_COLLECTION_MODEL
std::cerr << "Asking data of " << i << std::endl;
#endif
switch(role)
{
case Qt::DisplayRole: return displayRole(i,index.column());
@ -212,32 +283,54 @@ void RsCollectionModel::postMods()
mFileParents.clear();
mDirSizes.clear();
#ifdef DEBUG_COLLECTION_MODEL
std::cerr << "Updating from tree: " << std::endl;
#endif
uint64_t s;
recursUpdateLocalStructures(mCollection.fileTree().root(),s);
recursUpdateLocalStructures(mCollection.fileTree().root(),s,0);
mUpdating = false;
emit layoutChanged();
}
void RsCollectionModel::recursUpdateLocalStructures(RsFileTree::DirIndex dir_index,uint64_t& total_size)
void RsCollectionModel::recursUpdateLocalStructures(RsFileTree::DirIndex dir_index,uint64_t& total_size,int depth)
{
total_size = 0;
const auto& dd(mCollection.fileTree().directoryData(dir_index));
for(uint32_t i=0;i<dd.subfiles.size();++i)
{
total_size += mCollection.fileTree().fileData(dd.subfiles[i]).size;
mFileParents[dd.subfiles[i]] = dir_index;
}
for(uint32_t i=0;i<dd.subdirs.size();++i)
{
#ifdef DEBUG_COLLECTION_MODEL
for(int j=0;j<depth;++j) std::cerr << " ";
std::cerr << "Dir \"" << mCollection.fileTree().directoryData(dd.subdirs[i]).name << "\"" << std::endl ;
#endif
uint64_t ss;
recursUpdateLocalStructures(dd.subdirs[i],ss);
recursUpdateLocalStructures(dd.subdirs[i],ss,depth+1);
total_size += ss;
mDirParents[dd.subdirs[i]] = dir_index;
auto& ref(mDirParents[dd.subdirs[i]]);
ref.parent_index = dir_index;
ref.parent_row = i;
}
for(uint32_t i=0;i<dd.subfiles.size();++i)
{
#ifdef DEBUG_COLLECTION_MODEL
for(int j=0;j<depth;++j) std::cerr << " ";
std::cerr << "File \"" << mCollection.fileTree().fileData(dd.subfiles[i]).name << "\"" << std::endl;
#endif
total_size += mCollection.fileTree().fileData(dd.subfiles[i]).size;
auto& ref(mFileParents[dd.subfiles[i]]);
ref.parent_index = dir_index;
ref.parent_row = i + dd.subdirs.size();
}
mDirSizes[dir_index] = total_size;
}

View File

@ -18,7 +18,7 @@ class RsCollectionModel: public QAbstractItemModel
/* Callback from GUI */
void update() {}
void update() ;
void filterItems(const std::list<std::string>& keywords, uint32_t& found) ;
// Overloaded from QAbstractItemModel
@ -40,15 +40,15 @@ class RsCollectionModel: public QAbstractItemModel
#endif
#endif
private:
struct EntryIndex {
bool is_file; // false=dir, true=file
uint64_t index;
};
private:
static bool convertIndexToInternalId(const EntryIndex& e,quintptr& ref);
static bool convertInternalIdToIndex(quintptr ref, EntryIndex& e);
void recursUpdateLocalStructures(RsFileTree::DirIndex dir_index,uint64_t& total_size);
void recursUpdateLocalStructures(RsFileTree::DirIndex dir_index, uint64_t& total_size, int depth);
QVariant displayRole(const EntryIndex&,int col) const ;
QVariant sortRole(const EntryIndex&,int col) const ;
@ -59,8 +59,13 @@ class RsCollectionModel: public QAbstractItemModel
const RsCollection& mCollection;
std::map<uint64_t,RsFileTree::DirIndex> mFileParents;
std::map<uint64_t,RsFileTree::DirIndex> mDirParents;
struct ParentInfo {
RsFileTree::DirIndex parent_index; // index of the parent
RsFileTree::DirIndex parent_row; // row of that child, in this parent
};
std::map<uint64_t,ParentInfo> mFileParents;
std::map<uint64_t,ParentInfo> mDirParents;
std::map<uint64_t,uint64_t> mDirSizes;
// std::set<void*> mFilteredPointers ;