mirror of
https://github.com/swift-project/pilotclient.git
synced 2026-04-06 18:25:37 +08:00
refs #312, Navigator (aka navigation bars)
* different dyn. property names for main window, dock window and infoarea * dyn.properties for nested QWidgets * style sheet for navigator * utility function to delete layout * added standard OS icons, some formatting in CICons * actions in main window to be used in navigator * main window becomes normal window when minimized so it is correctly displayed in Win taskbar Remark: Frameless floating dockwidgets with rounded borders not yet working
This commit is contained in:
@@ -57,6 +57,11 @@ namespace BlackGui
|
||||
}
|
||||
}
|
||||
|
||||
CNavigatorDockWidget *CInvisibleInfoAreaComponent::getNavigatorComponent()
|
||||
{
|
||||
return this->ui->comp_Navigator;
|
||||
}
|
||||
|
||||
void CInvisibleInfoAreaComponent::toggleNavigator()
|
||||
{
|
||||
this->ui->comp_Navigator->toggleFloating();
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
#define BLACKGUI_COMPONENTS_INVISIBLEINFOAREACOMPONENT_H
|
||||
|
||||
#include "blackgui/infoarea.h"
|
||||
#include "blackgui/components/navigatordockwidget.h"
|
||||
#include <QMainWindow>
|
||||
|
||||
namespace Ui { class CInvisibleInfoAreaComponent; }
|
||||
@@ -47,6 +48,9 @@ namespace BlackGui
|
||||
//! \copydoc CInfoArea::indexToPixmap
|
||||
const QPixmap &indexToPixmap(int areaIndex) const override;
|
||||
|
||||
//! Get navigator component
|
||||
BlackGui::Components::CNavigatorDockWidget *getNavigatorComponent();
|
||||
|
||||
public slots:
|
||||
//! Navigator floating
|
||||
void toggleNavigator();
|
||||
|
||||
@@ -15,12 +15,6 @@
|
||||
</property>
|
||||
<widget class="QWidget" name="qw_InvisibleInfoArea"/>
|
||||
<widget class="BlackGui::Components::CNavigatorDockWidget" name="comp_Navigator">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>80</width>
|
||||
<height>80</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="floating">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
|
||||
@@ -281,7 +281,7 @@
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
<number>2</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
|
||||
@@ -8,9 +8,17 @@
|
||||
*/
|
||||
|
||||
#include "navigatordockwidget.h"
|
||||
#include "blackgui/infoarea.h"
|
||||
#include "blackgui/guiutility.h"
|
||||
#include "blackgui/stylesheetutility.h"
|
||||
#include "ui_navigatordockwidget.h"
|
||||
|
||||
#include <QToolButton>
|
||||
#include <QGridLayout>
|
||||
#include <QAction>
|
||||
|
||||
using namespace BlackGui;
|
||||
using namespace BlackMisc;
|
||||
|
||||
namespace BlackGui
|
||||
{
|
||||
@@ -27,5 +35,130 @@ namespace BlackGui
|
||||
CNavigatorDockWidget::~CNavigatorDockWidget()
|
||||
{ }
|
||||
|
||||
void CNavigatorDockWidget::addAction(QAction *action)
|
||||
{
|
||||
if (action)
|
||||
{
|
||||
this->m_actions.append(action);
|
||||
QToolButton *tb = new QToolButton(this->ui->fr_NavigatorDockWidgetInner);
|
||||
tb->setDefaultAction(action);
|
||||
tb->setObjectName(this->objectName().append(":").append(action->objectName()));
|
||||
this->m_widgets.append(tb);
|
||||
}
|
||||
}
|
||||
|
||||
void CNavigatorDockWidget::addActions(QList<QAction *> actions)
|
||||
{
|
||||
if (actions.isEmpty()) { return; }
|
||||
for (QAction *a : actions)
|
||||
{
|
||||
this->addAction(a);
|
||||
}
|
||||
}
|
||||
|
||||
void CNavigatorDockWidget::buildNavigator(int columns)
|
||||
{
|
||||
if (m_firstBuild)
|
||||
{
|
||||
m_firstBuild = false;
|
||||
this->insertOwnActions();
|
||||
}
|
||||
|
||||
// remove old layout
|
||||
CGuiUtility::deleteLayout(this->ui->fr_NavigatorDockWidgetInner->layout(), false);
|
||||
|
||||
// new layout
|
||||
QGridLayout *gridLayout = new QGridLayout(this->ui->fr_NavigatorDockWidgetInner);
|
||||
gridLayout->setObjectName("gl_CNavigatorDockWidget");
|
||||
gridLayout->setSpacing(0);
|
||||
gridLayout->setMargin(0);
|
||||
gridLayout->setContentsMargins(0, 0, 0, 0);
|
||||
|
||||
this->ui->fr_NavigatorDockWidgetInner->setLayout(gridLayout);
|
||||
int r = 0;
|
||||
int c = 0;
|
||||
for (int i = 0; i < this->m_widgets.size(); i++)
|
||||
{
|
||||
gridLayout->addWidget(this->m_widgets[i], r, c++);
|
||||
this->m_widgets[i]->show();
|
||||
if (c < columns) { continue; }
|
||||
c = 0;
|
||||
r++;
|
||||
}
|
||||
|
||||
// set the real values
|
||||
c = gridLayout->columnCount();
|
||||
r = gridLayout->rowCount();
|
||||
this->setMinimumSizeForWidgets(r, c);
|
||||
|
||||
// sizes
|
||||
QSize ws(gridLayout->sizeHint());
|
||||
this->resize(ws);
|
||||
|
||||
// see documentation, required as layout was changed
|
||||
// this requires setting widget again
|
||||
this->ui->fr_NavigatorDockWidgetInner->show();
|
||||
this->setWidget(this->ui->fr_NavigatorDockWidgetInner);
|
||||
}
|
||||
|
||||
void CNavigatorDockWidget::addToContextMenu(QMenu *contextMenu) const
|
||||
{
|
||||
QAction *a;
|
||||
a = contextMenu->addAction(CIcons::resize16(), "1 row", this, SLOT(ps_changeLayout()));
|
||||
a->setData("1r");
|
||||
a = contextMenu->addAction(CIcons::resize16(), "2 rows", this, SLOT(ps_changeLayout()));
|
||||
a->setData("2r");
|
||||
a = contextMenu->addAction(CIcons::resize16(), "1 column", this, SLOT(ps_changeLayout()));
|
||||
a->setData("1c");
|
||||
a = contextMenu->addAction(CIcons::resize16(), "2 columns", this, SLOT(ps_changeLayout()));
|
||||
a->setData("2c");
|
||||
contextMenu->addSeparator();
|
||||
CDockWidgetInfoArea::addToContextMenu(contextMenu);
|
||||
}
|
||||
|
||||
void CNavigatorDockWidget::ps_onStyleSheetsChanged()
|
||||
{
|
||||
const QString fn(CStyleSheetUtility::fileNameNavigator());
|
||||
const QString qss(CStyleSheetUtility::instance().style(fn));
|
||||
this->setStyleSheet(qss);
|
||||
}
|
||||
|
||||
void CNavigatorDockWidget::ps_changeLayout()
|
||||
{
|
||||
QAction *a = qobject_cast<QAction *>(QObject::sender());
|
||||
if (!a) { return; }
|
||||
QString v(a->data().toString());
|
||||
if (v == "1c") { buildNavigator(1);}
|
||||
else if (v == "2c") { buildNavigator(2);}
|
||||
else if (v == "1r") { buildNavigator(columnsForRows(1));}
|
||||
else if (v == "2r") { buildNavigator(columnsForRows(2));}
|
||||
}
|
||||
|
||||
void CNavigatorDockWidget::insertOwnActions()
|
||||
{
|
||||
QIcon i(CIcons::changeIconBackgroundColor(this->style()->standardIcon(QStyle::SP_TitleBarCloseButton), Qt::white, QSize(16, 16)));
|
||||
QAction *a = new QAction(i, "Close", this);
|
||||
connect(a, &QAction::triggered, this, &CNavigatorDockWidget::close);
|
||||
this->addAction(a);
|
||||
}
|
||||
|
||||
int CNavigatorDockWidget::columnsForRows(int rows)
|
||||
{
|
||||
Q_ASSERT(rows >= 0);
|
||||
int items = this->m_widgets.size();
|
||||
int c = items / rows;
|
||||
return (c * rows) < items ? c + 1 : c;
|
||||
}
|
||||
|
||||
void CNavigatorDockWidget::setMinimumSizeForWidgets(int rows, int columns)
|
||||
{
|
||||
int w = 10 * columns;
|
||||
int h = 10 * rows;
|
||||
QSize min(w, h);
|
||||
this->ui->qw_NavigatorDockWidgetOuter->setMinimumSize(min);
|
||||
this->ui->fr_NavigatorDockWidgetInner->setMinimumSize(min);
|
||||
this->setMinimumSize(min);
|
||||
}
|
||||
|
||||
} // ns
|
||||
} // ns
|
||||
|
||||
@@ -9,8 +9,8 @@
|
||||
|
||||
//! \file
|
||||
|
||||
#ifndef BLACKGUI_NAVIGATORDOCKWIDGET_H
|
||||
#define BLACKGUI_NAVIGATORDOCKWIDGET_H
|
||||
#ifndef BLACKGUI_COMPONENTS_NAVIGATORDOCKWIDGET_H
|
||||
#define BLACKGUI_COMPONENTS_NAVIGATORDOCKWIDGET_H
|
||||
|
||||
#include "blackgui/dockwidgetinfoarea.h"
|
||||
#include <QDockWidget>
|
||||
@@ -35,8 +35,42 @@ namespace BlackGui
|
||||
//! Destructor
|
||||
~CNavigatorDockWidget();
|
||||
|
||||
//! Add action as navigator item
|
||||
void addAction(QAction * action);
|
||||
|
||||
//! Add actions as navigator items
|
||||
void addActions(QList<QAction *> actions);
|
||||
|
||||
//! Navigator
|
||||
void buildNavigator(int columns);
|
||||
|
||||
protected:
|
||||
//! \copydoc CDockWidgetInfoArea::addToContextMenu
|
||||
virtual void addToContextMenu(QMenu *contextMenu) const override;
|
||||
|
||||
protected:
|
||||
//! \copydoc CDockWidget::ps_onStyleSheetsChanged
|
||||
virtual void ps_onStyleSheetsChanged() override;
|
||||
|
||||
private slots:
|
||||
//! Change the layout
|
||||
void ps_changeLayout();
|
||||
|
||||
private:
|
||||
QScopedPointer<Ui::CNavigatorDockWidget> ui;
|
||||
QList<QWidget *> m_widgets;
|
||||
QList<QAction *> m_actions;
|
||||
bool m_firstBuild = true;
|
||||
|
||||
//! Insert own actions
|
||||
void insertOwnActions();
|
||||
|
||||
//! How many columns for given rows
|
||||
int columnsForRows(int rows);
|
||||
|
||||
//! Set widgets to their minimum size
|
||||
void setMinimumSizeForWidgets(int rows, int columns);
|
||||
|
||||
};
|
||||
|
||||
} // ns
|
||||
|
||||
@@ -6,10 +6,16 @@
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>89</width>
|
||||
<height>300</height>
|
||||
<width>90</width>
|
||||
<height>383</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="floating">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
@@ -22,19 +28,33 @@
|
||||
<property name="windowTitle">
|
||||
<string>Navigator</string>
|
||||
</property>
|
||||
<widget class="QWidget" name="qw_NavigatorDockWidget">
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<item row="0" column="0">
|
||||
<widget class="QToolButton" name="toolButton">
|
||||
<property name="text">
|
||||
<string>...</string>
|
||||
<widget class="QWidget" name="qw_NavigatorDockWidgetOuter">
|
||||
<layout class="QVBoxLayout" name="vl_NavigatorDockWidgetOuter">
|
||||
<property name="spacing">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QFrame" name="fr_NavigatorDockWidgetInner">
|
||||
<property name="frameShape">
|
||||
<enum>QFrame::NoFrame</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QToolButton" name="toolButton_2">
|
||||
<property name="text">
|
||||
<string>...</string>
|
||||
<property name="frameShadow">
|
||||
<enum>QFrame::Plain</enum>
|
||||
</property>
|
||||
<property name="lineWidth">
|
||||
<number>0</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
|
||||
#include "dockwidget.h"
|
||||
#include "blackmisc/icons.h"
|
||||
#include "blackmisc/logmessage.h"
|
||||
#include "blackgui/stylesheetutility.h"
|
||||
#include "blackgui/guiutility.h"
|
||||
#include <QCloseEvent>
|
||||
@@ -16,14 +17,15 @@
|
||||
#include <QPainter>
|
||||
#include <QLayout>
|
||||
|
||||
using namespace BlackMisc;
|
||||
|
||||
namespace BlackGui
|
||||
{
|
||||
CDockWidget::CDockWidget(bool allowStatusBar, QWidget *parent) :
|
||||
QDockWidget(parent),
|
||||
CEnableForFramelessWindow(CEnableForFramelessWindow::WindowNormal, false, this),
|
||||
CEnableForFramelessWindow(CEnableForFramelessWindow::WindowTool, false, "framelessDockWidget", this),
|
||||
m_allowStatusBar(allowStatusBar)
|
||||
{
|
||||
|
||||
this->ps_onStyleSheetsChanged();
|
||||
this->initTitleBarWidgets();
|
||||
|
||||
@@ -35,7 +37,6 @@ namespace BlackGui
|
||||
connect(this, &QDockWidget::topLevelChanged, this, &CDockWidget::ps_onTopLevelChanged);
|
||||
connect(&CStyleSheetUtility::instance(), &CStyleSheetUtility::styleSheetsChanged, this, &CDockWidget::ps_onStyleSheetsChanged);
|
||||
connect(this, &QDockWidget::visibilityChanged, this, &CDockWidget::ps_onVisibilityChanged);
|
||||
|
||||
}
|
||||
|
||||
CDockWidget::CDockWidget(QWidget *parent): CDockWidget(true, parent)
|
||||
@@ -179,10 +180,7 @@ namespace BlackGui
|
||||
void CDockWidget::toggleFloating()
|
||||
{
|
||||
bool floating = !this->isFloating();
|
||||
if (!floating)
|
||||
{
|
||||
this->setFrameless(false);
|
||||
}
|
||||
if (!floating) { this->setFrameless(false); }
|
||||
this->setFloating(floating);
|
||||
}
|
||||
|
||||
@@ -263,8 +261,7 @@ namespace BlackGui
|
||||
|
||||
void CDockWidget::initialFloating()
|
||||
{
|
||||
|
||||
// init status bar, as we have now all structure set
|
||||
// init status bar, as we have now all structures set
|
||||
this->initStatusBar();
|
||||
|
||||
// for the first time resize
|
||||
@@ -289,36 +286,45 @@ namespace BlackGui
|
||||
QString sectionUsed(section.isEmpty() ? this->objectName() : section);
|
||||
if (sectionUsed.isEmpty()) { return false; }
|
||||
const QSettings *settings = CStyleSheetUtility::instance().iniFile();
|
||||
Q_ASSERT_X(settings, "CDockWidget::setMarginsFromSettings", "Missing ini settings");
|
||||
if (!settings) { return false; }
|
||||
|
||||
// checked if value exists as there is no way to check if key/section exist
|
||||
// check if value exists as there is no way to check if key/section exist
|
||||
if (settings->value(sectionUsed + "/margindocked.left").toString().isEmpty())
|
||||
{
|
||||
// no values considered as no section, now we check if an alias exists
|
||||
sectionUsed = settings->value("alias/" + sectionUsed).toString();
|
||||
if (sectionUsed.isEmpty()) { return false; }
|
||||
if (settings->value(sectionUsed + "/margindocked.left").toString().isEmpty()) { return false; }
|
||||
if (settings->value(sectionUsed + "/margindocked.left").toString().isEmpty())
|
||||
{
|
||||
Q_ASSERT_X(false, "CDockWidget::setMarginsFromSettings", "Wrong ini settings");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (settings)
|
||||
{
|
||||
this->setMarginsWhenDocked(
|
||||
settings->value(sectionUsed + "/margindocked.left", 1).toInt(),
|
||||
settings->value(sectionUsed + "/margindocked.top", 1).toInt(),
|
||||
settings->value(sectionUsed + "/margindocked.right", 1).toInt(),
|
||||
settings->value(sectionUsed + "/margindocked.bottom", 1).toInt());
|
||||
this->setMarginsWhenFloating(
|
||||
settings->value(sectionUsed + "/marginfloating.left", 10).toInt(),
|
||||
settings->value(sectionUsed + "/marginfloating.top", 10).toInt(),
|
||||
settings->value(sectionUsed + "/marginfloating.right", 10).toInt(),
|
||||
settings->value(sectionUsed + "/marginfloating.bottom", 10).toInt());
|
||||
this->setMarginsWhenFramelessFloating(
|
||||
settings->value(sectionUsed + "/marginfloating.frameless.left", 5).toInt(),
|
||||
settings->value(sectionUsed + "/marginfloating.frameless.top", 5).toInt(),
|
||||
settings->value(sectionUsed + "/marginfloating.frameless.right", 5).toInt(),
|
||||
settings->value(sectionUsed + "/marginfloating.frameless.bottom", 5).toInt());
|
||||
}
|
||||
return true;
|
||||
bool ok = true, ok1, ok2, ok3, ok4;
|
||||
this->setMarginsWhenDocked(
|
||||
settings->value(sectionUsed + "/margindocked.left", 1).toInt(&ok1),
|
||||
settings->value(sectionUsed + "/margindocked.top", 1).toInt(&ok2),
|
||||
settings->value(sectionUsed + "/margindocked.right", 1).toInt(&ok3),
|
||||
settings->value(sectionUsed + "/margindocked.bottom", 1).toInt(&ok4));
|
||||
if (!(ok1 && ok2 && ok3 && ok4)) { CLogMessage(this).error("Error in docked margins"); ok = false; }
|
||||
|
||||
this->setMarginsWhenFloating(
|
||||
settings->value(sectionUsed + "/marginfloating.left", 10).toInt(&ok1),
|
||||
settings->value(sectionUsed + "/marginfloating.top", 10).toInt(&ok2),
|
||||
settings->value(sectionUsed + "/marginfloating.right", 10).toInt(&ok3),
|
||||
settings->value(sectionUsed + "/marginfloating.bottom", 10).toInt(&ok4));
|
||||
if (!(ok1 && ok2 && ok3 && ok4)) { CLogMessage(this).error("Error in floating margins"); ok = false; }
|
||||
|
||||
this->setMarginsWhenFramelessFloating(
|
||||
settings->value(sectionUsed + "/marginfloating.frameless.left", 5).toInt(&ok1),
|
||||
settings->value(sectionUsed + "/marginfloating.frameless.top", 5).toInt(&ok2),
|
||||
settings->value(sectionUsed + "/marginfloating.frameless.right", 5).toInt(&ok3),
|
||||
settings->value(sectionUsed + "/marginfloating.frameless.bottom", 5).toInt(&ok4));
|
||||
if (!(ok1 && ok2 && ok3 && ok4)) { CLogMessage(this).error("Error in floating (frameless) margins"); ok = false; }
|
||||
|
||||
return ok;
|
||||
}
|
||||
|
||||
void CDockWidget::ps_onTopLevelChanged(bool topLevel)
|
||||
@@ -388,7 +394,7 @@ namespace BlackGui
|
||||
Q_ASSERT(compWidget);
|
||||
if (!compWidget) { return; }
|
||||
QSizePolicy sizePolicy = compWidget->sizePolicy();
|
||||
sizePolicy.setVerticalStretch(1);
|
||||
sizePolicy.setVerticalStretch(1); // make the original widget occupying maximum space
|
||||
compWidget->setSizePolicy(sizePolicy);
|
||||
}
|
||||
|
||||
|
||||
@@ -18,17 +18,18 @@ using namespace BlackMisc;
|
||||
namespace BlackGui
|
||||
{
|
||||
|
||||
CEnableForFramelessWindow::CEnableForFramelessWindow(CEnableForFramelessWindow::WindowMode mode, bool isMainApplicationWindow, QWidget *correspondingWidget) :
|
||||
m_windowMode(mode), m_mainApplicationWindow(isMainApplicationWindow), m_widget(correspondingWidget)
|
||||
CEnableForFramelessWindow::CEnableForFramelessWindow(CEnableForFramelessWindow::WindowMode mode, bool isMainApplicationWindow, const char *framelessPropertyName, QWidget *correspondingWidget) :
|
||||
m_windowMode(mode), m_mainApplicationWindow(isMainApplicationWindow), m_widget(correspondingWidget), m_framelessPropertyName(framelessPropertyName)
|
||||
{
|
||||
Q_ASSERT(correspondingWidget);
|
||||
Q_ASSERT(!m_framelessPropertyName.isEmpty());
|
||||
this->setWindowAttributes(mode);
|
||||
}
|
||||
|
||||
void CEnableForFramelessWindow::setMode(CEnableForFramelessWindow::WindowMode mode)
|
||||
{
|
||||
if (mode == this->m_windowMode) { return; }
|
||||
// set the main window or dock widget
|
||||
// set the main window or dock widget flags and attributes
|
||||
this->m_widget->setWindowFlags(modeToWindowFlags(mode));
|
||||
this->setWindowAttributes(mode);
|
||||
this->m_widget->show();
|
||||
@@ -37,18 +38,40 @@ namespace BlackGui
|
||||
|
||||
void CEnableForFramelessWindow::setFrameless(bool frameless)
|
||||
{
|
||||
setMode(frameless ? WindowFrameless : WindowNormal);
|
||||
setMode(frameless ? WindowFrameless : WindowTool);
|
||||
}
|
||||
|
||||
void CEnableForFramelessWindow::setWindowAttributes(CEnableForFramelessWindow::WindowMode mode)
|
||||
{
|
||||
Q_ASSERT_X(this->m_widget, "CEnableForFramelessWindow::setWindowAttributes", "Missing widget representing window");
|
||||
Q_ASSERT_X(!this->m_framelessPropertyName.isEmpty(), "CEnableForFramelessWindow::setWindowAttributes", "Missing property name");
|
||||
|
||||
bool frameless = (mode == WindowFrameless);
|
||||
// http://stackoverflow.com/questions/18316710/frameless-and-transparent-window-qt5
|
||||
this->m_widget->setAttribute(Qt::WA_NoSystemBackground, frameless);
|
||||
this->m_widget->setAttribute(Qt::WA_TranslucentBackground, frameless);
|
||||
|
||||
// Qt::WA_PaintOnScreen leads to a warning
|
||||
// setMask(QRegion(10, 10, 10, 10) would work, but requires "complex" calcs for rounded corners
|
||||
//! \todo Transparent dock widget,try out void QWidget::setMask
|
||||
this->setDynamicProperties(frameless);
|
||||
}
|
||||
|
||||
void CEnableForFramelessWindow::setDynamicProperties(bool frameless)
|
||||
{
|
||||
Q_ASSERT_X(this->m_widget, "CEnableForFramelessWindow::setDynamicProperties", "Missing widget representing window");
|
||||
Q_ASSERT_X(!this->m_framelessPropertyName.isEmpty(), "CEnableForFramelessWindow::setDynamicProperties", "Missing property name");
|
||||
|
||||
// property selector will check on string, so I directly provide a string
|
||||
this->m_widget->setProperty("frameless", BlackMisc::boolToTrueFalse(frameless));
|
||||
const QString f(BlackMisc::boolToTrueFalse(frameless));
|
||||
this->m_widget->setProperty(this->m_framelessPropertyName.constData(), f);
|
||||
for (QObject *w : this->m_widget->children())
|
||||
{
|
||||
if (w && w->isWidgetType())
|
||||
{
|
||||
w->setProperty(this->m_framelessPropertyName.constData(), f);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool CEnableForFramelessWindow::handleMouseMoveEvent(QMouseEvent *event)
|
||||
@@ -117,17 +140,35 @@ namespace BlackGui
|
||||
return menuBarLayout;
|
||||
}
|
||||
|
||||
void CEnableForFramelessWindow::toolToNormalWindow()
|
||||
{
|
||||
this->m_widget->setWindowFlags((this->m_widget->windowFlags() & (~Qt::Tool)) | Qt::Window);
|
||||
}
|
||||
|
||||
void CEnableForFramelessWindow::normalToToolWindow()
|
||||
{
|
||||
this->m_widget->setWindowFlags(this->m_widget->windowFlags() | Qt::Tool);
|
||||
}
|
||||
|
||||
bool CEnableForFramelessWindow::isToolWindow() const
|
||||
{
|
||||
|
||||
return (this->m_widget->windowFlags() & Qt::Tool) == Qt::Tool;
|
||||
}
|
||||
|
||||
Qt::WindowFlags CEnableForFramelessWindow::modeToWindowFlags(CEnableForFramelessWindow::WindowMode mode)
|
||||
{
|
||||
switch (mode)
|
||||
{
|
||||
case WindowFrameless:
|
||||
return (Qt::Window | Qt::FramelessWindowHint | Qt::WindowStaysOnTopHint);
|
||||
case WindowNormal:
|
||||
default:
|
||||
case WindowTool:
|
||||
// tool window and minimized not supported on windows
|
||||
// tool window always with close button on windows
|
||||
return (Qt::Tool | Qt::WindowStaysOnTopHint | Qt::WindowMinimizeButtonHint | Qt::WindowCloseButtonHint);
|
||||
case WindowNormal:
|
||||
default:
|
||||
return (Qt::Desktop | Qt::WindowStaysOnTopHint | Qt::WindowMinimizeButtonHint | Qt::WindowCloseButtonHint);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -33,11 +33,12 @@ namespace BlackGui
|
||||
enum WindowMode
|
||||
{
|
||||
WindowFrameless,
|
||||
WindowNormal
|
||||
WindowNormal,
|
||||
WindowTool
|
||||
};
|
||||
|
||||
//! Constructor
|
||||
CEnableForFramelessWindow(WindowMode mode, bool isMainApplicationWindow, QWidget *correspondingWidget);
|
||||
CEnableForFramelessWindow(WindowMode mode, bool isMainApplicationWindow, const char *framelessPropertyname, QWidget *correspondingWidget);
|
||||
|
||||
//! Window mode
|
||||
void setMode(WindowMode mode);
|
||||
@@ -64,18 +65,31 @@ namespace BlackGui
|
||||
//! Attributes
|
||||
void setWindowAttributes(WindowMode mode);
|
||||
|
||||
//! Set dynamic properties such as frameless
|
||||
void setDynamicProperties(bool frameless);
|
||||
|
||||
//! Close button for frameless windows
|
||||
QHBoxLayout *addFramelessCloseButton(QMenuBar *menuBar);
|
||||
|
||||
//! Remove tool and add desktop window
|
||||
void toolToNormalWindow();
|
||||
|
||||
//! Remove desktop and add tool window
|
||||
void normalToToolWindow();
|
||||
|
||||
//! Tool window
|
||||
bool isToolWindow() const;
|
||||
|
||||
//! Translate mode
|
||||
static Qt::WindowFlags modeToWindowFlags(WindowMode mode);
|
||||
|
||||
QPoint m_framelessDragPosition; //!< position, if moving is handled with frameless window */
|
||||
QPushButton *m_framelessCloseButton = nullptr; //!< close button
|
||||
WindowMode m_windowMode = WindowNormal; //!< Window mode, \sa WindowMode
|
||||
WindowMode m_windowMode = WindowTool; //!< Window mode, \sa WindowMode
|
||||
bool m_mainApplicationWindow = false; //!< is the main application window (only 1)
|
||||
QWidget *m_widget = nullptr; //!< corresponding main window or dock widget
|
||||
QSizeGrip *m_framelessSizeGrip = nullptr; //!< size grip object
|
||||
QByteArray m_framelessPropertyName; //!< property name for frameless widgets
|
||||
|
||||
//! Mouse press, required for frameless window
|
||||
bool handleMousePressEvent(QMouseEvent *event);
|
||||
|
||||
@@ -83,4 +83,32 @@ namespace BlackGui
|
||||
if (index < 0) { return QString(oldName).trimmed().append(v); }
|
||||
return QString(oldName.left(index)).trimmed().append(v);
|
||||
}
|
||||
}
|
||||
|
||||
void CGuiUtility::deleteLayout(QLayout *layout, bool deleteWidgets)
|
||||
{
|
||||
// http://stackoverflow.com/a/7569928/356726
|
||||
if (!layout) { return; }
|
||||
QLayoutItem *item {nullptr};
|
||||
QLayout *sublayout {nullptr};
|
||||
QWidget *widget {nullptr};
|
||||
while ((item = layout->takeAt(0)))
|
||||
{
|
||||
if ((sublayout = item->layout()))
|
||||
{
|
||||
deleteLayout(sublayout, deleteWidgets);
|
||||
}
|
||||
else if ((widget = item->widget()))
|
||||
{
|
||||
widget->hide();
|
||||
if (deleteWidgets)
|
||||
{
|
||||
delete widget;
|
||||
}
|
||||
}
|
||||
else {delete item;}
|
||||
}
|
||||
|
||||
// then finally
|
||||
delete layout;
|
||||
}
|
||||
} // ns
|
||||
|
||||
@@ -47,6 +47,9 @@ namespace BlackGui
|
||||
//! Replace count in name such as "stations (4)"
|
||||
static QString replaceTabCountValue(const QString &oldName, int count);
|
||||
|
||||
//! Delete hierarchy of layouts
|
||||
static void deleteLayout(QLayout *layout, bool deleteWidgets);
|
||||
|
||||
private:
|
||||
//! Constructor, use static methods only
|
||||
CGuiUtility() {}
|
||||
|
||||
@@ -27,7 +27,7 @@ using namespace BlackMisc;
|
||||
namespace BlackGui
|
||||
{
|
||||
CInfoArea::CInfoArea(QWidget *parent) :
|
||||
QMainWindow(parent), CEnableForFramelessWindow(CEnableForFramelessWindow::WindowNormal, false, this)
|
||||
QMainWindow(parent), CEnableForFramelessWindow(CEnableForFramelessWindow::WindowTool, false, "framelessInfoArea", this)
|
||||
{
|
||||
this->ps_setWholeInfoAreaFloating(this->m_infoAreaFloating);
|
||||
this->setWindowIcon(CIcons::swift24());
|
||||
@@ -69,7 +69,7 @@ namespace BlackGui
|
||||
|
||||
void CInfoArea::addToContextMenu(QMenu *menu) const
|
||||
{
|
||||
if (!menu) return;
|
||||
if (!menu) { return; }
|
||||
bool hasDockedWidgets = this->countDockedWidgetInfoAreas() > 0;
|
||||
if (hasDockedWidgets)
|
||||
{
|
||||
@@ -147,8 +147,8 @@ namespace BlackGui
|
||||
|
||||
bool CInfoArea::isSelectedDockWidgetInfoArea(const CDockWidgetInfoArea *infoArea) const
|
||||
{
|
||||
if (!infoArea) return false;
|
||||
if (infoArea->isFloating()) return false;
|
||||
if (!infoArea) { return false; }
|
||||
if (infoArea->isFloating()) { return false; }
|
||||
|
||||
return infoArea == this->getSelectedDockInfoArea();
|
||||
}
|
||||
@@ -188,13 +188,16 @@ namespace BlackGui
|
||||
|
||||
QList<QAction *> CInfoArea::getInfoAreaSelectActions(QWidget *parent) const
|
||||
{
|
||||
Q_ASSERT(parent);
|
||||
int i = 0;
|
||||
QList<QAction *> actions;
|
||||
foreach(const CDockWidgetInfoArea * dockWidgetInfoArea, m_dockWidgetInfoAreas)
|
||||
for (const CDockWidgetInfoArea *dockWidgetInfoArea : m_dockWidgetInfoAreas)
|
||||
{
|
||||
const QPixmap pm = this->indexToPixmap(i);
|
||||
QAction *action = new QAction(QIcon(pm), dockWidgetInfoArea->windowTitleBackup(), parent);
|
||||
const QString wt(dockWidgetInfoArea->windowTitleBackup());
|
||||
QAction *action = new QAction(QIcon(pm), wt, parent);
|
||||
action->setData(i);
|
||||
action->setObjectName(this->objectName().append(":getInfoAreaSelectActions:").append(wt));
|
||||
connect(action, &QAction::triggered, this, &CInfoArea::selectAreaByAction);
|
||||
actions.append(action);
|
||||
i++;
|
||||
@@ -202,6 +205,25 @@ namespace BlackGui
|
||||
return actions;
|
||||
}
|
||||
|
||||
QList<QAction *> CInfoArea::getInfoAreaToggleFloatingActions(QWidget *parent) const
|
||||
{
|
||||
Q_ASSERT(parent);
|
||||
int i = 0;
|
||||
QList<QAction *> actions;
|
||||
for (const CDockWidgetInfoArea *dockWidgetInfoArea : m_dockWidgetInfoAreas)
|
||||
{
|
||||
const QPixmap pm = this->indexToPixmap(i);
|
||||
const QString wt(dockWidgetInfoArea->windowTitleBackup());
|
||||
QAction *action = new QAction(QIcon(pm), wt, parent);
|
||||
action->setData(i);
|
||||
action->setObjectName(this->objectName().append(":getInfoAreaToggleFloatingActions:").append(wt));
|
||||
connect(action, &QAction::triggered, this, &CInfoArea::toggleAreaFloatingByAction);
|
||||
actions.append(action);
|
||||
i++;
|
||||
}
|
||||
return actions;
|
||||
}
|
||||
|
||||
QList<int> CInfoArea::getAreaIndexesDockedOrFloating(bool floating) const
|
||||
{
|
||||
QList<int> indexes;
|
||||
@@ -306,7 +328,18 @@ namespace BlackGui
|
||||
Q_ASSERT(sender);
|
||||
const QAction *action = qobject_cast<const QAction *>(sender);
|
||||
Q_ASSERT(action);
|
||||
this->selectArea(action->data().toInt());
|
||||
int index = action->data().toInt();
|
||||
this->selectArea(index);
|
||||
}
|
||||
|
||||
void CInfoArea::toggleAreaFloatingByAction()
|
||||
{
|
||||
const QObject *sender = QObject::sender();
|
||||
Q_ASSERT(sender);
|
||||
const QAction *action = qobject_cast<const QAction *>(sender);
|
||||
Q_ASSERT(action);
|
||||
int index = action->data().toInt();
|
||||
this->toggleFloatingByIndex(index);
|
||||
}
|
||||
|
||||
void CInfoArea::selectLeftTab()
|
||||
@@ -392,7 +425,6 @@ namespace BlackGui
|
||||
|
||||
void CInfoArea::tabifyAllWidgets()
|
||||
{
|
||||
// this->setDockArea(Qt::LeftDockWidgetArea);
|
||||
this->setTabPosition(Qt::LeftDockWidgetArea, QTabWidget::East);
|
||||
bool init = this->m_tabBar ? false : true;
|
||||
|
||||
|
||||
@@ -54,6 +54,11 @@ namespace BlackGui
|
||||
//! \param parent which will own the action (deletion)
|
||||
QList<QAction *> getInfoAreaSelectActions(QWidget *parent) const;
|
||||
|
||||
//! Create a list of actions to select the info areas and toogle its floating state.
|
||||
//! This could be used in a menu or somewhere else.
|
||||
//! \param parent which will own the action (deletion)
|
||||
QList<QAction *> getInfoAreaToggleFloatingActions(QWidget *parent) const;
|
||||
|
||||
//! Docked area indexes
|
||||
QList<int> getAreaIndexesDockedOrFloating(bool floating) const;
|
||||
|
||||
@@ -95,6 +100,9 @@ namespace BlackGui
|
||||
//! Select area (sender is QAction)
|
||||
void selectAreaByAction();
|
||||
|
||||
//! Toggle area floating (sender is QAction)
|
||||
void toggleAreaFloatingByAction();
|
||||
|
||||
//! Select next left tab
|
||||
void selectLeftTab();
|
||||
|
||||
|
||||
@@ -39,14 +39,14 @@ namespace BlackGui
|
||||
|
||||
this->m_statusBarIcon = new QLabel(this->m_statusBar);
|
||||
this->m_statusBarLabel = new QLabel(this->m_statusBar);
|
||||
this->m_statusBarLabel->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred);
|
||||
this->m_statusBarLabel->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Preferred);
|
||||
this->m_statusBarIcon->setObjectName(QString("lbl_StatusBarIcon").append(this->m_statusBar->objectName()));
|
||||
this->m_statusBarLabel->setObjectName(QString("lbl_StatusBarLabel").append(this->m_statusBar->objectName()));
|
||||
|
||||
// use insert to insert from left to right
|
||||
// this keeps any grip on the right size
|
||||
this->m_statusBar->insertPermanentWidget(0, this->m_statusBarIcon, 0);
|
||||
this->m_statusBar->insertPermanentWidget(1, this->m_statusBarLabel, 1);
|
||||
this->m_statusBar->insertPermanentWidget(0, this->m_statusBarIcon, 0); // status icon
|
||||
this->m_statusBar->insertPermanentWidget(1, this->m_statusBarLabel, 1); // status text
|
||||
|
||||
// timer
|
||||
this->m_timerStatusBar = new QTimer(this);
|
||||
|
||||
@@ -4,39 +4,59 @@
|
||||
; this alias makes sense as long there is one object per component
|
||||
CMainInfoAreaComponent = comp_MainInfoArea
|
||||
CCockpitInfoAreaComponent = comp_CockpitInfoArea
|
||||
CInvisibleInfoAreaComponent = comp_InvisibleInfoArea
|
||||
CInfoBarStatusComponent = dw_dw_InfoBarStatus
|
||||
|
||||
[comp_MainInfoArea]
|
||||
margindocked.left = 1
|
||||
margindocked.right = 1
|
||||
margindocked.top = 1
|
||||
margindocked.bottom = 1
|
||||
margindocked.left = 0
|
||||
margindocked.right = 0
|
||||
margindocked.top = 0
|
||||
margindocked.bottom = 0
|
||||
|
||||
marginfloating.left = 5
|
||||
marginfloating.right = 20
|
||||
marginfloating.top = 5
|
||||
marginfloating.bottom = 40
|
||||
; why the odd numbers??
|
||||
marginfloating.left = 0
|
||||
marginfloating.right = 15
|
||||
marginfloating.top = 0
|
||||
marginfloating.bottom = 35
|
||||
|
||||
marginfloating.frameless.left = 5
|
||||
marginfloating.frameless.right = 5
|
||||
marginfloating.frameless.top = 5
|
||||
marginfloating.frameless.bottom = 5
|
||||
marginfloating.frameless.left = 0
|
||||
marginfloating.frameless.right = 0
|
||||
marginfloating.frameless.top = 0
|
||||
marginfloating.frameless.bottom = 0
|
||||
|
||||
[comp_CockpitInfoArea]
|
||||
margindocked.left = 1
|
||||
margindocked.right = 1
|
||||
margindocked.top = 1
|
||||
margindocked.bottom = 1
|
||||
margindocked.left = 0
|
||||
margindocked.right = 0
|
||||
margindocked.top = 0
|
||||
margindocked.bottom = 0
|
||||
|
||||
marginfloating.left = 5
|
||||
marginfloating.right = 20
|
||||
marginfloating.top = 5
|
||||
marginfloating.bottom = 40
|
||||
; why the odd numbers??
|
||||
marginfloating.left = 0
|
||||
marginfloating.right = 15
|
||||
marginfloating.top = 0
|
||||
marginfloating.bottom = 35
|
||||
|
||||
marginfloating.frameless.left = 5
|
||||
marginfloating.frameless.right = 5
|
||||
marginfloating.frameless.top = 5
|
||||
marginfloating.frameless.bottom = 5
|
||||
marginfloating.frameless.left = 0
|
||||
marginfloating.frameless.right = 0
|
||||
marginfloating.frameless.top = 0
|
||||
marginfloating.frameless.bottom = 0
|
||||
|
||||
[comp_InvisibleInfoArea]
|
||||
margindocked.left = 0
|
||||
margindocked.right = 0
|
||||
margindocked.top = 0
|
||||
margindocked.bottom = 0
|
||||
|
||||
; why the odd numbers??
|
||||
marginfloating.left = 0
|
||||
marginfloating.right = 15
|
||||
marginfloating.top = 0
|
||||
marginfloating.bottom = 35
|
||||
|
||||
marginfloating.frameless.left = 0
|
||||
marginfloating.frameless.right = 0
|
||||
marginfloating.frameless.top = 0
|
||||
marginfloating.frameless.bottom = 0
|
||||
|
||||
[dw_InfoBarStatus]
|
||||
margindocked.left = 0
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/** style is applied to a CDockWidgetInfoBar **/
|
||||
/** frameless is dynamic property**/
|
||||
/** for frameless only use QDockWidget[frameless="true"] QFrame **/
|
||||
/** for frameless only use QDockWidget[framelessDockWidget="true"] QFrame **/
|
||||
|
||||
QFrame {
|
||||
margin: 0px;
|
||||
|
||||
@@ -8,7 +8,7 @@ Remarks:
|
||||
2) use -- instead of :: for namespaces
|
||||
|
||||
Used dynamic properties
|
||||
frameless (infobar.qss , here)
|
||||
framelessMainWindow (infobar.qss , here)
|
||||
**/
|
||||
|
||||
/** Main window **/
|
||||
@@ -17,14 +17,26 @@ QMainWindow {
|
||||
background-color: darkslategray;
|
||||
}
|
||||
|
||||
/** required when dock widget is floating **/
|
||||
/** background-image not working on QDockWidget, so I use direct children **/
|
||||
BlackGui--CDockWidgetInfoArea[frameless="false"] {
|
||||
background-color: black;
|
||||
/** separator between info areas and rest **/
|
||||
/** this hides them **/
|
||||
QMainWindow::separator {
|
||||
background: transparent;
|
||||
width: 0px; /* when vertical */
|
||||
height: 0px; /* when horizontal */
|
||||
}
|
||||
|
||||
BlackGui--CDockWidgetInfoArea[frameless="true"] {
|
||||
background-color: white;
|
||||
QMainWindow::separator:hover {
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
/**
|
||||
Required when dock widget is floating
|
||||
1) background-image not working on QDockWidget, so I use direct children for that
|
||||
2) seems to have only effect as normal (floating) window
|
||||
3) Borders between this widget and the inner child is the margin in gui.ini
|
||||
**/
|
||||
BlackGui--CDockWidgetInfoArea {
|
||||
background-color: green; /** I use green here so I can adjust the borders in gui.ini **/
|
||||
}
|
||||
|
||||
/** this is the first widget in the dock area **/
|
||||
@@ -62,12 +74,12 @@ QAbstractScrollArea #qw_RemarksGenerator { background-color: transparent; backg
|
||||
|
||||
/** in log component **/
|
||||
QAbstractScrollArea #pg_StatusPageMessages { background-color: black; }
|
||||
QAbstractScrollArea #pg_StatusPageConsole { background-color: black; }
|
||||
QAbstractScrollArea #pg_StatusPageCons ole { background-color: black; }
|
||||
|
||||
/** main GUI parts **/
|
||||
|
||||
/** style when main window is frameless **/
|
||||
#wi_CentralWidgetOutside[frameless="true"] {
|
||||
#wi_CentralWidgetOutside[framelessMainWindow="true"] {
|
||||
background-image: url(:/textures/icons/textures/texture-outer.jpg);
|
||||
background-color: darkslategray;
|
||||
margin: 0px;
|
||||
|
||||
9
src/blackgui/qss/navigator.qss
Normal file
9
src/blackgui/qss/navigator.qss
Normal file
@@ -0,0 +1,9 @@
|
||||
#fr_NavigatorDockWidgetInner[framelessDockWidget="true"] {
|
||||
margin: 0px;
|
||||
border: 2px solid green;
|
||||
border-radius: 20px;
|
||||
}
|
||||
|
||||
#fr_NavigatorDockWidgetInner QToolButton {
|
||||
margin: 0px;
|
||||
}
|
||||
@@ -244,6 +244,12 @@ namespace BlackGui
|
||||
return f;
|
||||
}
|
||||
|
||||
const QString &CStyleSheetUtility::fileNameNavigator()
|
||||
{
|
||||
static const QString f("navigator.qss");
|
||||
return f;
|
||||
}
|
||||
|
||||
const QString &CStyleSheetUtility::fileNameDockWidgetTab()
|
||||
{
|
||||
static const QString f("dockwidgettab.qss");
|
||||
|
||||
@@ -71,6 +71,9 @@ namespace BlackGui
|
||||
//! File name infobar.qss
|
||||
static const QString &fileNameInfoBar();
|
||||
|
||||
//! File name navigator.qss
|
||||
static const QString &fileNameNavigator();
|
||||
|
||||
//! File name dockwidgettab.qss
|
||||
static const QString &fileNameDockWidgetTab();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user