QTreeWidgetItem ChildIndicator strange behavior - c++

I have develop an app using a QTreeWidget and based on QTreeWidgetItem. The app is a file browser-like. Each time I had to display a folder, I create it like this :
item->setText(0, foldername);
item->setText(1,"--");
item->setText(2,"--");
item->setIcon(0,QIcon(":/Images/folder_pic.png"));
item->setFlags(Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsDropEnabled | Qt::ItemIsEditable);
item->setChildIndicatorPolicy(QTreeWidgetItem::ShowIndicator);
and I got this :
and when expand this
This working fine but when I delete the folder "NewFolder", I lose the indicator of the parent folder even if the indicator for this parent has been set to always show the indicator
The delete code is just
delete Item;
where Item is the selected item, in my case the child of the folder apps.
I have try to remove the delete and replace it by something like
ItParent = myItem->parent();
myItem->parent()->removeChild(myItem);
if(ItParent != NULL)
ItParent->setChildIndicatorPolicy(QTreeWidgetItem::ShowIndicator);
it's not working as well
Any idea ?

Related

Display a subdirectory (path retrieved from a string) inside a treeView

I have a QString fileName which stores in it a path to a subdirectory (eg. C:/Qt). I also have a treeView inside a dialog box.
Upon starting the application, we browse a file and once the file/folder is selected, I save the path of the file/folder in fileName string. Upon clicking "OK" (QPushButton), I intend to open a new Dialog Box divided into a treeView displaying the subdirectory with the selected folder as the root node of the tree, and a listView displaying all the files/folders within that folder and nothing if empty.
I used the following QFileSystemModel functions to display the C:/ directory (only drive on my pc) :
QString path;
//QFileSystemModel *dirModel;
//QFileSystemModel *fileModel;
//TreeView
dirModel = new QFileSystemModel;
dirModel->setFilter(QDir::NoDotAndDotDot | QDir::AllDirs);
dirModel->setRootPath(path);
ui->treeView->setModel(dirModel);
//ListView
fileModel = new QFileSystemModel;
fileModel->setFilter(QDir::NoDotAndDotDot | QDir::Files);
fileModel->setRootPath(path);
ui->listView->setModel(fileModel);
If I set the path to fileName (QString path = fileName;), nothing changes. I'm assuming QDir::AllDirs is the reason for this.
I looked for other QDir filters (like QDir::Dirs or setFilter) but nothing seems to work.
I even tried QDesktopServices::openUrl, but it just opens the file path in a new window instead of the treeView.

How to clear setNameFilters from a QFileSystemModel?

I have some code I am writing which displays the contents of a directory associated with a category whenever a new category is clicked on in a different list view. For convenience, I wanted to supply a filter option that would only display those contents of the directory that matched a given string input.
I have all of this working properly, but there's a bug whenever I apply a filter to one category, and then switch to another. The filter is properly applied to the category I'm presently viewing. But when I try to click on another category, every file list for every category shows up empty. This bug only occurs when I apply a filter, it does not occur when I switch between categories without ever using a filter.
I thought, "that's fine, I'll just nuke the filter between each category change." So I tried:
if (filemodel->nameFilters().size() > 0)
{
// create an empty list of strings to pass to the filter.
QListString clearFilter;
filemodel->setNameFilters(clearFilter);
fileView->setModel(filemodel);
}
Sadly, that made no change in the behavior. I even tried appending an empty string to the list. No change. Ultimately, I had to resort to the following code:
if (filemodel->nameFilters().size() > 0)
{
// throw away the old filemodel and start over with a fresh one.
delete filemodel;
filemodel = new QFileSystemModel;
filemodel->setFilter(QDir::Files);
filemodel->setRootPath("/");
fileView->setModel(filemodel);
}
That worked, but this seems horribly wrong. It doesn't seem like I should have to throw away the filemodel and start with a new one from scratch. Is there a better solution to this problem?
For the sake of reference, here is all the code relevant to how I set things up in the MainWindow constructor, and how I implemented the method to do the filtering:
MainWindow::MainWindow(...)
{
// ... skipping a bunch of stuff
fileView = new QListView(this);
filemodel = new QFileSystemModel;
filemodel->setFilter(QDir::Files);
filemodel->setRootPath("/");
fileView->setModel(filemodel);
filterText = new QLineEdit(this);
doFilter = new QPushButton(this);
doFilter->setText("Filter Filenames");
connect(doFilter, SIGNAL(clicked(bool)), this, SLOT(filterFileView()));
// ... skipping a bunch of other stuff
}
void MainWindow::filterFileView()
{
QStringList filterToApply;
filterToApply.append("*" + filterText->text() + "*");
filemodel->setNameFilters(filterToApply);
filemodel->setNameFilterDisables(false);
fileView->setModel(filemodel);
}
Resetting the filters to "*" works for me.
QStringList filters;
filters << "*";
filemodel->setNameFilters(filters);

How to clear a QTreeView / QFileSystemModel

I have a list of items displayed in a QTableWidget, each one corresponding to a specific folder.
Next to this, I have a QTreeView, with a QFileSystemModel. When I select an item from the QTableWidget, it calls a slot (shown below) in order to display the corresponding folder content.
void MyWidget::diplayFolder(int row)
{
if (auto item = table->item(row, 1))
{
QString correspondingDirectory = item->text();
if (QDir(correspondingDirectory).exists())
{
// treeModel => QFileSystemModel
// tree => QTreeView
treeModel->setRootPath("");
treeModel->setRootPath(correspondingDirectory);
tree->setRootIndex(treeModel->index(correspondingDirectory));
}
else
{
qDebug() << "Reset tree => do not display anything!";
// treeModel->setRootPath("");
// tree->reset();
}
}
}
If the directory does not exist, I don't want to display anything. However, when I try to set an empty root path or reset the view, it show all my computer drives.
How can I reset or clear the QTreeView ?
Had a similar issue. Im not quite sure how i solved it, because it was a long time ago. I think it should work if you set the QTreeview a nullptr as model. So when the QDir exists you set a new QFileSystemModel otherwise you call:
tree->setModel(nullptr);
Hope this helps you.
EDIT:
If your doing it this way the header is deleted too.

QCheckbox: more states than checked and unchecked

Is it possible to have more states for QCheckbox than Qt::Checked and Qt::Unchecked?
I have a QTreeWidget and if an Item is checked I want the parent to show a filled checkbox (some state like "Child checked") and the children should then have a state like "parent checked". If latter would be too complex to achieve I think the normal Qt::Checked would also work fine. But how to achieve the first? Here is my code how I am currently adding items with checkboxes:
QTreeWidgetItem* Options::folderMonitoringCreateTreeCheckbox(QDir *dir, bool state, QTreeWidget *parent)
{
QString text = dir->absolutePath().section('/', -1, -1, QString::SectionSkipEmpty);
QTreeWidgetItem *newItem = new QTreeWidgetItem(parent);
newItem->setText(0,text);
newItem->setFlags(newItem->flags() | Qt::ItemIsUserCheckable);
newItem->setCheckState(0, Qt::Unchecked);
newItem->setToolTip(0, dir->absolutePath());
return newItem;
}
Here is a Screenshot for what I want to achieve (screenshot taken from MediaMonkey):
Thank you!
I think you are looking for Qt::PartiallyChecked, the description of it says:
The item is partially checked. Items in hierarchical models may be partially checked if some, but not all, of their children are checked.

How can I organize QStandardItemModel`s in one QTreeView

I have two QTreeView's.
First (QTreeView1) displayed folders, second (QTreeView2) - displayed subfolders, that are loaded on folder click in first QTreeView1.
On click by folder in QTreeView1, I create QStandardItemModel with subfolders and set this model to QTreeView2. Also all items in both of QTreeView`s is checkable and I want to save all checked items state.
How can I organize models storage for each loaded folders.
Is it should be something like this:
// store folder model on subfolders check state changed
QMap<QStandardItemModel*, QString> modelStorage;
modelStorage.push_back(folderModel, folderPath);
and restore folder on folder click with:
QStandardItemModel* findFolderModel(QString folderPath)
{
QStandardItemModel* model;
foreach(auto path, modelStorage)
{
if (path == folderPath)
{
model = modelStorage.find(folderPath);
}
else model = nullptr;
}
return model;
}
and show model then ... Is it correct way to store all folder models? or it must be dynamically loaded? But in that case I need to store all model data by myself (for example, checked items state ...). Also model`s data can be changed for a while and I cant show "correct" data if I restore model from "snapshots".
UPD also I have question about implementation of my suggestion:
I store/restore models on click by folders in QTreeView1 and it seems to be worked ... but restored models doesn't contains/displays QStandardItems. It happens because treeItem allocated with new operator in local scope? How can I save all QStandardItems in each model in that case?
model = new QStandardItemModel;
QStandardItem* treeItem = new QStandardItem("item");
model->appendRow(treeItem);
//..
modelStorage.insert(folderItem, model);
ui.treeView->setModel(model);
// after restore model pointer is valid, but hadn't contains any items.
I think, you can try to use two QFileSystemModels for your both QTreeViews and don't create QStandardItemModel every time you click item in first QTreeView. As you can see in documentation, QFileSystemModel have setRootPath method. You can use this method for second model every time you click on folder in first QTreeView.
To make your items checkable, browse this helpful articles:
http://www.qtcentre.org/threads/27253-QFileSystemModel-with-checkboxes
QFilesystemmodel with Checkboxes
http://doc.qt.io/qt-5/qidentityproxymodel.html