mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-09-17 05:52:33 +00:00
Rename IfcViewerFull to Bonsai Viewer
Directory src/ifcviewer-full -> src/bonsaiviewer, CMake target IfcViewerFull -> BonsaiViewer, namespace ifcviewerfull -> bonsaiviewer, QApplication / window titles / connector path now use the new brand. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,77 @@
|
||||
// This file was generated with the assistance of an AI coding tool.
|
||||
/********************************************************************************
|
||||
* *
|
||||
* This file is part of IfcOpenShell. *
|
||||
* *
|
||||
* IfcOpenShell is free software: you can redistribute it and/or modify *
|
||||
* it under the terms of the Lesser GNU General Public License as published by *
|
||||
* the Free Software Foundation, either version 3.0 of the License, or *
|
||||
* (at your option) any later version. *
|
||||
* *
|
||||
* IfcOpenShell 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 *
|
||||
* Lesser GNU General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the Lesser GNU General Public License *
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
|
||||
* *
|
||||
********************************************************************************/
|
||||
|
||||
#include "Buttons.h"
|
||||
|
||||
#include "SvgIcon.h"
|
||||
|
||||
#include <QFrame>
|
||||
#include <QHBoxLayout>
|
||||
#include <QLabel>
|
||||
#include <QToolButton>
|
||||
#include <QVBoxLayout>
|
||||
|
||||
namespace bonsaiviewer::components::buttons {
|
||||
|
||||
QToolButton* makeButton(const QString& text,
|
||||
const QString& icon_path,
|
||||
QWidget* parent) {
|
||||
auto* button = new QToolButton(parent);
|
||||
button->setObjectName("ribbonButton");
|
||||
button->setToolButtonStyle(Qt::ToolButtonTextUnderIcon);
|
||||
button->setIcon(components::icons::makeAccentSvgIcon(icon_path));
|
||||
button->setIconSize(QSize(20, 20));
|
||||
button->setText(text);
|
||||
button->setMinimumSize(QSize(90, 68));
|
||||
button->setAutoRaise(false);
|
||||
return button;
|
||||
}
|
||||
|
||||
QWidget* makeButtonGroup(const QString& title,
|
||||
const QList<QToolButton*>& buttons,
|
||||
QWidget* parent,
|
||||
bool trailing_separator,
|
||||
int vertical_spacing) {
|
||||
auto* group = new QFrame(parent);
|
||||
group->setObjectName("ribbonGroup");
|
||||
group->setProperty("separator", trailing_separator);
|
||||
|
||||
auto* group_layout = new QVBoxLayout(group);
|
||||
group_layout->setContentsMargins(8, 6, 8, 4);
|
||||
group_layout->setSpacing(vertical_spacing);
|
||||
|
||||
auto* button_row = new QHBoxLayout();
|
||||
button_row->setContentsMargins(0, 0, 0, 0);
|
||||
button_row->setSpacing(4);
|
||||
for (auto* button : buttons) {
|
||||
button_row->addWidget(button);
|
||||
}
|
||||
|
||||
auto* label = new QLabel(title, group);
|
||||
label->setObjectName("ribbonGroupLabel");
|
||||
label->setProperty("textRole", "secondary");
|
||||
label->setAlignment(Qt::AlignCenter);
|
||||
|
||||
group_layout->addLayout(button_row);
|
||||
group_layout->addWidget(label);
|
||||
return group;
|
||||
}
|
||||
|
||||
} // namespace bonsaiviewer::components::buttons
|
||||
@@ -0,0 +1,43 @@
|
||||
// This file was generated with the assistance of an AI coding tool.
|
||||
/********************************************************************************
|
||||
* *
|
||||
* This file is part of IfcOpenShell. *
|
||||
* *
|
||||
* IfcOpenShell is free software: you can redistribute it and/or modify *
|
||||
* it under the terms of the Lesser GNU General Public License as published by *
|
||||
* the Free Software Foundation, either version 3.0 of the License, or *
|
||||
* (at your option) any later version. *
|
||||
* *
|
||||
* IfcOpenShell 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 *
|
||||
* Lesser GNU General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the Lesser GNU General Public License *
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
|
||||
* *
|
||||
********************************************************************************/
|
||||
|
||||
#ifndef IFCINTERFACE_COMPONENTS_BUTTONS_H
|
||||
#define IFCINTERFACE_COMPONENTS_BUTTONS_H
|
||||
|
||||
#include <QList>
|
||||
|
||||
class QToolButton;
|
||||
class QWidget;
|
||||
|
||||
namespace bonsaiviewer::components::buttons {
|
||||
|
||||
QToolButton* makeButton(const QString& text,
|
||||
const QString& icon_path,
|
||||
QWidget* parent);
|
||||
|
||||
QWidget* makeButtonGroup(const QString& title,
|
||||
const QList<QToolButton*>& buttons,
|
||||
QWidget* parent,
|
||||
bool trailing_separator = true,
|
||||
int vertical_spacing = 4);
|
||||
|
||||
} // namespace bonsaiviewer::components::buttons
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,143 @@
|
||||
// This file was generated with the assistance of an AI coding tool.
|
||||
/********************************************************************************
|
||||
* *
|
||||
* This file is part of IfcOpenShell. *
|
||||
* *
|
||||
* IfcOpenShell is free software: you can redistribute it and/or modify *
|
||||
* it under the terms of the Lesser GNU General Public License as published by *
|
||||
* the Free Software Foundation, either version 3.0 of the License, or *
|
||||
* (at your option) any later version. *
|
||||
* *
|
||||
* IfcOpenShell 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 *
|
||||
* Lesser GNU General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the Lesser GNU General Public License *
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
|
||||
* *
|
||||
********************************************************************************/
|
||||
|
||||
#include "Dialog.h"
|
||||
|
||||
#include "Style.h"
|
||||
#include "Tabs.h"
|
||||
|
||||
#include <QDialog>
|
||||
#include <QFrame>
|
||||
#include <QScrollArea>
|
||||
#include <QVBoxLayout>
|
||||
|
||||
namespace bonsaiviewer::components {
|
||||
|
||||
Dialog::Dialog(QWidget* parent, bool scrollable)
|
||||
: QDialog(parent)
|
||||
{
|
||||
auto* outer_layout = new QVBoxLayout(this);
|
||||
outer_layout->setContentsMargins(style::metrics::padding,
|
||||
style::metrics::padding,
|
||||
style::metrics::padding,
|
||||
style::metrics::padding);
|
||||
outer_layout->setSpacing(0);
|
||||
|
||||
auto* frame = new QFrame(this);
|
||||
frame->setObjectName("panel");
|
||||
auto* frame_layout = new QVBoxLayout(frame);
|
||||
frame_layout->setContentsMargins(0,
|
||||
style::metrics::section_body_padding,
|
||||
0,
|
||||
style::metrics::section_body_padding);
|
||||
frame_layout->setSpacing(0);
|
||||
|
||||
auto* scroll = new QScrollArea(frame);
|
||||
scroll->setWidgetResizable(true);
|
||||
scroll->setFrameShape(QFrame::NoFrame);
|
||||
|
||||
auto* scroll_body = new QWidget(scroll);
|
||||
scroll_body->setObjectName("panelScrollBody");
|
||||
body_layout_ = new QVBoxLayout(scroll_body);
|
||||
body_layout_->setContentsMargins(0, 0, 0, 0);
|
||||
body_layout_->setSpacing(style::metrics::section_body_padding);
|
||||
body_layout_->setAlignment(Qt::AlignTop);
|
||||
|
||||
scroll->setWidget(scroll_body);
|
||||
frame_layout->addWidget(scroll, scrollable ? 1 : 0);
|
||||
|
||||
auto* footer = new QWidget(frame);
|
||||
footer_layout_ = new QVBoxLayout(footer);
|
||||
footer_layout_->setContentsMargins(style::metrics::section_body_padding,
|
||||
style::metrics::section_body_padding,
|
||||
style::metrics::section_body_padding,
|
||||
0);
|
||||
footer_layout_->setSpacing(style::metrics::section_body_padding);
|
||||
footer_layout_->setAlignment(Qt::AlignTop);
|
||||
frame_layout->addWidget(footer);
|
||||
|
||||
outer_layout->addWidget(frame);
|
||||
}
|
||||
|
||||
void Dialog::addBodyWidget(QWidget* widget) {
|
||||
body_layout_->addWidget(widget);
|
||||
}
|
||||
|
||||
void Dialog::addFooterWidget(QWidget* widget) {
|
||||
footer_layout_->addWidget(widget);
|
||||
}
|
||||
|
||||
TabbedDialog::TabbedDialog(QWidget* parent)
|
||||
: QDialog(parent)
|
||||
{
|
||||
auto* outer_layout = new QVBoxLayout(this);
|
||||
outer_layout->setContentsMargins(style::metrics::padding,
|
||||
style::metrics::padding,
|
||||
style::metrics::padding,
|
||||
style::metrics::padding);
|
||||
outer_layout->setSpacing(0);
|
||||
|
||||
auto* frame = new QFrame(this);
|
||||
frame->setObjectName("panel");
|
||||
auto* frame_layout = new QVBoxLayout(frame);
|
||||
frame_layout->setContentsMargins(0,
|
||||
style::metrics::section_body_padding,
|
||||
0,
|
||||
style::metrics::section_body_padding);
|
||||
frame_layout->setSpacing(0);
|
||||
|
||||
tabs_ = new TabWidget(frame);
|
||||
frame_layout->addWidget(tabs_, 1);
|
||||
|
||||
auto* footer = new QWidget(frame);
|
||||
footer_layout_ = new QVBoxLayout(footer);
|
||||
footer_layout_->setContentsMargins(style::metrics::section_body_padding,
|
||||
style::metrics::section_body_padding,
|
||||
style::metrics::section_body_padding,
|
||||
0);
|
||||
footer_layout_->setSpacing(style::metrics::section_body_padding);
|
||||
footer_layout_->setAlignment(Qt::AlignTop);
|
||||
frame_layout->addWidget(footer);
|
||||
|
||||
outer_layout->addWidget(frame);
|
||||
}
|
||||
|
||||
void TabbedDialog::addTab(const QString& title, QWidget* widget) {
|
||||
auto* scroll = new QScrollArea(tabs_);
|
||||
scroll->setWidgetResizable(true);
|
||||
scroll->setFrameShape(QFrame::NoFrame);
|
||||
|
||||
auto* scroll_body = new QWidget(scroll);
|
||||
scroll_body->setObjectName("panelScrollBody");
|
||||
auto* layout = new QVBoxLayout(scroll_body);
|
||||
layout->setContentsMargins(0, 0, 0, 0);
|
||||
layout->setSpacing(style::metrics::section_body_padding);
|
||||
layout->setAlignment(Qt::AlignTop);
|
||||
layout->addWidget(widget);
|
||||
|
||||
scroll->setWidget(scroll_body);
|
||||
tabs_->addTab(scroll, title);
|
||||
}
|
||||
|
||||
void TabbedDialog::addFooterWidget(QWidget* widget) {
|
||||
footer_layout_->addWidget(widget);
|
||||
}
|
||||
|
||||
} // namespace bonsaiviewer::components
|
||||
@@ -0,0 +1,63 @@
|
||||
// This file was generated with the assistance of an AI coding tool.
|
||||
/********************************************************************************
|
||||
* *
|
||||
* This file is part of IfcOpenShell. *
|
||||
* *
|
||||
* IfcOpenShell is free software: you can redistribute it and/or modify *
|
||||
* it under the terms of the Lesser GNU General Public License as published by *
|
||||
* the Free Software Foundation, either version 3.0 of the License, or *
|
||||
* (at your option) any later version. *
|
||||
* *
|
||||
* IfcOpenShell 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 *
|
||||
* Lesser GNU General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the Lesser GNU General Public License *
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
|
||||
* *
|
||||
********************************************************************************/
|
||||
|
||||
#ifndef IFCINTERFACE_COMPONENTS_DIALOG_H
|
||||
#define IFCINTERFACE_COMPONENTS_DIALOG_H
|
||||
|
||||
#include <QDialog>
|
||||
|
||||
class QVBoxLayout;
|
||||
class QWidget;
|
||||
class QTabWidget;
|
||||
|
||||
namespace bonsaiviewer::components {
|
||||
|
||||
class Dialog : public QDialog {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit Dialog(QWidget* parent = nullptr,
|
||||
bool scrollable = false);
|
||||
|
||||
void addBodyWidget(QWidget* widget);
|
||||
void addFooterWidget(QWidget* widget);
|
||||
|
||||
private:
|
||||
QVBoxLayout* body_layout_ = nullptr;
|
||||
QVBoxLayout* footer_layout_ = nullptr;
|
||||
};
|
||||
|
||||
class TabbedDialog : public QDialog {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit TabbedDialog(QWidget* parent = nullptr);
|
||||
|
||||
void addTab(const QString& title, QWidget* widget);
|
||||
void addFooterWidget(QWidget* widget);
|
||||
|
||||
private:
|
||||
QTabWidget* tabs_ = nullptr;
|
||||
QVBoxLayout* footer_layout_ = nullptr;
|
||||
};
|
||||
|
||||
} // namespace bonsaiviewer::components
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,72 @@
|
||||
// This file was generated with the assistance of an AI coding tool.
|
||||
/********************************************************************************
|
||||
* *
|
||||
* This file is part of IfcOpenShell. *
|
||||
* *
|
||||
* IfcOpenShell is free software: you can redistribute it and/or modify *
|
||||
* it under the terms of the Lesser GNU General Public License as published by *
|
||||
* the Free Software Foundation, either version 3.0 of the License, or *
|
||||
* (at your option) any later version. *
|
||||
* *
|
||||
* IfcOpenShell 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 *
|
||||
* Lesser GNU General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the Lesser GNU General Public License *
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
|
||||
* *
|
||||
********************************************************************************/
|
||||
|
||||
#include "KeyValueTable.h"
|
||||
|
||||
#include "SvgIcon.h"
|
||||
|
||||
#include <QGridLayout>
|
||||
#include <QLabel>
|
||||
|
||||
namespace bonsaiviewer::components {
|
||||
|
||||
KeyValueTable::KeyValueTable(const QList<KeyValueTableRow>& rows, QWidget* parent)
|
||||
: QWidget(parent)
|
||||
{
|
||||
setObjectName("keyValueTable");
|
||||
|
||||
auto* layout = new QGridLayout(this);
|
||||
layout->setContentsMargins(0, 0, 0, 0);
|
||||
layout->setHorizontalSpacing(12);
|
||||
layout->setVerticalSpacing(6);
|
||||
layout->setColumnStretch(1, 1);
|
||||
|
||||
int row_index = 0;
|
||||
for (const auto& row_data : rows) {
|
||||
auto* key = new QLabel(row_data.key, this);
|
||||
key->setProperty("textRole", "secondary");
|
||||
if (row_data.key_minimum_width > 0) {
|
||||
key->setMinimumWidth(row_data.key_minimum_width);
|
||||
}
|
||||
|
||||
auto* value = new QLabel(row_data.value, this);
|
||||
value->setObjectName(row_data.value_object_name.isEmpty()
|
||||
? "keyValueValueLabel"
|
||||
: row_data.value_object_name);
|
||||
value->setWordWrap(true);
|
||||
value->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred);
|
||||
|
||||
layout->addWidget(key, row_index, 0, Qt::AlignLeft | Qt::AlignTop);
|
||||
layout->addWidget(value, row_index, 1);
|
||||
|
||||
if (!row_data.trailing_icon_path.isEmpty()) {
|
||||
auto* icon = new QLabel(this);
|
||||
icon->setObjectName(row_data.trailing_icon_object_name.isEmpty()
|
||||
? "keyValueTrailingIconLabel"
|
||||
: row_data.trailing_icon_object_name);
|
||||
icon->setPixmap(icons::makeSvgPixmap(row_data.trailing_icon_path, QSize(14, 14)));
|
||||
icon->setAlignment(Qt::AlignRight | Qt::AlignVCenter);
|
||||
layout->addWidget(icon, row_index, 2, Qt::AlignRight | Qt::AlignTop);
|
||||
}
|
||||
++row_index;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace bonsaiviewer::components
|
||||
@@ -0,0 +1,47 @@
|
||||
// This file was generated with the assistance of an AI coding tool.
|
||||
/********************************************************************************
|
||||
* *
|
||||
* This file is part of IfcOpenShell. *
|
||||
* *
|
||||
* IfcOpenShell is free software: you can redistribute it and/or modify *
|
||||
* it under the terms of the Lesser GNU General Public License as published by *
|
||||
* the Free Software Foundation, either version 3.0 of the License, or *
|
||||
* (at your option) any later version. *
|
||||
* *
|
||||
* IfcOpenShell 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 *
|
||||
* Lesser GNU General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the Lesser GNU General Public License *
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
|
||||
* *
|
||||
********************************************************************************/
|
||||
|
||||
#ifndef IFCINTERFACE_COMPONENTS_KEYVALUETABLE_H
|
||||
#define IFCINTERFACE_COMPONENTS_KEYVALUETABLE_H
|
||||
|
||||
#include <QList>
|
||||
#include <QString>
|
||||
#include <QWidget>
|
||||
|
||||
namespace bonsaiviewer::components {
|
||||
|
||||
struct KeyValueTableRow {
|
||||
QString key;
|
||||
QString value;
|
||||
QString value_object_name = "keyValueValueLabel";
|
||||
QString trailing_icon_path;
|
||||
QString trailing_icon_object_name;
|
||||
int key_minimum_width = 0;
|
||||
};
|
||||
|
||||
class KeyValueTable : public QWidget {
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit KeyValueTable(const QList<KeyValueTableRow>& rows, QWidget* parent = nullptr);
|
||||
};
|
||||
|
||||
} // namespace bonsaiviewer::components
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,140 @@
|
||||
// This file was generated with the assistance of an AI coding tool.
|
||||
/********************************************************************************
|
||||
* *
|
||||
* This file is part of IfcOpenShell. *
|
||||
* *
|
||||
* IfcOpenShell is free software: you can redistribute it and/or modify *
|
||||
* it under the terms of the Lesser GNU General Public License as published by *
|
||||
* the Free Software Foundation, either version 3.0 of the License, or *
|
||||
* (at your option) any later version. *
|
||||
* *
|
||||
* IfcOpenShell 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 *
|
||||
* Lesser GNU General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the Lesser GNU General Public License *
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
|
||||
* *
|
||||
********************************************************************************/
|
||||
|
||||
#include "Panel.h"
|
||||
|
||||
#include "Style.h"
|
||||
#include "SvgIcon.h"
|
||||
|
||||
#include <QDockWidget>
|
||||
#include <QFrame>
|
||||
#include <QHBoxLayout>
|
||||
#include <QLabel>
|
||||
#include <QMenu>
|
||||
#include <QScrollArea>
|
||||
#include <QToolButton>
|
||||
#include <QVBoxLayout>
|
||||
|
||||
namespace bonsaiviewer::components {
|
||||
|
||||
namespace {
|
||||
|
||||
class DockTitleBar : public QWidget {
|
||||
public:
|
||||
explicit DockTitleBar(const QString& title,
|
||||
bool has_settings = false,
|
||||
std::function<void()> on_settings = {},
|
||||
QWidget* parent = nullptr)
|
||||
: QWidget(parent)
|
||||
{
|
||||
auto* layout = new QHBoxLayout(this);
|
||||
layout->setContentsMargins(10, 6, 6, 6);
|
||||
layout->setSpacing(6);
|
||||
|
||||
auto* text = new QLabel(title.toUpper(), this);
|
||||
text->setObjectName("panelTitleText");
|
||||
|
||||
layout->addWidget(text);
|
||||
layout->addStretch(1);
|
||||
if (has_settings) {
|
||||
auto* settings = new QToolButton(this);
|
||||
settings->setIcon(icons::makeSvgIcon(":/icons/settings.svg"));
|
||||
settings->setAutoRaise(true);
|
||||
settings->setCursor(Qt::ArrowCursor);
|
||||
settings->setFixedSize(18, 18);
|
||||
settings->setObjectName("panelTitleButton");
|
||||
settings->setToolTip(QString("%1 settings").arg(title));
|
||||
connect(settings, &QToolButton::clicked, this, [on_settings = std::move(on_settings)]() {
|
||||
if (on_settings) on_settings();
|
||||
});
|
||||
layout->addWidget(settings);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
Panel::Panel(const QString& title, QWidget* content, QWidget* parent, bool has_settings, bool scrollable)
|
||||
: QDockWidget(title, parent)
|
||||
{
|
||||
auto* outer = new QFrame();
|
||||
auto* outer_layout = new QVBoxLayout(outer);
|
||||
outer_layout->setContentsMargins(style::metrics::padding,
|
||||
style::metrics::padding,
|
||||
style::metrics::padding,
|
||||
style::metrics::padding);
|
||||
outer_layout->setSpacing(0);
|
||||
|
||||
auto* frame = new QFrame(outer);
|
||||
frame->setObjectName("panel");
|
||||
auto* frame_layout = new QVBoxLayout(frame);
|
||||
frame_layout->setContentsMargins(0, style::metrics::section_body_padding, 0, style::metrics::section_body_padding);
|
||||
frame_layout->setSpacing(0);
|
||||
|
||||
if (scrollable) {
|
||||
auto* scroll = new QScrollArea(frame);
|
||||
scroll->setWidgetResizable(true);
|
||||
scroll->setFrameShape(QFrame::NoFrame);
|
||||
|
||||
auto* scroll_body = new QWidget(scroll);
|
||||
scroll_body->setObjectName("panelScrollBody");
|
||||
body_layout_ = new QVBoxLayout(scroll_body);
|
||||
body_layout_->setContentsMargins(0, 0, 0, 0);
|
||||
body_layout_->setSpacing(style::metrics::section_body_padding);
|
||||
body_layout_->setAlignment(Qt::AlignTop);
|
||||
|
||||
scroll->setWidget(scroll_body);
|
||||
frame_layout->addWidget(scroll);
|
||||
} else {
|
||||
auto* body = new QWidget(frame);
|
||||
body_layout_ = new QVBoxLayout(body);
|
||||
body_layout_->setContentsMargins(0, 0, 0, 0);
|
||||
body_layout_->setSpacing(style::metrics::section_body_padding);
|
||||
body_layout_->setAlignment(Qt::AlignTop);
|
||||
frame_layout->addWidget(body);
|
||||
}
|
||||
|
||||
if (content) {
|
||||
addBodyWidget(content);
|
||||
}
|
||||
outer_layout->addWidget(frame);
|
||||
|
||||
setObjectName(title);
|
||||
setFeatures(QDockWidget::DockWidgetMovable |
|
||||
QDockWidget::DockWidgetFloatable |
|
||||
QDockWidget::DockWidgetClosable);
|
||||
setTitleBarWidget(new DockTitleBar(title, has_settings, [this]() {
|
||||
emit settingsRequested();
|
||||
}, this));
|
||||
setWidget(outer);
|
||||
}
|
||||
|
||||
void Panel::addBodyWidget(QWidget* widget) {
|
||||
body_layout_->addWidget(widget);
|
||||
}
|
||||
|
||||
void Panel::clearBodyWidgets() {
|
||||
while (auto* item = body_layout_->takeAt(0)) {
|
||||
if (auto* widget = item->widget()) widget->deleteLater();
|
||||
delete item;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace bonsaiviewer::components
|
||||
@@ -0,0 +1,53 @@
|
||||
// This file was generated with the assistance of an AI coding tool.
|
||||
/********************************************************************************
|
||||
* *
|
||||
* This file is part of IfcOpenShell. *
|
||||
* *
|
||||
* IfcOpenShell is free software: you can redistribute it and/or modify *
|
||||
* it under the terms of the Lesser GNU General Public License as published by *
|
||||
* the Free Software Foundation, either version 3.0 of the License, or *
|
||||
* (at your option) any later version. *
|
||||
* *
|
||||
* IfcOpenShell 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 *
|
||||
* Lesser GNU General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the Lesser GNU General Public License *
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
|
||||
* *
|
||||
********************************************************************************/
|
||||
|
||||
#ifndef IFCINTERFACE_COMPONENTS_PANEL_PANELCHROME_H
|
||||
#define IFCINTERFACE_COMPONENTS_PANEL_PANELCHROME_H
|
||||
|
||||
#include <QDockWidget>
|
||||
|
||||
class QWidget;
|
||||
class QVBoxLayout;
|
||||
|
||||
namespace bonsaiviewer::components {
|
||||
|
||||
class Panel : public QDockWidget {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit Panel(const QString& title,
|
||||
QWidget* content = nullptr,
|
||||
QWidget* parent = nullptr,
|
||||
bool has_settings = false,
|
||||
bool scrollable = false);
|
||||
|
||||
void addBodyWidget(QWidget* widget);
|
||||
void clearBodyWidgets();
|
||||
|
||||
signals:
|
||||
void settingsRequested();
|
||||
|
||||
private:
|
||||
QVBoxLayout* body_layout_ = nullptr;
|
||||
};
|
||||
|
||||
} // namespace bonsaiviewer::components
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,118 @@
|
||||
// This file was generated with the assistance of an AI coding tool.
|
||||
/********************************************************************************
|
||||
* *
|
||||
* This file is part of IfcOpenShell. *
|
||||
* *
|
||||
* IfcOpenShell is free software: you can redistribute it and/or modify *
|
||||
* it under the terms of the Lesser GNU General Public License as published by *
|
||||
* the Free Software Foundation, either version 3.0 of the License, or *
|
||||
* (at your option) any later version. *
|
||||
* *
|
||||
* IfcOpenShell 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 *
|
||||
* Lesser GNU General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the Lesser GNU General Public License *
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
|
||||
* *
|
||||
********************************************************************************/
|
||||
|
||||
#include "Section.h"
|
||||
|
||||
#include "Style.h"
|
||||
|
||||
#include <QFrame>
|
||||
#include <QHBoxLayout>
|
||||
#include <QSizePolicy>
|
||||
#include <QToolButton>
|
||||
#include <QVBoxLayout>
|
||||
|
||||
namespace bonsaiviewer::components {
|
||||
|
||||
Section::Section(const QString& title, SectionHeaderMode header_mode, QWidget* parent)
|
||||
: QWidget(parent)
|
||||
{
|
||||
setObjectName("panelSection");
|
||||
setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Maximum);
|
||||
auto* layout = new QVBoxLayout(this);
|
||||
layout->setContentsMargins(0, 0, 0, 0);
|
||||
layout->setSpacing(style::metrics::padding);
|
||||
|
||||
if (header_mode == SectionHeaderMode::Visible) {
|
||||
auto* header = new QFrame(this);
|
||||
header->setObjectName("panelSectionHeader");
|
||||
header_layout_ = new QHBoxLayout(header);
|
||||
header_layout_->setContentsMargins(0, 0, 0, 0);
|
||||
header_layout_->setSpacing(style::metrics::padding);
|
||||
|
||||
toggle_button_ = new QToolButton(header);
|
||||
toggle_button_->setObjectName("panelSectionHeaderButton");
|
||||
toggle_button_->setText(title);
|
||||
toggle_button_->setCheckable(true);
|
||||
toggle_button_->setChecked(true);
|
||||
toggle_button_->setToolButtonStyle(Qt::ToolButtonTextBesideIcon);
|
||||
toggle_button_->setArrowType(Qt::DownArrow);
|
||||
header_layout_->addWidget(toggle_button_);
|
||||
header_layout_->addStretch(1);
|
||||
|
||||
layout->addWidget(header);
|
||||
|
||||
connect(toggle_button_, &QToolButton::toggled, this, [this](bool expanded) {
|
||||
toggle_button_->setArrowType(expanded ? Qt::DownArrow : Qt::RightArrow);
|
||||
body_->setVisible(expanded);
|
||||
body_->setMaximumHeight(expanded ? QWIDGETSIZE_MAX : 0);
|
||||
body_->setMinimumHeight(0);
|
||||
setSizePolicy(QSizePolicy::Preferred,
|
||||
body_expanding_ && expanded ? QSizePolicy::Expanding : QSizePolicy::Maximum);
|
||||
updateGeometry();
|
||||
});
|
||||
}
|
||||
|
||||
body_ = new QWidget(this);
|
||||
body_->setObjectName("panelSectionBody");
|
||||
body_layout_ = new QVBoxLayout(body_);
|
||||
body_layout_->setContentsMargins(style::metrics::section_body_padding,
|
||||
0,
|
||||
style::metrics::section_body_padding,
|
||||
0);
|
||||
body_layout_->setSpacing(style::metrics::padding);
|
||||
body_->setMinimumHeight(0);
|
||||
layout->addWidget(body_);
|
||||
}
|
||||
|
||||
void Section::addBodyWidget(QWidget* widget) {
|
||||
body_layout_->addWidget(widget);
|
||||
}
|
||||
|
||||
void Section::clearBody() {
|
||||
while (auto* item = body_layout_->takeAt(0)) {
|
||||
if (auto* widget = item->widget()) widget->deleteLater();
|
||||
delete item;
|
||||
}
|
||||
}
|
||||
|
||||
void Section::addHeaderWidget(QWidget* widget) {
|
||||
if (!header_layout_) return;
|
||||
header_layout_->addWidget(widget);
|
||||
}
|
||||
|
||||
bool Section::isExpanded() const {
|
||||
return !toggle_button_ || toggle_button_->isChecked();
|
||||
}
|
||||
|
||||
void Section::setExpanded(bool expanded) {
|
||||
if (!toggle_button_) return;
|
||||
toggle_button_->setChecked(expanded);
|
||||
}
|
||||
|
||||
void Section::setBodyExpanding(bool expanding) {
|
||||
body_expanding_ = expanding;
|
||||
body_->setSizePolicy(QSizePolicy::Preferred, expanding ? QSizePolicy::Expanding : QSizePolicy::Preferred);
|
||||
body_layout_->setStretch(0, expanding ? 1 : 0);
|
||||
setSizePolicy(QSizePolicy::Preferred,
|
||||
expanding && isExpanded() ? QSizePolicy::Expanding : QSizePolicy::Maximum);
|
||||
updateGeometry();
|
||||
}
|
||||
|
||||
} // namespace bonsaiviewer::components
|
||||
@@ -0,0 +1,61 @@
|
||||
// This file was generated with the assistance of an AI coding tool.
|
||||
/********************************************************************************
|
||||
* *
|
||||
* This file is part of IfcOpenShell. *
|
||||
* *
|
||||
* IfcOpenShell is free software: you can redistribute it and/or modify *
|
||||
* it under the terms of the Lesser GNU General Public License as published by *
|
||||
* the Free Software Foundation, either version 3.0 of the License, or *
|
||||
* (at your option) any later version. *
|
||||
* *
|
||||
* IfcOpenShell 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 *
|
||||
* Lesser GNU General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the Lesser GNU General Public License *
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
|
||||
* *
|
||||
********************************************************************************/
|
||||
|
||||
#ifndef IFCINTERFACE_COMPONENTS_SECTION_H
|
||||
#define IFCINTERFACE_COMPONENTS_SECTION_H
|
||||
|
||||
#include <QWidget>
|
||||
|
||||
class QHBoxLayout;
|
||||
class QToolButton;
|
||||
class QVBoxLayout;
|
||||
|
||||
namespace bonsaiviewer::components {
|
||||
|
||||
enum class SectionHeaderMode {
|
||||
Visible,
|
||||
Hidden,
|
||||
};
|
||||
|
||||
class Section : public QWidget {
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit Section(const QString& title,
|
||||
SectionHeaderMode header_mode = SectionHeaderMode::Visible,
|
||||
QWidget* parent = nullptr);
|
||||
|
||||
void addBodyWidget(QWidget* widget);
|
||||
void clearBody();
|
||||
void addHeaderWidget(QWidget* widget);
|
||||
bool isExpanded() const;
|
||||
void setExpanded(bool expanded);
|
||||
void setBodyExpanding(bool expanding);
|
||||
|
||||
private:
|
||||
QWidget* body_ = nullptr;
|
||||
QVBoxLayout* body_layout_ = nullptr;
|
||||
QHBoxLayout* header_layout_ = nullptr;
|
||||
QToolButton* toggle_button_ = nullptr;
|
||||
bool body_expanding_ = false;
|
||||
};
|
||||
|
||||
} // namespace bonsaiviewer::components
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,497 @@
|
||||
// This file was generated with the assistance of an AI coding tool.
|
||||
/********************************************************************************
|
||||
* *
|
||||
* This file is part of IfcOpenShell. *
|
||||
* *
|
||||
* IfcOpenShell is free software: you can redistribute it and/or modify *
|
||||
* it under the terms of the Lesser GNU General Public License as published by *
|
||||
* the Free Software Foundation, either version 3.0 of the License, or *
|
||||
* (at your option) any later version. *
|
||||
* *
|
||||
* IfcOpenShell 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 *
|
||||
* Lesser GNU General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the Lesser GNU General Public License *
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
|
||||
* *
|
||||
********************************************************************************/
|
||||
|
||||
#include "Style.h"
|
||||
|
||||
#include "../ViewerSettings.h"
|
||||
|
||||
namespace bonsaiviewer::components::style {
|
||||
|
||||
QString buildAppStyleSheet() {
|
||||
const auto& theme = bonsaiviewer::ViewerSettings::instance();
|
||||
QString stylesheet = QStringLiteral(R"(
|
||||
QMainWindow#appWindow {
|
||||
background: ${app_background};
|
||||
color: ${primary_text};
|
||||
selection-background-color: ${selection_background};
|
||||
selection-color: ${selection_text};
|
||||
}
|
||||
QDialog#appDialog {
|
||||
background: ${app_background};
|
||||
color: ${primary_text};
|
||||
}
|
||||
QMessageBox,
|
||||
QMessageBox QWidget,
|
||||
QMessageBox QLabel {
|
||||
background: ${app_background};
|
||||
color: ${primary_text};
|
||||
}
|
||||
QFileDialog,
|
||||
QFileDialog QWidget,
|
||||
QFileDialog QStackedWidget,
|
||||
QFileDialog QSplitter {
|
||||
background: ${app_background};
|
||||
color: ${primary_text};
|
||||
}
|
||||
QTabBar#appTabBar {
|
||||
background: ${tab_bar_background};
|
||||
}
|
||||
QTabBar#appTabBar::tab {
|
||||
background: ${tab_background};
|
||||
color: ${secondary_text};
|
||||
padding: 8px 14px;
|
||||
margin-right: 2px;
|
||||
border-bottom: 2px solid transparent;
|
||||
}
|
||||
QTabBar#appTabBar::tab:selected {
|
||||
color: ${primary_text};
|
||||
border-bottom: 2px solid ${selection_background};
|
||||
}
|
||||
QTabBar#appTabBar::tab:hover {
|
||||
color: ${hover_text};
|
||||
}
|
||||
QFrame#ribbonBand {
|
||||
background: ${ribbon_background};
|
||||
border-top: 1px solid ${border};
|
||||
}
|
||||
QTabWidget#appTabWidget::pane {
|
||||
border: none;
|
||||
background: transparent;
|
||||
}
|
||||
QFrame#ribbonPage {
|
||||
background: transparent;
|
||||
}
|
||||
QFrame#ribbonGroup {
|
||||
background: transparent;
|
||||
border-right: 1px solid ${border};
|
||||
}
|
||||
QFrame#ribbonGroup[separator="false"] {
|
||||
border-right: none;
|
||||
}
|
||||
QLabel#ribbonGroupLabel {
|
||||
font-size: ${font_small}px;
|
||||
font-weight: 600;
|
||||
}
|
||||
QToolButton#ribbonButton {
|
||||
background: transparent;
|
||||
border: none;
|
||||
padding: 6px 4px 4px 4px;
|
||||
color: ${primary_text};
|
||||
}
|
||||
QToolButton#ribbonButton:hover {
|
||||
background: ${ribbon_button_hover};
|
||||
}
|
||||
QToolButton#ribbonButton:pressed {
|
||||
background: ${ribbon_button_pressed};
|
||||
}
|
||||
QFrame#viewportShell {
|
||||
background: ${viewport_shell_background};
|
||||
border-top: none;
|
||||
}
|
||||
QFrame#viewportFrame {
|
||||
border: 1px solid ${border};
|
||||
}
|
||||
QDockWidget {
|
||||
color: ${primary_text};
|
||||
}
|
||||
QLabel {
|
||||
color: ${primary_text};
|
||||
background: transparent;
|
||||
}
|
||||
QAbstractItemView,
|
||||
QTreeWidget,
|
||||
QListWidget,
|
||||
QTableWidget,
|
||||
QLineEdit,
|
||||
QComboBox,
|
||||
QSpinBox,
|
||||
QDoubleSpinBox,
|
||||
QCheckBox,
|
||||
QRadioButton,
|
||||
QPushButton,
|
||||
QToolButton {
|
||||
color: ${primary_text};
|
||||
}
|
||||
QLabel[textRole="secondary"] {
|
||||
color: ${secondary_text};
|
||||
}
|
||||
QLabel[textRole="disabled"] {
|
||||
color: ${disabled_text};
|
||||
}
|
||||
QLabel[textRole="warning"] {
|
||||
color: ${warning_text};
|
||||
}
|
||||
QLabel#panelTitleText {
|
||||
color: ${primary_text};
|
||||
font-size: ${font_small}px;
|
||||
font-weight: 600;
|
||||
}
|
||||
QToolButton#panelTitleButton {
|
||||
border: none;
|
||||
background: transparent;
|
||||
}
|
||||
QToolButton#panelTitleButton:hover {
|
||||
color: ${hover_text};
|
||||
background: ${ribbon_button_hover};
|
||||
}
|
||||
QFrame#panel {
|
||||
background: ${panel_background};
|
||||
border: 1px solid ${border};
|
||||
border-radius: ${panel_radius}px;
|
||||
}
|
||||
QTreeWidget, QListWidget, QTableWidget, QAbstractScrollArea {
|
||||
background: ${panel_background};
|
||||
border: none;
|
||||
outline: none;
|
||||
gridline-color: ${border};
|
||||
}
|
||||
QTableWidget#modelCoordinatesTable {
|
||||
font-size: ${font_small}px;
|
||||
}
|
||||
QTableWidget#modelCoordinatesTable QHeaderView::section {
|
||||
font-size: ${font_small}px;
|
||||
}
|
||||
QTreeWidget::viewport, QListWidget::viewport, QTableWidget::viewport {
|
||||
background: ${panel_background};
|
||||
}
|
||||
QHeaderView::section {
|
||||
background: ${control_background};
|
||||
color: ${primary_text};
|
||||
border: none;
|
||||
border-bottom: 1px solid ${border};
|
||||
padding: 7px 8px;
|
||||
font-weight: 600;
|
||||
}
|
||||
QTableCornerButton::section {
|
||||
background: ${control_background};
|
||||
border: none;
|
||||
}
|
||||
QScrollArea {
|
||||
background: ${panel_background};
|
||||
border: none;
|
||||
}
|
||||
QScrollArea > QWidget > QWidget {
|
||||
background: ${panel_background};
|
||||
}
|
||||
QLineEdit {
|
||||
background: ${control_background};
|
||||
border: 1px solid ${border};
|
||||
border-radius: ${panel_radius}px;
|
||||
padding: ${padding}px ${padding}px;
|
||||
color: ${primary_text};
|
||||
}
|
||||
QLineEdit:focus {
|
||||
border: 1px solid ${control_border_focus};
|
||||
}
|
||||
QComboBox {
|
||||
background: ${control_background};
|
||||
border: 1px solid ${border};
|
||||
border-radius: ${panel_radius}px;
|
||||
padding: ${padding}px 24px ${padding}px ${padding}px;
|
||||
}
|
||||
QComboBox:focus {
|
||||
border: 1px solid ${control_border_focus};
|
||||
}
|
||||
QComboBox::drop-down {
|
||||
subcontrol-origin: padding;
|
||||
subcontrol-position: top right;
|
||||
width: 18px;
|
||||
border: none;
|
||||
background: transparent;
|
||||
}
|
||||
QComboBox::down-arrow {
|
||||
width: 0px;
|
||||
height: 0px;
|
||||
border-left: 5px solid transparent;
|
||||
border-right: 5px solid transparent;
|
||||
border-top: 6px solid ${secondary_text};
|
||||
margin-right: 4px;
|
||||
}
|
||||
QComboBox QAbstractItemView {
|
||||
background: ${panel_background};
|
||||
border: 1px solid ${border};
|
||||
selection-background-color: ${selection_background};
|
||||
selection-color: ${selection_text};
|
||||
}
|
||||
QSpinBox, QDoubleSpinBox {
|
||||
background: ${control_background};
|
||||
border: 1px solid ${border};
|
||||
border-radius: ${panel_radius}px;
|
||||
padding: ${padding}px 24px ${padding}px ${padding}px;
|
||||
}
|
||||
QSpinBox:focus, QDoubleSpinBox:focus {
|
||||
border: 1px solid ${control_border_focus};
|
||||
}
|
||||
QSpinBox::up-button, QDoubleSpinBox::up-button,
|
||||
QSpinBox::down-button, QDoubleSpinBox::down-button {
|
||||
subcontrol-origin: padding;
|
||||
width: 18px;
|
||||
border: none;
|
||||
background: transparent;
|
||||
}
|
||||
QSpinBox::up-button, QDoubleSpinBox::up-button {
|
||||
subcontrol-position: top right;
|
||||
}
|
||||
QSpinBox::down-button, QDoubleSpinBox::down-button {
|
||||
subcontrol-position: bottom right;
|
||||
}
|
||||
QSpinBox::up-arrow, QDoubleSpinBox::up-arrow {
|
||||
width: 0px;
|
||||
height: 0px;
|
||||
border-left: 4px solid transparent;
|
||||
border-right: 4px solid transparent;
|
||||
border-bottom: 5px solid ${secondary_text};
|
||||
}
|
||||
QSpinBox::down-arrow, QDoubleSpinBox::down-arrow {
|
||||
width: 0px;
|
||||
height: 0px;
|
||||
border-left: 4px solid transparent;
|
||||
border-right: 4px solid transparent;
|
||||
border-top: 5px solid ${secondary_text};
|
||||
}
|
||||
QCheckBox {
|
||||
background: transparent;
|
||||
spacing: 8px;
|
||||
}
|
||||
QCheckBox::indicator {
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
border: 1px solid ${border};
|
||||
border-radius: ${panel_radius}px;
|
||||
background: ${control_background};
|
||||
}
|
||||
QCheckBox::indicator:hover {
|
||||
background: ${ribbon_button_hover};
|
||||
}
|
||||
QCheckBox::indicator:checked {
|
||||
border: 1px solid ${selection_background};
|
||||
background: ${selection_background};
|
||||
}
|
||||
QRadioButton {
|
||||
background: transparent;
|
||||
color: ${primary_text};
|
||||
spacing: 8px;
|
||||
padding: 2px 0;
|
||||
}
|
||||
QRadioButton::indicator {
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
border: 1px solid ${border};
|
||||
border-radius: 8px;
|
||||
background: ${control_background};
|
||||
}
|
||||
QRadioButton::indicator:hover {
|
||||
background: ${ribbon_button_hover};
|
||||
}
|
||||
QRadioButton::indicator:checked {
|
||||
border: 1px solid ${selection_background};
|
||||
background: ${selection_background};
|
||||
}
|
||||
QRadioButton::indicator:unchecked {
|
||||
background: ${control_background};
|
||||
}
|
||||
QPushButton {
|
||||
background: ${control_background};
|
||||
border: 1px solid ${border};
|
||||
border-radius: ${panel_radius}px;
|
||||
padding: ${padding}px ${padding}px;
|
||||
}
|
||||
QPushButton:hover {
|
||||
background: ${ribbon_button_hover};
|
||||
}
|
||||
QPushButton:pressed {
|
||||
background: ${ribbon_button_pressed};
|
||||
}
|
||||
QMenu {
|
||||
background: ${panel_background};
|
||||
color: ${primary_text};
|
||||
border: 1px solid ${border};
|
||||
padding: 4px;
|
||||
}
|
||||
QMenu::item {
|
||||
background: transparent;
|
||||
color: ${primary_text};
|
||||
padding: 6px 24px 6px 10px;
|
||||
border-radius: ${panel_radius}px;
|
||||
}
|
||||
QMenu::item:selected {
|
||||
background: ${selection_background};
|
||||
color: ${selection_text};
|
||||
}
|
||||
QMenu::item:disabled {
|
||||
color: ${disabled_text};
|
||||
}
|
||||
QMenu::separator {
|
||||
height: 1px;
|
||||
background: ${border};
|
||||
margin: 4px 8px;
|
||||
}
|
||||
QMenu::icon {
|
||||
padding-left: 2px;
|
||||
}
|
||||
QFrame#entityClassBox,
|
||||
QGroupBox#propertySetBox {
|
||||
background: ${box_background};
|
||||
border: 1px solid ${border};
|
||||
border-radius: ${panel_radius}px;
|
||||
}
|
||||
QLabel#entityClassLabel {
|
||||
color: ${primary_text};
|
||||
font-weight: 700;
|
||||
background: transparent;
|
||||
}
|
||||
QWidget#keyValueTable {
|
||||
background: transparent;
|
||||
}
|
||||
QTreeView::item, QListView::item, QTableView::item {
|
||||
padding: 4px;
|
||||
}
|
||||
QScrollBar:vertical {
|
||||
background: transparent;
|
||||
width: 10px;
|
||||
margin: 2px 2px 2px 0;
|
||||
}
|
||||
QScrollBar:horizontal {
|
||||
background: transparent;
|
||||
height: 10px;
|
||||
margin: 0 2px 2px 2px;
|
||||
}
|
||||
QScrollBar::handle:vertical, QScrollBar::handle:horizontal {
|
||||
background: ${scroll_handle};
|
||||
border-radius: ${panel_radius}px;
|
||||
min-height: 24px;
|
||||
min-width: 24px;
|
||||
}
|
||||
QScrollBar::handle:vertical:hover, QScrollBar::handle:horizontal:hover {
|
||||
background: ${scroll_handle_hover};
|
||||
}
|
||||
QScrollBar::add-line, QScrollBar::sub-line,
|
||||
QScrollBar::add-page, QScrollBar::sub-page {
|
||||
background: transparent;
|
||||
border: none;
|
||||
}
|
||||
QStatusBar {
|
||||
background: ${status_background};
|
||||
}
|
||||
QStatusBar QLabel {
|
||||
color: ${secondary_text};
|
||||
background: transparent;
|
||||
border: none;
|
||||
padding: 2px 8px;
|
||||
}
|
||||
QGroupBox {
|
||||
background: transparent;
|
||||
border: 1px solid ${border};
|
||||
border-radius: ${panel_radius}px;
|
||||
margin-top: 10px;
|
||||
padding-top: 10px;
|
||||
}
|
||||
QGroupBox#propertySetBox::title {
|
||||
subcontrol-origin: margin;
|
||||
left: ${padding}px;
|
||||
padding: 0 4px;
|
||||
color: ${primary_text};
|
||||
}
|
||||
QGroupBox#propertySetBox > QWidget {
|
||||
background: ${box_background};
|
||||
}
|
||||
QWidget#panelSection {
|
||||
background: transparent;
|
||||
}
|
||||
QWidget#panelSectionFilterWrapper {
|
||||
background: transparent;
|
||||
}
|
||||
QLabel#keyValueTrailingIconLabel {
|
||||
background: transparent;
|
||||
}
|
||||
QWidget#panelScrollBody {
|
||||
background: ${panel_background};
|
||||
}
|
||||
QFrame#panelSectionHeader {
|
||||
background: ${section_header_background};
|
||||
}
|
||||
QToolButton#panelSectionHeaderButton {
|
||||
background: transparent;
|
||||
border: none;
|
||||
color: ${primary_text};
|
||||
font-weight: 700;
|
||||
text-align: left;
|
||||
padding: ${section_header_padding}px;
|
||||
margin: 0;
|
||||
}
|
||||
QToolButton#panelSectionHeaderButton:hover {
|
||||
color: ${hover_text};
|
||||
}
|
||||
QToolButton#panelSectionHeaderButton::menu-indicator {
|
||||
image: none;
|
||||
width: 0;
|
||||
}
|
||||
QToolButton#panelSectionFilterToggle {
|
||||
background: transparent;
|
||||
border: none;
|
||||
padding: ${section_header_padding}px;
|
||||
}
|
||||
QToolButton#panelSectionFilterToggle:hover {
|
||||
background: ${ribbon_button_hover};
|
||||
}
|
||||
QWidget#panelSectionBody {
|
||||
background: transparent;
|
||||
}
|
||||
QLabel#keyValueValueLabel {
|
||||
color: ${primary_text};
|
||||
background: transparent;
|
||||
}
|
||||
)");
|
||||
|
||||
stylesheet.replace("${panel_radius}", QString::number(metrics::panel_radius));
|
||||
stylesheet.replace("${padding}", QString::number(metrics::padding));
|
||||
stylesheet.replace("${section_header_padding}", QString::number(metrics::section_header_padding));
|
||||
stylesheet.replace("${font_small}", QString::number(typography::small));
|
||||
|
||||
stylesheet.replace("${app_background}", theme.color("app_background"));
|
||||
stylesheet.replace("${border}", theme.color("border"));
|
||||
stylesheet.replace("${selection_background}", theme.color("selection_background"));
|
||||
stylesheet.replace("${selection_text}", theme.color("selection_text"));
|
||||
stylesheet.replace("${tab_bar_background}", theme.color("tab_bar_background"));
|
||||
stylesheet.replace("${tab_background}", theme.color("tab_background"));
|
||||
stylesheet.replace("${hover_text}", theme.color("hover_text"));
|
||||
stylesheet.replace("${ribbon_background}", theme.color("ribbon_background"));
|
||||
stylesheet.replace("${ribbon_button_hover}", theme.color("ribbon_button_hover"));
|
||||
stylesheet.replace("${ribbon_button_pressed}", theme.color("ribbon_button_pressed"));
|
||||
stylesheet.replace("${viewport_shell_background}", theme.color("viewport_shell_background"));
|
||||
stylesheet.replace("${viewport_background}", theme.color("viewport_background"));
|
||||
stylesheet.replace("${panel_background}", theme.color("panel_background"));
|
||||
stylesheet.replace("${control_background}", theme.color("control_background"));
|
||||
stylesheet.replace("${control_border_focus}", theme.color("control_border_focus"));
|
||||
stylesheet.replace("${box_background}", theme.color("box_background"));
|
||||
stylesheet.replace("${scroll_handle}", theme.color("scroll_handle"));
|
||||
stylesheet.replace("${scroll_handle_hover}", theme.color("scroll_handle_hover"));
|
||||
stylesheet.replace("${status_background}", theme.color("status_background"));
|
||||
stylesheet.replace("${section_header_background}", theme.color("section_header_background"));
|
||||
|
||||
stylesheet.replace("${primary_text}", theme.color("primary_text"));
|
||||
stylesheet.replace("${secondary_text}", theme.color("secondary_text"));
|
||||
stylesheet.replace("${disabled_text}", theme.color("disabled_text"));
|
||||
stylesheet.replace("${warning_text}", theme.color("warning_text"));
|
||||
|
||||
return stylesheet;
|
||||
}
|
||||
|
||||
} // namespace bonsaiviewer::components::style
|
||||
@@ -0,0 +1,77 @@
|
||||
// This file was generated with the assistance of an AI coding tool.
|
||||
/********************************************************************************
|
||||
* *
|
||||
* This file is part of IfcOpenShell. *
|
||||
* *
|
||||
* IfcOpenShell is free software: you can redistribute it and/or modify *
|
||||
* it under the terms of the Lesser GNU General Public License as published by *
|
||||
* the Free Software Foundation, either version 3.0 of the License, or *
|
||||
* (at your option) any later version. *
|
||||
* *
|
||||
* IfcOpenShell 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 *
|
||||
* Lesser GNU General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the Lesser GNU General Public License *
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
|
||||
* *
|
||||
********************************************************************************/
|
||||
|
||||
#ifndef IFCINTERFACE_COMPONENTS_STYLE_H
|
||||
#define IFCINTERFACE_COMPONENTS_STYLE_H
|
||||
|
||||
#include <QString>
|
||||
|
||||
namespace bonsaiviewer::components::style::metrics {
|
||||
|
||||
inline constexpr int padding = 6;
|
||||
inline constexpr int section_body_padding = 10;
|
||||
inline constexpr int section_header_padding = 2;
|
||||
inline constexpr int panel_radius = 3;
|
||||
|
||||
} // namespace bonsaiviewer::components::style::metrics
|
||||
|
||||
namespace bonsaiviewer::components::style::typography {
|
||||
|
||||
inline constexpr int small = 10;
|
||||
|
||||
} // namespace bonsaiviewer::components::style::typography
|
||||
|
||||
namespace bonsaiviewer::components::style::palette {
|
||||
|
||||
inline constexpr auto app_background = "#26292f";
|
||||
inline constexpr auto border = "#3e444e";
|
||||
inline constexpr auto selection_background = "#39b54a";
|
||||
inline constexpr auto tab_bar_background = "#26292f";
|
||||
inline constexpr auto tab_background = "#31353d";
|
||||
inline constexpr auto ribbon_background = "#31353d";
|
||||
inline constexpr auto ribbon_button_hover = "#3a3f48";
|
||||
inline constexpr auto ribbon_button_pressed = "#24282f";
|
||||
inline constexpr auto viewport_shell_background = "#202329";
|
||||
inline constexpr auto viewport_background = "#2e3338";
|
||||
inline constexpr auto panel_background = "#2b2f36";
|
||||
inline constexpr auto control_background = "#31353d";
|
||||
inline constexpr auto control_border_focus = "#5b6472";
|
||||
inline constexpr auto box_background = "#26292f";
|
||||
inline constexpr auto scroll_handle = "#525a67";
|
||||
inline constexpr auto scroll_handle_hover = "#697385";
|
||||
inline constexpr auto status_background = "#26292f";
|
||||
inline constexpr auto section_header_background = "#26292f";
|
||||
|
||||
inline constexpr auto primary_text = "#d0d5dd";
|
||||
inline constexpr auto secondary_text = "#9aa4b3";
|
||||
inline constexpr auto disabled_text = "#8f98a6";
|
||||
inline constexpr auto warning_text = "#e4b35a";
|
||||
inline constexpr auto selection_text = "#14161a";
|
||||
inline constexpr auto hover_text = "#ffffff";
|
||||
|
||||
} // namespace bonsaiviewer::components::style::palette
|
||||
|
||||
namespace bonsaiviewer::components::style {
|
||||
|
||||
QString buildAppStyleSheet();
|
||||
|
||||
} // namespace bonsaiviewer::components::style
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,86 @@
|
||||
// This file was generated with the assistance of an AI coding tool.
|
||||
/********************************************************************************
|
||||
* *
|
||||
* This file is part of IfcOpenShell. *
|
||||
* *
|
||||
* IfcOpenShell is free software: you can redistribute it and/or modify *
|
||||
* it under the terms of the Lesser GNU General Public License as published by *
|
||||
* the Free Software Foundation, either version 3.0 of the License, or *
|
||||
* (at your option) any later version. *
|
||||
* *
|
||||
* IfcOpenShell 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 *
|
||||
* Lesser GNU General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the Lesser GNU General Public License *
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
|
||||
* *
|
||||
********************************************************************************/
|
||||
|
||||
#include "SvgIcon.h"
|
||||
|
||||
#include "../ViewerSettings.h"
|
||||
|
||||
#include <QFile>
|
||||
#include <QPainter>
|
||||
#include <QRegularExpression>
|
||||
#include <QSvgRenderer>
|
||||
|
||||
namespace bonsaiviewer::components::icons {
|
||||
|
||||
QPixmap renderTintedSvgPixmap(const QString& icon_path, const QString& color, const QSize& size) {
|
||||
QFile file(icon_path);
|
||||
if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
|
||||
return QIcon(icon_path).pixmap(size);
|
||||
}
|
||||
|
||||
QString svg = QString::fromUtf8(file.readAll());
|
||||
svg.replace("currentColor", color, Qt::CaseSensitive);
|
||||
svg.replace(QRegularExpression(R"(stroke="[^"]*")"), QString("stroke=\"%1\"").arg(color));
|
||||
svg.replace(QRegularExpression(R"(fill="none")"), "fill=\"none\"");
|
||||
|
||||
QSvgRenderer renderer(svg.toUtf8());
|
||||
QPixmap pixmap(size);
|
||||
pixmap.fill(Qt::transparent);
|
||||
QPainter painter(&pixmap);
|
||||
renderer.render(&painter);
|
||||
return pixmap;
|
||||
}
|
||||
|
||||
QIcon makeTintedSvgIcon(const QString& icon_path, const QString& normal,
|
||||
const QString& active, const QString& disabled) {
|
||||
QFile file(icon_path);
|
||||
if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
|
||||
return QIcon(icon_path);
|
||||
}
|
||||
|
||||
QIcon icon;
|
||||
icon.addPixmap(renderTintedSvgPixmap(icon_path, normal, QSize(20, 20)), QIcon::Normal, QIcon::Off);
|
||||
icon.addPixmap(renderTintedSvgPixmap(icon_path, active, QSize(20, 20)), QIcon::Active, QIcon::Off);
|
||||
icon.addPixmap(renderTintedSvgPixmap(icon_path, active, QSize(20, 20)), QIcon::Selected, QIcon::Off);
|
||||
icon.addPixmap(renderTintedSvgPixmap(icon_path, disabled, QSize(20, 20)), QIcon::Disabled, QIcon::Off);
|
||||
return icon;
|
||||
}
|
||||
|
||||
QIcon makeAccentSvgIcon(const QString& icon_path) {
|
||||
const auto& theme = bonsaiviewer::ViewerSettings::instance();
|
||||
return makeTintedSvgIcon(icon_path,
|
||||
theme.color("icon_accent_color"),
|
||||
theme.color("icon_accent_active_color"),
|
||||
theme.color("icon_disabled_color"));
|
||||
}
|
||||
|
||||
QIcon makeSvgIcon(const QString& icon_path) {
|
||||
const auto& theme = bonsaiviewer::ViewerSettings::instance();
|
||||
return makeTintedSvgIcon(icon_path,
|
||||
theme.color("icon_color"),
|
||||
theme.color("icon_active_color"),
|
||||
theme.color("icon_disabled_color"));
|
||||
}
|
||||
|
||||
QPixmap makeSvgPixmap(const QString& icon_path, const QSize& size) {
|
||||
return renderTintedSvgPixmap(icon_path, bonsaiviewer::ViewerSettings::instance().color("icon_color"), size);
|
||||
}
|
||||
|
||||
} // namespace bonsaiviewer::components::icons
|
||||
@@ -0,0 +1,42 @@
|
||||
// This file was generated with the assistance of an AI coding tool.
|
||||
/********************************************************************************
|
||||
* *
|
||||
* This file is part of IfcOpenShell. *
|
||||
* *
|
||||
* IfcOpenShell is free software: you can redistribute it and/or modify *
|
||||
* it under the terms of the Lesser GNU General Public License as published by *
|
||||
* the Free Software Foundation, either version 3.0 of the License, or *
|
||||
* (at your option) any later version. *
|
||||
* *
|
||||
* IfcOpenShell 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 *
|
||||
* Lesser GNU General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the Lesser GNU General Public License *
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
|
||||
* *
|
||||
********************************************************************************/
|
||||
|
||||
#ifndef IFCINTERFACE_COMPONENTS_ICONS_SVGICON_H
|
||||
#define IFCINTERFACE_COMPONENTS_ICONS_SVGICON_H
|
||||
|
||||
#include <QIcon>
|
||||
#include <QPixmap>
|
||||
#include <QString>
|
||||
#include <QSize>
|
||||
|
||||
namespace bonsaiviewer::components::icons {
|
||||
|
||||
QPixmap renderTintedSvgPixmap(const QString& icon_path, const QString& color, const QSize& size);
|
||||
QIcon makeTintedSvgIcon(const QString& icon_path,
|
||||
const QString& normal = "#39b54a",
|
||||
const QString& active = "#53c763",
|
||||
const QString& disabled = "#6f7988");
|
||||
QIcon makeAccentSvgIcon(const QString& icon_path);
|
||||
QIcon makeSvgIcon(const QString& icon_path);
|
||||
QPixmap makeSvgPixmap(const QString& icon_path, const QSize& size);
|
||||
|
||||
} // namespace bonsaiviewer::components::icons
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,40 @@
|
||||
// This file was generated with the assistance of an AI coding tool.
|
||||
/********************************************************************************
|
||||
* *
|
||||
* This file is part of IfcOpenShell. *
|
||||
* *
|
||||
* IfcOpenShell is free software: you can redistribute it and/or modify *
|
||||
* it under the terms of the Lesser GNU General Public License as published by *
|
||||
* the Free Software Foundation, either version 3.0 of the License, or *
|
||||
* (at your option) any later version. *
|
||||
* *
|
||||
* IfcOpenShell 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 *
|
||||
* Lesser GNU General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the Lesser GNU General Public License *
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
|
||||
* *
|
||||
********************************************************************************/
|
||||
|
||||
#include "Tabs.h"
|
||||
|
||||
namespace bonsaiviewer::components {
|
||||
|
||||
TabBar::TabBar(QWidget* parent)
|
||||
: QTabBar(parent)
|
||||
{
|
||||
setObjectName("appTabBar");
|
||||
setExpanding(false);
|
||||
setDrawBase(false);
|
||||
}
|
||||
|
||||
TabWidget::TabWidget(QWidget* parent)
|
||||
: QTabWidget(parent)
|
||||
{
|
||||
setObjectName("appTabWidget");
|
||||
setTabBar(new TabBar(this));
|
||||
}
|
||||
|
||||
} // namespace bonsaiviewer::components
|
||||
@@ -0,0 +1,45 @@
|
||||
// This file was generated with the assistance of an AI coding tool.
|
||||
/********************************************************************************
|
||||
* *
|
||||
* This file is part of IfcOpenShell. *
|
||||
* *
|
||||
* IfcOpenShell is free software: you can redistribute it and/or modify *
|
||||
* it under the terms of the Lesser GNU General Public License as published by *
|
||||
* the Free Software Foundation, either version 3.0 of the License, or *
|
||||
* (at your option) any later version. *
|
||||
* *
|
||||
* IfcOpenShell 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 *
|
||||
* Lesser GNU General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the Lesser GNU General Public License *
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
|
||||
* *
|
||||
********************************************************************************/
|
||||
|
||||
#ifndef IFCINTERFACE_COMPONENTS_TABS_H
|
||||
#define IFCINTERFACE_COMPONENTS_TABS_H
|
||||
|
||||
#include <QTabBar>
|
||||
#include <QTabWidget>
|
||||
|
||||
namespace bonsaiviewer::components {
|
||||
|
||||
class TabBar : public QTabBar {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit TabBar(QWidget* parent = nullptr);
|
||||
};
|
||||
|
||||
class TabWidget : public QTabWidget {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit TabWidget(QWidget* parent = nullptr);
|
||||
};
|
||||
|
||||
} // namespace bonsaiviewer::components
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user