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

@ -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;
}