Where are my QTreeWidgetIcons? - c++

I have a QTreeWidget with QTreeWidgetItem items, however only the root node is showing its icon:
I've been scratching my head on what could turn it off, any hints?
ui->folderTree1->setUpdatesEnabled( false );
QTreeWidgetItem* treeRoot1 = new QTreeWidgetItem(ui->folderTree1);
treeRoot1->setIcon(0, QIcon(":/icons/black.png"));
treeRoot1->setText(0, tr("Root"));
treeRoot1->setExpanded(true);
addFoldersToTreeView(treeRoot1, ui->filePath1->text(), ui->filePath2->text());
ui->folderTree1->setUpdatesEnabled( true );
}
void MainWindow::addFoldersToTreeView(QTreeWidgetItem* currentWidget, QString leftPath, QString rightPath)
{
qDebug() << "MainWindow::addFoldersToTreeView" << leftPath;
QDir dir(leftPath);
QDir dir2(rightPath);
/* Add the folders */
foreach (QString subDir, dir.entryList(QDir::Dirs | QDir::NoDotAndDotDot))
{
QString sImageName = ":/icons/black.png";
QTreeWidgetItem* newItem = new QTreeWidgetItem(currentWidget);
qDebug() << "MainWindow::addFoldersToTreeView.sImageName" << sImageName;
newItem->setIcon(0, QIcon(sImageName));
newItem->setText(0, subDir);
newItem->setExpanded(true);
newItem->setData(0, 1, QVariant(leftPath + QDir::separator() + subDir));
/* Recursively add sub-folders */
addFoldersToTreeView(newItem, leftPath + QDir::separator() + subDir, rightPath + QDir::separator() + subDir);
}

The problem is the line:
newItem->setData(0, 1, QVariant(leftPath + QDir::separator() + subDir));
The second argument is the item data role, which you specify to 1 (Qt::DecorationRole). The Qt::DecorationRole should be used for data that is rendered as a decoration in the form of an icon, i.e., this line will cause the the icon you specified before to be replaced with a QVariant object.
Remove that line or change the item data role to something else.

Related

QListWidget Remove selected Item and its settings QT

I need help creating a function for deleting items from a QListWidget. I need to copy the name of the last item in the list, remove settings from .ini then remove from from QListWidget. So far all I can find is to how to use QList to delete the selected item.
My add function looks like:
void Edge::on_slotNew_pressed()
{
int i = ui->slotList->count();
i++;
QString slotNumber = "Slot" + QString::number(i);
ui->slotList->addItem(slotNumber);
QSettings settings("config.ini",QSettings::IniFormat);
qDebug() << settings.fileName();
settings.beginGroup(slotNumber);
settings.setValue("slotSizeW", m_prefs.slotSizeW);
settings.setValue("slotSizeH", m_prefs.slotSizeH);
settings.setValue("slotPosX", m_prefs.slotPosX);
settings.setValue("slotPosY", m_prefs.slotPosY);
settings.setValue("slotMax", m_prefs.slotMax);
settings.setValue("slotPriority", m_prefs.slotPriority);
settings.setValue("slotBorderless", m_prefs.slotBorderless);
settings.setValue("slotHotkey", m_prefs.slotHotkey);
settings.endGroup();
qDebug() << slotNumber;
}
**EDIT:**Updated Remove function
Currently my remove function looks like
void Edge::on_slotDelete_clicked()
{
QSettings settings("slots.ini",QSettings::IniFormat);
int i = ui->slotList->count();
QString slotNumber = "Slot" + QString::number(i);
QList<QListWidgetItem*> items = ui->slotList->selectedItems();
foreach(QListWidgetItem* item, items)
{
ui->slotList->removeItemWidget(item);
delete item;
}
settings.beginGroup(slotNumber);
settings.remove("");
settings.endGroup();
qDebug() << settings.fileName();
}
I derped and forgot to update the config name so removal works, I just possibly need a better naming convention as it has to be passed as a QString, QListWidgetItem* will not pass correctly
To delete a group and his content call:
settings.beginGroup(item->getSlotNumber()); // please use here the correct method to get the SlotNumber
settings.remove(""); //removes the group, and all it keys
settings.endGroup();
To get the last name of ui->slotList use the count()-method or the last()-method to get the last item of slotItems:
ui->slotList->item(ui->slotList->count() - 1); // or
ui->slotList->last()
The final answer was to use
void Edge::on_slotDelete_clicked()
{
QSettings settings("slots.ini",QSettings::IniFormat);
QString slotText;
QList<QListWidgetItem*> items = ui->slotList->selectedItems();
foreach(QListWidgetItem* item, items)
{
ui->slotList->removeItemWidget(item);
slotText.append(item->text());//this grabs the name
delete item;// this deletes list item
}
settings.beginGroup(slotText);// only takes QString or const QString argument
settings.remove("");
settings.endGroup();
qDebug() << slotText;
}
And that is how you can delete a selected item and its settings! Not quite what I was looking for but it changes the burden to having a proper naming convention on the save portion. Thank you for all of the support, you pushed me to finding the answer!

How to capture parent directory from lambda

In my code I list subdirectories name(only child dir) and if i click this subdirectory , the images inside this subdir will be displayed. In my case I cant capture parent directory from inside lambda. How can I do that?
Dir directory = QFileDialog::getExistingDirectory(this, tr("Open Directory"),"/home",
QFileDialog::ShowDirsOnly| QFileDialog::DontResolveSymlinks);
for (const QFileInfo &finfo: directory.entryInfoList()) {
QDir dir(finfo.absoluteFilePath());
ui->listWidget_dirs->addItem(dir.dirName());
}
//QStringList files = directory.entryList(QDir::Dirs);
//ui->listWidget_dirs->addItems(files);
auto listWidget_images = new QListWidget();//set listwidget to display images
listWidget_images->setMinimumSize(1200,400);
listWidget_images->setViewMode(QListWidget::IconMode);
listWidget_images->setIconSize(QSize(320,240));
listWidget_images->setResizeMode(QListWidget::Adjust);
connect(ui->listWidget_dirs, & QListWidget::itemClicked,[listWidget_images,this](QListWidgetItem *item)
{
listWidget_images->show();
listWidget_images->clear();
/*this is where it is wrong*/ QDir path(directory + '/' + item->text());
path.setNameFilters({"*.png", "*.jpg"});
for(const QFileInfo & finfo: path.entryInfoList()){
QListWidgetItem *item = new QListWidgetItem(QIcon(finfo.absoluteFilePath()), finfo.fileName());
listWidget_images->addItem(item);
}
});
I just wanted to leave a note. Be sure that your objects alive during your lamda exist, especially listWidget_images. If you delete it elsewhere, your lamda will crash. I would recommment to change the connect line a little:
from
connect(ui->listWidget_dirs, & QListWidget::itemClicked,[directory,listWidget_images, this](QListWidgetItem *item)
to
connect(ui->listWidget_dirs, & QListWidget::itemClicked, listWidget_images, [directory,listWidget_images, this](QListWidgetItem *item)
If you put the pointer listWidget_images before the capture list [] the lamda will be destroyed, when the object from listWidget_images is destroyed. Otherwise your application will crash in the first line of your lamda if the object doesn't exist anymore.
Well I get how to do it, this is the code.
QDir directory = QFileDialog::getExistingDirectory(this, tr("Open Directory"),"/home",
QFileDialog::ShowDirsOnly| QFileDialog::DontResolveSymlinks);
for (const QFileInfo &finfo: directory.entryInfoList()) {
QDir dir(finfo.absoluteFilePath());
ui->listWidget_dirs->addItem(dir.dirName());
}
auto listWidget_images = new QListWidget();//set listwidget to display images
listWidget_images->setMinimumSize(1200,400);
listWidget_images->setViewMode(QListWidget::IconMode);
listWidget_images->setIconSize(QSize(320,240));
listWidget_images->setResizeMode(QListWidget::Adjust);
connect(ui->listWidget_dirs, & QListWidget::itemClicked,[directory,listWidget_images, this](QListWidgetItem *item)
{
listWidget_images->show();
listWidget_images->clear();
// QDir path(item->text());
QDir dir = directory.absolutePath() + '/' + item->text();
dir.setNameFilters({"*.png", "*.jpg"});
for(const QFileInfo & finfo: dir.entryInfoList()){
QListWidgetItem *item = new QListWidgetItem(QIcon(finfo.absoluteFilePath()), finfo.fileName());
listWidget_images->addItem(item);
}
});

Select query returns "value: not positioned on a valid record" in Qt

I have been working on a small code which is supposed to fill up columns on a QTableWidget with values fetched from a SQL table.
Here's a small snippet:
QString path = "C:\\ENTRIES.db";
QString itemToSearch = "ABC"; //This comes as a parameter to a slot actually, assigning it here for simplicity
QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE");
db.setDatabaseName(path);
db.open();
QSqlQuery query(db);
query.prepare("SELECT * FROM METADATA WHERE ITEM LIKE ':item %'");
query.bindValue(":item", itemToSearch);
if(query.exec())
{
ui->tableWidgetSearchResults->setVisible(true);
ui->tableWidgetSearchResults->clearContents();
int rCount = ui->tableWidgetSearchResults->rowCount();
while(query.next())
{
ui->tableWidgetSearchResults->setRowCount(rCount + 1);
QTableWidgetItem *qtwParamName = new QTableWidgetItem;
qtwParamName->setFlags(qtwParamName->flags() & ~Qt::ItemIsSelectable & ~Qt::ItemIsEditable);
qtwParamName->setText(query.value(0).toString());
ui->tableWidgetSearchResults->setItem(rCount, 0, qtwParamName);
QTableWidgetItem *qtwParamValue = new QTableWidgetItem;
qtwParamValue->setFlags(qtwParamValue->flags() & ~Qt::ItemIsSelectable & ~Qt::ItemIsEditable);
qtwParamValue->setText(query.value(1).toString());
ui->tableWidgetSearchResults->setItem(rCount, 1, qtwParamValue);
rCount++;
}
}
else
{
qDebug() << "Error message: " << query.lastError().text() ;
ui->tableWidgetSearchResults->setHidden(true);
}
db.close();
When executing query.value(<index here>).toString()); lines, the Application Output prints:
QSqlQuery::value: not positioned on a valid record
QSqlQuery::value: not positioned on a valid record
I'm not sure of what I am missing here.
Note: I am using Qt 5.6, MSVC 2013 compiler and SQLite 3.8.
#CL. Thanks for the hint. I tried this line and it worked:
query.prepare("SELECT * FROM METADATA WHERE ITEM LIKE '" + itemToSearch + "%'");
Apparently bindValue was inappropriate in this case.

Char* corrupted when trying to get it / set it

I used to add a feature in my app based on treewidget.
When right click on an item, I can create a folder on the FS over USB is used.
That mainly say that when selecting an item on the TreeWidget, I get its name and check if it's a folder, if yes, I create a child and add a new folder and file the name.
The make the folder creation done on the FS, I'm using this :
void TreeView::onAddFolderAction() {
char *parent_folder_name;
QList<QTreeWidgetItem *> item;
bool isFolder;
item = this->selectedItems();
if (item.empty())
parent_folder_name = NULL;
else {
QString str = item[0]->text(0);
QByteArray latin_str = str.toLatin1();
parent_folder_name = latin_str.data();
}
setParentFolder(parent_folder_name);
if(!item.empty())
isFolder = m_device.isParentFolder(parent_folder_name);
if(isFolder == false)
return;
QTreeWidgetItem* child = new QTreeWidgetItem();
child->setText(0, "New Folder");
child->setText(1, "--");
child->setText(2, "--");
child->setFlags(child->flags() | Qt::ItemIsEditable);
if(!item.empty()) {
item[0]->addChild(child);
item[0]->setExpanded(true);
}
else
addTopLevelItem(child);
this->editItem(child);
this->setCurrentItem(child);
connect(this, SIGNAL(itemChanged(QTreeWidgetItem*, int)), this, SLOT(onTreeItemChanged()));
}
this code is connected to a CONNECT when left click action and add folder is selected.
I have done this to avoid the use of a dialog box when renaming. what I'm doing in add an item named New Folder, make it editable and allow the user to change it. when user press enter, the itemChanged signal is triggered and I start onTreeItemChanged.
QList<QTreeWidgetItem *> items;
bool isFolderCreated;
items = this->selectedItems();
QString str = items[0]->text(0);
QByteArray latin_str = str.toLatin1();
char *newFolder = latin_str.data();
char *parent = getParentFolder();
isFolderCreated = m_device.CreateFolder(newFolder, parent);
My issue is that parent do not contain the rigth name.
I'm backuping it in the onAddFolderAction using
setParentFolder(parent_folder_name);
and get it back using
getParentFolder();
Both are declared as below
void TreeView::setParentFolder(char *name) {
this->ParentFolder = name;
}
char *TreeView::getParentFolder() {
return this->ParentFolder;
}
when using the getParent, the value return is not correct. but it seems that what the value is corrupted earlier.
in the on AddFolderACtion(), I had:
else {
QString str = item[0]->text(0);
QByteArray latin_str = str.toLatin1();
parent_folder_name = latin_str.data();
}
setParentFolder(parent_folder_name);
parent_folder_name contain "BLABLA" but when moving step-by-step on setParentFolder, the parent_folder_name change to "XFZV" strange caracters.
Any idea why ?
In the code
else {
QString str = item[0]->text(0);
QByteArray latin_str = str.toLatin1();
parent_folder_name = latin_str.data();
}
setParentFolder(parent_folder_name);
the variable latin_str is local inside the else block, and will go out of scope and get destructed once the else block end. This leaves you with a stray pointer, pointing to now destructed and unallocated memory, leading to undefined behavior when you dereference it.
My recommendation is to use QString as much as possible, and only convert to pointer when actually needed (even if you need to do it multiple times). Either that, or change the rest of the code to accept QString (which would be a better solution IMO).

How to make a subchild to a child in QTreeWidget?

I want to make it so that I can expand a third level (subchild) to a child under the top level item (root). All I've been able to do is make multiple children to a single root.
this is in my .cpp
QStringList string1, string2;
string1 << "xxxxxxxx" << "xxxxxxxxxxx";
string2 << "yyyyyy" << "yy";
m_treeWidget->insertTopLevelItem(0, new QTreeWidgetItem(string1));
m_treeWidget->insertTopLevelItem(1, new QTreeWidgetItem(string2));
//here I add a child
AddChild(m_treeWidget->topLevelItem(0),"hello","world", m_treeWidget);
//here I make two attempts to make a sub child
AddChild(m_treeWidget->itemBelow(m_treeWidget->topLevelItem(0)),"hello_sub1","world_sub1", m_treeWidget);
AddChild(m_treeWidget->itemAt(0,0),"hello_sub2","world_sub2", m_treeWidget);
The following is my Add Child Method also in the same .cpp file:
void Dialog::AddChild (QTreeWidgetItem *parent, QString name, QString Description, QTreeWidget* treeWidget)
{
QTreeWidgetItem *item = new QTreeWidgetItem(treeWidget);
item->setText(0,name);
item->setText(1, Description);
parent->addChild(item);
}
In order to make a tree hierarchy you can use the QTreeWidgetItem's API, especially its constructors. Constructors can accept either QTreeWidget or QTreeWidgetItem as a parent object. In the first case, the top level item will be added to the tree widget and in the second case - child item of another item. This API is easier to use because you don't need to explicitly append items to the tree widget. Here is the sample code that implements the idea:
QStringList string1, string2;
string1 << "xxxxxxxx" << "xxxxxxxxxxx";
string2 << "yyyyyy" << "yy";
QTreeWidget tv;
// The top level items
QTreeWidgetItem *top1 = new QTreeWidgetItem(&tv, string1);
QTreeWidgetItem *top2 = new QTreeWidgetItem(&tv, string2);
// A child item.
QTreeWidgetItem *child1 =
new QTreeWidgetItem(top1, QStringList() << "Hello" << "World");
// The grandchildren.
new QTreeWidgetItem(child1, QStringList() << "Hello_sub1" << "World_sub1");
new QTreeWidgetItem(child1, QStringList() << "Hello_sub2" << "World_sub2");
Actually I was able to solve it another way...
in the .cpp:
//Initialize the QTreeWidget with 2 columns
QTreeWidget m_treeWidget = new QTreeWidget();
m_treeWidget->setColumnCount(2);
//these are the method calls:
AddRoot("Root1_Column1", "Root2_Column2", m_treeWidget);
AddRoot("Root2_Column1", "Root2_Column2", m_treeWidget);
//topLevelItem(0) makes it a child of the first root... topLevelItem(1) makes it a child of the second root
AddChild(m_treeWidget->topLevelItem(0),"Child1_Column1","Child1_Column2");
AddChild(m_treeWidget->topLevelItem(1),"Child2_Column1","Child2_Column2");
AddSubChild(m_treeWidget->itemBelow(m_treeWidget->topLevelItem(0)),"SubChild_Column1", "SubChild_Column2");
With these being the methods I used within the same .cpp file:
void Dialog::AddRoot (QString name, QString Description, QTreeWidget* treeWidget)
{
QTreeWidgetItem *item = new QTreeWidgetItem(treeWidget);
item->setText(0,name);
item->setText(1,Description);
item->setExpanded(true); //expand automatically
treeWidget->addTopLevelItem(item);
}
void Dialog::AddChild (QTreeWidgetItem *parent, QString name, QString Description)
{
QTreeWidgetItem *item = new QTreeWidgetItem();
item->setText(0,name);
item->setText(1, Description);
parent->addChild(item);
}
void Dialog::AddSubChild (QTreeWidgetItem *parent, QString name, QString Description)
{
QTreeWidgetItem *item = new QTreeWidgetItem();
item->setText(0,name);
item->setText(1, Description);
parent->addChild(item);
}