Changing application's main window GUI layout to be in code - c++

In my application the main window's GUI is designed in the Qt-Creator designer. I have had some trouble in getting it to look just the way I'd like, but I can when doing the GUI in C++ code.
So, I plan to change the application's main window to be laid out in code.
What should I keep in mind when doing this?
How do I make sure all the menu items and button clicks etc. get migrated, too?

In my Qt experience I almost always write layout in code and here is what I can suggest:
a) Spend some time thinking which Layout to use, personally I tend to use either QGridLayout or nested QHboxLayout and QVBoxLayout which give you lot of flexibility.
b) I normally declare all child widgets as class variables always pointers and I create the real objects in the Main windows constructor.
About not to forget any control I suggest to print the XML of the UI file and draw a line on each control you recreate in the code.

As a good starting point, simply copy-pase the setupUi method from the ui_xxx.h file that uic had generated for you. You can then manually edit the setup code to suit your needs.

Related

Qt mac switch between panels without changing window

I extensively researched this topic, mainly hindered by that I'm not sure I'm using the right words to describe my issue.
So the point is I'm developing a GUI application in C++ with Qt. The app is being developped on Mac and ftm it's intended only for mac deployment.
I want my app to behave much like System Preferences on Mac, thus accessing different views/panes by clicking buttons on the toolbar.
What I want to avoid is to have one separate window for each pane.
The closest thing I found seems to be QStackedWidget however I'm not sure what's the best way for implementing it.
Should I use it as the main class of my application? Or can I treat it as an object of MainWindow? I'm not a Qt Expert so any further insight or suggestion will be much appreciated. Thanks
QStackedWidget is definitely the way to go. Use it as your main 'container' for your widgets and implement a default main panel widget which contains your entry items, then when you click on one you can push it to be the currently displayed widget in the stack. You could try more complicated solutions to achieve it, but it's significantly easier to do with a QStackedWidget and then focus on how the interaction is handled.

How do you programatically update the UI in Qt?

I'm fairly new to Qt, and am trying to wrap my head around signals and slots. Though I've figured out how to create custom slots, I've yet to figure out how do update the GUI from my C++ code. I realized that the entire UI, which I created in the designer, is only written in what appears to be XML based UI code. Do I have to handwrite my own Qt C++ UI in order to update the interface, or can I somehow use C++ to update the XML based UI? I'm just looking to add a widget to the main form on a button click. Any help is appreciated. Thanks!
To add a widget to a form you can simply do
ui->layout()->addWidget(new Widget);
XML is used by QtDesigner as a mean to create, update, and persist your GUI, enabling a visual approach to development, but in the end you can build your application entirely without it.
you dont havfe to update the xml of UI . you can inherit the ui into your own class using setupUi
http://crpppc19.epfl.ch/doc/qt4-doc-html/html/qwidget.html#setupUi
now in your C++ class you can update the widgets like changing label text, lineEdit text, setting up spinbox value using Signals & slot.
That xml is used by Qt designer and outside of designer it's only used by uic as a source to generate C++ code, so everything that you do in the designer end-up as C++ code, so it can be updated (or done completely) in C++ code (you can look into the code and see that you most likely have a member called ui that is most likely a pointer, but it can also be an instance of a C++ class that is generated for you by uic, and trough that ui member you can access the widgets and layouts that you created in the designer).
A generic resource that i recommend you to read can be found here and then (if you still can't figure it out) ask a specific question about what exactly are you trying to achieve.
LE: that link contains 3 methods to use the generated code into C++ code, don't try all of them into your working project, you may choose one method or use the default one (ui member pointer)

How to avoid ugly overlap with too many dockwidgets in QMainWindow?

In our application, we have a variable number of dockwidgets because some of them are added by plugins that are loaded at runtime. Not all dockwidgets need to be visible at the same time necessarily. This depends strongly on what the user is working on and what plugins are active.
However, if too many dockwidgets are added programmatically with addDockWidget(...), they start to overlap each other (not in terms of tabs, but in terms of content of one being painted on the area of a different one, which obviously looks broken).
The user can move the dockwidgets to dockareas that still have space left, but the layout/main window successfully prevents (untabbed) re-addition to the "crowded" dockarea.
We do allow tabbed docks to allow the user to arrange the dockwidgets a required, but we don't want to enable QMainWindow::ForceTabbedDocks since this would constrain the number of simultaneously visible dockwidgets too much (one per dock area).
How can I prevent this or better control how dockwidgets are added?
Not answering your question directly but it might be worthwhile to actually forget about Qt and actually think of how the whole interaction should work. What are the user expectations? What should actually happen if 10 different plugins become active? Should they be docked or should they be floating or should they become pin-able docking windows with initial state as a small button on the MainWindow edges? I think once you do that ground work and come up with user interface mock-ups, you can then start looking at Qt and figure out if Qt provides a direct way to develop that interface and if not what additional components you will need to develop to get that interface working.
From my own experience, I had developed a similar interface long back but in MFC. The way we did it was that some of the docked windows were deemed to be must have and they would come up as docked. Then there were a set of windows that didnt need to be visible always but should be quickly available and their initial state was as hidden pin-able dock window which meant they came up as buttons on the MainWindow edge. Finally there was a third set that was not required by the user always and could be called in from File->View Menu. Once the user made it visible, the user typically would assign it to one of the first two groups or keep it afloat. This whole configuration was saved in a config file and from there onwards whenever the plugin was loaded/became active the last used state of the associated docking window was used. It though involved quite a bit of extra work but the end result was to the satisfaction of all users.
Have you tryed setDockOptions(QMainWindow::AllowNestedDocks)? I can't test it now but it may help.
By default, QMainWindow::dockOptions is set to AnimatedDocks | AllowTabbedDocks so you would want something like
setDockOptions(QMainWindow::AllowNestedDocks | QMainWindow::AnimatedDocks | QMainWindow::AllowTabbedDocks)
EDIT:
If you are having too many problems, you may be going about this the wrong way. Instead of using docks, you may want to try using QMdiArea with QMdiWindow. This may not work for your program, but its something to think about.
This is the solution I tried:
I created in QTCreator an empty project with a window, a minimalistic menu labelled "New Dock" and a DockWidget named dockWidget
This is the triggered() handler for my menu item:
void MainWindow::on_actionNew_Dock_triggered()
{
QDockWidget* w = new QDockWidget("Demo", ui->dockWidget);
this->addDockWidget(Qt::LeftDockWidgetArea,w);
this->tabifyDockWidget(ui->dockWidget,w);
}
tabifyDockWidget(QDockWidget* first, QDockWidget* second) is a QMainWindow method that stacks the second dockwidget upon the first one. Hope it helps...

QT. QLabel perfomance

In my application I have a file manager similar to the standart windows explorer.
The structure is:
QScrollArea
QWidget
EFile
EFile
EFile
etc...
Each EFile widget contains 5 QLabels. So when the count of files is more than 30 I have a little delay while they are being created. I decided to create only visible files and create hidden on scroll or resize when they become visible. But it's not a solution - the delay remained (although it decreased of course).
The question is how should I modify my application to remove the delay while showing files.
The answer is that you do not compose your custom widget of QLabels. Instead, you overwrite the paint() function and draw the texts/pixmaps with QPainter. It is not as much work as it sounds. There are tons of examples for that in the Qt examples/tutorials.
If it really is a file explorer you want to implement, you should consider using a QFileSystemModel in combination with a QTreeView as shown in the example here:
http://qt-project.org/doc/qt-4.8/qfilesystemmodel.html
This will save you a lot of trouble.

Floating/Embedded QDockWidget in a QWidget (KXmlGuiWindow's CentralWidget designed in QT Designer)

I'm just trying to get into QT (and KDE) program, and have hit a snag trying to add a floatable, draggable QDockWidget to the .ui file (based as a QWidget) that is embedded into my KDE 4 program.
This is all from the basic template provided by KDevelop 4, so while I understand what's going on, I just don't know the best way to change it.
Here's the deal: main.cpp spawns a new AEmpire window, which starts the whole show off:
AEmpire::AEmpire()
: KXmlGuiWindow(),
m_view(new AEmpireView(this)),
m_printer(0)
{
// tell the KXmlGuiWindow that this is indeed the main widget
setCentralWidget(m_view);
setupActions();
setupGUI();
}
When a new AEmpireView(this) is created (which inherits from QWidget) and is assigned to m_view, this constructor is called:
AEmpireView::AEmpireView(QWidget *)
{
ui_aempireview_base.setupUi(this);
settingsChanged();
setAutoFillBackground(true);
}
So, when I am editing the ui to my program in QT Designer, I'm actually editing the AEmpireView_base ui file, which is a QWidget. It just represents the main view of the KXmlGuiWindow (derived from QMainWindow) and is loaded at runtime.
So, how do I add floatable, draggable QDockWidgets into my main application? Is designing them separately, and add them to the UI the best option? Or maybe removing the entire AEmpireView class, and making my ui file directly represent a KXmlGuiWindow object to be loaded by the AEmpireClass?
Or am I totally overlooking something obvious? Thanks for reading!
I would design the QDockWidget contents as separate UI files. Then create them and stick them into the QDockWidgets in the AEmpire constructor.