diff --git a/ArchitectureColoredPainting/src/Editor/EditorWidget.cpp b/ArchitectureColoredPainting/src/Editor/EditorWidget.cpp index dbe7e0c..e9fe251 100644 --- a/ArchitectureColoredPainting/src/Editor/EditorWidget.cpp +++ b/ArchitectureColoredPainting/src/Editor/EditorWidget.cpp @@ -84,7 +84,7 @@ void EditorWidget::initFileMenu() auto* item = dynamic_cast(this->tabWidget->currentWidget()); if (item != nullptr) { - //item->save(); + item->save(); } }); connect(actionSaveAs, &QAction::triggered, this, [this] { diff --git a/ArchitectureColoredPainting/src/Editor/EditorWidgetItem.cpp b/ArchitectureColoredPainting/src/Editor/EditorWidgetItem.cpp index e9aeae0..b2a04f9 100644 --- a/ArchitectureColoredPainting/src/Editor/EditorWidgetItem.cpp +++ b/ArchitectureColoredPainting/src/Editor/EditorWidgetItem.cpp @@ -25,9 +25,9 @@ EditorWidgetItem::EditorWidgetItem(QString filePath,QWidget *parent) : QWidget(p qDebug() << elementInfoDisplayWidget; auto centralRefresh = [this]() { layerInfoDisplayWidget->refresh(); - elementInfoDisplayWidget->refresh(); treeWidget->refresh(); previewWindow->refresh(); + elementInfoDisplayWidget->lazyRefresh(); }; connect(previewWindow, &PreviewWindow::triggerCentralRefresh, centralRefresh); connect(layerInfoDisplayWidget, &InfoDisplayWidget::triggerCentralRefresh, centralRefresh); diff --git a/ArchitectureColoredPainting/src/Editor/ElementPoolWidget.cpp b/ArchitectureColoredPainting/src/Editor/ElementPoolWidget.cpp index 95825e1..e6c18a2 100644 --- a/ArchitectureColoredPainting/src/Editor/ElementPoolWidget.cpp +++ b/ArchitectureColoredPainting/src/Editor/ElementPoolWidget.cpp @@ -4,6 +4,7 @@ #include #include #include +#include ElementPoolWidget::ElementPoolWidget(QWidget* parent) : QWidget(parent) @@ -38,10 +39,15 @@ void ElementPoolWidget::setElementList(std::vector elements) { pictureList->clear(); this->elements = elements; for (int index = 0; index < elements.size(); index++) { - QListWidgetItem* pItem = new QListWidgetItem( - elements[index]->getPreview(QSize(iconWidth - 25, iconHeight - 25)), - elements[index]->name); + QListWidgetItem* pItem = new QListWidgetItem(elements[index]->name); + QPainter* painter = new QPainter(); + QImage* image = new QImage(QSize(iconWidth - 12, iconHeight - 12), QImage::Format_ARGB32); + image->fill(Qt::transparent); + pItem->setIcon(QIcon(QPixmap::fromImage(*image))); pItem->setSizeHint(QSize(iconWidth, iconHeight)); + painter->begin(image); + elements[index]->paintPreview(painter); + painter->end(); pictureList->insertItem(index, pItem); } if(elements.size() > 0) @@ -66,15 +72,47 @@ void ElementPoolWidget::setElementManager(ElementManager* element) this->setElementList(this->elementManager->elements); } +void ElementPoolWidget::lazyRefresh() +{ + if (!refreshWait) { + refreshWait = true; + QTimer::singleShot(1000, this, SLOT(refresh())); + } +} + void ElementPoolWidget::refresh() { - this->setElementList(this->elementManager->elements); - // update(); + refreshWait = false; + if (elementManager != nullptr) + { + for (int i = 0; i < elements.size(); i++) + { + QListWidgetItem* pItem = pictureList->item(i); + if (pItem == nullptr) + { + pItem = new QListWidgetItem(elements[i]->name); + pictureList->insertItem(i, pItem); + } + QPainter* painter = new QPainter(); + QImage* image = new QImage(QSize(iconWidth - 12, iconHeight - 12), QImage::Format_ARGB32); + image->fill(Qt::transparent); + painter->begin(image); + elements[i]->paintPreview(painter); + painter->end(); + pItem->setIcon(QIcon(QPixmap::fromImage(*image))); + pItem->setData(Qt::UserRole, QVariant::fromValue(image)); + pItem->setSizeHint(QSize(iconWidth, iconHeight)); + pictureList->insertItem(i, pItem); + } + } } void ElementPoolWidget::refreshPicture(GraphicElement* element) { for (int i = 0; i < elements.size(); i++) { if (element == elements[i]) { - pictureList->item(i)->setIcon(elements[i]->getPreview(QSize(iconWidth - 25, iconHeight - 25))); + QPainter* painter = new QPainter(); + painter->begin(pictureList->item(i)->data(Qt::UserRole).value()); + elements[i]->paintPreview(painter); + painter->end(); // update(); return; } @@ -84,7 +122,10 @@ void ElementPoolWidget::refreshPicture(GraphicElement* element) { void ElementPoolWidget::refreshPictureByIndex(int index) { if (index >= 0 && index < elements.size()) { - pictureList->item(index)->setIcon(elements[index]->getPreview(QSize(iconWidth - 25, iconHeight - 25))); + QPainter* painter = new QPainter(); + painter->begin(pictureList->item(index)->data(Qt::UserRole).value()); + elements[index]->paintPreview(painter); + painter->end(); // update(); } } @@ -118,7 +159,6 @@ void ElementPoolWidget::popMenu(const QPoint& pos) }); menu->addAction(QString::fromLocal8Bit("ɾ³ý"), this, [this, currentElement]() { this->elementManager->removeElement(currentElement); - emit triggerCentralRefresh(); }); menu->actions().last()->setDisabled(currentElement->referencedCount > 0); } diff --git a/ArchitectureColoredPainting/src/Editor/ElementPoolWidget.h b/ArchitectureColoredPainting/src/Editor/ElementPoolWidget.h index 472b1ba..24eb763 100644 --- a/ArchitectureColoredPainting/src/Editor/ElementPoolWidget.h +++ b/ArchitectureColoredPainting/src/Editor/ElementPoolWidget.h @@ -14,6 +14,7 @@ private: QListWidget* pictureList; int iconWidth, iconHeight; ElementManager* elementManager; + bool refreshWait = false; public: int currentIndex = -1; @@ -22,6 +23,7 @@ public: void setElementManager(ElementManager* element); ~ElementPoolWidget(); void enableEdit(); + void lazyRefresh(); signals: void elementSelected(GraphicElement* element); diff --git a/ArchitectureColoredPainting/src/Editor/GraphicElement.cpp b/ArchitectureColoredPainting/src/Editor/GraphicElement.cpp index 0b810e9..580d3a3 100644 --- a/ArchitectureColoredPainting/src/Editor/GraphicElement.cpp +++ b/ArchitectureColoredPainting/src/Editor/GraphicElement.cpp @@ -45,7 +45,6 @@ void GroupElement::setSourceLayer(FolderLayerWrapper* sourceLayer) PixelPath GroupElement::getPaintObject() const { if (sourceLayer != nullptr) { - sourceLayer->refresh(); return sourceLayer->getCache(); } else @@ -113,8 +112,9 @@ void SimpleElement::paint(QPainter* painter, QTransform transform, const LayerSt maxScale = std::max(fabs(transform.m11() / cos(angle)), fabs(transform.m22() / cos(angle))); else maxScale = std::max(fabs(transform.m12() / sin(angle)), fabs(transform.m21() / sin(angle))); - double pixelRatio = maxScale * QGuiApplication::primaryScreen()->devicePixelRatio(); - if (painterPath == painterPathPrev && styles.getHash() == stylesHashValue && pixelRatio == pixelRatioPrev) + //double pixelRatio = maxScale * QGuiApplication::primaryScreen()->devicePixelRatio(); + double pixelRatio = 5; + if (painterPath == painterPathPrev && styles.getHash() == stylesHashValue && fabs(pixelRatio - pixelRatioPrev) < 1e-3) { transform.translate(movPrev.x(), movPrev.y()); painter->setTransform(transform.scale(1 / pixelRatio, 1 / pixelRatio)); @@ -153,31 +153,26 @@ bool GroupElement::isClosed() const } -QPixmap SimpleElement::getPreview(QSize size) +void SimpleElement::paintPreview(QPainter* painter) { - QPixmap result(size + QSize(5, 5)); - QPainter painter(&result); - painter.setRenderHint(QPainter::Antialiasing); - painter.setRenderHint(QPainter::SmoothPixmapTransform); - painter.scale(size.width() / painterPath.boundingRect().width(), size.height() / painterPath.boundingRect().height()); - painter.drawPath(painterPath); - return result; + painter->save(); + painter->setWindow(painterPath.boundingRect().x() - 5, painterPath.boundingRect().y() - 5, (painterPath.boundingRect().width() + 10) * QGuiApplication::primaryScreen()->devicePixelRatio(), (painterPath.boundingRect().height() + 10) * QGuiApplication::primaryScreen()->devicePixelRatio()); + painter->drawPath(painterPath); + painter->restore(); } -QPixmap GroupElement::getPreview(QSize size) +void GroupElement::paintPreview(QPainter* painter) { + painter->save(); auto cache = sourceLayer->getCache(); - QPixmap result(QSize(1024, 1024)); - QPainter painter(&result); - painter.setRenderHint(QPainter::Antialiasing); - painter.setRenderHint(QPainter::SmoothPixmapTransform); - sourceLayer->paint(&painter, QTransform(), true); - painter.end(); - QRect rect(cache.getBoundingRect().toRect()); - rect.setTopLeft(rect.topLeft() - QPoint(5, 5)); - rect.setBottomRight(rect.bottomRight() + QPoint(5, 5)); - result = result.copy(rect); - return result.scaled(size, Qt::KeepAspectRatio, Qt::SmoothTransformation); + painter->setRenderHint(QPainter::Antialiasing, true); + painter->setRenderHint(QPainter::SmoothPixmapTransform, true); + painter->setWindow(cache.getBoundingRect().toRect().x() - 5, cache.getBoundingRect().toRect().y() - 5, (cache.getBoundingRect().toRect().width() + 10) * QGuiApplication::primaryScreen()->devicePixelRatio(), (cache.getBoundingRect().toRect().height() + 10) * QGuiApplication::primaryScreen()->devicePixelRatio()); + //painter->translate(-cache.getBoundingRect().toRect().x() - 5, -cache.getBoundingRect().toRect().y() - 5); + //double maxScale = std::max(cache.getBoundingRect().toRect().width() + 10, cache.getBoundingRect().toRect().height() + 10) * QGuiApplication::primaryScreen()->devicePixelRatio(); + //painter->scale(1 / maxScale, 1/ maxScale); + sourceLayer->paint(painter, QTransform(), true); + painter->restore(); } void GroupElement::collectReachable(std::set& set) const diff --git a/ArchitectureColoredPainting/src/Editor/GraphicElement.h b/ArchitectureColoredPainting/src/Editor/GraphicElement.h index 50073e4..6e6c301 100644 --- a/ArchitectureColoredPainting/src/Editor/GraphicElement.h +++ b/ArchitectureColoredPainting/src/Editor/GraphicElement.h @@ -20,6 +20,7 @@ class ComposedPainterPath; class GraphicElement { public: + bool needRefresh = true; size_t referencedCount = 0; Renderer::ElementRenderer *renderer; QString name = ""; @@ -35,7 +36,7 @@ public: virtual PixelPath getPaintObject(const LayerStyleContainer& styles) const = 0; virtual void paint(QPainter* painter, QTransform transform, const LayerStyleContainer& styles) = 0; virtual bool isClosed() const = 0; - virtual QPixmap getPreview(QSize size) = 0; + virtual void paintPreview(QPainter* painter) = 0; }; @@ -59,7 +60,7 @@ public: PixelPath getPaintObject(const LayerStyleContainer& styles) const override; void paint(QPainter* painter, QTransform transform, const LayerStyleContainer& styles) override; bool isClosed() const override; - QPixmap getPreview(QSize size) override; + void paintPreview(QPainter* painter) override; }; class GroupElement : public GraphicElement @@ -77,10 +78,12 @@ public: void setSourceLayer(FolderLayerWrapper* sourceLayer); void paint(QPainter* painter, QTransform transform, const LayerStyleContainer& styles) override; bool isClosed() const override; - QPixmap getPreview(QSize size) override; + void paintPreview(QPainter* painter) override; void collectReachable(std::set& set) const; }; +Q_DECLARE_METATYPE(GraphicElement*) + //******************************** BitmapPath ********************************// //using std::vector; diff --git a/ArchitectureColoredPainting/src/Editor/LayerManager.cpp b/ArchitectureColoredPainting/src/Editor/LayerManager.cpp index b1d2e60..917941a 100644 --- a/ArchitectureColoredPainting/src/Editor/LayerManager.cpp +++ b/ArchitectureColoredPainting/src/Editor/LayerManager.cpp @@ -14,6 +14,7 @@ LayerWrapper *LayerManager::getRoot() const void LayerManager::paint(QPainter *painter, QSize size,LayerWrapper* selecetedLayer) const { painter->save(); + root->markNeedRefresh(); root->getCache(); root->paint(painter); painter->restore(); diff --git a/ArchitectureColoredPainting/src/Editor/LayerWrapper.cpp b/ArchitectureColoredPainting/src/Editor/LayerWrapper.cpp index bf4dcce..1c95e4e 100644 --- a/ArchitectureColoredPainting/src/Editor/LayerWrapper.cpp +++ b/ArchitectureColoredPainting/src/Editor/LayerWrapper.cpp @@ -25,10 +25,10 @@ FolderLayerWrapper*LayerWrapper::getParent() const PixelPath LayerWrapper::getCache(LayerWrapper* selectedLayer) { - this->refresh(selectedLayer); - if (selectedLayer == this) + if (needRefresh) { - this->cache.highLight(); + this->refresh(selectedLayer); + needRefresh = false; } return cache; } @@ -460,4 +460,16 @@ void LayerWrapper::paintVisualBounding(QPainter* painter) const painter->setTransform(transform); painter->drawRect(cache.getBoundingRect()); painter->restore(); +} + +void LayerWrapper::markNeedRefresh() +{ + this->needRefresh = true; +} + +void FolderLayerWrapper::markNeedRefresh() +{ + LayerWrapper::markNeedRefresh(); + for (auto& child : children) + child->markNeedRefresh(); } \ No newline at end of file diff --git a/ArchitectureColoredPainting/src/Editor/LayerWrapper.h b/ArchitectureColoredPainting/src/Editor/LayerWrapper.h index 35b6c1f..a6cc5ac 100644 --- a/ArchitectureColoredPainting/src/Editor/LayerWrapper.h +++ b/ArchitectureColoredPainting/src/Editor/LayerWrapper.h @@ -35,6 +35,7 @@ class LayerWrapper PixelPath cache; public: + bool needRefresh = true; QTreeWidgetItem* qTreeWidgetItem; bool selected; bool hidden; @@ -77,6 +78,7 @@ class LayerWrapper virtual bool referencingGroupElement() const; virtual void paintVisualBounding(QPainter* painter) const; bool canApplyStyles() const; + virtual void markNeedRefresh(); }; class FolderLayerWrapper : public LayerWrapper @@ -104,6 +106,7 @@ class FolderLayerWrapper : public LayerWrapper void refreshTreeItem() override; size_t referencedCount(bool excludeSelf = false) const override; bool deleteable(bool excludeSubTree = false) const override; + void markNeedRefresh() override; }; class LeafLayerWrapper : public LayerWrapper diff --git a/ArchitectureColoredPainting/src/Editor/RightBar/InfoDisplayWidget.cpp b/ArchitectureColoredPainting/src/Editor/RightBar/InfoDisplayWidget.cpp index df61f0a..96950ae 100644 --- a/ArchitectureColoredPainting/src/Editor/RightBar/InfoDisplayWidget.cpp +++ b/ArchitectureColoredPainting/src/Editor/RightBar/InfoDisplayWidget.cpp @@ -21,37 +21,51 @@ InfoDisplayWidget::InfoDisplayWidget(QWidget* parent) :QWidget(parent) ui.rotation->setLabel(("旋转角度")); ui.scaleX->setLabel(("水平缩放")); ui.scaleY->setLabel(("垂直缩放")); - ui.rotation->setValidator(new QIntValidator(-10000, 10000, this)); + ui.rotation->setValidator(new QDoubleValidator(-10000, 10000, 6, this)); ui.styleList->setDisabled(true); connect(ui.rotation, &QLineEdit::textChanged, [=](QString content) { + if (fabs(content.toDouble() - this->displayLayer->property.rotation) < 1e-6) + return; this->displayLayer->property.rotation = content.toDouble(); emit triggerCentralRefresh(); }); - ui.offsetX->setValidator(new QIntValidator(-10000, 10000, this)); + ui.offsetX->setValidator(new QDoubleValidator(-10000, 10000, 2, this)); connect(ui.offsetX, &QLineEdit::textChanged, [=](QString content) { + if (fabs(content.toDouble() - this->displayLayer->property.offset.x()) < 1e-6) + return; this->displayLayer->property.offset = { content.toDouble(), this->displayLayer->property.offset.y() }; emit triggerCentralRefresh(); }); - ui.offsetY->setValidator(new QIntValidator(-10000, 10000, this)); + ui.offsetY->setValidator(new QDoubleValidator(-10000, 10000, 2, this)); connect(ui.offsetY, &QLineEdit::textChanged, [=](QString content) { + if (fabs(content.toDouble() - this->displayLayer->property.offset.y()) < 1e-6) + return; this->displayLayer->property.offset = { this->displayLayer->property.offset.x(), content.toDouble() }; emit triggerCentralRefresh(); }); - ui.scaleX->setValidator(new QDoubleValidator(0, 1000, 4, this)); + ui.scaleX->setValidator(new QDoubleValidator(0, 10000, 6, this)); connect(ui.scaleX, &QLineEdit::textChanged, [=](QString content) { + if (fabs(content.toDouble() - this->displayLayer->property.scale.x()) < 1e-6) + return; this->displayLayer->property.scale = { content.toDouble(), this->displayLayer->property.scale.y() }; emit triggerCentralRefresh(); }); - ui.scaleY->setValidator(new QDoubleValidator(0, 1000, 4, this)); + ui.scaleY->setValidator(new QDoubleValidator(0, 10000, 6, this)); connect(ui.scaleY, &QLineEdit::textChanged, [=](QString content) { + if (fabs(content.toDouble() - this->displayLayer->property.scale.y()) < 1e-6) + return; this->displayLayer->property.scale = { this->displayLayer->property.scale.x(), content.toDouble() }; emit triggerCentralRefresh(); }); connect(ui.flipX, &QtMaterialCheckBox::toggled, [=](bool state) { + if (state == this->displayLayer->property.flipX) + return; this->displayLayer->property.flipX = state; emit triggerCentralRefresh(); }); connect(ui.flipY, &QtMaterialCheckBox::toggled, [=](bool state) { + if (state == this->displayLayer->property.flipY) + return; this->displayLayer->property.flipY = state; emit triggerCentralRefresh(); }); diff --git a/ArchitectureColoredPainting/src/Editor/RightBar/LayerTreeWidget.cpp b/ArchitectureColoredPainting/src/Editor/RightBar/LayerTreeWidget.cpp index f7bddc9..721594c 100644 --- a/ArchitectureColoredPainting/src/Editor/RightBar/LayerTreeWidget.cpp +++ b/ArchitectureColoredPainting/src/Editor/RightBar/LayerTreeWidget.cpp @@ -239,6 +239,7 @@ QAction* LayerTreeWidget::getPromoteUpAction() auto layer = pair.first; auto parent = pair.second; this->moveLayer(layer, parent); + this->setCurrentItem(layer->qTreeWidgetItem); }); optionList.append(option); } @@ -255,6 +256,11 @@ QAction* LayerTreeWidget::getPromoteDownAction() std::vector layers; auto layer = this->selectedItem->data(0, Qt::UserRole).value(); auto parent = layer->getParent(); + if (parent == nullptr) + { + action->setEnabled(false); + return action; + } for (auto child : parent->children) { if (child.get() == layer || typeid(*child) != typeid(FolderLayerWrapper)) @@ -278,6 +284,7 @@ QAction* LayerTreeWidget::getPromoteDownAction() auto layer = pair.first; auto parent = pair.second; this->moveLayer(layer, parent); + this->setCurrentItem(layer->qTreeWidgetItem); }); optionList.append(option); }