From dc860b69b03b88ab7d57b0d659340faaae7a9f0c Mon Sep 17 00:00:00 2001
From: Kubat <mael.martin31@gmail.com>
Date: Thu, 26 Aug 2021 14:06:54 +0200
Subject: [PATCH] UI: Add clean title bars for dock widgets (transparent to
 avoid some ugly spaces on the right side)

---
 src/UI/DockWidgetTitleBar.cc | 68 ++++++++++++++++++++++++++++++++++++
 src/UI/DockWidgetTitleBar.hh | 26 ++++++++++++++
 src/UI/VivyDocumentView.cc   | 13 +++----
 3 files changed, 99 insertions(+), 8 deletions(-)
 create mode 100644 src/UI/DockWidgetTitleBar.cc
 create mode 100644 src/UI/DockWidgetTitleBar.hh

diff --git a/src/UI/DockWidgetTitleBar.cc b/src/UI/DockWidgetTitleBar.cc
new file mode 100644
index 00000000..5fdc2719
--- /dev/null
+++ b/src/UI/DockWidgetTitleBar.cc
@@ -0,0 +1,68 @@
+#include "DockWidgetTitleBar.hh"
+
+#include <QLabel>
+#include <QHBoxLayout>
+#include <QPushButton>
+
+using namespace Vivy;
+
+DockWidgetTitleBar::DockWidgetTitleBar(QDockWidget *parent) noexcept
+    : QWidget(parent)
+    , attachedDock(parent)
+{
+    if (parent == nullptr)
+        qFatal("Can't pass a nullptr as a parent widget pointer");
+
+    auto *box = new QHBoxLayout(this);
+    box->addWidget(new QLabel(parent->windowTitle(), this));
+    qobject_cast<QHBoxLayout *>(layout())->setStretch(0, 1);
+}
+
+void
+DockWidgetTitleBar::handleFeaturesChanged(QDockWidget::DockWidgetFeatures feature) noexcept
+{
+    clearControls();
+
+    if (feature & QDockWidget::DockWidgetFloatable) {
+        QPushButton *const button = new QPushButton("float", this);
+        button->setEnabled(true);
+        connect(button, &QPushButton::clicked, attachedDock,
+                [this](bool) { attachedDock->setFloating(!attachedDock->isFloating()); });
+        layout()->addWidget(button);
+    }
+
+    if (feature & QDockWidget::DockWidgetClosable) {
+        QPushButton *const button = new QPushButton("close", this);
+        button->setEnabled(true);
+        connect(button, &QPushButton::clicked, attachedDock, [this](bool) {
+            QAction *const act = attachedDock->toggleViewAction();
+            Q_ASSERT(act->isCheckable());
+            act->trigger();
+        });
+        layout()->addWidget(button);
+    }
+}
+
+void
+DockWidgetTitleBar::clearControls() noexcept
+{
+    QHBoxLayout *const box = qobject_cast<QHBoxLayout *>(layout());
+    QLayoutItem *item      = nullptr;
+
+    for (int i = 1; i < box->count(); ++i) {
+        item = box->takeAt(i);
+        delete item->widget();
+        delete item;
+    }
+}
+
+void
+DockWidgetTitleBar::addToDock(QDockWidget *const dock) noexcept
+{
+    DockWidgetTitleBar *const titleBar = new DockWidgetTitleBar(dock);
+    Utils::setTransparentBackgroundForWidget(titleBar);
+    connect(dock, &QDockWidget::featuresChanged, titleBar,
+            &DockWidgetTitleBar::handleFeaturesChanged);
+    dock->setTitleBarWidget(titleBar);
+    titleBar->handleFeaturesChanged(dock->features());
+}
diff --git a/src/UI/DockWidgetTitleBar.hh b/src/UI/DockWidgetTitleBar.hh
new file mode 100644
index 00000000..97c2ad6d
--- /dev/null
+++ b/src/UI/DockWidgetTitleBar.hh
@@ -0,0 +1,26 @@
+#pragma once
+
+#include "Utils.hh"
+#include "../Lib/Utils.hh"
+
+class QDockWidget;
+
+namespace Vivy
+{
+class DockWidgetTitleBar final : public QWidget {
+    Q_OBJECT
+    VIVY_UNMOVABLE_OBJECT(DockWidgetTitleBar)
+
+    QDockWidget *attachedDock{ nullptr };
+    QDockWidget::DockWidgetFeature currentFeatures{ QDockWidget::NoDockWidgetFeatures };
+
+    explicit DockWidgetTitleBar(QDockWidget *parent) noexcept;
+    void handleFeaturesChanged(QDockWidget::DockWidgetFeatures) noexcept;
+    void clearControls() noexcept;
+    void addCloseButton() noexcept;
+    void addFloatButton() noexcept;
+
+public:
+    static void addToDock(QDockWidget *const) noexcept;
+};
+}
diff --git a/src/UI/VivyDocumentView.cc b/src/UI/VivyDocumentView.cc
index 0f36c52b..3bbf3a9e 100644
--- a/src/UI/VivyDocumentView.cc
+++ b/src/UI/VivyDocumentView.cc
@@ -1,5 +1,6 @@
 #include "VivyDocumentView.hh"
 #include "PropertyModel.hh"
+#include "DockWidgetTitleBar.hh"
 #include "Utils.hh"
 #include "DocumentViews/AudioVisualizer.hh"
 #include "DocumentViews/AssLinesView.hh"
@@ -92,8 +93,7 @@ VivyDocumentView::loadVideoView() noexcept
                                    QDockWidget::DockWidgetFloatable |
                                    QDockWidget::DockWidgetClosable);
             addDockWidget(Qt::BottomDockWidgetArea, videoView, Qt::Vertical);
-            videoView->setTitleBarWidget(new QWidget(this));
-            Utils::setTransparentBackgroundForWidget(videoView->titleBarWidget());
+            DockWidgetTitleBar::addToDock(videoView);
         }
 
         // Kubat: because the dock is "closable", when closed the widget itself
@@ -115,8 +115,7 @@ VivyDocumentView::loadAssView() noexcept
             assLines->setAllowedAreas(Qt::LeftDockWidgetArea | Qt::RightDockWidgetArea |
                                       Qt::BottomDockWidgetArea);
             addDockWidget(Qt::BottomDockWidgetArea, assLines, Qt::Vertical);
-            assLines->setTitleBarWidget(new QWidget(this));
-            Utils::setTransparentBackgroundForWidget(assLines->titleBarWidget());
+            DockWidgetTitleBar::addToDock(assLines);
         }
 
         assModel.reset(new AssLinesModel(document->getAssSubDocument()->getLines()));
@@ -147,8 +146,7 @@ VivyDocumentView::loadAudioView() noexcept
             visualizer->setFeatures(QDockWidget::DockWidgetMovable |
                                     QDockWidget::DockWidgetClosable);
             addDockWidget(Qt::LeftDockWidgetArea, visualizer, Qt::Horizontal);
-            visualizer->setTitleBarWidget(new QWidget(this));
-            Utils::setTransparentBackgroundForWidget(visualizer->titleBarWidget());
+            DockWidgetTitleBar::addToDock(visualizer);
         }
 
         // Kubat: don't check, may throw an error but don't think we can
@@ -196,8 +194,7 @@ VivyDocumentView::openProperties() noexcept
         property = new QDockWidget("Properties", this);
         property->setAllowedAreas(Qt::AllDockWidgetAreas);
         addDockWidget(Qt::RightDockWidgetArea, property, Qt::Vertical);
-        property->setTitleBarWidget(new QWidget(this));
-        Utils::setTransparentBackgroundForWidget(property->titleBarWidget());
+        DockWidgetTitleBar::addToDock(property);
     }
 
     property->setWidget(view);
-- 
GitLab