Proper way to create a QTreeView + QTabWidget application
-
Greetings everyone!
I've met some troubles figuring out the proper way of implementing QTreeView and QTabWidget in one-window config. I'm aiming for a simple app, where user clicks the item in a QTreeView and QTabWIdget adjusts itself to display corresponding variety of tabs with info inside them (i'm still thinking on which widget to choose for info in tabs) using signals and slots.
While looking for answers i stumbled upon Simple Tree Model Example and MIME Type Browser Example. After a few deep dives into docs i began my attempts to create the model, starting with basic data types (i'm a naughty boy and will redefine these as classes with respectable methods):
struct File { QString m_fileName; QString m_fileExtension; File(const QString& _name, const QString& _extension) : m_fileName(_name), m_fileExtension(_extension){} File(const File& _file) : m_fileName(_file.m_fileName), m_fileExtension(_file.m_fileExtension){} ~File(){} }; struct Process { QString m_processName; QList<File> m_files; Process(const QString& _name, const QList<File>& _files) : m_processName(_name), m_files(_files){} Process(const Process& _p) : m_processName(_p.m_processName), m_files(_p.m_files){} ~Process(){} }; struct Product { QString m_productName; QList<Process> m_processes; Product(const QString& _name, const QList<Process>& _processes) : m_productName(_name), m_processes(_processes){} Product(const Product& _p) : m_productName(_p.m_productName), m_processes(_p.m_processes){} ~Product(){} };
But now there are some questions. Both examples mentioned above utilize tree view, but do it differently:
-
MIME Type browser has no root element (simple tree model does);
-
MIME Type browser stores some data in the model (simple tree model only has a root item pointer).
I chose to inherit from QStandardItem to use it with model inherited form QStandardItemModel (it seems appropriate in this case) and wrote simple DataItem class based on provided examples:
typedef QPair<QString, int> Data; class DataItem : public QStandardItem { Q_OBJECT public: explicit DataItem(const Data& _data, DataItem* _parent = nullptr); ~DataItem(); void appendChild(DataItem* _child); DataItem* child(int _row); int childCount() const; int columnCount() const; QVariant data(int _column) const override; int row() const; DataItem* parentItem() const; private: DataItem* m_parentItem; QList<DataItem*> m_childItems; Data m_itemData; };
Aaaaaaand after that i found myself completely lost.
Any tips/ideas/advices are appreciated!
-
-
@BeaverShallBurn
Like anywhere in OOP, slot methods belong as close to whatever it is they call!Try to keep the model and widget code very separate. Widgets can include model classes (e.g.
QTreeView
), but don't let model classes include/call anything in widgets/the UI. Models emit signals when something changes. UI/widgets place slots when they want to be notified about these and act on them. -
Hi,
You should first design the widget you want to use to show your data.
If this includes several different panels, then design each panel and finally put them all together in a widget that will contain your QTabWidget. Since you are using the model view framework, you should also set the model on it so you can extract the data as needed.
-
Thanks for your advice!
I've settled with using QTableView inside each tab of QTabWidget.
I get that QTableView needs its own model, but do i really need to implement another model for QTabWidget? Current state of the app:
MainWindow(QTreeView(model)|QTabWidget(QTableView(model)))
I suppose the way to do this is when item is clicked, MainWindow destructs QTabWidget and creates a new one with correct number of tabs. Feels kinda clunky.
-
@BeaverShallBurn said in Proper way to create a QTreeView + QTabWidget application:
MainWindow destructs QTabWidget and creates a new one with correct number of tabs. Feels kinda clunky.
I don't claim to have understood all that you have written, but
QTabWidget
can have tabs/pages inserted/removed, so why do you have to destroy/re-creates the wholeQTabWidget
if you don't like that? -
Thanks a lot, just came back from docs on
QTabWidget
and i'm doing it the proper way now.Do you have any tips on where to add signals and slots? Most examples show signals being declared in
QMainWindow
subclass, but where do slots belong (model/widget)?P.S.
Pardon my english, not a native speaker -
@BeaverShallBurn
Like anywhere in OOP, slot methods belong as close to whatever it is they call!Try to keep the model and widget code very separate. Widgets can include model classes (e.g.
QTreeView
), but don't let model classes include/call anything in widgets/the UI. Models emit signals when something changes. UI/widgets place slots when they want to be notified about these and act on them.