How to get qtoolbars order - qt

I need to save and restore position of QToolbars in my application.
When toolbars are docked to different area, i am able to save the area and assign it in function QMainWindow::addToolBar. But when several toolbars are docked to the same area, i don't know in what order they are currently on the screen.
I tried
QList<QToolBar*> toolbars = findChildren<QToolBar*>();
But this seems to return toolbars in order of creation and not how there are currently arranges on the screen (user can move them).

There is an easy and straightforward way of doing what you want in Qt. QMainWindow has a method saveState() that
saves the current state of this mainwindow's toolbars and dockwidgets.
and a method restoreState() that does the opposite.
Further information can be found here.
To save and restore the QMainWindow's geometry itself you can still use QWidget::saveGeometry() and QWidget::restoreGeometry().
An example of both combined that can also be found in saveState()'s documentation:
To save the geometry when the window closes, you can implement a close
event like this:
void MyMainWindow::closeEvent(QCloseEvent *event)
{
QSettings settings("MyCompany", "MyApp");
settings.setValue("geometry", saveGeometry());
settings.setValue("windowState", saveState());
QMainWindow::closeEvent(event);
}

Related

Docking with QWinWidget: Adding DockWidgetAreas to QWidgets

I have an application utilizing QWinWidget in a Win32 window. I'd like to add DockWidgets and the associated behaviour to it. There don't seem to be any exposed APIs for adding custom DockAreas, and the latest docs are sparse beyond adding DockWidgets to a QMainWindow. Older docs imply there once was a public QDockArea class.
So far, my best option appears to be adding a neutered QMainWindow (no top-level status, no frame, etc.) to the QWinWidget and going from there (second source).
I was hoping there was a way to add DockAreas to any container, but it doesn't appear that way. As a side note, QWinWidget is used to have window manager control with our custom frame requirement, but if there's a pure QMainWindow/QWidget way to have the same result (with Qt::FramelessWindowHint), I'd be happy to switch over.
As I said in the comments, I've added within my QWinWidget in my Win32 window a QMainWindow field. That is:
class QWinWidget : public QWidget
{
...
QMainWidget* mainWidget;
}
QWinWidget::QWinWidget()
{
mainWidget = new QMainWindow(this);
mainWidget->setWindowFlags(Qt::Widget); //1
}
Note that while the docs and some forum posts (from this post) indicate you need to set window flags explicitly due to the QMainWindow constructor setting Qt::Window, I tested it without the setWindowFlags() line (marked with //1 above) without noticing anything wrong.
So, this gives me the nice QWinWidget window I spent so much time making, inside a frameless Win32 window, with a QMainWindow child and all the features that brings along with it. Docking, menu bar, status bar, etc.

How to draw something in a tooltip?

I am trying to develop a functionality using Qt which I don't know whether it is possible to implement. Here is the requirement:
When the user hovers over a node (an object derived from QGraphicsItem), a window will be shown near the node, in the window there might be some histograms or buttons that can be clicked to show further information. When the mouse leaves the window, it will automatically close.
I tried to use a tooltip, because it can pop-up near the node and close when the mouse leaves it, but it can only show text. So, it still cannot work that way. I am wondering if there is another way to do this? I did lots of google search, but there is still no answer.
Thanks so much for helping me with this.
If you're ok with using a 3rd party library, Qxt provides a class that provides a tooltip that is QWidget based, which will let you use an arbitrary widget as the tooltip rather than just text.
See: Qxt::ToolTip
you don't have to use tooltip for your app
you can use or call widget or dialog, on hover mouse event
Please refer Qt Example EmbeddedDialog Example, It is advanced, But you can understand how hover Enter/Leaving events are working. I personally prefer don not create instance of Popupdialog for each item, create it if only nesessary. Otherwise create one dialog and pass its reference to all the items through the constructor initialization.
1. These are the API you are intrested on, reimplemet this.
QGraphicsItem::hoverEnterEvent(QGraphicsSceneHoverEvent *event) and void QGraphicsItem::hoverLeaveEvent(QGraphicsSceneHoverEvent *event)
2. When You create Dialog, You can pass Qt::WindowFlags as Qt::ToolTip.

How can I customize the appearance of the actions in my QToolBar?

I have just changed some toolbars from Q3ToolBars (with QToolButtons explicitly added to them) into Q4 toolbars (with actions added to them straight away instead.)
The old tool buttons had a nice outline around them, but this is not displayed in the new version; the QActions in the Q4 toolbar just look like a line of icons. Is there a way to change the 'button' style in the new version (assuming these actions can be considered as such) and give them the outline? I've looked through the QToolBar reference, but the toolButtonStyle() function only appears to work with whether you want to display icon, text, etc.
...Or will I have to just make actual tool buttons and/or QPushButtons and use addWidget()?
The widget associated with a given action is accessible through QToolBar::widgetForAction (since Qt 4.2). So, you can pass your actions to this method, get the QWidgets returned by it, convert them to QToolBar, and handle them like you normally would (code not tested):
// ...
auto toolButton =
static_cast<QToolButton *>(
m_ui.toolbar->widgetForAction(m_ui.my_Action));
// Will make the toolButton always appear raised:
toolButton->setAutoRaise(false);
// ...
As far as I've been testing, some methods might not work (i.e., QWidget::hide), so do your own testing.
Yes, of course you can edit look of QToolButtons in two different ways:
You can set it style sheet using void QWidget::setStyleSheet(const QString &)
You can reimplement QToolButtons class with new paintEvent function where you will be able to exactly set how your button should looks like.

Directing keyboard input to a widget when using Qt

I am creating a GUI using Qt. Basically it is an interactive map that shows robots moving in an arena in real time and allows the user to interact with the robots(tell them to go/stop) by using the mouse and keyboard keys. I used opengl to create the map itself and everything is working perfectly, I can see the robots moving on the map and I can press different keys on the keyboard and send the actual robots commands.
Now, I need to take this map and make it become a part of a bigger GUI that holds this map along with other objects as well,not all objects are necessarily using opengl. So, by using the Qt creator (designer) I have some dragged/dropped tabs in my GUI and I have also added a "dockwidget" in my GUI. The dockwidget holds in it the interactive map that I had created earlier. Now, however I can no longer send commands using my keyboard to my map. I can still click on different robots on my map and I can see that they get selected and change colors (as I coded it to do) but pressing keys have no corresponding actions(as it has been coded).
This is what the map by itself looks like. http://dl.dropbox.com/u/46437808/collision3.png
This is the map as a docked widget. (Inside the widge,I was able to click on one robot and make it turn yellow) https://www.dropbox.com/s/lpo43rl6z4268im/argHRI.png
So, my question is how do we direct keyboard input to a specific widget in a window when using Qt. From what I read that it might have to do with setting focus policy. So, I tried to set the focuspolicy of my dockwidget to "StrongFocus" (so that it can take keyboard input) in the constructor but that did not help.
Here is the code in which I'm setting my map as the dockwidget and I'm trying to set the focus as well.
#include "ui_arghri.h"
argHRI::argHRI(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::argHRI)
{
ui->setupUi(this);
ui->dockMap->activateWindow();
//ui->dockMap->keyboardGrabber();
//ui->dockMap->grabKeyboard();
ui->dockMap->setFocus();
ui->dockMap->setFocusPolicy(Qt::StrongFocus);
}
argHRI::~argHRI()
{
delete ui;
}
void argHRI::addMap(Map * map)
{
qDebug()<<"argHRI::in AddMap test is "<<map->test;
//ui->dockMap->show();
ui->dockMap->setWidget(map);
}
Add an event filter that handles KeyPress events to your class. There are examples here: http://doc.qt.io/archives/qt-4.7/eventsandfilters.html
Just don't forget to add:
installEventFilter(this);
to the constructor or it won't work otherwise.

Attach Qt windows?

Is there any way to attach two Qt windows together? For example, if window A is the main window and window B is another widget I want to be able to show window B to the side of A and have both windows move together if the windows are dragged.
Not that I am aware of, but you can try following the trail of QMoveEvent. When a given widget is moved void QWidget::moveEvent ( QMoveEvent * event ) is called, and the QMoveEvent contains both old and new pos. Using this information, you can inject a move event in the other widget as well, and make it follow.
Of course, I am speaking of two independent widgets, each one in its own window. If they are contained, you don't need anything but a Layout management (see QLayout and related classes).
I don't work with Qt since a long time, so there could be a better method, but if I had to do it right now, this is the strategy I would use.
Also, I have the feeling that the QMoveEvent will be invoked only at start and end, unless you enable mouse tracking. If the former is the case, you will obtain that the other widget will "teleport" at the end of the move, instead of following smoothly.
You might be after something like this:
http://doc.qt.io/archives/4.6/qt4-mainwindow.html
Window A would be a QMainWindow and window B would be a QDockWidget.

Resources