added checkable items in RsCollectionModel

This commit is contained in:
csoler 2024-03-07 22:15:12 +01:00
parent be96f417b3
commit f375912bc5
2 changed files with 125 additions and 32 deletions

View File

@ -4,6 +4,10 @@
// #define DEBUG_COLLECTION_MODEL 1 // #define DEBUG_COLLECTION_MODEL 1
static const int COLLECTION_MODEL_FILENAME = 0;
static const int COLLECTION_MODEL_SIZE = 1;
static const int COLLECTION_MODEL_HASH = 2;
static const int COLLECTION_MODEL_COUNT = 3;
static const int COLLECTION_MODEL_NB_COLUMN = 4; static const int COLLECTION_MODEL_NB_COLUMN = 4;
RsCollectionModel::RsCollectionModel(const RsCollection& col, QObject *parent) RsCollectionModel::RsCollectionModel(const RsCollection& col, QObject *parent)
@ -172,6 +176,14 @@ QModelIndex RsCollectionModel::index(int row, int column, const QModelIndex & pa
return QModelIndex(); return QModelIndex();
} }
Qt::ItemFlags RsCollectionModel::flags ( const QModelIndex & index ) const
{
if(index.isValid() && index.column() == COLLECTION_MODEL_FILENAME)
return QAbstractItemModel::flags(index) | Qt::ItemIsUserTristate;
return QAbstractItemModel::flags(index) & ~Qt::ItemIsUserTristate;
}
QModelIndex RsCollectionModel::parent(const QModelIndex & index) const QModelIndex RsCollectionModel::parent(const QModelIndex & index) const
{ {
if(!index.isValid()) if(!index.isValid())
@ -187,8 +199,8 @@ QModelIndex RsCollectionModel::parent(const QModelIndex & index) const
if(i.is_file) if(i.is_file)
{ {
const auto it = mFileParents.find(i.index); const auto it = mFileInfos.find(i.index);
if(it == mFileParents.end()) if(it == mFileInfos.end())
{ {
RsErr() << "Error: parent not found for index " << index.row() << ", " << index.column(); RsErr() << "Error: parent not found for index " << index.row() << ", " << index.column();
return QModelIndex(); return QModelIndex();
@ -198,8 +210,8 @@ QModelIndex RsCollectionModel::parent(const QModelIndex & index) const
} }
else else
{ {
const auto it = mDirParents.find(i.index); const auto it = mDirInfos.find(i.index);
if(it == mDirParents.end()) if(it == mDirInfos.end())
{ {
RsErr() << "Error: parent not found for index " << index.row() << ", " << index.column(); RsErr() << "Error: parent not found for index " << index.row() << ", " << index.column();
return QModelIndex(); return QModelIndex();
@ -228,11 +240,61 @@ QVariant RsCollectionModel::data(const QModelIndex& index, int role) const
case Qt::DisplayRole: return displayRole(i,index.column()); case Qt::DisplayRole: return displayRole(i,index.column());
//case Qt::SortRole: return SortRole(i,index.column()); //case Qt::SortRole: return SortRole(i,index.column());
case Qt::DecorationRole: return decorationRole(i,index.column()); case Qt::DecorationRole: return decorationRole(i,index.column());
case Qt::CheckStateRole: return checkStateRole(i,index.column());
default: default:
return QVariant(); return QVariant();
} }
} }
bool RsCollectionModel::setData(const QModelIndex& index,const QVariant& value,int role)
{
if(!index.isValid())
return false;
if (role==Qt::CheckStateRole)
{
#ifdef DEBUG_COLLECTION_MODEL
std::cerr << "Setting check state of item " << index << " to " << value.toBool() << std::endl;
#endif
return true;
}
else
return setData(index,value,role);
}
QVariant RsCollectionModel::checkStateRole(const EntryIndex& i,int col) const
{
if(col == COLLECTION_MODEL_FILENAME)
{
if(i.is_file)
{
auto it = mFileInfos.find(i.index);
if(it == mFileInfos.end())
return QVariant();
if(it->second.is_checked)
return QVariant(Qt::Checked);
else
return QVariant(Qt::Unchecked);
}
else
{
auto it = mDirInfos.find(i.index);
if(it == mDirInfos.end())
return QVariant();
switch(it->second.check_state)
{
case SELECTED: return QVariant(Qt::Checked);
case PARTIALLY_SELECTED: return QVariant(Qt::PartiallyChecked);
default:
case UNSELECTED: return QVariant(Qt::Unchecked);
}
}
}
else
return QVariant();
}
QVariant RsCollectionModel::displayRole(const EntryIndex& i,int col) const QVariant RsCollectionModel::displayRole(const EntryIndex& i,int col) const
{ {
switch(col) switch(col)
@ -245,12 +307,12 @@ QVariant RsCollectionModel::displayRole(const EntryIndex& i,int col) const
return QVariant((qulonglong)mCollection.fileTree().fileData(i.index).size) ; return QVariant((qulonglong)mCollection.fileTree().fileData(i.index).size) ;
{ {
auto it = mDirSizes.find(i.index); auto it = mDirInfos.find(i.index);
if(it == mDirSizes.end()) if(it == mDirInfos.end())
return QVariant(); return QVariant();
else else
return QVariant((qulonglong)it->second); return QVariant((qulonglong)it->second.total_size);
} }
case 2: return (i.is_file)? case 2: return (i.is_file)?
@ -279,9 +341,8 @@ void RsCollectionModel::postMods()
{ {
// update all the local structures // update all the local structures
mDirParents.clear(); mDirInfos.clear();
mFileParents.clear(); mFileInfos.clear();
mDirSizes.clear();
#ifdef DEBUG_COLLECTION_MODEL #ifdef DEBUG_COLLECTION_MODEL
std::cerr << "Updating from tree: " << std::endl; std::cerr << "Updating from tree: " << std::endl;
@ -296,9 +357,29 @@ void RsCollectionModel::postMods()
void RsCollectionModel::recursUpdateLocalStructures(RsFileTree::DirIndex dir_index,uint64_t& total_size,int depth) void RsCollectionModel::recursUpdateLocalStructures(RsFileTree::DirIndex dir_index,uint64_t& total_size,int depth)
{ {
total_size = 0; total_size = 0;
bool all_checked = true;
bool all_unchecked = false;
const auto& dd(mCollection.fileTree().directoryData(dir_index)); const auto& dd(mCollection.fileTree().directoryData(dir_index));
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(mFileInfos[dd.subfiles[i]]);
ref.parent_index = dir_index;
ref.parent_row = i + dd.subdirs.size();
all_checked = all_checked && ref.is_checked;
all_unchecked = all_unchecked && !ref.is_checked;
}
for(uint32_t i=0;i<dd.subdirs.size();++i) for(uint32_t i=0;i<dd.subdirs.size();++i)
{ {
#ifdef DEBUG_COLLECTION_MODEL #ifdef DEBUG_COLLECTION_MODEL
@ -310,28 +391,25 @@ void RsCollectionModel::recursUpdateLocalStructures(RsFileTree::DirIndex dir_ind
recursUpdateLocalStructures(dd.subdirs[i],ss,depth+1); recursUpdateLocalStructures(dd.subdirs[i],ss,depth+1);
total_size += ss; total_size += ss;
auto& ref(mDirParents[dd.subdirs[i]]); auto& ref(mDirInfos[dd.subdirs[i]]);
ref.parent_index = dir_index; ref.parent_index = dir_index;
ref.parent_row = i; ref.parent_row = i;
all_checked = all_checked && (ref.check_state == SELECTED);
all_unchecked = all_unchecked && (ref.check_state == UNSELECTED);
} }
for(uint32_t i=0;i<dd.subfiles.size();++i) auto& r(mDirInfos[dir_index]);
{
#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; r.total_size = total_size;
auto& ref(mFileParents[dd.subfiles[i]]); if(all_checked)
r.check_state = SELECTED;
ref.parent_index = dir_index; else if(all_unchecked)
ref.parent_row = i + dd.subdirs.size(); r.check_state = UNSELECTED;
} else
r.check_state = PARTIALLY_SELECTED;
mDirSizes[dir_index] = total_size;
} }

View File

@ -31,8 +31,9 @@ class RsCollectionModel: public QAbstractItemModel
virtual QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override; virtual QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override;
virtual QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override; virtual QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
#ifdef TODO virtual bool setData(const QModelIndex& index,const QVariant& value,int role) override;
virtual Qt::ItemFlags flags ( const QModelIndex & index ) const override; virtual Qt::ItemFlags flags ( const QModelIndex & index ) const override;
#ifdef TODO
virtual QStringList mimeTypes () const override; virtual QStringList mimeTypes () const override;
virtual QMimeData * mimeData ( const QModelIndexList & indexes ) const override; virtual QMimeData * mimeData ( const QModelIndexList & indexes ) const override;
#if QT_VERSION >= QT_VERSION_CHECK (5, 0, 0) #if QT_VERSION >= QT_VERSION_CHECK (5, 0, 0)
@ -53,20 +54,34 @@ class RsCollectionModel: public QAbstractItemModel
QVariant displayRole(const EntryIndex&,int col) const ; QVariant displayRole(const EntryIndex&,int col) const ;
QVariant sortRole(const EntryIndex&,int col) const ; QVariant sortRole(const EntryIndex&,int col) const ;
QVariant decorationRole(const EntryIndex&,int col) const ; QVariant decorationRole(const EntryIndex&,int col) const ;
QVariant checkStateRole(const EntryIndex& i,int col) const;
//QVariant filterRole(const DirDetails& details,int coln) const; //QVariant filterRole(const DirDetails& details,int coln) const;
bool mUpdating ; bool mUpdating ;
const RsCollection& mCollection; const RsCollection& mCollection;
struct ParentInfo { enum DirCheckState: uint8_t {
RsFileTree::DirIndex parent_index; // index of the parent UNSELECTED = 0x00,
RsFileTree::DirIndex parent_row; // row of that child, in this parent PARTIALLY_SELECTED = 0x01,
SELECTED = 0x02,
}; };
std::map<uint64_t,ParentInfo> mFileParents; struct ModelDirInfo {
std::map<uint64_t,ParentInfo> mDirParents; RsFileTree::DirIndex parent_index; // index of the parent
std::map<uint64_t,uint64_t> mDirSizes; RsFileTree::DirIndex parent_row; // row of that child, in this parent
DirCheckState check_state;
uint64_t total_size;
};
struct ModelFileInfo {
RsFileTree::DirIndex parent_index; // index of the parent
RsFileTree::DirIndex parent_row; // row of that child, in this parent
bool is_checked;
};
std::map<uint64_t,ModelFileInfo> mFileInfos;
std::map<uint64_t,ModelDirInfo> mDirInfos;
// std::set<void*> mFilteredPointers ; // std::set<void*> mFilteredPointers ;
}; };