2 ******************************************************************************
4 * @file fancymainwindow.cpp
5 * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
6 * Parts by Nokia Corporation (qt-info@nokia.com) Copyright (C) 2009.
8 * @see The GNU Public License (GPL) Version 3
12 *****************************************************************************/
14 * This program is free software; you can redistribute it and/or modify
15 * it under the terms of the GNU General Public License as published by
16 * the Free Software Foundation; either version 3 of the License, or
17 * (at your option) any later version.
19 * This program is distributed in the hope that it will be useful, but
20 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
21 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
24 * You should have received a copy of the GNU General Public License along
25 * with this program; if not, write to the Free Software Foundation, Inc.,
26 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
29 #include "fancymainwindow.h"
31 #include "qtcassert.h"
33 #include <QContextMenuEvent>
35 #include <QDockWidget>
38 static const char lockedKeyC
[] = "Locked";
39 static const char stateKeyC
[] = "State";
40 static const int settingsVersion
= 2;
41 static const char dockWidgetActiveState
[] = "DockWidgetActiveState";
44 /*! \class Utils::FancyMainWindow
46 \brief MainWindow with dock widgets and additional "lock" functionality
47 (locking the dock widgets in place) and "reset layout" functionality.
49 The dock actions and the additional actions should be accessible
53 struct FancyMainWindowPrivate
{
54 FancyMainWindowPrivate();
57 bool m_handleDockVisibilityChanges
;
59 QAction m_menuSeparator1
;
60 QAction m_toggleLockedAction
;
61 QAction m_menuSeparator2
;
62 QAction m_resetLayoutAction
;
63 QDockWidget
*m_toolBarDockWidget
;
66 FancyMainWindowPrivate::FancyMainWindowPrivate() :
68 m_handleDockVisibilityChanges(true),
70 m_toggleLockedAction(FancyMainWindow::tr("Locked"), 0),
72 m_resetLayoutAction(FancyMainWindow::tr("Reset to Default Layout"), 0),
73 m_toolBarDockWidget(0)
75 m_toggleLockedAction
.setCheckable(true);
76 m_toggleLockedAction
.setChecked(m_locked
);
77 m_menuSeparator1
.setSeparator(true);
78 m_menuSeparator2
.setSeparator(true);
81 FancyMainWindow::FancyMainWindow(QWidget
*parent
) :
82 QMainWindow(parent
), d(new FancyMainWindowPrivate
)
84 connect(&d
->m_toggleLockedAction
, SIGNAL(toggled(bool)),
85 this, SLOT(setLocked(bool)));
86 connect(&d
->m_resetLayoutAction
, SIGNAL(triggered()),
87 this, SIGNAL(resetLayout()));
90 FancyMainWindow::~FancyMainWindow()
95 QDockWidget
*FancyMainWindow::addDockForWidget(QWidget
*widget
)
97 QDockWidget
*dockWidget
= new QDockWidget(widget
->windowTitle(), this);
99 dockWidget
->setWidget(widget
);
100 // Set an object name to be used in settings, derive from widget name
101 const QString objectName
= widget
->objectName();
102 if (objectName
.isEmpty()) {
103 dockWidget
->setObjectName(QLatin1String("dockWidget") + QString::number(dockWidgets().size() + 1));
105 dockWidget
->setObjectName(objectName
+ QLatin1String("DockWidget"));
107 connect(dockWidget
->toggleViewAction(), SIGNAL(triggered()),
108 this, SLOT(onDockActionTriggered()), Qt::QueuedConnection
);
109 connect(dockWidget
, SIGNAL(visibilityChanged(bool)),
110 this, SLOT(onDockVisibilityChange(bool)));
111 connect(dockWidget
, SIGNAL(topLevelChanged(bool)),
112 this, SLOT(onTopLevelChanged()));
113 dockWidget
->setProperty(dockWidgetActiveState
, true);
114 updateDockWidget(dockWidget
);
118 void FancyMainWindow::updateDockWidget(QDockWidget
*dockWidget
)
120 const QDockWidget::DockWidgetFeatures features
=
121 (d
->m_locked
) ? QDockWidget::DockWidgetClosable
| QDockWidget::DockWidgetFloatable
122 : QDockWidget::DockWidgetMovable
| QDockWidget::DockWidgetClosable
| QDockWidget::DockWidgetFloatable
;
124 if (dockWidget
->property("managed_dockwidget").isNull()) { // for the debugger tool bar
125 QWidget
*titleBarWidget
= dockWidget
->titleBarWidget();
126 if (d
->m_locked
&& !titleBarWidget
&& !dockWidget
->isFloating()) {
127 titleBarWidget
= new QWidget(dockWidget
);
128 } else if ((!d
->m_locked
|| dockWidget
->isFloating()) && titleBarWidget
) {
129 delete titleBarWidget
;
132 dockWidget
->setTitleBarWidget(titleBarWidget
);
134 dockWidget
->setFeatures(features
);
137 void FancyMainWindow::onDockActionTriggered()
139 QDockWidget
*dw
= qobject_cast
<QDockWidget
*>(sender()->parent());
142 if (dw
->isVisible()) {
148 void FancyMainWindow::onDockVisibilityChange(bool visible
)
150 if (d
->m_handleDockVisibilityChanges
) {
151 sender()->setProperty(dockWidgetActiveState
, visible
);
155 void FancyMainWindow::onTopLevelChanged()
157 updateDockWidget(qobject_cast
<QDockWidget
*>(sender()));
160 void FancyMainWindow::setTrackingEnabled(bool enabled
)
163 d
->m_handleDockVisibilityChanges
= true;
164 foreach(QDockWidget
* dockWidget
, dockWidgets())
165 dockWidget
->setProperty(dockWidgetActiveState
, dockWidget
->isVisible());
167 d
->m_handleDockVisibilityChanges
= false;
171 void FancyMainWindow::setLocked(bool locked
)
173 d
->m_locked
= locked
;
174 foreach(QDockWidget
* dockWidget
, dockWidgets()) {
175 updateDockWidget(dockWidget
);
179 void FancyMainWindow::hideEvent(QHideEvent
*event
)
182 handleVisibilityChanged(false);
185 void FancyMainWindow::showEvent(QShowEvent
*event
)
188 handleVisibilityChanged(true);
191 void FancyMainWindow::contextMenuEvent(QContextMenuEvent
*event
)
193 QMenu
*menu
= createPopupMenu();
195 menu
->exec(event
->globalPos());
199 void FancyMainWindow::handleVisibilityChanged(bool visible
)
201 d
->m_handleDockVisibilityChanges
= false;
202 foreach(QDockWidget
* dockWidget
, dockWidgets()) {
203 if (dockWidget
->isFloating()) {
204 dockWidget
->setVisible(visible
205 && dockWidget
->property(dockWidgetActiveState
).toBool());
209 d
->m_handleDockVisibilityChanges
= true;
213 void FancyMainWindow::saveSettings(QSettings
*settings
) const
215 QHash
<QString
, QVariant
> hash
= saveSettings();
216 QHashIterator
<QString
, QVariant
> it(hash
);
217 while (it
.hasNext()) {
219 settings
->setValue(it
.key(), it
.value());
223 void FancyMainWindow::restoreSettings(const QSettings
*settings
)
225 QHash
<QString
, QVariant
> hash
;
226 foreach(const QString
&key
, settings
->childKeys()) {
227 hash
.insert(key
, settings
->value(key
));
229 restoreSettings(hash
);
232 QHash
<QString
, QVariant
> FancyMainWindow::saveSettings() const
234 QHash
<QString
, QVariant
> settings
;
235 settings
.insert(QLatin1String(stateKeyC
), saveState(settingsVersion
));
236 settings
.insert(QLatin1String(lockedKeyC
), d
->m_locked
);
237 foreach(QDockWidget
* dockWidget
, dockWidgets()) {
238 settings
.insert(dockWidget
->objectName(),
239 dockWidget
->property(dockWidgetActiveState
));
244 void FancyMainWindow::restoreSettings(const QHash
<QString
, QVariant
> &settings
)
246 QByteArray ba
= settings
.value(QLatin1String(stateKeyC
), QByteArray()).toByteArray();
249 restoreState(ba
, settingsVersion
);
251 d
->m_locked
= settings
.value(QLatin1String("Locked"), true).toBool();
252 d
->m_toggleLockedAction
.setChecked(d
->m_locked
);
253 foreach(QDockWidget
* widget
, dockWidgets()) {
254 widget
->setProperty(dockWidgetActiveState
,
255 settings
.value(widget
->objectName(), false));
259 QList
<QDockWidget
*> FancyMainWindow::dockWidgets() const
261 return findChildren
<QDockWidget
*>();
264 bool FancyMainWindow::isLocked() const
269 static bool actionLessThan(const QAction
*action1
, const QAction
*action2
)
271 QTC_ASSERT(action1
, return true);
272 QTC_ASSERT(action2
, return false);
273 return action1
->text().toLower() < action2
->text().toLower();
276 QMenu
*FancyMainWindow::createPopupMenu()
278 QList
<QAction
*> actions
;
279 QList
<QDockWidget
*> dockwidgets
= findChildren
<QDockWidget
*>();
280 for (int i
= 0; i
< dockwidgets
.size(); ++i
) {
281 QDockWidget
*dockWidget
= dockwidgets
.at(i
);
282 if (dockWidget
->property("managed_dockwidget").isNull()
283 && dockWidget
->parentWidget() == this) {
284 actions
.append(dockwidgets
.at(i
)->toggleViewAction());
287 qSort(actions
.begin(), actions
.end(), actionLessThan
);
288 QMenu
*menu
= new QMenu(this);
289 foreach(QAction
* action
, actions
)
290 menu
->addAction(action
);
291 menu
->addAction(&d
->m_menuSeparator1
);
292 menu
->addAction(&d
->m_toggleLockedAction
);
293 menu
->addAction(&d
->m_menuSeparator2
);
294 menu
->addAction(&d
->m_resetLayoutAction
);
298 QAction
*FancyMainWindow::menuSeparator1() const
300 return &d
->m_menuSeparator1
;
303 QAction
*FancyMainWindow::toggleLockedAction() const
305 return &d
->m_toggleLockedAction
;
308 QAction
*FancyMainWindow::menuSeparator2() const
310 return &d
->m_menuSeparator2
;
313 QAction
*FancyMainWindow::resetLayoutAction() const
315 return &d
->m_resetLayoutAction
;
318 void FancyMainWindow::setDockActionsVisible(bool v
)
320 foreach(const QDockWidget
* dockWidget
, dockWidgets())
321 dockWidget
->toggleViewAction()->setVisible(v
);
322 d
->m_toggleLockedAction
.setVisible(v
);
323 d
->m_menuSeparator1
.setVisible(v
);
324 d
->m_menuSeparator2
.setVisible(v
);
325 d
->m_resetLayoutAction
.setVisible(v
);
328 QDockWidget
*FancyMainWindow::toolBarDockWidget() const
330 return d
->m_toolBarDockWidget
;
333 void FancyMainWindow::setToolBarDockWidget(QDockWidget
*dock
)
335 d
->m_toolBarDockWidget
= dock
;