6 #include <QApplication>
10 #include <QLayoutItem>
13 #include <QScopedPointer>
15 #include <QSizePolicy>
19 #include <QVBoxLayout>
22 #include <QWidgetAction>
29 #include "gui/menus/fontmenus.h"
37 using namespace swift::gui::settings;
38 using namespace swift::gui::menus;
42 CDockWidget::CDockWidget(
bool allowStatusBar, QWidget *parent)
45 m_allowStatusBar(allowStatusBar)
49 this->initTitleBarWidgets();
50 m_originalAreas = this->allowedAreas();
54 m_input->setMaximumWidth(150);
55 m_marginMenuAction =
new QWidgetAction(
this);
56 m_marginMenuAction->setDefaultWidget(m_input);
57 m_fontMenu =
new CFontMenu(
this, Qt::WidgetWithChildrenShortcut);
59 this->setContextMenuPolicy(Qt::CustomContextMenu);
60 connect(
this, &CDockWidget::customContextMenuRequested,
this, &CDockWidget::showContextMenu,
61 Qt::QueuedConnection);
62 connect(m_input, &CMarginsInput::changedMargins,
this,
63 &CDockWidget::menuChangeMargins);
68 Qt::QueuedConnection);
69 connect(
this, &QDockWidget::topLevelChanged,
this, &CDockWidget::onTopLevelChanged, Qt::QueuedConnection);
70 connect(
this, &QDockWidget::visibilityChanged,
this, &CDockWidget::onVisibilityChanged, Qt::QueuedConnection);
77 if (this->isFloating())
89 if (!m_titleBarWidgetOriginal) { this->initTitleBarWidgets(); }
90 if (this->titleBarWidget() == m_titleBarWidgetOriginal)
94 this->setTitleBarWidget(m_titleBarWidgetOriginal);
99 if (!m_titleBarWidgetOriginal) { this->initTitleBarWidgets(); }
100 if (this->titleBarWidget() == m_titleBarWidgetEmpty)
104 this->setTitleBarWidget(m_titleBarWidgetEmpty);
113 this->saveSettings(s);
127 this->saveSettings(s);
144 this->saveSettings(s);
158 m_windowTitleBackup = title;
159 QDockWidget::setWindowTitle(title);
164 if (!m_allowStatusBar || !this->isFloating()) {
return; }
170 if (!m_allowStatusBar || !this->isFloating()) {
return; }
176 m_windowTitleWhenDocked = show;
177 if (show) { QDockWidget::setWindowTitle(m_windowTitleBackup); }
178 else { QDockWidget::setWindowTitle(
""); }
188 m_offsetWhenFloating = point;
209 QWidget *innerWidget = this->widget();
210 Q_ASSERT(innerWidget);
211 this->resize(innerWidget->size());
215 this->forceStyleSheetUpdate();
220 static const QString s(
"outerwidget");
226 static const QString s(
"innerwidget");
232 const bool changeToFloating = !this->isFloating();
236 if (changeToFloating)
238 m_originalAreas = this->allowedAreas();
239 this->setAllowedAreas(Qt::NoDockWidgetArea);
241 else { this->setAllowedAreas(m_originalAreas); }
244 this->setFloating(changeToFloating);
246 const Qt::KeyboardModifiers km = QGuiApplication::queryKeyboardModifiers();
247 const bool shift = km.testFlag(Qt::ShiftModifier);
251 if (changeToFloating)
254 const QPoint p = this->rect().topLeft();
280 if (this->isFloating())
283 m_alwaysOnTop =
true;
289 if (this->isFloating())
292 m_alwaysOnTop =
false;
298 if (onTop) { this->setWindowFlags(this->windowFlags() | Qt::WindowStaysOnTopHint); }
299 else { this->setWindowFlags(this->windowFlags() & ~Qt::WindowStaysOnTopHint); }
308 QPointer<CDockWidget> myself(
this);
310 if (myself) { myself->restoreFromSettings(); }
318 QPointer<CDockWidget> myself(
this);
320 if (myself) { myself->restoreFromSettings(); }
329 const bool ok = this->restoreGeometry(geo);
330 if (ok) { this->rememberFloatingSizeAndPosition(); }
339 if (this->isFloating())
355 event->setAccepted(
false);
357 else { QDockWidget::closeEvent(event); }
363 QDockWidget::paintEvent(event);
364 this->rememberFloatingSizeAndPosition();
374 if (event->key() == Qt::Key_Escape && this->isFloating()) { this->
toggleFloating(); }
375 QDockWidget::keyPressEvent(event);
385 if (this->isFloating())
390 contextMenu->addAction(CIcons::tableSheet16(), frameless ?
"Normal window" :
"Frameless",
this,
394 contextMenu->addAction(CIcons::refresh16(),
"Redraw",
this, qOverload<>(&CDockWidget::update));
399 Q_ASSERT_X(m_fontMenu, Q_FUNC_INFO,
"Missing menu object");
400 if (m_fontMenu) { contextMenu->addActions(m_fontMenu->
getActions()); }
409 contextMenu->addAction(CIcons::tableSheet16(),
"Margins",
this, &CDockWidget::dummy);
410 contextMenu->addAction(m_marginMenuAction);
416 this->initStatusBarAndProperties();
420 if (!m_preferredSizeWhenFloating.isNull())
422 m_initialDockedMinimumSize = this->minimumSize();
423 this->resize(m_preferredSizeWhenFloating);
430 this->restoreFloatingSizeAndPositionDeferred();
435 const QString t(windowTitle());
440 void CDockWidget::onTopLevelChanged(
bool topLevel)
445 QThread::msleep(100);
451 if (m_windowTitleBackup != QDockWidget::windowTitle()) { QDockWidget::setWindowTitle(m_windowTitleBackup); }
468 m_wasAlreadyFloating =
true;
475 if (!m_windowTitleWhenDocked) { QDockWidget::setWindowTitle(
""); }
480 if (this->minimumHeight() > m_initialDockedMinimumSize.height())
482 this->setMinimumSize(m_initialDockedMinimumSize);
490 void CDockWidget::initTitleBarWidgets()
492 m_titleBarWidgetOriginal = this->titleBarWidget();
493 m_titleBarWidgetEmpty =
new QWidget(
this);
494 this->setTitleBarWidget(m_titleBarWidgetEmpty);
497 void CDockWidget::initStatusBarAndProperties()
507 QWidget *outerWidget = this->widget();
508 Q_ASSERT_X(outerWidget,
"CDockWidget::initStatusBar",
"No outer widget");
509 if (!outerWidget) {
return; }
512 Q_ASSERT_X(outerWidget->layout(),
"CDockWidget::initStatusBar",
"No outer widget layout");
513 if (!outerWidget->layout()) {
return; }
514 Q_ASSERT_X(outerWidget->layout()->itemAt(0) && outerWidget->layout()->itemAt(0)->widget(),
515 "CDockWidget::initStatusBar",
"No outer widget layout item");
516 if (!outerWidget->layout()->itemAt(0) || !outerWidget->layout()->itemAt(0)->widget())
518 m_allowStatusBar =
false;
523 QFrame *innerWidget = qobject_cast<QFrame *>(
524 outerWidget->layout()->itemAt(0)->widget());
525 Q_ASSERT_X(innerWidget,
"CDockWidget::initStatusBar",
"No inner widget");
528 m_allowStatusBar =
false;
534 if (!m_allowStatusBar) {
return; }
538 QVBoxLayout *vLayout = qobject_cast<QVBoxLayout *>(innerWidget->layout());
539 Q_ASSERT_X(vLayout,
"CDockWidget::initStatusBar",
"No outer widget layout");
542 m_allowStatusBar =
false;
545 vLayout->addWidget(m_statusBar.
getStatusBar(), 0, Qt::AlignBottom);
549 QWidget *compWidget = innerWidget->findChild<QWidget *>(QString(), Qt::FindDirectChildrenOnly);
550 Q_ASSERT(compWidget);
551 if (!compWidget) {
return; }
552 QSizePolicy sizePolicy = compWidget->sizePolicy();
553 sizePolicy.setVerticalStretch(1);
554 compWidget->setSizePolicy(sizePolicy);
557 if (!this->isFloating()) { m_statusBar.
hide(); }
560 void CDockWidget::showContextMenu(
const QPoint &pos)
562 const QPoint globalPos = this->mapToGlobal(pos);
563 QScopedPointer<QMenu> contextMenu(
new QMenu(
this));
565 QAction *selectedItem = contextMenu.data()->exec(globalPos);
566 Q_UNUSED(selectedItem)
569 void CDockWidget::onVisibilityChanged(
bool visible) { m_dockWidgetVisible = visible; }
571 void CDockWidget::menuChangeMargins(
const QMargins &margins)
574 const bool floating = this->isFloating();
581 this->setContentsMargins(margins);
585 void CDockWidget::settingsChanged()
590 void CDockWidget::dummy()
600 void CDockWidget::forceStyleSheetUpdate()
602 const QString qss = this->styleSheet();
603 this->setStyleSheet(qss.isEmpty() ? QStringLiteral(
" ") : QString());
604 this->setStyleSheet(qss);
607 void CDockWidget::rememberFloatingSizeAndPosition()
609 if (!this->isFloating()) {
return; }
610 m_lastFloatingSize = this->size();
611 m_lastFloatingPosition = this->pos();
614 void CDockWidget::restoreFloatingSizeAndPosition()
616 if (!m_lastFloatingSize.isValid() || m_lastFloatingPosition.isNull()) {
return; }
617 this->resize(m_lastFloatingSize);
618 this->move(m_lastFloatingPosition);
621 void CDockWidget::restoreFloatingSizeAndPositionDeferred()
624 QPointer<CDockWidget> myself(
this);
626 if (!myself) {
return; }
627 const Qt::KeyboardModifiers km = QGuiApplication::queryKeyboardModifiers();
628 const bool shift = km.testFlag(Qt::ShiftModifier);
629 if (shift) {
return; }
632 myself->restoreFromSettings();
647 SWIFT_VERIFY_X(!this->objectName().isEmpty(), Q_FUNC_INFO,
"Need object name for settings %OwnerName%");
648 if (this->objectName().isEmpty())
655 if (m.
isFailure()) { CLogMessage::preformatted(m); }
661 const bool floating = this->isFloating();
663 const QByteArray geo = this->saveGeometry();
667 this->saveSettings(s);
674 this->saveSettings(s);
681 if (!this->isFloating()) {
return; }
682 if (!
sGui) {
return; }
689 const int osFloatingX = m_offsetWhenFloating.x();
690 const int osFloatingY = m_offsetWhenFloating.y();
691 const int x = pos.x() + osFloatingX;
692 const int y = pos.y() + osFloatingY;
Main window which can be frameless.
bool handleMousePressEvent(QMouseEvent *event)
Mouse press, required for frameless window.
void addFramelessSizeGripToStatusBar(QStatusBar *statusBar)
Resize grip handle.
void hideFramelessSizeGripInStatusBar()
Resize grip handle.
virtual void setFrameless(bool frameless)
Framless.
bool handleMouseMoveEvent(QMouseEvent *event)
Mouse moving, required for frameless window.
bool isFrameless() const
Frameless?
bool isCmdWindowSizeResetSet() const
Window size reset mode set.
static QScreen * currentScreen()
Current screen.
void styleSheetsChanged()
Style sheet changed.
static QPoint mainWidgetGlobalPosition()
Position of main widget.
static QWidget * mainApplicationWidget()
Main application window widget.
void displayStatusMessages(const swift::misc::CStatusMessageList &statusMessages)
Display status messages.
void displayStatusMessage(const swift::misc::CStatusMessage &statusMessage)
Display status message.
void initStatusBar(QStatusBar *statusBar=nullptr)
Init.
QStatusBar * getStatusBar() const
Get the status bar.
static bool useStyleSheetInDerivedWidget(QWidget *derivedWidget, QStyle::PrimitiveElement element=QStyle::PE_Widget)
Use style sheets in derived widgets.
CStatusMessage setAndSave(const T &value, qint64 timestamp=0)
Write and save in the same step. Must be called from the thread in which the owner lives.
T get() const
Get a copy of the current value.
Derived & error(const char16_t(&format)[N])
Set the severity to error, providing a format string.
Streamable status message, e.g.
bool isFailure() const
Operation considered unsuccessful.
Status messages, e.g. from Core -> GUI.
SWIFT_GUI_EXPORT swift::gui::CGuiApplication * sGui
Single instance of GUI application object.
High level reusable GUI components.
Free functions in swift::misc.
auto singleShot(int msec, QObject *target, F &&task)
Starts a single-shot timer which will call a task in the thread of the given object when it times out...
#define SWIFT_VERIFY_X(COND, WHERE, WHAT)
A weaker kind of assert.
#define SWIFT_VERIFY(COND)
A weaker kind of assert.