PDA

View Full Version : QDirModel+QTreeView and checkable items



L.Marvell
10th May 2007, 14:40
I'm trying to implement QTreeView + QDirModel with checkable items. I have found topic (http://www.qtcentre.org/forum/f-qt-programming-2/t-qtreeview-with-checkboxes-2072.html/?highlight=checkable) with similar problem, I've derived new class from QDirModel but I don't get how to reimplement flags() and data() methods to have needed functionality. Can somebody help?

patrik08
10th May 2007, 15:15
I'm trying to implement QTreeView + QDirModel with checkable items. I have found topic (http://www.qtcentre.org/forum/f-qt-programming-2/t-qtreeview-with-checkboxes-2072.html/?highlight=checkable) with similar problem, I've derived new class from QDirModel but I don't get how to reimplement flags() and data() methods to have needed functionality. Can somebody help?

checkable dir & file...

A Context menu can run ... on file & dir.... like other file explorer ...




void User_File::Load_Connector()
{
startnow = QDir::currentPath();
dirsizebite = 0;
dirandfile.clear();
qtcpeed = true;
modeluser = new QDirModel;
modellocal = new QDirModel;
setAcceptDrops(true);
modellocal->setResolveSymlinks(false);
modeluser->setResolveSymlinks(false);
usertree->setModel(modeluser);
mlocal->setModel(modellocal);

modeluser->setSupportedDragActions(Qt::CopyAction);
modellocal->setSupportedDragActions(Qt::CopyAction);
usertree->setDragEnabled(true);
mlocal->setDragEnabled(true);

mlocal->setRootIndex(modellocal->index(lstart));
usertree->setRootIndex(modeluser->index(ustart));
connect(usertree, SIGNAL(clicked(const QModelIndex &)),this, SLOT(GlobalContextU(const QModelIndex&)));
connect(mlocal, SIGNAL(clicked(const QModelIndex &)),this, SLOT(OpenLocalFile(const QModelIndex&)));
connect(pushButton, SIGNAL(clicked()),this, SLOT(ResetDBDir()));





usertree->resizeColumnToContents (0);
mlocal->resizeColumnToContents (0);
IndexDir(ustart);
qDebug() << "### dirsizebite " << dirsizebite;


dirowerflow = false;

if (dirsizebite > MAXDIRSIZE) {
dirowerflow = true;
QMessageBox::warning(this, tr("User dir."),tr("The maxiumum capacity of user dir is %1!").arg(BiteorMega(MAXDIRSIZE)));
}
label_2->setText(tr("User Dir size %1 - %2 ")
.arg(BiteorMega(dirsizebite))
.arg(UmanTimeFromUnix(QTime_Null())));
dirandfile.clear();


Q_ASSERT(qtcpeed);
qtcpeed = false;

}


void User_File::GlobalContextU( const QModelIndex &index )
{
if (!index.isValid()) {
return;
}
ResetDD();
userselect = true;
acc = true;
const QString filepath = modeluser->filePath(index);
fi = QFileInfo(filepath);
last = QCursor::pos();
/* model to fast! */
QTimer::singleShot(200, this, SLOT(User_Context()));
}


void User_File::User_Context()
{
TContext = new QMenu(this);
QString wat = fi.absoluteFilePath();
QDir checkdir(wat);
dir = checkdir.exists();
if (dir) {
TContext->addAction(tr( "Delete dir \"%1\" " ).arg(fi.fileName()), this , SLOT( DDrm() ) );
TContext->addAction(tr( "Open dir \"%1\" " ).arg(fi.fileName()), this , SLOT( DDop() ) );
} else {
TContext->addAction(tr( "Delete file \"%1\" " ).arg(fi.fileName()), this , SLOT( DDrm() ) );
TContext->addAction(tr( "Open file \"%1\" " ).arg(fi.fileName()), this , SLOT( DDop() ) );
}
TContext->addAction(tr( "New Dir here" ), this , SLOT( DDmkdir() ) );
TContext->addAction(tr( "Reload ..." ), this , SLOT( Load_Connector() ) );
TContext->addAction(tr( "User dir Close contex" ), TContext , SLOT( close() ) );
TContext->exec(last);

}

L.Marvell
10th May 2007, 15:28
It seems you didn't understand me (or maybe I don't understand something...). I need QTreeView with tree of directories and each has checkbox near (with flag Qt::ItemIsUserCheckable). I think new class has to be derived from QDirModel with flags(), data() and maybe some other methods reimplemented, but I don't get how to do it. Need some example.

jpn
10th May 2007, 17:26
I think new class has to be derived from QDirModel with flags(), data() and maybe some other methods reimplemented, but I don't get how to do it. Need some example.
Yes, that's right. You need to reimplement flags(), data() and setData(). flags() should indeed return Qt::ItemIsUserCheckable amongst the other flags, data() should return a valid value for Qt::CheckStateRole and setData() should store the passed value for Qt::CheckStateRole. The toughest part is to implement a data structure of some kind for storing the check states as QDirModel is not able to store them for you.

wysota
10th May 2007, 23:12
The toughest part is to implement a data structure of some kind for storing the check states as QDirModel is not able to store them for you.

I suggest QSet<QString> where the key is the FilePathRole (defined in QDirModel). The only trick is to update the contents if the dir model changes (i.e. file gets deleted). If a path is in the set, it is checked.

L.Marvell
11th May 2007, 18:01
Yes, that's right. You need to reimplement flags(), data() and setData(). flags() should indeed return Qt::ItemIsUserCheckable amongst the other flags, data() should return a valid value for Qt::CheckStateRole and setData() should store the passed value for Qt::CheckStateRole. The toughest part is to implement a data structure of some kind for storing the check states as QDirModel is not able to store them for you.

That's the point. I can't get how should data() look like and what should it return. It seems I need to read Assistant again and again about Models...

jpn
11th May 2007, 18:24
class MyDirModel : public QDirModel
{
...

private:
QSet<QString> checked; // wysota's suggestion
}

Qt::ItemFlags MyDirModel::flags(const QModelIndex& index) const
{
Qt::ItemFlags f = QDirModel::flags(index);
if (index.column() == 0) // make the first column checkable
f |= Qt::ItemIsUserCheckable;
return f;
}

QVariant MyDirModel::data(const QModelIndex& index, int role = Qt::DisplayRole) const
{
if (index.isValid() && index.column() == 0 && role == Qt::CheckStateRole)
{
// the item is checked only if we have stored its path
return (checked.contains(filePath(index)) ? Qt::Checked : Qt::Unchecked);
}
return QDirModel::data(index, role);
}

bool MyDirModel::setData(const QModelIndex& index, const QVariant& value, int role = Qt::EditRole)
{
if (index.isValid() && index.column() == 0 && role == Qt::CheckStateRole)
{
// store checked paths, remove unchecked paths
if (value.toInt() == Qt::Checked)
checked.insert(filePath(index));
else
checked.remove(filePath(index));
return true;
}
return QDirModel::setData(index, value, role);
}

L.Marvell
11th May 2007, 18:54
Great thanks man! I'll try it surely.