[editor] style接入新的UI实现 | #10

dev-wuyize
ArgonarioD 2023-03-22 00:09:44 +08:00
parent 3edca0287b
commit 2e7d20d0d7
18 changed files with 452 additions and 259 deletions

View File

@ -104,6 +104,7 @@
</Link> </Link>
</ItemDefinitionGroup> </ItemDefinitionGroup>
<ItemGroup> <ItemGroup>
<ClCompile Include="src\Editor\EditorWidgetComponent\LayerContainerListWidget.cpp" />
<ClCompile Include="src\Editor\DataManager\ProjectDataManager.cpp" /> <ClCompile Include="src\Editor\DataManager\ProjectDataManager.cpp" />
<ClCompile Include="src\Editor\EditorWidgetComponent\FillStyleWidget.cpp" /> <ClCompile Include="src\Editor\EditorWidgetComponent\FillStyleWidget.cpp" />
<ClCompile Include="src\Editor\RightBar\EditorSettingWidget.cpp" /> <ClCompile Include="src\Editor\RightBar\EditorSettingWidget.cpp" />
@ -205,6 +206,7 @@
<QtMoc Include="src\Editor\EditorWidgetComponent\ColorPicker.h" /> <QtMoc Include="src\Editor\EditorWidgetComponent\ColorPicker.h" />
<QtMoc Include="src\Editor\RightBar\EditorSettingWidget.h" /> <QtMoc Include="src\Editor\RightBar\EditorSettingWidget.h" />
<QtMoc Include="src\Editor\EditorWidgetComponent\FillStyleWidget.h" /> <QtMoc Include="src\Editor\EditorWidgetComponent\FillStyleWidget.h" />
<QtMoc Include="src\Editor\EditorWidgetComponent\LayerContainerListWidget.h" />
<ClInclude Include="src\Editor\DataManager\ProjectDataManager.h" /> <ClInclude Include="src\Editor\DataManager\ProjectDataManager.h" />
<ClInclude Include="src\ColorHelper.hpp" /> <ClInclude Include="src\ColorHelper.hpp" />
<ClInclude Include="src\Editor\LayerWrapper.h" /> <ClInclude Include="src\Editor\LayerWrapper.h" />

View File

@ -267,6 +267,9 @@
<ClCompile Include="src\FluentMenuButton.cpp"> <ClCompile Include="src\FluentMenuButton.cpp">
<Filter>Source Files</Filter> <Filter>Source Files</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="src\Editor\EditorWidgetComponent\LayerContainerListWidget.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<QtMoc Include="src\Renderer\RendererGLWidget.h"> <QtMoc Include="src\Renderer\RendererGLWidget.h">
@ -323,6 +326,9 @@
<QtMoc Include="src\Editor\EditorWidgetComponent\FillStyleWidget.h"> <QtMoc Include="src\Editor\EditorWidgetComponent\FillStyleWidget.h">
<Filter>Header Files</Filter> <Filter>Header Files</Filter>
</QtMoc> </QtMoc>
<QtMoc Include="src\Editor\EditorWidgetComponent\LayerContainerListWidget.h">
<Filter>Header Files</Filter>
</QtMoc>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<None Include="..\data.json" /> <None Include="..\data.json" />

View File

@ -71,7 +71,7 @@
</widget> </widget>
</item> </item>
<item row="5" column="0" colspan="2"> <item row="5" column="0" colspan="2">
<widget class="QListWidget" name="styleList"/> <widget class="LayerContainerListWidget" name="styleList"/>
</item> </item>
</layout> </layout>
</widget> </widget>
@ -86,6 +86,11 @@
<extends>QCheckBox</extends> <extends>QCheckBox</extends>
<header location="global">qtmaterialcheckbox.h</header> <header location="global">qtmaterialcheckbox.h</header>
</customwidget> </customwidget>
<customwidget>
<class>LayerContainerListWidget</class>
<extends>QListWidget</extends>
<header location="global">EditorWidgetComponent/LayerContainerListWidget.h</header>
</customwidget>
</customwidgets> </customwidgets>
<resources/> <resources/>
<connections/> <connections/>

View File

@ -41,7 +41,7 @@
<number>0</number> <number>0</number>
</property> </property>
<item> <item>
<layout class="QHBoxLayout" name="horizontalLayout_2" stretch="1,1,1,1,1,0"> <layout class="QHBoxLayout" name="horizontalLayout_2" stretch="1,1,0">
<property name="spacing"> <property name="spacing">
<number>0</number> <number>0</number>
</property> </property>
@ -49,7 +49,7 @@
<number>0</number> <number>0</number>
</property> </property>
<item> <item>
<widget class="QPushButton" name="createButton"> <widget class="FluentMenuButton" name="fileMenuButton">
<property name="minimumSize"> <property name="minimumSize">
<size> <size>
<width>80</width> <width>80</width>
@ -63,12 +63,12 @@
</size> </size>
</property> </property>
<property name="text"> <property name="text">
<string>新建</string> <string>文件</string>
</property> </property>
</widget> </widget>
</item> </item>
<item> <item>
<widget class="QPushButton" name="openButton"> <widget class="FluentMenuButton" name="projectMenuButton">
<property name="minimumSize"> <property name="minimumSize">
<size> <size>
<width>80</width> <width>80</width>
@ -82,70 +82,7 @@
</size> </size>
</property> </property>
<property name="text"> <property name="text">
<string>打开</string> <string>项目</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="saveButton">
<property name="minimumSize">
<size>
<width>80</width>
<height>40</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>80</width>
<height>16777215</height>
</size>
</property>
<property name="text">
<string>保存</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="saveAsButton">
<property name="minimumSize">
<size>
<width>80</width>
<height>40</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>80</width>
<height>16777215</height>
</size>
</property>
<property name="text">
<string>另存为</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="closeButton">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>80</width>
<height>40</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>80</width>
<height>16777215</height>
</size>
</property>
<property name="text">
<string>关闭</string>
</property> </property>
</widget> </widget>
</item> </item>
@ -178,6 +115,9 @@
<property name="currentIndex"> <property name="currentIndex">
<number>0</number> <number>0</number>
</property> </property>
<property name="tabsClosable">
<bool>true</bool>
</property>
<widget class="QWidget" name="tab"> <widget class="QWidget" name="tab">
<attribute name="title"> <attribute name="title">
<string>Tab 1</string> <string>Tab 1</string>
@ -194,6 +134,13 @@
</item> </item>
</layout> </layout>
</widget> </widget>
<customwidgets>
<customwidget>
<class>FluentMenuButton</class>
<extends>QPushButton</extends>
<header location="global">../FluentMenuButton.h</header>
</customwidget>
</customwidgets>
<resources/> <resources/>
<connections/> <connections/>
</ui> </ui>

View File

@ -39,7 +39,7 @@
<widget class="QWidget" name="MainWindow" native="true"> <widget class="QWidget" name="MainWindow" native="true">
<layout class="QVBoxLayout" name="verticalLayout_2" stretch="20,1"> <layout class="QVBoxLayout" name="verticalLayout_2" stretch="20,1">
<item> <item>
<layout class="QHBoxLayout" name="horizontalLayout" stretch="0,12,5"> <layout class="QHBoxLayout" name="horizontalLayout" stretch="0,7,4,3">
<item> <item>
<widget class="QWidget" name="LeftBar" native="true"/> <widget class="QWidget" name="LeftBar" native="true"/>
</item> </item>
@ -147,18 +147,13 @@
</size> </size>
</property> </property>
<property name="currentIndex"> <property name="currentIndex">
<number>2</number> <number>0</number>
</property> </property>
<widget class="InfoDisplayWidget" name="LayerDisplay"> <widget class="InfoDisplayWidget" name="LayerDisplay">
<attribute name="title"> <attribute name="title">
<string>图层信息</string> <string>图层信息</string>
</attribute> </attribute>
</widget> </widget>
<widget class="ElementPoolWidget" name="ElementDisplay">
<attribute name="title">
<string>图元池</string>
</attribute>
</widget>
<widget class="EditorSettingWidget" name="EditorSetting"> <widget class="EditorSettingWidget" name="EditorSetting">
<attribute name="title"> <attribute name="title">
<string>设置</string> <string>设置</string>
@ -201,6 +196,23 @@
</layout> </layout>
</widget> </widget>
</item> </item>
<item>
<layout class="QVBoxLayout" name="ElementBar">
<item>
<widget class="QLabel" name="ElementDisplayLabel">
<property name="text">
<string>图元</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
<item>
<widget class="ElementPoolWidget" name="ElementDisplay" native="true"/>
</item>
</layout>
</item>
</layout> </layout>
</item> </item>
<item> <item>

View File

@ -8,42 +8,25 @@
EditorWidget::EditorWidget(QWidget* parent) : QWidget(parent) EditorWidget::EditorWidget(QWidget* parent) : QWidget(parent)
{ {
ui.setupUi(this); ui.setupUi(this);
this->createButton = ui.createButton; this->fileMenuButton = ui.fileMenuButton;
this->closeButton = ui.closeButton; this->projectMenuButton = ui.projectMenuButton;
this->saveButton = ui.saveButton;
this->saveAsButton = ui.saveAsButton;
this->openButton = ui.openButton;
this->tabWidget = ui.tabWidget; this->tabWidget = ui.tabWidget;
while (this->tabWidget->count() > 0) while (this->tabWidget->count() > 0)
{ {
this->tabWidget->removeTab(0); this->tabWidget->removeTab(0);
} }
connect(this->createButton, &QPushButton::clicked, this, [this]() {
static int count = 0; connect(this, &EditorWidget::tabCountChanged, this, &EditorWidget::onTabCountChanged);
this->tabWidget->addTab(new EditorWidgetItem("../data.json",this), "untitled" + QString::number(count++));
}); initFileMenu();
connect(this->openButton, &QPushButton::clicked, this, [this]() { initProjectMenu();
QString fileName = QFileDialog::getOpenFileName(this->saveAsButton, QString::fromLocal8Bit("´ò¿ª"), "", QString::fromLocal8Bit("JSONÎļþ(*.json)"));
if(!fileName.isEmpty()) connect(this->tabWidget, &QTabWidget::tabCloseRequested, [this](int index) {
this->tabWidget->addTab(new EditorWidgetItem(fileName, this), fileName); const int prevCount = this->tabWidget->count();
}); this->tabWidget->removeTab(index);
connect(this->closeButton, &QPushButton::clicked, this, [this]() { const int nowCount = this->tabWidget->count();
this->tabWidget->removeTab(this->tabWidget->currentIndex());
}); emit tabCountChanged(prevCount, nowCount);
connect(this->saveButton, &QPushButton::clicked, this, [this]() {
EditorWidgetItem* item = dynamic_cast<EditorWidgetItem*>(this->tabWidget->currentWidget());
if (item != nullptr)
{
//item->save();
}
});
connect(this->saveAsButton, &QPushButton::clicked, this, [this]() {
EditorWidgetItem* item = dynamic_cast<EditorWidgetItem*>(this->tabWidget->currentWidget());
if (item != nullptr)
{
QString fileName = QFileDialog::getSaveFileName(this->saveAsButton, QString::fromLocal8Bit("Áí´æΪ"), "", QString::fromLocal8Bit("JSONÎļþ(*.json)"));
item->saveAs(fileName);
}
}); });
} }
@ -55,3 +38,72 @@ void EditorWidget::renameTab(QWidget* target, QString name)
this->tabWidget->setTabText(index, name); this->tabWidget->setTabText(index, name);
} }
} }
void EditorWidget::onTabCountChanged(int prev, int now)
{
if (now != 0)
{
this->projectMenuButton->setDisabled(false);
}
else
{
this->projectMenuButton->setDisabled(true);
}
}
void EditorWidget::initFileMenu()
{
auto* actionCreate = new QAction(QStringLiteral("新建"), fileMenuButton);
auto* actionOpen = new QAction(QStringLiteral("打开"), fileMenuButton);
auto* actionSave = new QAction(QStringLiteral("保存"), fileMenuButton);
auto* actionSaveAs = new QAction(QStringLiteral("另存为"), fileMenuButton);
fileMenuButton->addMenuAction(actionCreate);
fileMenuButton->addMenuAction(actionOpen);
fileMenuButton->addMenuAction(actionSave);
fileMenuButton->addMenuAction(actionSaveAs);
connect(actionCreate, &QAction::triggered, [this] {
static int count = 0;
const int prevCount = this->tabWidget->count();
this->tabWidget->addTab(new EditorWidgetItem("../data.json", this), "untitled" + QString::number(count++));
const int nowCount = this->tabWidget->count();
emit tabCountChanged(prevCount, nowCount);
});
connect(actionOpen, &QAction::triggered, this, [this] {
const QString fileName = QFileDialog::getOpenFileName(this, QStringLiteral("打开"), "", QStringLiteral("JSON文件(*.json)"));
if (!fileName.isEmpty())
{
const int prevCount = this->tabWidget->count();
this->tabWidget->addTab(new EditorWidgetItem(fileName, this), fileName);
const int nowCount = this->tabWidget->count();
emit tabCountChanged(prevCount, nowCount);
}
});
connect(actionSave, &QAction::triggered, this, [this] {
auto* item = dynamic_cast<EditorWidgetItem*>(this->tabWidget->currentWidget());
if (item != nullptr)
{
//item->save();
}
});
connect(actionSaveAs, &QAction::triggered, this, [this] {
const auto* item = dynamic_cast<EditorWidgetItem*>(this->tabWidget->currentWidget());
if (item != nullptr)
{
const QString fileName = QFileDialog::getSaveFileName(this, QStringLiteral("另存为"), "", QStringLiteral("JSON文件(*.json)"));
item->saveAs(fileName);
}
});
}
void EditorWidget::initProjectMenu()
{
if (tabWidget->count() == 0)
{
projectMenuButton->setDisabled(true);
}
auto* actionSettings = new QAction(QStringLiteral("项目设置"), projectMenuButton);
projectMenuButton->addMenuAction(actionSettings);
}

View File

@ -1,5 +1,6 @@
#pragma once #pragma once
#include <qwidget.h> #include <qwidget.h>
#include "../FluentMenuButton.h"
#include "ui_EditorWidget.h" #include "ui_EditorWidget.h"
class EditorWidget : class EditorWidget :
@ -9,15 +10,21 @@ class EditorWidget :
private: private:
Ui::EditorWidget ui; Ui::EditorWidget ui;
QTabWidget* tabWidget; QTabWidget* tabWidget;
QPushButton* createButton; FluentMenuButton* fileMenuButton;
QPushButton* closeButton; FluentMenuButton* projectMenuButton;
QPushButton* saveButton;
QPushButton* saveAsButton; void initFileMenu();
QPushButton* openButton; void initProjectMenu();
public: public:
EditorWidget(QWidget* parent = nullptr); EditorWidget(QWidget* parent = nullptr);
~EditorWidget()=default; ~EditorWidget()=default;
void renameTab(QWidget* target, QString name); void renameTab(QWidget* target, QString name);
protected slots:
void onTabCountChanged(int prev, int now);
signals:
void tabCountChanged(int prev, int now);
}; };

View File

@ -0,0 +1,178 @@
#include "LayerContainerListWidget.h"
#include "LayerStyleDialog.h"
#include <QLabel>
#include <ranges>
LayerContainerListWidget::LayerContainerListWidget(QWidget* parent, const PLayerStyleContainer& styleContainer)
: QListWidget(parent), styleContainer(styleContainer)
{
connect(this, &LayerContainerListWidget::addLayerStyle,
this, &LayerContainerListWidget::onAddLayerStyle);
connect(this, &LayerContainerListWidget::removeLayerStyle,
this, &LayerContainerListWidget::onRemoveLayerStyle);
initHeader();
setStyleContainer(styleContainer, true);
}
bool comparePStyleContainersEquality(const LayerStyleContainer* a, const LayerStyleContainer* b)
{
if (a == nullptr && b == nullptr)
{
return true;
}
if (a == nullptr || b == nullptr)
{
return false;
}
return a == b || *a == *b;
}
void LayerContainerListWidget::setStyleContainer(const PLayerStyleContainer& styleContainer, bool forceRefresh)
{
if (!forceRefresh && comparePStyleContainersEquality(this->styleContainer, styleContainer))
{
return;
}
const int count = this->count();
for (int i = 1; i < count; i++)
{
const auto* item = this->takeItem(1);
delete item;
}
if (!styleContainer)
{
return;
}
this->styleContainer = styleContainer;
for (auto& style : *styleContainer | std::views::values)
{
auto* item = new QListWidgetItem(this);
item->setSizeHint(QSize(50, 40));
this->setItemWidget(item, buildStyleListWidget(style));
}
resetAddButton();
}
LayerContainerListWidget::PLayerStyleContainer LayerContainerListWidget::getStyleContainer() const
{
return styleContainer;
}
void LayerContainerListWidget::resetAddButton()
{
if (!styleContainer)
{
return;
}
qDebug() << "resetAddButton" << styleContainer->full();
addButton->setDisabled(styleContainer->full());
}
void LayerContainerListWidget::onAddLayerStyle(const std::shared_ptr<LayerStyle>& style)
{
if (const bool ok = styleContainer->useStyle(style))
{
styleContainer->computeNewHash();
resetAddButton();
auto* newItem = new QListWidgetItem(this);
styleItemMap[style->getDisplayName()] = newItem;
newItem->setSizeHint(QSize(50, 40));
this->setItemWidget(newItem, buildStyleListWidget(style));
}
}
void LayerContainerListWidget::onRemoveLayerStyle(const QString& styleName)
{
if (const bool ok = styleContainer->dropStyle(styleName))
{
styleContainer->computeNewHash();
auto* removedItem = styleItemMap.extract(styleName).mapped();
resetAddButton();
delete this->takeItem(this->row(removedItem));
}
}
void LayerContainerListWidget::initHeader()
{
this->headerWidget = new QWidget(this);
auto* headerLayout = new QHBoxLayout;
auto* headerLabel = new QLabel(headerWidget);
headerLabel->setText(QStringLiteral("ÑùʽÁбí"));
headerLabel->setSizePolicy(QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding));
//auto* addStyleButton = new QtMaterialRaisedButton("+", headerWidget);
this->addButton = new QPushButton("+", headerWidget);
addButton->setFixedSize(QSize(20, 20));
connect(addButton, &QPushButton::clicked, [this] {
auto* dialog = new LayerStyleDialog(this->styleContainer, nullptr, this);
dialog->exec();
if (dialog->layerStyle)
{
emit addLayerStyle(dialog->layerStyle);
}
});
headerLayout->addWidget(headerLabel);
headerLayout->addWidget(addButton);
headerLayout->setContentsMargins(5, 0, 5, 0);
headerWidget->setLayout(headerLayout);
auto* headerItem = new QListWidgetItem(this);
headerItem->setFlags(Qt::NoItemFlags);
this->addItem(headerItem);
this->setItemWidget(headerItem, headerWidget);
}
QWidget* LayerContainerListWidget::buildStyleListWidget(std::shared_ptr<LayerStyle> style)
{
auto* w = new QWidget(this);
auto* layout = new QHBoxLayout;
layout->setAlignment(Qt::AlignmentFlag::AlignRight);
//QtMaterialFlatButton* detailButton = new QtMaterialFlatButton(w);
//QtMaterialFlatButton* removeButton = new QtMaterialFlatButton(w);
auto* detailButton = new QPushButton(w);
auto* removeButton = new QPushButton(w);
detailButton->setText("...");
detailButton->setFixedSize(QSize(20, 20));
removeButton->setText(QStringLiteral("¡Á"));
removeButton->setFixedSize(QSize(20, 20));
const QString styleDisplayName = style->getDisplayName();
connect(detailButton, &QPushButton::clicked,
[this, styleDisplayName]
{
const auto targetStyle = this->styleContainer->getStyle(styleDisplayName);
auto* dialog = new LayerStyleDialog(this->styleContainer, targetStyle, this);
dialog->exec();
if (dialog->layerStyle)
{
this->styleContainer->overrideStyle(dialog->layerStyle);
this->styleContainer->computeNewHash();
emit editLayerStyle(targetStyle);
}
});
connect(removeButton, &QPushButton::clicked,
[this, styleDisplayName]
{
emit removeLayerStyle(styleDisplayName);
});
QWidget* styleDisplayWidget = style->getListDisplayWidget();
styleDisplayWidget->setParent(w);
styleDisplayWidget->setSizePolicy(QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding));
layout->addWidget(styleDisplayWidget);
layout->addWidget(detailButton);
layout->addWidget(removeButton);
w->setLayout(layout);
return w;
}

View File

@ -0,0 +1,35 @@
#pragma once
#include <map>
#include <QListWidget>
#include <qtmaterialraisedbutton.h>
#include "LayerStyle.h"
class LayerContainerListWidget : public QListWidget
{
Q_OBJECT
using PLayerStyleContainer = LayerStyleContainer*;
private:
QWidget* headerWidget;
QPushButton* addButton;
PLayerStyleContainer styleContainer;
std::map<QString, QListWidgetItem*> styleItemMap;
void initHeader();
void resetAddButton();
QWidget* buildStyleListWidget(std::shared_ptr<LayerStyle> style);
public:
LayerContainerListWidget(QWidget* parent = nullptr, const PLayerStyleContainer& styleContainer = nullptr);
void setStyleContainer(const PLayerStyleContainer& styleContainer, bool forceRefresh = false);
PLayerStyleContainer getStyleContainer() const;
protected slots:
void onAddLayerStyle(const std::shared_ptr<LayerStyle>& style);
void onRemoveLayerStyle(const QString& styleName);
signals:
void addLayerStyle(const std::shared_ptr<LayerStyle>& style);
void editLayerStyle(const std::shared_ptr<LayerStyle>& style);
void removeLayerStyle(const QString& styleName);
};

View File

@ -4,10 +4,10 @@
#include <QGridLayout> #include <QGridLayout>
LayerStyleDialog::LayerStyleDialog( LayerStyleDialog::LayerStyleDialog(
LayerStyleContainer& styles, LayerStyleContainer* pStyles,
const std::shared_ptr<LayerStyle>& existedStyle, const std::shared_ptr<LayerStyle>& existedStyle,
QWidget* parent QWidget* parent
) : QDialog(parent), styles(&styles) ) : QDialog(parent), styles(pStyles)
{ {
dialogLayout = new QGridLayout; dialogLayout = new QGridLayout;
dialogLayout->setAlignment(Qt::AlignmentFlag::AlignHCenter); dialogLayout->setAlignment(Qt::AlignmentFlag::AlignHCenter);
@ -23,13 +23,13 @@ LayerStyleDialog::LayerStyleDialog(
} }
else else
{ {
QStringList unusedStyleNames = styles.unusedStyleNames(); QStringList unusedStyleNames = styles->unusedStyleNames();
auto* typeSelector = new QComboBox(this); auto* typeSelector = new QComboBox(this);
if (!unusedStyleNames.empty()) if (!unusedStyleNames.empty())
{ {
typeSelector->addItems(unusedStyleNames); typeSelector->addItems(unusedStyleNames);
this->modifyingStyle = std::move(styles.makeUnusedStyle(unusedStyleNames[0])); this->modifyingStyle = std::move(styles->makeUnusedStyle(unusedStyleNames[0]));
dialogLayout->addWidget(typeSelector, 0, 0); dialogLayout->addWidget(typeSelector, 0, 0);

View File

@ -13,7 +13,7 @@ private:
std::unique_ptr<LayerStyle> modifyingStyle; std::unique_ptr<LayerStyle> modifyingStyle;
public: public:
LayerStyleDialog( LayerStyleDialog(
LayerStyleContainer& styles, LayerStyleContainer* pStyles,
const std::shared_ptr<LayerStyle>& existedStyle = nullptr, const std::shared_ptr<LayerStyle>& existedStyle = nullptr,
QWidget* parent = nullptr QWidget* parent = nullptr
); );

View File

@ -1,108 +0,0 @@
#include "StrokeStyleListView.h"
#include "ColorPicker.h"
#include <qtmaterialraisedbutton.h>
constexpr int COLUMN_WIDTH = 0;
constexpr int COLUMN_COLOR = 1;
constexpr int COLUMN_METALLIC = 2;
constexpr int COLUMN_ROUGHNESS = 3;
constexpr int COLUMN_OPERATIONS = 4;
// TODO: 将这个类改为继承QWidget把table转为其中的一个元素加上新增行按钮和宽度设置
StrokeStyleListView::StrokeStyleListView(
std::shared_ptr<Renderer::StrokeRadialGradient> stroke,
QWidget* parent
) : QTableWidget(parent), stroke(stroke)
{
this->setSizeAdjustPolicy(QAbstractScrollArea::AdjustToContentsOnFirstShow);
this->setColumnCount(5);
this->setRowCount(stroke->materialMap.size());
QStringList headers;
headers.append(QStringLiteral("离心距离占比"));
headers.append(QStringLiteral("颜色"));
headers.append(QStringLiteral("金属度"));
headers.append(QStringLiteral("粗糙度"));
headers.append(QStringLiteral("其他操作"));
this->setHorizontalHeaderLabels(headers);
for (int row = 0; auto& strokePair : stroke->materialMap)
{
QTableWidgetItem* widthItem = new QTableWidgetItem;
widthItem->setData(Qt::EditRole, strokePair.first);
this->setItem(row, COLUMN_WIDTH, widthItem);
QColor* colorPtr = &(strokePair.second.color);
QTableWidgetItem* colorItem = new QTableWidgetItem;
colorItem->setData(Qt::DisplayRole, *colorPtr);
this->setItem(row, COLUMN_COLOR, colorItem);
ColorPicker* colorPicker = new ColorPicker(*colorPtr, this);
this->setCellWidget(row, COLUMN_COLOR, colorPicker);
connect(colorPicker, &ColorPicker::colorChanged, [this, colorPtr](QColor color) {
*colorPtr = color;
this->update();
});
QTableWidgetItem* metallicItem = new QTableWidgetItem;
metallicItem->setData(Qt::EditRole, strokePair.second.metallic);
this->setItem(row, COLUMN_METALLIC, metallicItem);
QTableWidgetItem* roughnessItem = new QTableWidgetItem;
roughnessItem->setData(Qt::EditRole, strokePair.second.roughness);
this->setItem(row, COLUMN_ROUGHNESS, roughnessItem);
QtMaterialRaisedButton* removeButton = new QtMaterialRaisedButton("-", this);
removeButton->setFixedSize(20, 20);
this->setCellWidget(row, COLUMN_OPERATIONS, removeButton);
connect(removeButton, &QtMaterialRaisedButton::clicked, [this, row]() {
this->stroke->materialMap.erase(this->item(row, COLUMN_WIDTH)->text().toFloat());
this->removeRow(row);
});
row++;
}
connect(this, &StrokeStyleListView::currentItemChanged, this, &StrokeStyleListView::onCurrentItemChanged);
connect(this, &StrokeStyleListView::cellChanged, this, &StrokeStyleListView::onCellChanged);
this->adjustSize();
}
void StrokeStyleListView::onCurrentItemChanged(QTableWidgetItem* current, QTableWidgetItem* previous)
{
if (!current) return;
int column = current->column();
if (column != COLUMN_COLOR && column != COLUMN_OPERATIONS)
{
this->currentItemValue = current->text();
}
}
void StrokeStyleListView::onCellChanged(int row, int column)
{
auto changedItem = this->item(row, column);
auto changedItemValue = changedItem->text().toFloat();
if (changedItemValue < 0 || 1 < changedItemValue)
{
changedItem->setData(Qt::EditRole, this->currentItemValue.toFloat());
return;
}
auto changedWidth = this->item(row, COLUMN_WIDTH)->text().toFloat();
switch (row)
{
case COLUMN_WIDTH:
{
float oldWidth = this->currentItemValue.toFloat();
auto node = stroke->materialMap.extract(oldWidth);
node.key() = changedWidth;
stroke->materialMap.insert(std::move(node));
break;
}
case COLUMN_METALLIC:
{
stroke->materialMap[changedWidth].metallic = changedItemValue;
break;
}
case COLUMN_ROUGHNESS:
{
stroke->materialMap[changedWidth].roughness = changedItemValue;
break;
}
}
}

View File

@ -1,21 +0,0 @@
#pragma once
#include "LayerStyle.h"
#include "../Renderer/Painting/MaterialStyleStroke.h"
#include <QListView>
#include <QListWidget>
#include <QTableWidget>
class StrokeStyleListView : public QTableWidget
{
Q_OBJECT
private:
QString currentItemValue;
public:
StrokeStyleListView(std::shared_ptr<Renderer::StrokeRadialGradient> stroke, QWidget* parent = nullptr);
std::shared_ptr<Renderer::StrokeRadialGradient> stroke;
protected slots:
void onCurrentItemChanged(QTableWidgetItem* current, QTableWidgetItem* previous);
void onCellChanged(int row, int column);
};

View File

@ -17,9 +17,9 @@ EditorWidgetItem::EditorWidgetItem(QString filePath,QWidget *parent) : QWidget(p
treeWidget = ui.LayerTree; treeWidget = ui.LayerTree;
tabWidget = ui.DisplayTab; tabWidget = ui.DisplayTab;
this->filePath = filePath; this->filePath = filePath;
elementInfoDisplayWidget = ui.ElementDisplay;
layerInfoDisplayWidget = dynamic_cast<InfoDisplayWidget*>(tabWidget->widget(0)); layerInfoDisplayWidget = dynamic_cast<InfoDisplayWidget*>(tabWidget->widget(0));
elementInfoDisplayWidget = dynamic_cast<ElementPoolWidget *>(tabWidget->widget(1)); editorSettingWidget = dynamic_cast<EditorSettingWidget*>(tabWidget->widget(1));
editorSettingWidget = dynamic_cast<EditorSettingWidget*>(tabWidget->widget(2));
elementInfoDisplayWidget->enableEdit(); elementInfoDisplayWidget->enableEdit();
qDebug() << layerInfoDisplayWidget; qDebug() << layerInfoDisplayWidget;
qDebug() << elementInfoDisplayWidget; qDebug() << elementInfoDisplayWidget;

View File

@ -9,6 +9,7 @@
#include <QLabel> #include <QLabel>
#include <QObject> #include <QObject>
#include <QDebug> #include <QDebug>
#include <QListView>
#define _USE_JOIN_VIEW_INPUT_RANGE #define _USE_JOIN_VIEW_INPUT_RANGE
#include <QJsonArray> #include <QJsonArray>
#include <ranges> #include <ranges>
@ -193,6 +194,16 @@ bool LayerStyleContainer::useStyle(const std::shared_ptr<LayerStyle>& style)
return true; return true;
} }
bool LayerStyleContainer::overrideStyle(const std::shared_ptr<LayerStyle>& style)
{
if (!styles.contains(style->getDisplayName()))
{
return false;
}
styles[style->getDisplayName()] = style;
return true;
}
bool LayerStyleContainer::dropStyle(const QString& styleName) bool LayerStyleContainer::dropStyle(const QString& styleName)
{ {
auto styleNode = usedStyles.extract(styleName); auto styleNode = usedStyles.extract(styleName);
@ -205,6 +216,11 @@ bool LayerStyleContainer::dropStyle(const QString& styleName)
return true; return true;
} }
std::shared_ptr<LayerStyle> LayerStyleContainer::getStyle(const QString& styleName) const
{
return styles.at(styleName);
}
float LayerStyleContainer::boundingBoxAffectValue() const { float LayerStyleContainer::boundingBoxAffectValue() const {
float maxLineWidth = 0; float maxLineWidth = 0;
const auto strokeStyle = styles.find(StrokeElementLayerStyle::displayName()); const auto strokeStyle = styles.find(StrokeElementLayerStyle::displayName());
@ -234,6 +250,15 @@ size_t LayerStyleContainer::getHash() const
return hash; return hash;
} }
bool LayerStyleContainer::operator==(const LayerStyleContainer& other) const
{
if (getHash() != other.getHash() || unusedStyleNames() != other.unusedStyleNames())
{
return false;
}
return std::ranges::equal(styles | std::views::values, other.styles | std::views::values);
}
std::unique_ptr<StrokeElementLayerStyle> StrokeElementLayerStyle::fromJson(const QJsonObject& json) std::unique_ptr<StrokeElementLayerStyle> StrokeElementLayerStyle::fromJson(const QJsonObject& json)
{ {
auto ptr = std::make_unique<StrokeElementLayerStyle>( auto ptr = std::make_unique<StrokeElementLayerStyle>(
@ -298,6 +323,20 @@ std::unique_ptr<LayerStyle> StrokeElementLayerStyle::clone() const
return std::make_unique<StrokeElementLayerStyle>(StrokeElementLayerStyle(*this)); return std::make_unique<StrokeElementLayerStyle>(StrokeElementLayerStyle(*this));
} }
bool StrokeElementLayerStyle::operator==(const LayerStyle& other) const
{
if (!LayerStyle::operator==(other))
{
return false;
}
const auto otherStyle = dynamic_cast<const StrokeElementLayerStyle*>(&other);
if (!otherStyle)
{
return false;
}
return this->strokePair.first == otherStyle->strokePair.first && this->strokePair.second == otherStyle->strokePair.second;
}
std::unique_ptr<FillElementLayerStyle> FillElementLayerStyle::fromJson(const QJsonObject& json) std::unique_ptr<FillElementLayerStyle> FillElementLayerStyle::fromJson(const QJsonObject& json)
{ {
auto ptr = std::make_unique<FillElementLayerStyle>( auto ptr = std::make_unique<FillElementLayerStyle>(
@ -359,6 +398,20 @@ std::unique_ptr<LayerStyle> FillElementLayerStyle::clone() const
return std::make_unique<FillElementLayerStyle>(FillElementLayerStyle(*this)); return std::make_unique<FillElementLayerStyle>(FillElementLayerStyle(*this));
} }
bool FillElementLayerStyle::operator==(const LayerStyle& other) const
{
if (!LayerStyle::operator==(other))
{
return false;
}
const auto otherStyle = dynamic_cast<const FillElementLayerStyle*>(&other);
if (!otherStyle)
{
return false;
}
return this->fillMaterialStyle == otherStyle->fillMaterialStyle;
}
std::unique_ptr<LayerStyle> LayerStyle::fromJson(const QJsonObject& json) std::unique_ptr<LayerStyle> LayerStyle::fromJson(const QJsonObject& json)
{ {
QString type = json["type"].toString(); QString type = json["type"].toString();
@ -379,3 +432,8 @@ QJsonObject LayerStyle::toJson() const
json["type"] = this->getTypeName(); json["type"] = this->getTypeName();
return json; return json;
} }
bool LayerStyle::operator==(const LayerStyle& other) const
{
return this->getTypeName() == other.getTypeName();
}

View File

@ -3,7 +3,6 @@
#include <utility> #include <utility>
#include <set> #include <set>
#include <map> #include <map>
#include <QListWidget>
#include <QJsonObject> #include <QJsonObject>
#include <QJsonArray> #include <QJsonArray>
#include "../Renderer/Painting/ElementStyle.h" #include "../Renderer/Painting/ElementStyle.h"
@ -36,6 +35,8 @@ public:
virtual QJsonObject toJson() const; virtual QJsonObject toJson() const;
virtual std::unique_ptr<LayerStyle> clone() const = 0; virtual std::unique_ptr<LayerStyle> clone() const = 0;
virtual bool operator==(const LayerStyle& other) const;
}; };
class StrokeElementLayerStyle : public LayerStyle class StrokeElementLayerStyle : public LayerStyle
@ -57,6 +58,8 @@ public:
QJsonObject toJson() const override; QJsonObject toJson() const override;
std::unique_ptr<LayerStyle> clone() const override; std::unique_ptr<LayerStyle> clone() const override;
bool operator==(const LayerStyle& other) const override;
std::pair<PMaterialStyleStroke, PMaterialStyleStroke> strokePair; std::pair<PMaterialStyleStroke, PMaterialStyleStroke> strokePair;
bool enableEachSideIndependent = false; bool enableEachSideIndependent = false;
}; };
@ -79,6 +82,8 @@ public:
QJsonObject toJson() const override; QJsonObject toJson() const override;
std::unique_ptr<LayerStyle> clone() const override; std::unique_ptr<LayerStyle> clone() const override;
bool operator==(const LayerStyle& other) const override;
PMaterialStyleFill fillMaterialStyle; PMaterialStyleFill fillMaterialStyle;
}; };
@ -125,10 +130,14 @@ public:
QStringList unusedStyleNames() const; QStringList unusedStyleNames() const;
std::unique_ptr<LayerStyle> makeUnusedStyle(const QString& styleName) const; std::unique_ptr<LayerStyle> makeUnusedStyle(const QString& styleName) const;
bool useStyle(const std::shared_ptr<LayerStyle>& style); bool useStyle(const std::shared_ptr<LayerStyle>& style);
bool overrideStyle(const std::shared_ptr<LayerStyle>& style);
bool dropStyle(const QString& styleName); bool dropStyle(const QString& styleName);
std::shared_ptr<LayerStyle> getStyle(const QString& styleName) const;
float boundingBoxAffectValue() const; float boundingBoxAffectValue() const;
size_t getHash() const; size_t getHash() const;
bool operator==(const LayerStyleContainer& other) const;
/** /**
* *
*/ */

View File

@ -2,12 +2,7 @@
#include "./EditorWidgetComponent/LayerStyleDialog.h" #include "./EditorWidgetComponent/LayerStyleDialog.h"
#include <QLineEdit> #include <QLineEdit>
#include <QTextBlock> #include <QTextBlock>
#include <QListWidget>
#include <QDialog>
#include <QComboBox> #include <QComboBox>
#include <qtmaterialraisedbutton.h>
#include <qtmaterialflatbutton.h>
#include <QLabel>
#include <QCheckBox> #include <QCheckBox>
void InfoDisplayWidget::setLayer(LayerWrapper *layer) void InfoDisplayWidget::setLayer(LayerWrapper *layer)
@ -27,6 +22,7 @@ InfoDisplayWidget::InfoDisplayWidget(QWidget* parent) :QWidget(parent)
ui.scaleX->setLabel(("水平缩放")); ui.scaleX->setLabel(("水平缩放"));
ui.scaleY->setLabel(("垂直缩放")); ui.scaleY->setLabel(("垂直缩放"));
ui.rotation->setValidator(new QIntValidator(-10000, 10000, this)); ui.rotation->setValidator(new QIntValidator(-10000, 10000, this));
ui.styleList->setDisabled(true);
connect(ui.rotation, &QLineEdit::textChanged, [=](QString content) { connect(ui.rotation, &QLineEdit::textChanged, [=](QString content) {
this->displayLayer->property.rotation = content.toDouble(); this->displayLayer->property.rotation = content.toDouble();
emit triggerCentralRefresh(); emit triggerCentralRefresh();
@ -59,6 +55,15 @@ InfoDisplayWidget::InfoDisplayWidget(QWidget* parent) :QWidget(parent)
this->displayLayer->property.flipY = state; this->displayLayer->property.flipY = state;
emit triggerCentralRefresh(); emit triggerCentralRefresh();
}); });
connect(ui.styleList, &LayerContainerListWidget::addLayerStyle, [this](const std::shared_ptr<LayerStyle>& style) {
emit triggerCentralRefresh();
});
connect(ui.styleList, &LayerContainerListWidget::editLayerStyle, [this](const std::shared_ptr<LayerStyle>& style) {
emit triggerCentralRefresh();
});
connect(ui.styleList, &LayerContainerListWidget::removeLayerStyle, [this](const QString& styleName) {
emit triggerCentralRefresh();
});
} }
void InfoDisplayWidget::setVisiable(bool visiable) void InfoDisplayWidget::setVisiable(bool visiable)
@ -79,5 +84,14 @@ void InfoDisplayWidget::refresh()
ui.scaleY->setText(QString::number(this->displayLayer->property.scale.y())); ui.scaleY->setText(QString::number(this->displayLayer->property.scale.y()));
ui.flipX->setChecked(this->displayLayer->property.flipX); ui.flipX->setChecked(this->displayLayer->property.flipX);
ui.flipY->setChecked(this->displayLayer->property.flipY); ui.flipY->setChecked(this->displayLayer->property.flipY);
if (this->displayLayer->canApplyStyles())
{
ui.styleList->setDisabled(false);
ui.styleList->setStyleContainer(&static_cast<LeafLayerWrapper*>(this->displayLayer)->styles);
}
else
{
ui.styleList->setDisabled(true);
}
} }
} }

View File

@ -1,8 +1,5 @@
#pragma once #pragma once
#include "GraphicElement.h" #include "GraphicElement.h"
#include "LayerWrapper.h"
#include <QFormLayout>
#include <QLabel>
#include <QWidget> #include <QWidget>
#include "ElementPoolWidget.h" #include "ElementPoolWidget.h"
#include "ui_EditorLayerInfoWidget.h" #include "ui_EditorLayerInfoWidget.h"