refs #299, dockable main info area

This commit is contained in:
Klaus Basan
2014-07-27 15:08:32 +02:00
parent edf4a6b80e
commit 4fe8144c3d
8 changed files with 1547 additions and 0 deletions

View File

@@ -0,0 +1,535 @@
/* Copyright (C) 2014
* swift Project Community / Contributors
*
* This file is part of swift Project. It is subject to the license terms in the LICENSE file found in the top-level
* directory of this distribution and at http://www.swift-project.org/license.html. No part of Swift Project,
* including this file, may be copied, modified, propagated, or distributed except according to the terms
* contained in the LICENSE file.
*/
#include "maininfoareacomponent.h"
#include "ui_maininfoareacomponent.h"
#include "../stylesheetutility.h"
#include "../guiutility.h"
#include "blackmisc/iconsstandard.h"
#include <QMenu>
#include <QListIterator>
#include <QSignalMapper>
#include <QCloseEvent>
using namespace BlackMisc;
namespace BlackGui
{
namespace Components
{
CMainInfoAreaComponent::CMainInfoAreaComponent(QWidget *parent) :
QMainWindow(parent), ui(new Ui::CMainInfoAreaComponent)
{
this->ps_setInfoAreaFloating(this->m_infoAreaFloating);
ui->setupUi(this);
this->setWindowIcon(CIconsStandard::swift24());
// after setup, GUI established
if (this->m_dockableWidgets.isEmpty())
{
this->m_dockableWidgets = this->findChildren<CDockWidgetInfoArea *>();
Q_ASSERT(!this->m_dockableWidgets.isEmpty());
}
this->ps_setDockArea(Qt::TopDockWidgetArea);
this->setMarginsWhenFloating(5, 5, 5, 5); // left, top, right bottom
this->setMarginsWhenDocked(1, 1, 1, 1); // top has no effect
this->connectAllWidgets();
this->setFeaturesForDockableWidgets(QDockWidget::DockWidgetFloatable | QDockWidget::DockWidgetMovable | QDockWidget::DockWidgetClosable);
this->tabifyAllWidgets();
// context menu
this->setContextMenuPolicy(Qt::CustomContextMenu);
connect(this, &CMainInfoAreaComponent::customContextMenuRequested, this, &CMainInfoAreaComponent::ps_showContextMenu);
connect(&CStyleSheetUtility::instance(), &CStyleSheetUtility::styleSheetsChanged, this, &CMainInfoAreaComponent::ps_onStyleSheetChanged);
// initial style sheet setting
this->ps_onStyleSheetChanged();
}
CMainInfoAreaComponent::~CMainInfoAreaComponent()
{
delete ui;
}
void CMainInfoAreaComponent::addToContextMenu(QMenu *menu) const
{
if (!menu) return;
menu->addAction(CIconsStandard::dockTop16(), "Dock all", this, SLOT(dockAllWidgets()));
menu->addAction(CIconsStandard::floatAll16(), "Float all", this, SLOT(floatAllWidgets()));
menu->addAction(CIconsStandard::floatOne16(), "Dock / float info area", this, SLOT(toggleFloating()));
bool c = false;
if (!this->m_dockableWidgets.isEmpty())
{
menu->addSeparator();
QMenu *subMenuToggleFloat = new QMenu("Toggle Float/Dock", menu);
QMenu *subMenuDisplay = new QMenu("Display", menu);
QSignalMapper *signalMapperToggleFloating = new QSignalMapper(menu);
QSignalMapper *signalMapperDisplay = new QSignalMapper(menu);
for (int i = 0; i < this->m_dockableWidgets.size(); i++)
{
const CDockWidgetInfoArea *dw = this->m_dockableWidgets.at(i);
const QPixmap pm = infoAreaToIcon(static_cast<InfoArea>(i));
const QString t = dw->windowTitleBackup();
QAction *checkableMenuAction = new QAction(menu);
checkableMenuAction->setObjectName(QString(t).append("ToggleFloatingAction"));
checkableMenuAction->setIconText(t);
checkableMenuAction->setIcon(pm);
checkableMenuAction->setData(QVariant(i));
checkableMenuAction->setCheckable(true);
checkableMenuAction->setChecked(!dw->isFloating());
subMenuToggleFloat->addAction(checkableMenuAction);
c = connect(checkableMenuAction, SIGNAL(toggled(bool)), signalMapperToggleFloating, SLOT(map()));
Q_ASSERT(c);
signalMapperToggleFloating->setMapping(checkableMenuAction, i);
QAction *displayMenuAction = new QAction(menu);
displayMenuAction->setObjectName(QString(t).append("DisplayAction"));
displayMenuAction->setIconText(t);
displayMenuAction->setIcon(pm);
displayMenuAction->setData(QVariant(i));
displayMenuAction->setCheckable(false);
subMenuDisplay->addAction(displayMenuAction);
c = connect(displayMenuAction, SIGNAL(triggered(bool)), signalMapperDisplay, SLOT(map()));
Q_ASSERT(c);
signalMapperDisplay->setMapping(displayMenuAction, i);
}
c = connect(signalMapperToggleFloating, SIGNAL(mapped(int)), this, SLOT(toggleFloating(int)));
Q_ASSERT(c);
c = connect(signalMapperDisplay, SIGNAL(mapped(int)), this, SLOT(selectArea(int)));
Q_ASSERT(c);
menu->addMenu(subMenuDisplay);
menu->addMenu(subMenuToggleFloat);
// where and how to display tab
menu->addSeparator();
QAction *showMenuText = new QAction(menu);
showMenuText->setObjectName("ShowDockedWidgetTextAction");
showMenuText->setIconText("Show tab text");
showMenuText->setIcon(CIconsStandard::headingOne16());
showMenuText->setCheckable(true);
showMenuText->setChecked(this->m_showTabTexts);
menu->addAction(showMenuText);
connect(showMenuText, &QAction::toggled, this, &CMainInfoAreaComponent::ps_showTabTexts);
menu->addAction(CIconsStandard::dockBottom16(), "Toogle tabbar position", this, SLOT(ps_toggleTabBarPosition()));
}
}
CAtcStationComponent *CMainInfoAreaComponent::getAtcStationComponent()
{
return this->ui->comp_AtcStations;
}
CAircraftComponent *CMainInfoAreaComponent::getAircraftComponent()
{
return this->ui->comp_Aircrafts;
}
CUserComponent *CMainInfoAreaComponent::getUserComponent()
{
return this->ui->comp_Users;
}
CFlightPlanComponent *CMainInfoAreaComponent::getFlightPlanComponent()
{
return this->ui->comp_FlightPlan;
}
CSettingsComponent *CMainInfoAreaComponent::getSettingsComponent()
{
return this->ui->comp_Settings;
}
CLogComponent *CMainInfoAreaComponent::getLogComponent()
{
return this->ui->comp_Log;
}
CSimulatorComponent *CMainInfoAreaComponent::getSimulatorComponent()
{
return this->ui->comp_Simulator;
}
CTextMessageComponent *CMainInfoAreaComponent::getTextMessageComponent()
{
return this->ui->comp_TextMessages;
}
void CMainInfoAreaComponent::dockAllWidgets()
{
this->tabifyAllWidgets();
}
void CMainInfoAreaComponent::floatAllWidgets()
{
// I fake the double click here, which queues the events in the queue
// and hence fires all depending signals in order
if (!this->m_tabBar) return;
for (int i = 0; i < this->m_tabBar->count(); i++)
{
emit this->m_tabBar->tabBarDoubleClicked(i);
}
}
void CMainInfoAreaComponent::toggleFloating()
{
this->ps_setInfoAreaFloating(!this->m_infoAreaFloating);
}
void CMainInfoAreaComponent::toggleFloating(CMainInfoAreaComponent::InfoArea infoArea)
{
CDockWidgetInfoArea *dw = this->m_dockableWidgets.at(static_cast<int>(infoArea));
Q_ASSERT(dw);
if (!dw) return;
dw->toggleFloating();
}
void CMainInfoAreaComponent::toggleFloating(int index)
{
if (index < 0 || index >= this->m_dockableWidgets.size()) return;
CDockWidgetInfoArea *dw = this->m_dockableWidgets.at(index);
Q_ASSERT(dw);
if (!dw) return;
dw->toggleFloating();
}
void CMainInfoAreaComponent::selectArea(CMainInfoAreaComponent::InfoArea infoArea)
{
CDockWidgetInfoArea *dw = this->m_dockableWidgets.at(static_cast<int>(infoArea));
Q_ASSERT(dw);
if (!dw) return;
Q_ASSERT(this->m_tabBar);
if (m_tabBar->count() < 1) return;
if (dw->isFloating())
{
dw->show();
}
else
{
int index = this->widgetToTabBarIndex(dw);
Q_ASSERT(index >= 0);
if (index >= 0 && index < m_tabBar->count())
{
m_tabBar->setCurrentIndex(index);
}
}
}
void CMainInfoAreaComponent::selectArea(int index)
{
if (index < 0 || index >= this->m_dockableWidgets.count()) return;
this->selectArea(static_cast<InfoArea>(index));
}
void CMainInfoAreaComponent::ps_setDockArea(Qt::DockWidgetArea area)
{
QList<CDockWidgetInfoArea *>::iterator i;
for (i = this->m_dockableWidgets.begin(); i != this->m_dockableWidgets.end(); ++i)
{
CDockWidgetInfoArea *dw = (*i);
Qt::DockWidgetAreas newAreas = static_cast<Qt::DockWidgetAreas>(area);
Qt::DockWidgetAreas oldAreas = dw->allowedAreas();
if (oldAreas == newAreas) continue;
dw->setAllowedAreas(newAreas);
this->addDockWidget(area, dw);
}
}
void CMainInfoAreaComponent::ps_setInfoAreaFloating(bool floating)
{
this->m_infoAreaFloating = floating;
if (this->m_infoAreaFloating)
{
QPoint p = CGuiUtility::mainWindowPosition();
this->setWindowFlags(Qt::Dialog);
this->move(p.rx() + 20, p.ry() + 20);
this->show(); // not working without show
}
else
{
// make this compliant as QWidget
// https://qt-project.org/forums/viewthread/17519
// http://www.qtcentre.org/threads/12569-QMainWindow-as-a-child-of-QMainWindow
// this->setParent(this->m_originalParent, this->windowFlags() & ~Qt::Window);
this->setWindowFlags(this->windowFlags() & ~Qt::Window);
this->setVisible(true); // after redocking this is required
}
}
void CMainInfoAreaComponent::tabifyAllWidgets()
{
// this->setDockArea(Qt::LeftDockWidgetArea);
this->setTabPosition(Qt::LeftDockWidgetArea, QTabWidget::East);
bool init = this->m_tabBar ? false : true;
QPoint pos = CGuiUtility::assumedMainWindowPosition(); //main window pos. not initialized yet
if (!this->m_dockableWidgets.isEmpty())
{
for (int i = 0; i < this->m_dockableWidgets.size(); i++)
{
CDockWidgetInfoArea *first = i > 0 ? this->m_dockableWidgets.at(i - 1) : nullptr;
CDockWidgetInfoArea *after = this->m_dockableWidgets.at(i);
Q_ASSERT(after);
// trick, init widget as floating
if (init)
{
QPoint initPoint(pos.rx() + i * 25, pos.ry() + i * 20);
after->setVisible(false);
after->setFloating(true);
after->move(initPoint);
after->setVisible(true);
}
after->setFloating(false);
if (!first) { continue; }
this->tabifyDockWidget(first, after);
}
}
// as now tabified, now set tab
if (!this->m_tabBar)
{
this->m_tabBar = this->findChild<QTabBar *>();
Q_ASSERT(m_tabBar);
QString qss = CStyleSheetUtility::instance().style(CStyleSheetUtility::fileNameDockWidgetTab());
this->m_tabBar->setStyleSheet(qss);
this->m_tabBar->setObjectName("comp_MainInfoAreaDockWidgetTab");
this->m_tabBar->setMovable(false);
this->m_tabBar->setElideMode(Qt::ElideNone);
this->m_tabBar->setShape(QTabBar::TriangularEast);
// East / West does not work (shown, but area itself empty)
// South does not have any effect
this->m_tabBar->setShape(QTabBar::TriangularSouth);
connect(this->m_tabBar, &QTabBar::tabBarDoubleClicked, this, &CMainInfoAreaComponent::ps_tabBarDoubleClicked);
}
this->setTabPixmaps();
if (this->countDockedWidgets() > 0)
{
this->m_tabBar->setCurrentIndex(0);
}
}
void CMainInfoAreaComponent::unTabifyAllWidgets()
{
if (this->m_dockableWidgets.size() < 2) return;
CDockWidgetInfoArea *first = this->m_dockableWidgets.first();
for (int i = 1; i < this->m_dockableWidgets.size(); i++)
{
CDockWidgetInfoArea *after = this->m_dockableWidgets.at(i);
Q_ASSERT(after);
this->splitDockWidget(first, after, Qt::Horizontal);
}
}
void CMainInfoAreaComponent::connectAllWidgets()
{
QList<CDockWidgetInfoArea *>::iterator i;
for (i = this->m_dockableWidgets.begin(); i != this->m_dockableWidgets.end(); ++i)
{
connect(*i, &CDockWidgetInfoArea::widgetTopLevelChanged, this, &CMainInfoAreaComponent::ps_onWidgetTopLevelChanged);
}
}
void CMainInfoAreaComponent::setMarginsWhenFloating(int left, int top, int right, int bottom)
{
QList<CDockWidgetInfoArea *>::iterator i;
for (i = this->m_dockableWidgets.begin(); i != this->m_dockableWidgets.end(); ++i)
{
//! Margins when window is floating
(*i)->setMarginsWhenFloating(left, top, right, bottom);
}
}
void CMainInfoAreaComponent::setMarginsWhenDocked(int left, int top, int right, int bottom)
{
QList<CDockWidgetInfoArea *>::iterator i;
for (i = this->m_dockableWidgets.begin(); i != this->m_dockableWidgets.end(); ++i)
{
//! Margins when window is floating
(*i)->setMarginsWhenDocked(left, top, right, bottom);
}
}
const QPixmap &CMainInfoAreaComponent::infoAreaToIcon(CMainInfoAreaComponent::InfoArea infoArea)
{
switch (infoArea)
{
case InfoAreaUsers:
return CIconsStandard::appUsers16();
case InfoAreaWeather:
return CIconsStandard::appWeather16();
case InfoAreaAtc:
return CIconsStandard::appAtc16();
case InfoAreaAircrafts:
return CIconsStandard::appAircrafts16();
case InfoAreaSettings:
return CIconsStandard::appSettings16();
case InfoAreaFlightPlan:
return CIconsStandard::appFlightplan16();
case InfoAreaTextMessages:
return CIconsStandard::appTextMessages16();
case InfoAreaSimulator:
return CIconsStandard::appSimulator16();
case InfoAreaMappings:
return CIconsStandard::appMappings16();
case InfoAreaLog:
return CIconsStandard::appLog16();
default:
return CIconsStandard::empty();
}
}
CDockWidgetInfoArea *CMainInfoAreaComponent::getDockableWidgetByIndex(int index) const
{
if (index >= this->m_dockableWidgets.count() || index < 0) return nullptr;
return this->m_dockableWidgets.at(index);
}
CDockWidgetInfoArea *CMainInfoAreaComponent::selectedDockableWidget() const
{
if (!this->m_tabBar) return nullptr;
int i = this->m_tabBar->currentIndex();
return getDockableWidgetByIndex(i);
}
int CMainInfoAreaComponent::countDockedWidgets() const
{
if (!this->m_tabBar) return 0;
return this->m_tabBar->count();
}
int CMainInfoAreaComponent::widgetToTabBarIndex(const CDockWidgetInfoArea *dockWidget)
{
if (!dockWidget) return -1;
if (dockWidget->isFloating()) return -1;
int tabBarIndex = 0;
QList<CDockWidgetInfoArea *>::iterator i;
for (i = this->m_dockableWidgets.begin(); i != this->m_dockableWidgets.end(); ++i)
{
CDockWidgetInfoArea *dw = (*i);
if (dw->isFloating()) continue; // not in tab bar
if (dw == dockWidget) return tabBarIndex;
tabBarIndex++;
}
return -1;
}
void CMainInfoAreaComponent::setFeaturesForDockableWidgets(QDockWidget::DockWidgetFeatures features)
{
for (int i = 0; i < this->m_dockableWidgets.size(); i++)
{
CDockWidgetInfoArea *dw = this->m_dockableWidgets.at(i);
dw->setFeatures(features);
}
}
void CMainInfoAreaComponent::setTabPixmaps()
{
if (!this->m_tabBar) return;
for (int i = 0; i < this->m_tabBar->count(); i++)
{
InfoArea area = static_cast<InfoArea>(i);
const QPixmap p(infoAreaToIcon(area));
this->m_tabBar->setTabIcon(i, p);
}
}
void CMainInfoAreaComponent::ps_tabBarDoubleClicked(int index)
{
CDockWidgetInfoArea *dw = (index >= 0) ?
this->getDockableWidgetByIndex(index) :
this->selectedDockableWidget();
if (!dw) return;
dw->toggleFloating();
}
void CMainInfoAreaComponent::ps_onWidgetTopLevelChanged(CDockWidget *widget, bool topLevel)
{
Q_ASSERT(widget);
Q_UNUSED(topLevel);
if (!widget) return;
// fix pixmaps
this->setTabPixmaps();
}
void CMainInfoAreaComponent::ps_onStyleSheetChanged()
{
QString qss = CStyleSheetUtility::instance().style(CStyleSheetUtility::fileNameMainInfoArea());
this->setStyleSheet(qss);
if (this->m_tabBar)
{
QString qss = CStyleSheetUtility::instance().style(CStyleSheetUtility::fileNameDockWidgetTab());
this->m_tabBar->setStyleSheet(qss);
}
}
void CMainInfoAreaComponent::ps_showContextMenu(const QPoint &pos)
{
QPoint globalPos = this->mapToGlobal(pos);
QScopedPointer<QMenu> contextMenu(new QMenu(this));
this->addToContextMenu(contextMenu.data());
QAction *selectedItem = contextMenu.data()->exec(globalPos);
Q_UNUSED(selectedItem);
}
void CMainInfoAreaComponent::ps_showTabTexts(bool show)
{
if (show == this->m_showTabTexts) return;
this->m_showTabTexts = show;
QList<CDockWidgetInfoArea *>::iterator i;
for (i = this->m_dockableWidgets.begin(); i != this->m_dockableWidgets.end(); ++i)
{
CDockWidgetInfoArea *dw = (*i);
dw->showTitleWhenDocked(show);
}
}
void CMainInfoAreaComponent::ps_setTabBarPosition(QTabWidget::TabPosition position)
{
Q_ASSERT(position == QTabWidget::North || position == QTabWidget::South);
this->setTabPosition(Qt::TopDockWidgetArea, position);
}
void CMainInfoAreaComponent::ps_toggleTabBarPosition()
{
QTabWidget::TabPosition p = (this->tabPosition(Qt::TopDockWidgetArea) == QTabWidget::North) ?
QTabWidget::South : QTabWidget::North;
this->ps_setTabBarPosition(p);
}
void CMainInfoAreaComponent::closeEvent(QCloseEvent *event)
{
if (this->isFloating())
{
this->toggleFloating();
event->setAccepted(false); // refuse -> do not close
}
else
{
QMainWindow::closeEvent(event);
}
}
}
}

View File

@@ -0,0 +1,200 @@
/* Copyright (C) 2014
* swift Project Community / Contributors
*
* This file is part of swift Project. It is subject to the license terms in the LICENSE file found in the top-level
* directory of this distribution and at http://www.swift-project.org/license.html. No part of Swift Project,
* including this file, may be copied, modified, propagated, or distributed except according to the terms
* contained in the LICENSE file.
*/
#ifndef BLACKGUI_MAININFOAREACOMPONENT_H
#define BLACKGUI_MAININFOAREACOMPONENT_H
//! \file
#include "../dockwidgetinfoarea.h"
#include "atcstationcomponent.h"
#include "aircraftcomponent.h"
#include "usercomponent.h"
#include "textmessagecomponent.h"
#include "simulatorcomponent.h"
#include "flightplancomponent.h"
#include "settingscomponent.h"
#include "logcomponent.h"
#include <QMainWindow>
#include <QTabBar>
#include <QPixmap>
namespace Ui { class CMainInfoAreaComponent; }
namespace BlackGui
{
namespace Components
{
//! Main info area
class CMainInfoAreaComponent : public QMainWindow
{
Q_OBJECT
public:
//! Constructor
explicit CMainInfoAreaComponent(QWidget *parent = nullptr);
//! Destructor
~CMainInfoAreaComponent();
//! Info areas
enum InfoArea
{
// index must match tab index!
InfoAreaAircrafts = 0,
InfoAreaAtc = 1,
InfoAreaUsers = 2,
InfoAreaTextMessages = 3,
InfoAreaSimulator = 4,
InfoAreaFlightPlan = 5,
InfoAreaWeather = 6,
InfoAreaMappings = 7,
InfoAreaLog = 8,
InfoAreaSettings = 9
};
//! Add items to context menu
void addToContextMenu(QMenu *menu) const;
//! Is this area floating?
bool isFloating() const { return this->m_infoAreaFloating; }
//! ATC stations
CAtcStationComponent *getAtcStationComponent();
//! Aircrafts
CAircraftComponent *getAircraftComponent();
//! User component
CUserComponent *getUserComponent();
//! Flight plan
CFlightPlanComponent *getFlightPlanComponent();
//! Settings
CSettingsComponent *getSettingsComponent();
//! Log messages
CLogComponent *getLogComponent();
//! Simulator
CSimulatorComponent *getSimulatorComponent();
//! Text messages
CTextMessageComponent *getTextMessageComponent();
public slots:
//! Dock all widgets
void dockAllWidgets();
//! All widgets floating
void floatAllWidgets();
//! Toggle dock / floating of the whole info area
void toggleFloating();
//! Toggle floating of given area
void toggleFloating(InfoArea infoArea);
//! Toggle floating of index
void toggleFloating(int index);
//! Select area
void selectArea(InfoArea infoArea);
//! Select area
void selectArea(int index);
protected:
//! Override close event
virtual void closeEvent(QCloseEvent *event) override;
private:
Ui::CMainInfoAreaComponent *ui = nullptr;
QList<CDockWidgetInfoArea *> m_dockableWidgets ;
QTabBar *m_tabBar = nullptr;
bool m_showTabTexts = true;
bool m_infoAreaFloating = false; //!< whole info area floating
//! Tabify the widgets
void tabifyAllWidgets();
//! Untabify
void unTabifyAllWidgets();
//! The tab bar of the docked widgets
QTabBar *tabBarDockedWidgets() const;
//! Corresponding dockable widgets
QList<CDockWidgetInfoArea *> dockableWidgets() const;
//! Corresponding dockable widget
CDockWidgetInfoArea *getDockableWidgetByIndex(int index) const;
//! Selected dockable widget
CDockWidgetInfoArea *selectedDockableWidget() const;
//! Features of the dockable widgets
void setFeaturesForDockableWidgets(QDockWidget::DockWidgetFeatures features);
//! Number of tabbed widgets
int countDockedWidgets() const;
//! Widget to tab bar index
int widgetToTabBarIndex(const CDockWidgetInfoArea *dockWidget);
//! Set the tab's icons
void setTabPixmaps();
//! Connect all widgets
void connectAllWidgets();
//! Margins for the floating widgets
void setMarginsWhenFloating(int left, int top, int right, int bottom);
//! Margins for the dockable widgets
void setMarginsWhenDocked(int left, int top, int right, int bottom);
//! Info area to icon
static const QPixmap &infoAreaToIcon(InfoArea infoArea);
private slots:
//! Tab bar has been double clicked
void ps_tabBarDoubleClicked(int index);
//! A widget has changed its top level
void ps_onWidgetTopLevelChanged(CDockWidget *widget, bool topLevel);
//! Style sheet has been changed
void ps_onStyleSheetChanged();
//! Context menu
void ps_showContextMenu(const QPoint &pos);
//! Show the tab texts, or just the icons
void ps_showTabTexts(bool show);
//! Tab position for docked widgets tab
//! \remarks North or South working, East / West not
void ps_setTabBarPosition(QTabWidget::TabPosition position);
//! Toggle tab position North - South
void ps_toggleTabBarPosition();
//! Set dock area used
void ps_setDockArea(Qt::DockWidgetArea area);
//! Dock / floating of the whole info area
void ps_setInfoAreaFloating(bool floating);
};
}
}
#endif // guard

View File

@@ -0,0 +1,494 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>CMainInfoAreaComponent</class>
<widget class="QMainWindow" name="CMainInfoAreaComponent">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>1207</width>
<height>97</height>
</rect>
</property>
<property name="minimumSize">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
<property name="windowTitle">
<string>Main info area</string>
</property>
<property name="windowIcon">
<iconset resource="../../blackmisc/blackmisc.qrc">
<normaloff>:/own/icons/own/swift/swift24.png</normaloff>:/own/icons/own/swift/swift24.png</iconset>
</property>
<property name="styleSheet">
<string notr="true"/>
</property>
<property name="animated">
<bool>true</bool>
</property>
<property name="documentMode">
<bool>true</bool>
</property>
<property name="dockNestingEnabled">
<bool>false</bool>
</property>
<property name="dockOptions">
<set>QMainWindow::AllowTabbedDocks|QMainWindow::AnimatedDocks|QMainWindow::ForceTabbedDocks</set>
</property>
<widget class="QWidget" name="qw_centralWidgetEmpty"/>
<widget class="BlackGui::CDockWidgetInfoArea" name="dw_Aircrafts">
<property name="minimumSize">
<size>
<width>149</width>
<height>80</height>
</size>
</property>
<property name="features">
<set>QDockWidget::AllDockWidgetFeatures</set>
</property>
<property name="allowedAreas">
<set>Qt::TopDockWidgetArea</set>
</property>
<property name="windowTitle">
<string>Aircrafts</string>
</property>
<attribute name="dockWidgetArea">
<number>4</number>
</attribute>
<widget class="QWidget" name="dw_AircraftsInner">
<property name="minimumSize">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
<layout class="QVBoxLayout" name="vl_Aircrafts">
<property name="spacing">
<number>0</number>
</property>
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>2</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="BlackGui::Components::CAircraftComponent" name="comp_Aircrafts">
<property name="minimumSize">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
</widget>
</item>
</layout>
</widget>
</widget>
<widget class="BlackGui::CDockWidgetInfoArea" name="dw_AtcStations">
<property name="minimumSize">
<size>
<width>127</width>
<height>38</height>
</size>
</property>
<property name="floating">
<bool>false</bool>
</property>
<property name="allowedAreas">
<set>Qt::TopDockWidgetArea</set>
</property>
<property name="windowTitle">
<string>ATC stations</string>
</property>
<attribute name="dockWidgetArea">
<number>4</number>
</attribute>
<widget class="QWidget" name="dw_AtcStationsInner">
<property name="minimumSize">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
<layout class="QVBoxLayout" name="vl_AtcStations">
<property name="spacing">
<number>0</number>
</property>
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>2</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="BlackGui::Components::CAtcStationComponent" name="comp_AtcStations">
<property name="minimumSize">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
</widget>
</item>
</layout>
</widget>
</widget>
<widget class="BlackGui::CDockWidgetInfoArea" name="dw_Users">
<property name="allowedAreas">
<set>Qt::TopDockWidgetArea</set>
</property>
<property name="windowTitle">
<string>Users</string>
</property>
<attribute name="dockWidgetArea">
<number>4</number>
</attribute>
<widget class="QWidget" name="dw_UsersInner">
<layout class="QVBoxLayout" name="vl_Users">
<property name="spacing">
<number>0</number>
</property>
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>2</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="BlackGui::Components::CUserComponent" name="comp_Users"/>
</item>
</layout>
</widget>
</widget>
<widget class="BlackGui::CDockWidgetInfoArea" name="dw_TextMessages">
<property name="allowedAreas">
<set>Qt::TopDockWidgetArea</set>
</property>
<property name="windowTitle">
<string>Text messages</string>
</property>
<attribute name="dockWidgetArea">
<number>4</number>
</attribute>
<widget class="QWidget" name="dw_TextMessagesInner">
<layout class="QVBoxLayout" name="vl_TextMessages">
<property name="spacing">
<number>0</number>
</property>
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>2</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="BlackGui::Components::CTextMessageComponent" name="comp_TextMessages"/>
</item>
</layout>
</widget>
</widget>
<widget class="BlackGui::CDockWidgetInfoArea" name="dw_Simulator">
<property name="allowedAreas">
<set>Qt::TopDockWidgetArea</set>
</property>
<property name="windowTitle">
<string>Simulator</string>
</property>
<attribute name="dockWidgetArea">
<number>4</number>
</attribute>
<widget class="QWidget" name="dw_SimulatorInner">
<layout class="QVBoxLayout" name="verticalLayout">
<property name="spacing">
<number>0</number>
</property>
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>2</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="BlackGui::Components::CSimulatorComponent" name="comp_Simulator"/>
</item>
</layout>
</widget>
</widget>
<widget class="BlackGui::CDockWidgetInfoArea" name="dw_FlightPlan">
<property name="allowedAreas">
<set>Qt::TopDockWidgetArea</set>
</property>
<property name="windowTitle">
<string>Flight plan</string>
</property>
<attribute name="dockWidgetArea">
<number>4</number>
</attribute>
<widget class="QWidget" name="dw_FlightPlanInner">
<layout class="QVBoxLayout" name="vl_FlightPlan">
<property name="spacing">
<number>0</number>
</property>
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>2</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="BlackGui::Components::CFlightPlanComponent" name="comp_FlightPlan"/>
</item>
</layout>
</widget>
</widget>
<widget class="BlackGui::CDockWidgetInfoArea" name="dw_Weather">
<property name="allowedAreas">
<set>Qt::TopDockWidgetArea</set>
</property>
<property name="windowTitle">
<string>Weather</string>
</property>
<attribute name="dockWidgetArea">
<number>4</number>
</attribute>
<widget class="QWidget" name="dw_WeatherInner">
<property name="minimumSize">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
<layout class="QVBoxLayout" name="vl_Weather">
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>2</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QFrame" name="fr_WeatherDummy">
<property name="frameShape">
<enum>QFrame::StyledPanel</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Raised</enum>
</property>
</widget>
</item>
</layout>
</widget>
</widget>
<widget class="BlackGui::CDockWidgetInfoArea" name="dw_Mappings">
<property name="allowedAreas">
<set>Qt::TopDockWidgetArea</set>
</property>
<property name="windowTitle">
<string>Mappings</string>
</property>
<attribute name="dockWidgetArea">
<number>4</number>
</attribute>
<widget class="QWidget" name="dw_MappingsInner">
<layout class="QVBoxLayout" name="vl_Mappings">
<property name="spacing">
<number>0</number>
</property>
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>2</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QTabWidget" name="comp_Mappings"/>
</item>
</layout>
</widget>
</widget>
<widget class="BlackGui::CDockWidgetInfoArea" name="dw_Log">
<property name="allowedAreas">
<set>Qt::TopDockWidgetArea</set>
</property>
<property name="windowTitle">
<string>Log</string>
</property>
<attribute name="dockWidgetArea">
<number>4</number>
</attribute>
<widget class="QWidget" name="dw_LogInner">
<layout class="QVBoxLayout" name="vl_Log">
<property name="spacing">
<number>0</number>
</property>
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>2</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="BlackGui::Components::CLogComponent" name="comp_Log">
<property name="frameShape">
<enum>QFrame::StyledPanel</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Raised</enum>
</property>
</widget>
</item>
</layout>
</widget>
</widget>
<widget class="BlackGui::CDockWidgetInfoArea" name="dw_Settings">
<property name="allowedAreas">
<set>Qt::TopDockWidgetArea</set>
</property>
<property name="windowTitle">
<string>Settings</string>
</property>
<attribute name="dockWidgetArea">
<number>4</number>
</attribute>
<widget class="QWidget" name="dw_SettingsInner">
<layout class="QVBoxLayout" name="vl_Settings">
<property name="spacing">
<number>0</number>
</property>
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>2</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="BlackGui::Components::CSettingsComponent" name="comp_Settings"/>
</item>
</layout>
</widget>
</widget>
</widget>
<customwidgets>
<customwidget>
<class>BlackGui::Components::CAtcStationComponent</class>
<extends>QTabWidget</extends>
<header>blackgui/components/atcstationcomponent.h</header>
<container>1</container>
</customwidget>
<customwidget>
<class>BlackGui::Components::CAircraftComponent</class>
<extends>QTabWidget</extends>
<header>blackgui/components/aircraftcomponent.h</header>
<container>1</container>
</customwidget>
<customwidget>
<class>BlackGui::Components::CFlightPlanComponent</class>
<extends>QTabWidget</extends>
<header>blackgui/components/flightplancomponent.h</header>
<container>1</container>
</customwidget>
<customwidget>
<class>BlackGui::Components::CUserComponent</class>
<extends>QTabWidget</extends>
<header>blackgui/components/usercomponent.h</header>
<container>1</container>
</customwidget>
<customwidget>
<class>BlackGui::Components::CTextMessageComponent</class>
<extends>QTabWidget</extends>
<header>blackgui/components/textmessagecomponent.h</header>
<container>1</container>
</customwidget>
<customwidget>
<class>BlackGui::Components::CSettingsComponent</class>
<extends>QTabWidget</extends>
<header>blackgui/components/settingscomponent.h</header>
<container>1</container>
</customwidget>
<customwidget>
<class>BlackGui::CDockWidgetInfoArea</class>
<extends>QDockWidget</extends>
<header>blackgui/dockwidgetinfoarea.h</header>
<container>1</container>
</customwidget>
<customwidget>
<class>BlackGui::Components::CLogComponent</class>
<extends>QFrame</extends>
<header>blackgui/components/logcomponent.h</header>
<container>1</container>
</customwidget>
<customwidget>
<class>BlackGui::Components::CSimulatorComponent</class>
<extends>QTabWidget</extends>
<header>blackgui/components/simulatorcomponent.h</header>
<container>1</container>
</customwidget>
</customwidgets>
<resources>
<include location="../../blackmisc/blackmisc.qrc"/>
</resources>
<connections/>
</ui>

136
src/blackgui/dockwidget.cpp Normal file
View File

@@ -0,0 +1,136 @@
/* Copyright (C) 2014
* swift Project Community / Contributors
*
* This file is part of swift Project. It is subject to the license terms in the LICENSE file found in the top-level
* directory of this distribution and at http://www.swift-project.org/license.html. No part of Swift Project,
* including this file, may be copied, modified, propagated, or distributed except according to the terms
* contained in the LICENSE file.
*/
#include "dockwidget.h"
#include "blackmisc/iconsstandard.h"
#include <QCloseEvent>
namespace BlackGui
{
CDockWidget::CDockWidget(QWidget *parent) : QDockWidget(parent)
{
this->initTitleBarWidgets();
// connect
connect(this, &QDockWidget::topLevelChanged, this, &CDockWidget::ps_onTopLevelChanged);
// context menu
this->setContextMenuPolicy(Qt::CustomContextMenu);
connect(this, &CDockWidget::customContextMenuRequested, this, &CDockWidget::ps_showContextMenu);
}
void CDockWidget::setOriginalTitleBar()
{
if (!this->m_titleBarOriginal) { this->initTitleBarWidgets(); }
if (this->titleBarWidget() == this->m_titleBarOriginal) return; // on purpose, as I do not know what happens when I call setTitleBar
this->setTitleBarWidget(this->m_titleBarOriginal);
}
void CDockWidget::setEmptyTitleBar()
{
if (!this->m_titleBarOriginal) { this->initTitleBarWidgets(); }
if (this->titleBarWidget() == this->m_emptyTitleBar) return; // on purpose, as I do not know what happens when I call setTitleBar
this->setTitleBarWidget(this->m_emptyTitleBar);
}
void CDockWidget::setNullTitleBar()
{
this->setTitleBarWidget(nullptr);
}
void CDockWidget::setWindowTitle(const QString &title)
{
this->m_windowTitleBackup = title;
QDockWidget::setWindowTitle(title);
}
void CDockWidget::showTitleWhenDocked(bool show)
{
this->m_windowTitleWhenDocked = show;
if (show)
{
QDockWidget::setWindowTitle(this->m_windowTitleBackup);
}
else
{
QDockWidget::setWindowTitle("");
}
}
void CDockWidget::toggleFloating()
{
this->setFloating(!this->isFloating());
}
void CDockWidget::closeEvent(QCloseEvent *event)
{
if (this->isFloating())
{
this->toggleFloating();
event->setAccepted(false); // refuse -> do not close
}
else
{
QDockWidget::closeEvent(event);
}
}
void CDockWidget::addToContextMenu(QMenu *contextMenu) const
{
if (this->isFloating())
{
contextMenu->addAction(BlackMisc::CIconsStandard::dockTop16(), "Dock", this, SLOT(toggleFloating()));
}
else
{
contextMenu->addAction(BlackMisc::CIconsStandard::floatOne16(), "Float", this, SLOT(toggleFloating()));
}
}
void CDockWidget::ps_onTopLevelChanged(bool topLevel)
{
if (topLevel)
{
if (this->m_windowTitleBackup != QDockWidget::windowTitle())
{
QDockWidget::setWindowTitle(this->m_windowTitleBackup);
}
this->setNullTitleBar();
this->setContentsMargins(this->m_marginsWhenFloating);
}
else
{
if (!this->m_windowTitleWhenDocked)
{
QDockWidget::setWindowTitle("");
}
this->setEmptyTitleBar();
this->setContentsMargins(this->m_marginsWhenDocked);
}
emit this->widgetTopLevelChanged(this, topLevel);
}
void CDockWidget::initTitleBarWidgets()
{
this->m_titleBarOriginal = this->titleBarWidget();
this->m_emptyTitleBar = new QWidget(this);
this->setTitleBarWidget(this->m_emptyTitleBar);
}
void CDockWidget::ps_showContextMenu(const QPoint &pos)
{
// for most widgets
QPoint globalPos = this->mapToGlobal(pos);
QScopedPointer<QMenu> contextMenu(new QMenu(this));
this->addToContextMenu(contextMenu.data());
QAction *selectedItem = contextMenu.data()->exec(globalPos);
Q_UNUSED(selectedItem);
}
}

102
src/blackgui/dockwidget.h Normal file
View File

@@ -0,0 +1,102 @@
/* Copyright (C) 2014
* Swift Project Community / Contributors
*
* This file is part of swift Project. It is subject to the license terms in the LICENSE file found in the top-level
* directory of this distribution and at http://www.swift-project.org/license.html. No part of Swift Project,
* including this file, may be copied, modified, propagated, or distributed except according to the terms
* contained in the LICENSE file.
*/
#ifndef BLACKGUI_DOCKWIDGET_H
#define BLACKGUI_DOCKWIDGET_H
//! \file
#include <QDockWidget>
#include <QTabWidget>
#include <QMenu>
#include <QLabel>
namespace BlackGui
{
//! Our base class for dock widgets, containing some specialized functionality
class CDockWidget : public QDockWidget
{
Q_OBJECT
public:
//! Constructor
explicit CDockWidget(QWidget *parent = nullptr);
//! Set original title bar
void setOriginalTitleBar();
//! Set empty title bar
void setEmptyTitleBar();
//! Set null title bar
void setNullTitleBar();
//! Margins when window is floating
void setMarginsWhenFloating(const QMargins &margins) { this->m_marginsWhenFloating = margins; }
//! Margins when window is floating
void setMarginsWhenFloating(int left, int top, int right, int bottom) { this->m_marginsWhenFloating = QMargins(left, top, right, bottom); }
//! Margins when widget is floating
void setMarginsWhenDocked(const QMargins &margins) { this->m_marginsWhenDocked = margins; }
//! Margins when widget is floating
void setMarginsWhenDocked(int left, int top, int right, int bottom) { this->m_marginsWhenDocked = QMargins(left, top, right, bottom); }
//! Window title backup
const QString &windowTitleBackup() const { return this->m_windowTitleBackup; }
//! Window title when window is docked
bool showTitleWhenDocked() const { return this->m_windowTitleWhenDocked; }
//! Show the window title when docked
void showTitleWhenDocked(bool show);
public slots:
//! Toggle floating
void toggleFloating();
//! Set title and internally keep a backup
void setWindowTitle(const QString &title);
signals:
//! Top level has changed for given widget
void widgetTopLevelChanged(CDockWidget *, bool topLevel);
protected:
//! Override close event
virtual void closeEvent(QCloseEvent *event) override;
//! Contribute to menu
virtual void addToContextMenu(QMenu *contextMenu) const;
private slots:
//! Top level has been chaged
virtual void ps_onTopLevelChanged(bool topLevel);
//! Context menu
void ps_showContextMenu(const QPoint &pos);
private:
QWidget *m_emptyTitleBar = nullptr; //!< replacing default title bar
QWidget *m_titleBarOriginal = nullptr; //!< the original title bar
QMargins m_marginsWhenFloating; //!< Offsets when window is floating
QMargins m_marginsWhenDocked; //!< Offsets when window is floating
QString m_windowTitleBackup; //!< original title, even if the widget title is deleted for layout purposes
bool m_windowTitleWhenDocked = true;
//! Empty widget with no size
void initTitleBarWidgets();
};
} // namespace
#endif // guard

View File

@@ -0,0 +1,33 @@
/* Copyright (C) 2013
* Swift Project Community / Contributors
*
* This file is part of swift Project. It is subject to the license terms in the LICENSE file found in the top-level
* directory of this distribution and at http://www.swift-project.org/license.html. No part of Swift Project,
* including this file, may be copied, modified, propagated, or distributed except according to the terms
* contained in the LICENSE file.
*/
#include "dockwidgetinfoarea.h"
#include "components/maininfoareacomponent.h"
#include "blackmisc/iconsstandard.h"
using namespace BlackGui::Components;
namespace BlackGui
{
CDockWidgetInfoArea::CDockWidgetInfoArea(QWidget *parent) : CDockWidget(parent) { }
void CDockWidgetInfoArea::addToContextMenu(QMenu *contextMenu) const
{
Components::CMainInfoAreaComponent *mainWidget = qobject_cast<CMainInfoAreaComponent *>(parentWidget());
Q_ASSERT(mainWidget);
if (!mainWidget) return;
// Dockable widget's context menu
CDockWidget::addToContextMenu(contextMenu);
// from main component
contextMenu->addSeparator();
mainWidget->addToContextMenu(contextMenu);
}
}

View File

@@ -0,0 +1,37 @@
/* Copyright (C) 2014
* Swift Project Community / Contributors
*
* This file is part of swift Project. It is subject to the license terms in the LICENSE file found in the top-level
* directory of this distribution and at http://www.swift-project.org/license.html. No part of Swift Project,
* including this file, may be copied, modified, propagated, or distributed except according to the terms
* contained in the LICENSE file.
*/
#ifndef BLACKGUI_DOCKWIDGETINFOAREA_H
#define BLACKGUI_DOCKWIDGETINFOAREA_H
//! \file
#include "blackgui/dockwidget.h"
namespace BlackGui
{
//! Class for dock widgets in the info area, containing some specialized functionality
class CDockWidgetInfoArea : public CDockWidget
{
Q_OBJECT
public:
//! Constructor
explicit CDockWidgetInfoArea(QWidget *parent = nullptr);
protected:
//! Contribute to menu
virtual void addToContextMenu(QMenu *contextMenu) const override;
};
} // namespace
#endif // guard

View File

@@ -0,0 +1,10 @@
QTabBar::tab {
margin-top: 2px;
margin-bottom: 2px;
margin-left: 2px;
margin-right: 2px;
padding-top: 2px;
padding-bottom: 2px;
border: 0px;
border-radius: 0px;
}