diff --git a/src/Gui/CMakeLists.txt b/src/Gui/CMakeLists.txt index 20570a70ed..28def36037 100644 --- a/src/Gui/CMakeLists.txt +++ b/src/Gui/CMakeLists.txt @@ -1145,6 +1145,7 @@ SET(Workbench_CPP_SRCS OverlayWidgets.cpp MenuManager.cpp PythonWorkbenchPyImp.cpp + ToolBarAreaWidget.cpp ToolBarManager.cpp ToolBoxManager.cpp Workbench.cpp @@ -1160,6 +1161,7 @@ SET(Workbench_SRCS OverlayManager.h OverlayWidgets.h MenuManager.h + ToolBarAreaWidget.h ToolBarManager.h ToolBoxManager.h Workbench.h diff --git a/src/Gui/ToolBarAreaWidget.cpp b/src/Gui/ToolBarAreaWidget.cpp new file mode 100644 index 0000000000..d3a80ae6f5 --- /dev/null +++ b/src/Gui/ToolBarAreaWidget.cpp @@ -0,0 +1,137 @@ +/*************************************************************************** + * Copyright (c) 2024 Kacper Donat * + * * + * This file is part of FreeCAD. * + * * + * FreeCAD is free software: you can redistribute it and/or modify it * + * under the terms of the GNU Lesser General Public License as * + * published by the Free Software Foundation, either version 2.1 of the * + * License, or (at your option) any later version. * + * * + * FreeCAD is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with FreeCAD. If not, see * + * . * + * * + ***************************************************************************/ + +#include "PreCompiled.h" +#ifndef _PreComp_ +#include +#include +#endif + +#include "MainWindow.h" +#include "ToolBarAreaWidget.h" +#include + +using namespace Gui; + +ToolBarAreaWidget::ToolBarAreaWidget(QWidget* parent, + ToolBarArea area, + const ParameterGrp::handle& hParam, + boost::signals2::scoped_connection& conn, + QTimer* timer) + : QWidget(parent) + , _sizingTimer(timer) + , _hParam(hParam) + , _conn(conn) + , _area(area) +{ + _layout = new QHBoxLayout(this); + _layout->setContentsMargins(QMargins()); +} + +void ToolBarAreaWidget::addWidget(QWidget* widget) +{ + // if widget already exist don't do anything + if (_layout->indexOf(widget) >= 0) { + return; + } + + _layout->addWidget(widget); + adjustParent(); + + QString name = widget->objectName(); + + if (!name.isEmpty()) { + Base::ConnectionBlocker block(_conn); + _hParam->SetInt(widget->objectName().toUtf8().constData(), _layout->count() - 1); + } +} + +void ToolBarAreaWidget::insertWidget(int index, QWidget* widget) +{ + int currentIndex = _layout->indexOf(widget); + + // we are inserting widget at the same place, this is no-op + if (currentIndex == index) { + return; + } + + // widget already exists in the area, we need to first remove it and then recreate + if (currentIndex > 0) { + _layout->removeWidget(widget); + } + + _layout->insertWidget(index, widget); + + adjustParent(); + saveState(); +} + +void ToolBarAreaWidget::removeWidget(QWidget* widget) +{ + _layout->removeWidget(widget); + + QString name = widget->objectName(); + if (!name.isEmpty()) { + Base::ConnectionBlocker block(_conn); + _hParam->RemoveInt(name.toUtf8().constData()); + } + + adjustParent(); +} + +void ToolBarAreaWidget::adjustParent() +{ + if (_sizingTimer) { + _sizingTimer->start(10); + } +} + +void ToolBarAreaWidget::saveState() +{ + Base::ConnectionBlocker block(_conn); + + for (auto &v : _hParam->GetIntMap()) { + _hParam->RemoveInt(v.first.c_str()); + } + + foreachToolBar([this](QToolBar *toolbar, int idx, ToolBarAreaWidget*) { + _hParam->SetInt(toolbar->objectName().toUtf8().constData(), idx); + }); +} + +void ToolBarAreaWidget::restoreState(const std::map& toolbars) +{ + for (const auto &[index, toolbar] : toolbars) { + bool visible = toolbar->isVisible(); + getMainWindow()->removeToolBar(toolbar); + toolbar->setOrientation(Qt::Horizontal); + insertWidget(index, toolbar); + toolbar->setVisible(visible); + } + + for (const auto &[name, visible] : _hParam->GetBoolMap()) { + auto widget = findChild(QString::fromUtf8(name.c_str())); + + if (widget) { + widget->setVisible(visible); + } + } +} diff --git a/src/Gui/ToolBarAreaWidget.h b/src/Gui/ToolBarAreaWidget.h new file mode 100644 index 0000000000..0c96ffb1db --- /dev/null +++ b/src/Gui/ToolBarAreaWidget.h @@ -0,0 +1,116 @@ +/*************************************************************************** + * Copyright (c) 2024 Kacper Donat * + * * + * This file is part of FreeCAD. * + * * + * FreeCAD is free software: you can redistribute it and/or modify it * + * under the terms of the GNU Lesser General Public License as * + * published by the Free Software Foundation, either version 2.1 of the * + * License, or (at your option) any later version. * + * * + * FreeCAD is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with FreeCAD. If not, see * + * . * + * * + ***************************************************************************/ + +#ifndef GUI_TOOLBARAREAWIDGET_H +#define GUI_TOOLBARAREAWIDGET_H + +#include +#include +#include +#include +#include +#include + +namespace Gui +{ + +// Qt treats area as Flag so in theory toolbar could be in multiple areas at once. +// We don't do that here so simple enum should suffice. +enum class ToolBarArea { + NoToolBarArea, + LeftToolBarArea, + RightToolBarArea, + TopToolBarArea, + BottomToolBarArea, + LeftMenuToolBarArea, + RightMenuToolBarArea, + StatusBarToolBarArea, +}; + +class ToolBarAreaWidget : public QWidget +{ + Q_OBJECT + using inherited = QWidget; + +public: + ToolBarAreaWidget(QWidget *parent, + ToolBarArea area, + const ParameterGrp::handle& hParam, + boost::signals2::scoped_connection &conn, + QTimer *timer = nullptr); + + void addWidget(QWidget *widget); + void insertWidget(int index, QWidget *widget); + void removeWidget(QWidget *widget); + + void adjustParent(); + + QWidget *widgetAt(int index) const + { + auto item = _layout->itemAt(index); + + return item ? item->widget() : nullptr; + } + + int count() const + { + return _layout->count(); + } + + int indexOf(QWidget *widget) const + { + return _layout->indexOf(widget); + } + + ToolBarArea area() const + { + return _area; + } + + template + void foreachToolBar(FuncT &&func) + { + for (int i = 0, count = _layout->count(); i < count; ++i) { + auto toolbar = qobject_cast(widgetAt(i)); + + if (!toolbar || toolbar->objectName().isEmpty() + || toolbar->objectName().startsWith(QStringLiteral("*"))) { + continue; + } + + func(toolbar, i, this); + } + } + + void saveState(); + void restoreState(const std::map &toolbars); + +private: + QHBoxLayout *_layout; + QPointer _sizingTimer; + ParameterGrp::handle _hParam; + boost::signals2::scoped_connection &_conn; + ToolBarArea _area; +}; + +} + +#endif // GUI_TOOLBARAREAWIDGET_H diff --git a/src/Gui/ToolBarManager.cpp b/src/Gui/ToolBarManager.cpp index b52197c307..221bde476d 100644 --- a/src/Gui/ToolBarManager.cpp +++ b/src/Gui/ToolBarManager.cpp @@ -21,18 +21,14 @@ ***************************************************************************/ #include "PreCompiled.h" -#include "Selection.h" -#include #ifndef _PreComp_ -# include -# include -# include -# include -# include -# include -# include -# include -# include +#include +#include +#include +#include +#include +#include +#include #endif #include @@ -40,6 +36,7 @@ #include #include "ToolBarManager.h" +#include "ToolBarAreaWidget.h" #include "Application.h" #include "Command.h" #include "MainWindow.h" @@ -163,113 +160,6 @@ QList ToolBarItem::getItems() const return _items; } -// ----------------------------------------------------------- -ToolBarAreaWidget::ToolBarAreaWidget(QWidget* parent, - ToolBarArea area, - const ParameterGrp::handle& hParam, - boost::signals2::scoped_connection& conn, - QTimer* timer) - : QWidget(parent) - , _sizingTimer(timer) - , _hParam(hParam) - , _conn(conn) - , _area(area) -{ - _layout = new QHBoxLayout(this); - _layout->setContentsMargins(QMargins()); -} - -void ToolBarAreaWidget::addWidget(QWidget* widget) -{ - // if widget already exist don't do anything - if (_layout->indexOf(widget) >= 0) { - return; - } - - _layout->addWidget(widget); - adjustParent(); - - QString name = widget->objectName(); - - if (!name.isEmpty()) { - Base::ConnectionBlocker block(_conn); - _hParam->SetInt(widget->objectName().toUtf8().constData(), _layout->count() - 1); - } -} - -void ToolBarAreaWidget::insertWidget(int index, QWidget* widget) -{ - int currentIndex = _layout->indexOf(widget); - - // we are inserting widget at the same place, this is no-op - if (currentIndex == index) { - return; - } - - // widget already exists in the area, we need to first remove it and then recreate - if (currentIndex > 0) { - _layout->removeWidget(widget); - } - - _layout->insertWidget(index, widget); - - adjustParent(); - saveState(); -} - -void ToolBarAreaWidget::removeWidget(QWidget* widget) -{ - _layout->removeWidget(widget); - - QString name = widget->objectName(); - if (!name.isEmpty()) { - Base::ConnectionBlocker block(_conn); - _hParam->RemoveInt(name.toUtf8().constData()); - } - - adjustParent(); -} - -void ToolBarAreaWidget::adjustParent() -{ - if (_sizingTimer) { - _sizingTimer->start(10); - } -} - -void ToolBarAreaWidget::saveState() -{ - Base::ConnectionBlocker block(_conn); - - for (auto &v : _hParam->GetIntMap()) { - _hParam->RemoveInt(v.first.c_str()); - } - - foreachToolBar([this](QToolBar *toolbar, int idx, ToolBarAreaWidget*) { - _hParam->SetInt(toolbar->objectName().toUtf8().constData(), idx); - }); -} - -void ToolBarAreaWidget::restoreState(const std::map& toolbars) -{ - for (const auto &[index, toolbar] : toolbars) { - bool visible = toolbar->isVisible(); - getMainWindow()->removeToolBar(toolbar); - toolbar->setOrientation(Qt::Horizontal); - insertWidget(index, toolbar); - toolbar->setVisible(visible); - } - - for (const auto &[name, visible] : _hParam->GetBoolMap()) { - auto widget = findChild(QString::fromUtf8(name.c_str())); - - if (widget) { - widget->setVisible(visible); - } - } -} - - // ----------------------------------------------------------- ToolBarManager* ToolBarManager::_instance = nullptr; // NOLINT diff --git a/src/Gui/ToolBarManager.h b/src/Gui/ToolBarManager.h index 5f7e34679a..e245a6660b 100644 --- a/src/Gui/ToolBarManager.h +++ b/src/Gui/ToolBarManager.h @@ -29,7 +29,6 @@ #include #include -#include #include #include @@ -43,84 +42,8 @@ class QMouseEvent; namespace Gui { -// Qt treats area as Flag so in theory toolbar could be in multiple areas at once. -// We don't do that here so simple enum should suffice. -enum class ToolBarArea { - NoToolBarArea, - LeftToolBarArea, - RightToolBarArea, - TopToolBarArea, - BottomToolBarArea, - LeftMenuToolBarArea, - RightMenuToolBarArea, - StatusBarToolBarArea, -}; - -class ToolBarAreaWidget : public QWidget -{ - Q_OBJECT - using inherited = QWidget; - -public: - ToolBarAreaWidget(QWidget *parent, - ToolBarArea area, - const ParameterGrp::handle& hParam, - boost::signals2::scoped_connection &conn, - QTimer *timer = nullptr); - - void addWidget(QWidget *widget); - void insertWidget(int index, QWidget *widget); - void removeWidget(QWidget *widget); - - void adjustParent(); - - QWidget *widgetAt(int index) const - { - auto item = _layout->itemAt(index); - - return item ? item->widget() : nullptr; - } - - int count() const - { - return _layout->count(); - } - - int indexOf(QWidget *widget) const - { - return _layout->indexOf(widget); - } - - ToolBarArea area() const - { - return _area; - } - - template - void foreachToolBar(FuncT &&func) - { - for (int i = 0, count = _layout->count(); i < count; ++i) { - auto toolbar = qobject_cast(widgetAt(i)); - - if (!toolbar || toolbar->objectName().isEmpty() - || toolbar->objectName().startsWith(QStringLiteral("*"))) { - continue; - } - - func(toolbar, i, this); - } - } - - void saveState(); - void restoreState(const std::map &toolbars); - -private: - QHBoxLayout *_layout; - QPointer _sizingTimer; - ParameterGrp::handle _hParam; - boost::signals2::scoped_connection &_conn; - ToolBarArea _area; -}; +class ToolBarAreaWidget; +enum class ToolBarArea; class GuiExport ToolBarItem { diff --git a/src/Gui/WorkbenchSelector.cpp b/src/Gui/WorkbenchSelector.cpp index 8a08a950c2..173c5cbbc3 100644 --- a/src/Gui/WorkbenchSelector.cpp +++ b/src/Gui/WorkbenchSelector.cpp @@ -42,7 +42,7 @@ #include "DlgPreferencesImp.h" #include "MainWindow.h" #include "WorkbenchSelector.h" -#include "ToolBarManager.h" +#include "ToolBarAreaWidget.h" using namespace Gui;