Gui: Split declaration and definition of ToolBarAreaWidget

In order to support targeting ToolBarAreaWidgets via the QSS we need to
make it a proper QObject using Q_OBJECT macro, which must be placed in
header files.
This commit is contained in:
Kacper Donat
2024-06-09 18:00:03 +02:00
committed by Chris Hennes
parent 5dad1ef528
commit 5328ca828f
2 changed files with 159 additions and 147 deletions

View File

@@ -164,165 +164,111 @@ QList<ToolBarItem*> ToolBarItem::getItems() const
}
// -----------------------------------------------------------
namespace Gui {
class ToolBarAreaWidget : public QWidget
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)
{
using inherited = QWidget;
_layout = new QHBoxLayout(this);
_layout->setContentsMargins(QMargins());
}
public:
ToolBarAreaWidget(QWidget *parent,
ToolBarArea area,
const ParameterGrp::handle& hParam,
boost::signals2::scoped_connection &conn,
QTimer *timer = nullptr)
: 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;
}
void addWidget(QWidget *widget)
{
// if widget already exist don't do anything
if (_layout->indexOf(widget) >= 0) {
return;
}
_layout->addWidget(widget);
adjustParent();
_layout->addWidget(widget);
adjustParent();
QString name = widget->objectName();
QString name = widget->objectName();
if (!name.isEmpty()) {
Base::ConnectionBlocker block(_conn);
_hParam->SetInt(widget->objectName().toUtf8().constData(), _layout->count() - 1);
}
}
void 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 adjustParent()
{
if (_sizingTimer) {
_sizingTimer->start(10);
}
}
void removeWidget(QWidget *widget)
{
_layout->removeWidget(widget);
QString name = widget->objectName();
if (!name.isEmpty()) {
Base::ConnectionBlocker block(_conn);
_hParam->RemoveInt(name.toUtf8().constData());
}
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<class FuncT>
void foreachToolBar(FuncT &&func)
{
for (int i = 0, c = _layout->count(); i < c; ++i) {
auto toolbar = qobject_cast<QToolBar*>(widgetAt(i));
if (!toolbar || toolbar->objectName().isEmpty()
|| toolbar->objectName().startsWith(QStringLiteral("*"))) {
continue;
}
func(toolbar, i, this);
}
}
void saveState()
{
if (!name.isEmpty()) {
Base::ConnectionBlocker block(_conn);
_hParam->SetInt(widget->objectName().toUtf8().constData(), _layout->count() - 1);
}
}
for (auto &v : _hParam->GetIntMap()) {
_hParam->RemoveInt(v.first.c_str());
}
void ToolBarAreaWidget::insertWidget(int index, QWidget* widget)
{
int currentIndex = _layout->indexOf(widget);
foreachToolBar([this](QToolBar *toolbar, int idx, ToolBarAreaWidget*) {
_hParam->SetInt(toolbar->objectName().toUtf8().constData(), idx);
});
// we are inserting widget at the same place, this is no-op
if (currentIndex == index) {
return;
}
void restoreState(const std::map<int, QToolBar*> &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<QWidget*>(QString::fromUtf8(name.c_str()));
if (widget) {
widget->setVisible(visible);
}
}
// widget already exists in the area, we need to first remove it and then recreate
if (currentIndex > 0) {
_layout->removeWidget(widget);
}
private:
QHBoxLayout *_layout;
QPointer<QTimer> _sizingTimer;
ParameterGrp::handle _hParam;
boost::signals2::scoped_connection &_conn;
ToolBarArea _area;
};
_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<int, QToolBar*>& 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<QWidget*>(QString::fromUtf8(name.c_str()));
if (widget) {
widget->setVisible(visible);
}
}
}
} // namespace Gui
// -----------------------------------------------------------

View File

@@ -29,6 +29,9 @@
#include <QStringList>
#include <QTimer>
#include <QLayout>
#include <QToolBar>
#include <QPointer>
#include <FCGlobal.h>
#include <Base/Parameter.h>
@@ -37,7 +40,6 @@ class QAction;
class QLayout;
class QMenu;
class QMouseEvent;
class QToolBar;
namespace Gui {
@@ -54,7 +56,71 @@ enum class ToolBarArea {
StatusBarToolBarArea,
};
class ToolBarAreaWidget;
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<class FuncT>
void foreachToolBar(FuncT &&func)
{
for (int i = 0, count = _layout->count(); i < count; ++i) {
auto toolbar = qobject_cast<QToolBar*>(widgetAt(i));
if (!toolbar || toolbar->objectName().isEmpty()
|| toolbar->objectName().startsWith(QStringLiteral("*"))) {
continue;
}
func(toolbar, i, this);
}
}
void saveState();
void restoreState(const std::map<int, QToolBar*> &toolbars);
private:
QHBoxLayout *_layout;
QPointer<QTimer> _sizingTimer;
ParameterGrp::handle _hParam;
boost::signals2::scoped_connection &_conn;
ToolBarArea _area;
};
class GuiExport ToolBarItem
{