I have created a table using qtablewidget. I would like to selectively merge cells of some rows. Is there any built-in function for that(sorry, I couldn't find one)? Otherwise, please specify how it can be done. Thanks
You could use the setSpan function of QTableView (which QTableWidget inherits) to achieve something like that for rows and columns.
That is, unless you're looking to really just merge individual cells. I'm not sure that can be achieved with setSpan, but have a look at it anyway.
Try QTableWidget::setSpan(int row, int column, int rowSpan, int columnSpan);
But in some versions it doesn't work.
Sample program
#include <QApplication>
#include <QVBoxLayout>
#include <QPushButton>
#include <QLabel>
#include <QTableWidget>
#include <QHeaderView>
class TestWidget: public QWidget
{
Q_OBJECT
private:
QTableWidget *testTable;
QVBoxLayout *mainLayout;
QPushButton *button;
public:
TestWidget(QWidget *parent=nullptr) : QWidget(parent)
{
mainLayout = new QVBoxLayout(this);
testTable = new QTableWidget;
testTable = new QTableWidget(this);
testTable->setObjectName("testTable");
testTable->setFixedWidth(400);
testTable->setSizePolicy(QSizePolicy::Fixed,QSizePolicy::Minimum);
testTable->setColumnCount(4);
testTable->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
testTable->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
QTableWidgetItem *itemC1 = new QTableWidgetItem("Column 1");
testTable->setHorizontalHeaderItem(0, itemC1);
QTableWidgetItem *itemC2 = new QTableWidgetItem("Column 2");
testTable->setHorizontalHeaderItem(1, itemC2);
QTableWidgetItem *itemC3 = new QTableWidgetItem("Column 3");
testTable->setHorizontalHeaderItem(2, itemC3);
QTableWidgetItem *itemC4 = new QTableWidgetItem("Column 4");
testTable->setHorizontalHeaderItem(3, itemC4);
testTable->setColumnWidth(0,100);
testTable->setColumnWidth(1,100);
testTable->setColumnWidth(2,100);
testTable->setColumnWidth(3,100);
testTable->horizontalHeader()->setSectionResizeMode(QHeaderView::Fixed);
testTable->setEditTriggers(QAbstractItemView::DoubleClicked | QAbstractItemView::AnyKeyPressed);
testTable->setProperty("showDropIndicator", QVariant(false));
testTable->setDragDropOverwriteMode(false);
testTable->setSelectionMode(QAbstractItemView::SingleSelection);
testTable->setSelectionBehavior(QAbstractItemView::SelectRows);
testTable->setShowGrid(true);
testTable->setGridStyle(Qt::SolidLine);
testTable->setSortingEnabled(false);
testTable->setCornerButtonEnabled(false);
testTable->horizontalHeader()->setHighlightSections(false);
testTable->horizontalHeader()->setProperty("showSortIndicator", QVariant(false));
testTable->verticalHeader()->setVisible(false);
testTable->setAlternatingRowColors(true);
button = new QPushButton("Group");
connect(button, SIGNAL(clicked(bool)), this, SLOT(buttonClicked(bool)));
mainLayout->addWidget(testTable);
mainLayout->addWidget(button);
this->setLayout(mainLayout);
}
void addRow(QString c1, QString c2, QString c3, QString c4)
{
int row = testTable->rowCount();
testTable->insertRow(row);
QTableWidgetItem *c1Item = new QTableWidgetItem(c1);
QTableWidgetItem *c2Item = new QTableWidgetItem(c2);
QTableWidgetItem *c3Item = new QTableWidgetItem(c3);
QTableWidgetItem *c4Item = new QTableWidgetItem(c4);
c1Item->setTextAlignment(Qt::AlignLeft | Qt::AlignVCenter);
c2Item->setTextAlignment(Qt::AlignLeft | Qt::AlignVCenter);
c3Item->setTextAlignment(Qt::AlignLeft | Qt::AlignVCenter);
c4Item->setTextAlignment(Qt::AlignLeft | Qt::AlignVCenter);
testTable->setItem(row, 0, c1Item);
testTable->setItem(row, 1, c2Item);
testTable->setItem(row, 2, c3Item);
testTable->setItem(row, 3, c4Item);
}
void updateCell(int rowNumber, int columnNumber, QString textString)
{
if(rowNumber>=testTable->rowCount() || columnNumber>=testTable->columnCount()) return;
testTable->item(rowNumber, columnNumber)->setText(textString);
}
void groupCells(int rowNumber, int columnNumber, int rowSpan, int columnSpan)
{
if(rowNumber>=testTable->rowCount() || columnNumber>=testTable->columnCount()) return;
testTable->setSpan(rowNumber,columnNumber,rowSpan,columnSpan);
}
void ungroupCells(int rowNumber, int columnNumber)
{
if(rowNumber>=testTable->rowCount() || columnNumber>=testTable->columnCount()) return;
testTable->setSpan(rowNumber,columnNumber,1,1);
}
public slots:
void buttonClicked(bool event)
{
Q_UNUSED(event)
if(button->text()=="Group")
{
groupCells(1,1,2,1);
button->setText("Ungroup");
}
else
{
ungroupCells(1,1);
button->setText("Group");
}
}
};
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
TestWidget wid;
wid.addRow("0,0", "0,1", "0,2", "0,3");
wid.addRow("1,0", "1,1", "1,2", "1,3");
wid.addRow("2,0", "2,1", "2,2", "2,3");
wid.addRow("3,0", "3,1", "3,2", "3,3");
wid.show();
return a.exec();
}
#include "main.moc"
Project file shall be downloaded from github
Related
I want to show custom widget in each QListView cells (3 labels width different fonts and 2 tool buttons). The widget must handle mouse events for correct handling of the hover events and button clicks. (Therefore I cannot just draw it in QStyledItemDelegate::paint()).
Here is what I want each row in a list view looks like:
The main idea: QAbstractItemView::openPersistentEditor().
#include <QApplication>
#include <QWidget>
#include <QHBoxLayout>
#include <QLabel>
#include <QToolButton>
#include <QVBoxLayout>
#include <QDateTime>
#include <QListView>
#include <QStringListModel>
#include <QStyledItemDelegate>
class Form : public QWidget
{
//Q_OBJECT
public:
explicit Form(QWidget *parent = nullptr)
:QWidget(parent)
{
verticalLayout = new QVBoxLayout(this);
horizontalLayout = new QHBoxLayout();
labelTitle = new QLabel(this);
labelTitle->setFont(QFont("Calibri", 12, QFont::Bold));
horizontalLayout->addWidget(labelTitle);
toolButtonEdit = new QToolButton(this);
toolButtonEdit->setText("E");
horizontalLayout->addWidget(toolButtonEdit);
toolButtonRemove = new QToolButton(this);
toolButtonRemove->setText("R");
horizontalLayout->addWidget(toolButtonRemove);
verticalLayout->addLayout(horizontalLayout);
labelDate = new QLabel(this);
labelDate->setFont(QFont("Calibri", 8));
verticalLayout->addWidget(labelDate);
labelText = new QLabel(this);
labelText->setFont(QFont("Calibri", 10));
verticalLayout->addWidget(labelText);
verticalLayout->setStretch(2, 1);
setMinimumSize(QSize(300, 50));
}
public:
QVBoxLayout *verticalLayout;
QHBoxLayout *horizontalLayout;
QLabel *labelTitle;
QToolButton *toolButtonEdit;
QToolButton *toolButtonRemove;
QLabel *labelDate;
QLabel *labelText;
};
class MyDelegate : public QStyledItemDelegate
{
public:
QWidget* createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const override
{
auto editor = new Form(parent);
return editor;
}
void setEditorData(QWidget *ed, const QModelIndex &index) const override
{
QVariant var = index.model()->data(index, Qt::DisplayRole);
if (Form *editor = dynamic_cast<Form*>(ed))
{
editor->labelTitle->setText("SYMBOL");
editor->labelDate->setText("date-time");
editor->labelText->setText(var.toString());
}
}
void updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem& option, const QModelIndex &)const override
{
editor->setGeometry(option.rect);
}
};
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
Form form(nullptr);
form.labelTitle->setText("TITLE");
form.labelDate->setText(QDateTime::currentDateTime().toString());
form.labelText->setText("text body");
form.show();
auto model = new QStringListModel;
model->setStringList(QStringList()
<< "text body 1"
<< "text body 2"
<< "text body 3");
auto view = new QListView(nullptr);
view->setModel(model);
view->setItemDelegate(new MyDelegate);
int rowCount = model->rowCount();
for (int row = 0; row < rowCount; ++row)
{
QModelIndex index = model->index(row, 0);
view->openPersistentEditor(index);
}
view->show();
return a.exec();
}
Here is how the list view actually looks:
What how can one set such a custom widget to show view cells?
Note that while you are defining your own delegate MyDelegate you never actually use it (i.e. by calling QAbstractItemView::setItemDelegate(). Therefore you see the default delegate (a simple QLineEdit for data of type QString) when calling openPersistentEditor().
I am trying to design something like a timeline view for my video player. I decided to use QTableWidget as the timeline since it suits my purpose. My widget looks like this:
I want the green line to run through the widget when i click on play. Here is my MVCE example:
//View.cpp
View::View(QWidget* parent) : QGraphicsView(parent)
{
QGraphicsScene* scene = new QGraphicsScene(this);
TableWidget* wgt = new TableWidget;
scene->addWidget(wgt);
QGraphicsLineItem* item = new QGraphicsLineItem(30, 12, 30, wgt->height() - 9);
item->setPen(QPen(QBrush(Qt::green), 3));
item->setFlags(QGraphicsItem::ItemIsMovable);
scene->addItem(item);
setScene(scene);
}
Here is TableWidget
TableWidget::TableWidget(QWidget* parent) : QTableWidget(parent)
{
setColumnCount(10);
setRowCount(10);
//Hides the numbers on the left side of the table
verticalHeader()->hide();
//Prevents top header from highlighting on selection
horizontalHeader()->setHighlightSections(false);
//Makes the cells un-editable
setEditTriggers(QAbstractItemView::NoEditTriggers);
setSelectionMode(QAbstractItemView::MultiSelection);
}
Problem:
Moving the line item reflects changes to the scene it has been added to i.e. when i drag the line using mouse, the line moves in the scene but not inside the TableWidget.
What do i want
I want the green bar to act like a horizontal slider. It should go through the TableWidget horizontally making the widget scroll along with it showing the current position of the frame indicated by the numbers shown on the header.
Something like as shown below (notice the Red line):
I know this might not be the best way to implement a timeline but i would appreciate any other ideas to implement.
A possible solution is to overwrite the itemChange method to restrict movement as shown below:
#include <QApplication>
#include <QGraphicsRectItem>
#include <QGraphicsView>
#include <QTableWidget>
#include <QHeaderView>
#include <QGraphicsProxyWidget>
class SeekBarItem: public QGraphicsRectItem{
public:
SeekBarItem(QRectF rect, QGraphicsItem *parent=nullptr)
: QGraphicsRectItem(rect, parent)
{
setFlag(QGraphicsItem::ItemIsMovable, true);
setFlag(QGraphicsItem::ItemSendsGeometryChanges, true);
setBrush(Qt::red);
}
protected:
QVariant itemChange(GraphicsItemChange change, const QVariant &value){
if(change == QGraphicsItem::ItemPositionChange){
QPointF p = value.toPointF();
qreal max = parentItem()->boundingRect().bottom()- boundingRect().bottom();
qreal min = parentItem()->boundingRect().top()-boundingRect().top();
if(p.y() > max) p.setY(max);
else if (p.y() < min) p.setY(min);
p.setX(pos().x());
return p;
}
return QGraphicsRectItem::itemChange(change, value);
}
};
class TableWidget: public QTableWidget
{
public:
TableWidget(QWidget* parent=nullptr) : QTableWidget(10, 10, parent)
{
verticalHeader()->hide();
horizontalHeader()->setHighlightSections(false);
setEditTriggers(QAbstractItemView::NoEditTriggers);
setSelectionMode(QAbstractItemView::MultiSelection);
}
};
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QGraphicsView view;
QGraphicsScene *scene = new QGraphicsScene;
view.setScene(scene);
QGraphicsProxyWidget *proxy = scene->addWidget(new TableWidget);
QGraphicsRectItem *it = new QGraphicsRectItem(QRectF(0, 0, 10, proxy->boundingRect().height()), proxy);
it->setBrush(Qt::green);
SeekBarItem *seekBarItem = new SeekBarItem(QRectF(-5, 0, 20, 50));
seekBarItem->setParentItem(it);
view.resize(640, 480);
view.show();
return a.exec();
}
Update:
#include <QApplication>
#include <QGraphicsRectItem>
#include <QGraphicsView>
#include <QTableWidget>
#include <QHeaderView>
#include <QGraphicsProxyWidget>
#include <QScrollBar>
class TableWidget: public QTableWidget
{
public:
TableWidget(QWidget* parent=nullptr) : QTableWidget(10, 10, parent)
{
verticalHeader()->hide();
horizontalHeader()->setHighlightSections(false);
setEditTriggers(QAbstractItemView::NoEditTriggers);
setSelectionMode(QAbstractItemView::MultiSelection);
setHorizontalScrollMode(QAbstractItemView::ScrollPerPixel);
}
};
class SeekBarItem: public QGraphicsRectItem{
public:
SeekBarItem(int width, QAbstractItemView *view, QGraphicsScene *scene)
: QGraphicsRectItem(nullptr),
proxy(new QGraphicsProxyWidget()),
m_view(view)
{
proxy->setWidget(m_view);
scene->addItem(proxy);
setParentItem(proxy);
setFlag(QGraphicsItem::ItemIsMovable, true);
setFlag(QGraphicsItem::ItemSendsGeometryChanges, true);
setBrush(Qt::red);
setRect(0, 0, width, m_view->height());
scrollbar = m_view->horizontalScrollBar();
}
protected:
QVariant itemChange(GraphicsItemChange change, const QVariant &value){
if(change == QGraphicsItem::ItemPositionChange){
QPointF p = value.toPointF();
qreal max = parentItem()->boundingRect().right()- boundingRect().right();
qreal min = parentItem()->boundingRect().left()-boundingRect().left();
if(p.x() > max) p.setX(max);
else if (p.x() < min) p.setX(min);
p.setY(pos().y());
float percentage = (p.x()-min)*1.0/(max-min);
int value = scrollbar->minimum() + percentage*(scrollbar->maximum() - scrollbar->minimum());
scrollbar->setValue(value);
return p;
}
return QGraphicsRectItem::itemChange(change, value);
}
private:
QGraphicsProxyWidget *proxy;
QAbstractItemView *m_view;
QScrollBar *scrollbar;
};
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QGraphicsView view;
QGraphicsScene *scene = new QGraphicsScene;
view.setScene(scene);
TableWidget *table = new TableWidget;
SeekBarItem *seekBarItem = new SeekBarItem(15, table, scene);
view.resize(640, 480);
view.show();
return a.exec();
}
I am learning Qt for fun. And I got a question:
How could I drag and drop the QLabel in Qt among two different windows?
Here is what I have so far:
As you can tell from the .gif(which does not want to become downloaded and visible here for some reasons, but if you click on the link to it, you can clearly see it) provided above right now there are two main problems:
I can not move the QLabel outside of the window (and hence am not able to register the drag and drop event).
The label is flashing for some reasons when I am moving it.
Here is the relevant part of the implementation from the .gif:
#ifndef DRAGGERP_H
#define DRAGGERP_H
#include <QLabel>
#include <QApplication>
#include <QMouseEvent>
#include <QPoint>
class DraggerP : public QLabel
{
QPoint offset;
QPoint startingPosition;
public:
DraggerP(QWidget* parent = nullptr) : QLabel(parent){ }
protected:
void enterEvent(QEvent* event) override
{
QApplication::setOverrideCursor(Qt::PointingHandCursor);
}
void leaveEvent(QEvent* event) override
{
QApplication::restoreOverrideCursor();
}
void mousePressEvent(QMouseEvent* event) override
{
startingPosition = pos();
offset = QPoint(
event->pos().x() - pos().x() + 0.5*width(),
event->pos().y() - pos().y() + 0.5*height()
);
}
void mouseMoveEvent(QMouseEvent* event) override
{
move(event->pos() + offset);
}
void mouseReleaseEvent(QMouseEvent* event) override
{
move(startingPosition);
}
};
#endif // DRAGGERP_H
This is the extension of the QLabel I am using to create the drag and drop effect.
I do not need the whole solution, at least an idea of how to accomplish this and what am I doing wrong here.
Here is a pretty good example and I used it as a starting point.
That strange movement that the QLabel suffers is because the position of the QLabel now depends on the layout, the job of the layout is to establish the position of the widgets depending on the policies you establish.
The solution is not to implement those actions in the QLabel but in the MainWindow as I show below:
#include <QApplication>
#include <QLabel>
#include <QMainWindow>
#include <QScrollArea>
#include <QVBoxLayout>
#include <QTime>
#include <QDrag>
#include <QMimeData>
#include <QMouseEvent>
class MainWindow: public QMainWindow {
QScrollArea scrollArea;
QWidget contentWidget;
QVBoxLayout lay;
public:
MainWindow(QWidget* parent=nullptr): QMainWindow(parent){
qsrand((uint) QTime::currentTime().msec());
setCentralWidget(&scrollArea);
scrollArea.setWidget(&contentWidget);
contentWidget.setLayout(&lay);
scrollArea.setWidgetResizable(true);
for(int i=0; i< 20; i++){
QLabel *label = new QLabel(QString("label %1").arg(i));
QPalette pal = label->palette();
pal.setColor(QPalette::Background, QColor(10 +qrand() % 240, 10 +qrand() % 240, 10 +qrand() % 240));
label->setAutoFillBackground(true);
label->setPalette(pal);
lay.addWidget(label);
}
setAcceptDrops(true);
}
protected:
void mousePressEvent(QMouseEvent *event){
QMainWindow::mousePressEvent(event);
QWidget *child = childAt(event->pos());
if(qobject_cast<QLabel *>(child))
createDrag(event->pos(), child);
}
void dropEvent(QDropEvent *event){
QByteArray byteArray = event->mimeData()->data("Label");
QWidget * widget = *reinterpret_cast<QWidget**>(byteArray.data());
QLabel * new_label = qobject_cast<QLabel *>(widget);
QWidget *current_children = childAt(event->pos());
QLabel * current_label = qobject_cast<QLabel*>(current_children);
int index = 0;
if(new_label){
if(current_label)
index = lay.indexOf(current_label);
else{
index = 0;
QLayoutItem *item = lay.itemAt(index);
while(item->widget()->pos().y() < event->pos().y() && item)
item = lay.itemAt(index++);
}
lay.insertWidget(index, new_label);
}
}
private:
void createDrag(const QPoint &pos, QWidget *widget){
if(widget == Q_NULLPTR)
return;
QByteArray byteArray(reinterpret_cast<char*>(&widget),sizeof(QWidget*));
QDrag *drag = new QDrag(this);
QMimeData * mimeData = new QMimeData;
mimeData->setData("Label",byteArray);
drag->setMimeData(mimeData);
QPoint globalPos = mapToGlobal(pos);
QPoint p = widget->mapFromGlobal(globalPos);
drag->setHotSpot(p);
drag->setPixmap(widget->grab());
drag->exec(Qt::CopyAction | Qt::MoveAction);
}
protected:
void dragEnterEvent(QDragEnterEvent *event){
if(event->mimeData()->hasFormat("Label"))
event->acceptProposedAction();
}
};
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w1;
MainWindow w2;
w1.show();
w2.show();
return a.exec();
}
I added a QLabel inside my widget and it is editable through UI, able to set new text also, but not able to retrieve the updated text using function text();
QLabel *m_ColorName = new QLabel("_________");
m_ColorName->setTextInteractionFlags(Qt::TextSelectableByMouse | Qt::TextEditable);
In UI i am able to edit to new text but by calling function
m_ColorName->text();
Its giving default txt _________
Code
H file
class CascadeColorHighlightWidgetItem : public QWidget
{
Q_OBJECT
public:
CascadeColorHighlightWidgetItem(int jobID, QColor selectedColor, QWidget *parent = 0);
int getJobID();
QString getSelectedColor();
QString getColorText();
private:
QString m_titleName;
QRectF m_textRect;
QVBoxLayout *m_mainLyt;
QLineEdit *m_pTitleEditor;
QLabel *m_ColorName;
QColor m_SelectedColor;
};
Source File
CascadeColorHighlightWidgetItem::CascadeColorHighlightWidgetItem(QColor selectedColor, QWidget *parent)
: QWidget(parent),m_titleName("______"),m_SelectedColor(selectedColor)
{
setFixedHeight(40);
setContentsMargins(0,0,0,0);
setFocusPolicy(Qt::StrongFocus);
m_pTitleEditor = new QLineEdit();
m_ColorName = new QLabel("_________");
m_ColorName->setTextInteractionFlags(Qt::TextSelectableByMouse | Qt::TextEditable);
QFont font( "Calibri" );
font.setPixelSize(14);
m_ColorName->setFont(font);
QPixmap pixmap;
pixmap.fill(QColor("transparent"));
QWidget *pixMap = new QWidget;
pixMap->resize(100,100);
QString styl = QString("background-color: rgb(%1, %2, %3)").arg(QString::number(m_SelectedColor.red()),
QString::number(m_SelectedColor.green()),
QString::number(m_SelectedColor.blue()));
pixMap->setStyleSheet(styl);
m_ColorToStringMap.insert(m_ColorName->text(),m_SelectedColor);
QHBoxLayout * mnLyt = new QHBoxLayout(this);
mnLyt->addWidget(pixMap);
mnLyt->addWidget(m_ColorName);
mnLyt->addSpacerItem(new QSpacerItem(30, 0, QSizePolicy::Minimum, QSizePolicy::Minimum));
int width = pixMap->width();
int height = pixMap->height();
int side = qMin(width, height);
QRegion maskedRegion(width/2- side/2, height/2- side/2, 20,
20, QRegion::Ellipse);
pixMap->setMask(maskedRegion);
}
QString CascadeColorHighlightWidgetItem::getColorText()
{
qDebug() << "!!!CascadeColorHighlightWidgetItem::getColorText" << m_ColorName->text(); // returns "_________"
return m_ColorName->text();
}
It seems that although the text is editable, the data is not updated in the text, that can be solved with a hack, we use findChild to find the QTextDocument that is created when the flags are activated and get the text of that element:
QTextDocument *td = m_ColorName->findChild<QTextDocument *>();
if(td){
QString text = td->toRawText(); // >= Qt 5.9
// td->toPlainText();
// td->toHtml();
}
Example:
#include <QApplication>
#include <QLabel>
#include <QTextDocument>
#include <QTimer>
#include <QVBoxLayout>
#include <QWidget>
#include <QDebug>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QWidget widget;
QLabel label("_________");
label.setTextInteractionFlags(Qt::TextSelectableByMouse | Qt::TextEditable);
widget.setLayout(new QVBoxLayout);
widget.layout()->addWidget(&label);
QTimer timer;
QObject::connect(&timer, &QTimer::timeout, [&label](){
QTextDocument *td = label.findChild<QTextDocument*>();
if(td){
qDebug()<<td->toRawText();
//qDebug()<<td->toPlainText();
//qDebug()<<td->toHtml();
}
});
timer.start(100);
widget.show();
return a.exec();
}
Output:
[...]
"________"
"________"
"_______"
"____f___"
"____f___"
"____ff___"
"____fff___"
"____fff___"
"____ffff___"
"____fffff___"
"____fffff___"
[...]
How should i store data which is going into a TreeView? A Dictionary (QHash)? Plain Text? JSON?
My Hierarchy would be something like:
{
'Cloth': {
'Tissue':None,
'Leather': {
'Bandage': None
}
},
'Smoke': {
'White':{
'Smallscale': None,
'Largescale':None
}
}
}
Actions:
When I click a leaf-Element it will retrieve the Fullpath, like "Smoke/White/Smallscale" and this will be used as a key to place a SQL-Query.
I would use QStandardItem for every entry and when clicked, I would recursively call their parents, till I hit root.
Any thoughts?
Do you know QJsonTreeWidget?
Of course you don't need to use that library, but I do think you should use JSON in any case. It's almost a standard nowadays and very useful when we're working with trees.
Boost also has a wonderful library to work with JSON.
You can use one of the json library (like cajun) to parse json file.
This is the Qt part:
#include <QtGui>
#include <QTreeView>
class SimpleTreeView :public QTreeView
{
Q_OBJECT
public:
SimpleTreeView(QWidget *parent = 0);
public slots:
void slot_item_clicked(const QModelIndex &idx);
private:
QStandardItemModel *model;
};
#include <simpletreeview.h>
#include <qmessagebox.h>
#include <qobject.h>
SimpleTreeView::SimpleTreeView(QWidget *parent) : QTreeView(parent)
{
model = new QStandardItemModel(2,1);
QStandardItem *item1 = new QStandardItem("Cloth");
QStandardItem *item2 = new QStandardItem("Smoke");
model->setItem(0, 0, item1);
model->setItem(1, 0, item2);
QStandardItem *item3 = new QStandardItem("White");
item2->appendRow(item3);
QStandardItem *leaf = new QStandardItem("Smallscale");
leaf->setData("Smoke/White/Smallscale");
item3->appendRow(leaf);
setModel(model);
connect(this, SIGNAL(clicked(const QModelIndex &)), this, SLOT(slot_item_clicked(const QModelIndex &)));
}
void SimpleTreeView::slot_item_clicked(const QModelIndex & idx)
{
QString strData = model->itemFromIndex(idx)->data().toString();
QMessageBox::information(NULL, "Title", strData, QMessageBox::Yes, QMessageBox::Yes);
}
// main.cpp
#include <QApplication>
#include <simpletreeview.h>
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
SimpleTreeView view;
view.show();
return app.exec();
}