Level as list in QtreeWidget - qt

I have vector with 6 numbers, which I want insert to list and add this list to QTreeWidget. First number of list is on "root" level and other numbers are sublevel "root".
I don't know how to do it.
Image with describe:
Code:
void modal::zapis() {
ui->listWidget->clear();
ui->treeWidget->clear();
QList<QTreeWidgetItem *> items;
for(int i=0;i<v.size();i++)
{
QString string;
string.setNum(v.at(i));
ui->listWidget->addItem(string);
QTreeWidgetItem *root = new QTreeWidgetItem(ui->treeWidget);
if(i==0)
{
root->setText(0, string);
}
else
{
QTreeWidgetItem *item = new QTreeWidgetItem(root);
item->setText(0, string);
}
}
}
Thank you for any ideas.

You are creating a new root node on every iteration, it just needs creating once per call.

Related

Qt: QFormLayout::addRow(QWidget* label, QWidget* field) not adding a new row

I am trying to add a new row to my QFormLayout after I have loaded two QLineEdits from a file, which works, but when I run my code it doesnt add anything, ot atleast anything that I can see. And I am also not able to add any wigets using QLayout::addWidget(QWidget* widget) anymore, which I used to be able to.
Thanks
The code, where it doesnt work:
void Kegelbuch::load(QString path, QString tab) {
//Load json file
Datastream* loadStream = new Datastream;
QJsonObject data = loadStream->loadData(path);
//Declaring all important Variables
QJsonArray keglerFullName;
QJsonArray keglerShortName;
QFormLayout* formLayout = (QFormLayout*)ui.keglerTab->layout();
int defaultRows = 2, width = 155;
//Retriev arrays from file
if (data.contains("KeglerFullName") && data["KeglerFullName"].isArray()) {
keglerFullName = data["KeglerFullName"].toArray();
}
if (data.contains("KeglerShortName") && data["KeglerShortName"].isArray()) {
keglerShortName = data["KeglerShortName"].toArray();
}
//Correctly add QLineEdits to the FormLayout
for (auto names : boost::combine(keglerFullName, keglerShortName)) {
QLineEdit fullNameEdit;
QLineEdit shortNameEdit;
QJsonValue fullNameValue, shortNameValue;
boost::tie(fullNameValue, shortNameValue) = names;
if (fullNameValue.isString()) {
fullNameEdit.setText(fullNameValue.toString());
fullNameEdit.setObjectName("fullName");
fullNameEdit.setMinimumWidth(width);
}
if (shortNameValue.isString()) {
shortNameEdit.setText(shortNameValue.toString());
shortNameEdit.setMaximumWidth(width);
shortNameEdit.setObjectName("shortName");
}
/*
if (keglerFullName.at(1).isString()) {
fullNameEdit->setText(keglerFullName.at(1).toString());
fullNameEdit->setObjectName("fullName");
fullNameEdit->setMinimumWidth(width);
}
if (keglerShortName.at(1).isString()) {
shortNameEdit->setText(keglerShortName.at(1).toString());
shortNameEdit->setMaximumWidth(width);
shortNameEdit->setObjectName("shortName");
}
*/
formLayout->addRow(&fullNameEdit, &shortNameEdit);
}
}

Creating subtree with QTreeWidgetItem

Im trying to create a subtree using QTreeWidgetItem.
Here's code
m_pRoot = new QTreeWidgetItem(treeWidget);
m_pRoot->setText(0, "root");
m_pRoot->setData(0, Qt::UserRole, IT_ROOT);
createTreeItem(m_pRoot, m_pText, "subtree_1", IT_TEXT);
m_pRoot->setExpanded(true);
createTreeItem(m_pText, m_pPlainText, "subtree_2", IT_TEXT);
that's method:
void createTreeItem(PTR(QTreeWidgetItem) parent, PTR(QTreeWidgetItem) item, CREF(QString) name, ItemType itemType)
{
item = new QTreeWidgetItem(parent);
item->setText(0, name);
item->setData(0, Qt::UserRole, QVariant(itemType));
}
It's ok when im creating a "subtree_1" with m_pRoot as root item, but it breaks down when i want to create "subtree_2" with m_pText as root item.
P.S PTR() equal *parent.
Cant understand what's the problem. Any suggestions?
If your PTR(QTreeQWidgetItem) macro yields QTreeWidgetItem*, then item is not initialized by createTreeItem function.
The simplest and most logical fix seems to change createTreeItem function to return new item:
QTreeWidgetItem* createTreeItem(PTR(QTreeWidgetItem) parent, PTR(QTreeWidgetItem) item,
CREF(QString) name, ItemType itemType)
{
item = new QTreeWidgetItem(parent);
item->setText(0, name);
item->setData(0, Qt::UserRole, QVariant(itemType));
return item;
}
and use the returned value to initialize m_pText.

searching for a particular entry in a table by qlineedit?

What i want is that if i enter an ID in the textbox and then press enter,then if the ID is present ,then it gets displayed on the table the valuesof the table are inserted with the help of map in another window from which this window Box1 is opened as map.So as far as i have an idea,we have to run find command of map and then using if loop if that entered value in textbox is presentthen will display it in the same way as dummy data is displayed.
code used
Box1::Box1(QWidget *parent)
:QDialog(parent)
{
searchgroup = new QGroupBox(tr("Data Search"));
QHBoxLayout *layout2 = new QHBoxLayout;
text = new QLineEdit(this);
searchh = new QLabel(tr("&Enter ID:"));
searchh->setBuddy(text);
layout2->addWidget(searchh);
layout2->addWidget(text);
searchgroup->setLayout(layout2);
tableegroup = new QGroupBox(tr("Searched Data"));
QVBoxLayout *layout1 = new QVBoxLayout;
tablee = new QTableView(this);
mode1 = new QStandardItemModel(1,2,this);
mode1->setHorizontalHeaderItem(0, new QStandardItem(QString("ID")));
mode1->setHorizontalHeaderItem(1, new QStandardItem(QString("DATA")));
map<int,QString>::iterator itt;
itt=dataa.begin();
for (int colu = 0; colu < 2; colu++)
{
item1 = new QStandardItem();
if (colu == 0)
{
item1->setData(((*itt).first), Qt::DisplayRole);
mode1->setItem(0,0,item1);
} else
{
item1->setData(((*itt).second), Qt::DisplayRole);
mode1->setItem(0,1,item1);
}
}
tablee->setModel(mode1);
layout1->addWidget(tablee);
tableegroup->setLayout(layout1);
QVBoxLayout *mainlayout1 = new QVBoxLayout;
//mainlayout1->addWidget(menubarr);
mainlayout1->addWidget(searchgroup);
mainlayout1->addWidget(tableegroup);
setLayout(mainlayout1);
}
Thanks for any help in advance
EDIT
what i want
void Box1::textReturn()
{
bool ok;
int id = text->text().toInt(&ok);
// map<int,QString>::iterator itt;
if (ok && dataa.contains(id))
{
// add row (id, data[id] to table
}
else
{
QMessageBox msgbox = new QMessagebox();
msgbox->setWindowTitle("Alert");
msgbox->setText("No such ID present!");
msgbox->show();
}
}
EDIT2
void Box1::textReturn()
{
int id = (text->text()).toInt();
map<int,QString>::iterator itt;
itt = dataa.find(id);
if(itt != dataa.end()) //returns 1 if we found something
{
QList<QStandardItem *> items;
items << new QStandardItem(QString("%1").arg(id));
items << new QStandardItem((*itt).second);
mode1->appendRow(items);
tablee->update();
}
else
{
QMessageBox *msgbox = new QMessageBox();
msgbox->setWindowTitle("Alert");
msgbox->setText("INVALID ID ENTERED");
msgbox->show();
}
}
As #KCiebiera said, you have to do this connection
connect(text, SIGNAL(returnPressed()), this, SLOT(textReturnPressed());
Then you need to find your key in the table using
QList<QStandardItem *> QStandardItemModel::findItems ( const QString & text,
Qt::MatchFlags flags = Qt::MatchExactly, int column = 0 )
As you have map, so elements shouldn't repeat, your QList should be NULL or contains just one element. When u'll get your element (as QStandardItem) you just need to invoke
tablee->showColumn ( int column )
tablee->showRow ( int row )
Where your column will be QStandarItem->column() and row QStandardItem->row();
EDIT
void Box1::textReturnPressed()
{
int id = (test->text()).toInt();
map<int, string>::iterator it;
it = dataa.find(id);
if(it != dataa.end()) //we found something
{
QList<QStandardItem *> items;
items << new QStandardItem(QString("%1").arg(id));
items << new QStandardItem((*it).second);
mode1->appendRow(items);
}
else
QMessageBox::information(this, "Info", "ID not found!", QMessageBox::ok);
}
Something like this;
As far as I understand your question. You need to create a new slot in the Box1 class. Let's call it textReturnPressed(). Then you have to connect it to returnPressed() signal from text
connect(text, SIGNAL(returnPressed()), this, SLOT(textReturnPressed());
and here is textReturnPressed (I hope it compiles)
void textReturnPressed()
{
bool ok;
int id = text->text().toInt(&ok);
if (ok && dataa.count(id) > 0) {
QList<QStandardItem *> items;
items << new QStandardItem(QString("%1").arg(id));
items << new QStandardItem(dataa[id]);
mode1.appendRow(items);
}
}
You don't need an iterator to check if an item is in the map. Just call map.count() function.

QAbstactTableModel insert at top

I have addFile function in my TableModel class which inserts a new record at the end.
void TableModel::addFile(const QString &path)
{
beginInsertRows(QModelIndex(), list.size(),list.size());
TableItem item;
item.filename = path;
QFile file(path);
item.size = file.size();
item.status = StatusNew;
list << item;
endInsertRows();
}
This function works fine but instead of appending record at the end I would like to insert it at the top. Any pointers on how to update my existing function ?
I have already tried some combinations but there is no Luck.
There are two things that you need to do. First is to adjust the call to beginInsertRows. Because it is here that we are telling the model that we are adding rows, where they will go, and how many we are adding. Here is the method description:
void QAbstractItemModel::beginInsertRows ( const QModelIndex & parent,
int first, int last )
So in your case since you want to add a row at the first index, and only one row, we pass 0 as the index of the first item, and 0 which is the index of the last item we are adding (because of course we are only adding one item).
beginInsertRows(modelIndex(), 0, 0);
Next we have to provide the data for the item. I assume that 'list' is a QList (if not it is probably similar). So we want to call the 'insert' method.
list.insert(0, item);
And that should be it.
For display you can try delegates as explained in the link (I haven't tried the example though). It will help the community if you can add your observations.
Thanks to everyone for replying. I have found the solution by my own:
In case if anyone is interested
void TableModel::addFile(const QString &path)
{
beginInsertRows(QModelIndex(), list.size(), list.size());
TableItem item;
item.filename = path;
QFile file(path);
item.size = file.size();
item.status = StatusNew;
list << item; // Why Assign first? Maybe not required
for (int i = list.size() - 1; i > 0; i--)
{
list[i] = list[i-1];
}
list[0] = item; // set newly added item at the top
endInsertRows();
}

HowTo find Subitem in QAbstractItemModel and QTreeView class?

Question: how to find sub item, in a QTreeView loaded QAbstractItemModel model with model->match() method?
Problem: model->match() can't find sub items, wtf?!
Here is the example:
As you can see from the picture, I'm trying to expand Layouts sub item with this code:
void Dialog::restoreState(void)
{
// get list
QSettings settings("settings.ini", QSettings::IniFormat);
settings.beginGroup("MainWindow");
QStringList List = settings.value("ExpandedItems").toStringList();
settings.endGroup();
foreach (QString item, List)
{
if (item.contains('|'))
item = item.split('|').last();
// search `item` text in model
QModelIndexList Items = model->match(model->index(0, 0), Qt::DisplayRole, QVariant::fromValue(item));
if (!Items.isEmpty())
{
// Information: with this code, expands ONLY first level in QTreeView
view->setExpanded(Items.first(), true);
}
}
}
Where settings.ini file contains:
[MainWindow]
ExpandedItems=Using Containers, Connection Editing Mode, Form Editing Mode, Form Editing Mode|Layouts
PS: root items successfully expands on start!
Here is the solution:
QModelIndexList Items = model->match(
model->index(0, 0),
Qt::DisplayRole,
QVariant::fromValue(item),
2, // look *
Qt::MatchRecursive); // look *
* Without that argument match() function searches only 1 level
My working example on QTreeView.
QModelIndexList Indexes = this->ui->treeView->selectionModel()->selectedIndexes();
if(Indexes.count() > 0)
{
QStandardItemModel *am = (QStandardItemModel*)this->ui->treeView->model();
QStack<QModelIndex> mis;
QModelIndex mi = Indexes.at(0);
while(mi.isValid())
{
mis.push(mi);
mi = mi.parent();
}
QStandardItem *si;
bool FirstTime = true;
while (!mis.isEmpty())
{
mi = mis.pop();
if(FirstTime)
{
FirstTime = false;
si = am->item(mi.row());
}
else
{
si = si->child(mi.row());
}
}
// "si" - is selected item
}
Wanted to add to the answer that #mosg gave
The forth parameter is actually the hits parameters.
It decides ho many matches one wants to return.
For all matches specify -1 as can be seen
here:
QModelIndexList Items = model->match(
model->index(0, 0),
Qt::DisplayRole,
QVariant::fromValue(item),
-1, // any number of hits
Qt::MatchRecursive); // look *

Resources