添加‘撤回/重做’功能模块,并完成了对‘添加图形’和‘删除图形’的指令实现

This commit is contained in:
duanshengchao 2024-08-15 10:15:56 +08:00
parent 2c4a2ad19b
commit be85c9d570
11 changed files with 212 additions and 69 deletions

View File

@ -39,6 +39,7 @@ set(H_HEADER_FILES
include/drawingPanel.h include/drawingPanel.h
include/designerScene.h include/designerScene.h
include/designerView.h include/designerView.h
include/operationCommand.h
include/util/baseSelector.h include/util/baseSelector.h
include/util/creatingSelector.h include/util/creatingSelector.h
@ -57,6 +58,7 @@ set(CPP_SOURCE_FILES
source/drawingPanel.cpp source/drawingPanel.cpp
source/designerScene.cpp source/designerScene.cpp
source/designerView.cpp source/designerView.cpp
source/operationCommand.cpp
source/util/baseSelector.cpp source/util/baseSelector.cpp
source/util/creatingSelector.cpp source/util/creatingSelector.cpp

View File

@ -16,12 +16,17 @@ public:
QGraphicsView *getView() { return m_pView; } QGraphicsView *getView() { return m_pView; }
void callParentEvent(QGraphicsSceneMouseEvent*); void callParentEvent(QGraphicsSceneMouseEvent*);
signals:
void signalAddItem(QGraphicsItem*);
protected: protected:
void drawBackground(QPainter*, const QRectF&) override; void drawBackground(QPainter*, const QRectF&) override;
void mousePressEvent(QGraphicsSceneMouseEvent*) override; void mousePressEvent(QGraphicsSceneMouseEvent*) override;
void mouseMoveEvent(QGraphicsSceneMouseEvent*) override; void mouseMoveEvent(QGraphicsSceneMouseEvent*) override;
void mouseReleaseEvent(QGraphicsSceneMouseEvent*) override; void mouseReleaseEvent(QGraphicsSceneMouseEvent*) override;
void mouseDoubleClickEvent(QGraphicsSceneMouseEvent*) override; void mouseDoubleClickEvent(QGraphicsSceneMouseEvent*) override;
void keyPressEvent(QKeyEvent*) override;
void keyReleaseEvent(QKeyEvent*) override;
private: private:
bool m_bGridVisible; bool m_bGridVisible;

View File

@ -19,6 +19,9 @@ public:
DrawingPanel(QWidget *parent = nullptr); DrawingPanel(QWidget *parent = nullptr);
~DrawingPanel(); ~DrawingPanel();
QGraphicsScene* getQGraphicsScene();
DesignerScene* getDesignerScene();
public slots: public slots:
void onSignal_addGraphicsItem(GraphicsItemType&); void onSignal_addGraphicsItem(GraphicsItemType&);

View File

@ -13,8 +13,11 @@ QT_BEGIN_NAMESPACE
namespace Ui { class CMainWindow; } namespace Ui { class CMainWindow; }
QT_END_NAMESPACE QT_END_NAMESPACE
class QGraphicsItem;
class QUndoStack;
class DrawingPanel; class DrawingPanel;
class GraphicElementsPanel; class GraphicElementsPanel;
class DesignerScene;
class CMainWindow : public QMainWindow class CMainWindow : public QMainWindow
{ {
@ -27,11 +30,21 @@ public:
protected: protected:
virtual void closeEvent(QCloseEvent* event) override; virtual void closeEvent(QCloseEvent* event) override;
private:
void initializeDockUi();
void initializeAction();
private slots:
void onSignal_addItem(QGraphicsItem*);
void onSignal_deleteItem();
private: private:
QAction* SavePerspectiveAction = nullptr; QAction* SavePerspectiveAction = nullptr;
QWidgetAction* PerspectiveListAction = nullptr; QWidgetAction* PerspectiveListAction = nullptr;
QComboBox* PerspectiveComboBox = nullptr; QComboBox* PerspectiveComboBox = nullptr;
QUndoStack* m_pUndoStack;
Ui::CMainWindow *ui; Ui::CMainWindow *ui;
ads::CDockManager* DockManager; ads::CDockManager* DockManager;
@ -40,10 +53,5 @@ private:
DrawingPanel* m_pDrawingPanel; DrawingPanel* m_pDrawingPanel;
GraphicElementsPanel* m_pGraphicElementsPanel; GraphicElementsPanel* m_pGraphicElementsPanel;
void createPerspectiveUi();
private slots:
void savePerspective();
}; };
#endif // MAINWINDOW_H #endif // MAINWINDOW_H

View File

@ -0,0 +1,46 @@
/**
*\file operationCommand.h
*
*\brief /,QUndoCommand
*
*\author dsc
*/
#ifndef OPERATIONCOMMAND_H
#define OPERATIONCOMMAND_H
#include <QUndoCommand>
#include <QGraphicsScene>
class AddItemCommand : public QUndoCommand
{
public:
explicit AddItemCommand(QGraphicsItem* item, QGraphicsScene* graphicsScene, QUndoCommand* parent = 0);
~AddItemCommand();
public:
void undo() override;
void redo() override;
private:
QGraphicsItem* m_pItem;
QPointF m_itemPos;
QGraphicsScene* m_pGraphicsScene;
};
class DeleteItemCommand : public QUndoCommand
{
public:
explicit DeleteItemCommand(QGraphicsScene* graphicsScene, QUndoCommand* parent = 0);
~DeleteItemCommand();
public:
void undo() override;
void redo() override;
private:
QList<QGraphicsItem*> m_listItem;
QGraphicsScene* m_pGraphicsScene;
};
#endif

View File

@ -83,6 +83,16 @@ void DesignerScene::mouseDoubleClickEvent(QGraphicsSceneMouseEvent* mouseEvent)
QGraphicsScene::mouseReleaseEvent(mouseEvent); QGraphicsScene::mouseReleaseEvent(mouseEvent);
} }
void DesignerScene::keyPressEvent(QKeyEvent* event)
{
QGraphicsScene::keyPressEvent(event);
}
void DesignerScene::keyReleaseEvent(QKeyEvent* event)
{
QGraphicsScene::keyReleaseEvent(event);
}
void DesignerScene::setGridVisible(bool bVisible) void DesignerScene::setGridVisible(bool bVisible)
{ {
m_bGridVisible = bVisible; m_bGridVisible = bVisible;

View File

@ -19,8 +19,6 @@ DrawingPanel::DrawingPanel(QWidget *parent)
m_pGraphicsView->setScene(m_pGraphicsScene); m_pGraphicsView->setScene(m_pGraphicsScene);
m_pGraphicsScene->setView(m_pGraphicsView); m_pGraphicsScene->setView(m_pGraphicsView);
ui->mainLayout->addWidget(m_pGraphicsView); ui->mainLayout->addWidget(m_pGraphicsView);
} }
DrawingPanel::~DrawingPanel() DrawingPanel::~DrawingPanel()
@ -28,6 +26,16 @@ DrawingPanel::~DrawingPanel()
delete ui; delete ui;
} }
QGraphicsScene* DrawingPanel::getQGraphicsScene()
{
return m_pGraphicsView->scene();
}
DesignerScene* DrawingPanel::getDesignerScene()
{
return m_pGraphicsScene;
}
void DrawingPanel::onSignal_addGraphicsItem(GraphicsItemType& itemType) void DrawingPanel::onSignal_addGraphicsItem(GraphicsItemType& itemType)
{ {
if(SelectorManager::getInstance()) if(SelectorManager::getInstance())

View File

@ -3,20 +3,11 @@
#include "ui_mainwindow.h" #include "ui_mainwindow.h"
#include <QWidgetAction> #include <QWidgetAction>
#include <QLabel>
#include <QCalendarWidget>
#include <QTreeView>
#include <QFileSystemModel>
#include <QTableWidget> #include <QTableWidget>
#include <QHBoxLayout>
#include <QRadioButton>
#include <QPushButton>
#include <QInputDialog>
#include <QFileDialog>
#include <QSettings> #include <QSettings>
#include <QMessageBox> #include <QUndoStack>
#include <QPlainTextEdit> #include <QGraphicsScene>
#include <QToolBar> #include <QGraphicsItem>
#include "DockAreaWidget.h" #include "DockAreaWidget.h"
#include "DockAreaTitleBar.h" #include "DockAreaTitleBar.h"
@ -25,7 +16,9 @@
#include "DockComponentsFactory.h" #include "DockComponentsFactory.h"
#include "drawingPanel.h" #include "drawingPanel.h"
#include "designerScene.h"
#include "graphicElementsPanel.h" #include "graphicElementsPanel.h"
#include "operationCommand.h"
using namespace ads; using namespace ads;
@ -35,6 +28,30 @@ CMainWindow::CMainWindow(QWidget *parent)
, ui(new Ui::CMainWindow) , ui(new Ui::CMainWindow)
{ {
ui->setupUi(this); ui->setupUi(this);
m_pUndoStack = nullptr;
initializeDockUi();
initializeAction();
connect(m_pGraphicElementsPanel,SIGNAL(addGraphicsItem(GraphicsItemType&)),m_pDrawingPanel,SLOT(onSignal_addGraphicsItem(GraphicsItemType&)));
}
CMainWindow::~CMainWindow()
{
delete ui;
}
void CMainWindow::closeEvent(QCloseEvent* event)
{
// Delete dock manager here to delete all floating widgets. This ensures
// that all top level windows of the dock manager are properly closed
DockManager->deleteLater();
QMainWindow::closeEvent(event);
}
void CMainWindow::initializeDockUi()
{
CDockManager::setConfigFlag(CDockManager::OpaqueSplitterResize, true); CDockManager::setConfigFlag(CDockManager::OpaqueSplitterResize, true);
CDockManager::setConfigFlag(CDockManager::XmlCompressionEnabled, false); CDockManager::setConfigFlag(CDockManager::XmlCompressionEnabled, false);
CDockManager::setConfigFlag(CDockManager::FocusHighlighting, true); CDockManager::setConfigFlag(CDockManager::FocusHighlighting, true);
@ -42,6 +59,7 @@ CMainWindow::CMainWindow(QWidget *parent)
// Set central widget // Set central widget
m_pDrawingPanel = new DrawingPanel(); m_pDrawingPanel = new DrawingPanel();
connect(m_pDrawingPanel->getDesignerScene(), SIGNAL(signalAddItem(QGraphicsItem*)), this, SLOT(onSignal_addItem(QGraphicsItem*)));
CDockWidget* CentralDockWidget = new CDockWidget("CentralWidget"); CDockWidget* CentralDockWidget = new CDockWidget("CentralWidget");
CentralDockWidget->setWidget(m_pDrawingPanel); CentralDockWidget->setWidget(m_pDrawingPanel);
auto* CentralDockArea = DockManager->setCentralWidget(CentralDockWidget); auto* CentralDockArea = DockManager->setCentralWidget(CentralDockWidget);
@ -54,10 +72,9 @@ CMainWindow::CMainWindow(QWidget *parent)
GrapicElementsDockWidget->setMinimumSizeHintMode(CDockWidget::MinimumSizeHintFromDockWidget); GrapicElementsDockWidget->setMinimumSizeHintMode(CDockWidget::MinimumSizeHintFromDockWidget);
GrapicElementsDockWidget->resize(400, 150); GrapicElementsDockWidget->resize(400, 150);
GrapicElementsDockWidget->setMinimumSize(200,150); GrapicElementsDockWidget->setMinimumSize(200,150);
auto TableArea = DockManager->addDockWidget(DockWidgetArea::LeftDockWidgetArea, GrapicElementsDockWidget); DockManager->addDockWidget(DockWidgetArea::LeftDockWidgetArea, GrapicElementsDockWidget);
ui->menuView->addAction(GrapicElementsDockWidget->toggleViewAction()); ui->menuView->addAction(GrapicElementsDockWidget->toggleViewAction());
QTableWidget* propertiesTable = new QTableWidget(); QTableWidget* propertiesTable = new QTableWidget();
propertiesTable->setColumnCount(3); propertiesTable->setColumnCount(3);
propertiesTable->setRowCount(10); propertiesTable->setRowCount(10);
@ -68,57 +85,41 @@ CMainWindow::CMainWindow(QWidget *parent)
PropertiesDockWidget->setMinimumSize(200,150); PropertiesDockWidget->setMinimumSize(200,150);
DockManager->addDockWidget(DockWidgetArea::RightDockWidgetArea, PropertiesDockWidget, CentralDockArea); DockManager->addDockWidget(DockWidgetArea::RightDockWidgetArea, PropertiesDockWidget, CentralDockArea);
ui->menuView->addAction(PropertiesDockWidget->toggleViewAction()); ui->menuView->addAction(PropertiesDockWidget->toggleViewAction());
//createPerspectiveUi();
connect(m_pGraphicElementsPanel,SIGNAL(addGraphicsItem(GraphicsItemType&)),m_pDrawingPanel,SLOT(onSignal_addGraphicsItem(GraphicsItemType&)));
} }
CMainWindow::~CMainWindow() void CMainWindow::initializeAction()
{ {
delete ui; //撤销、重做
m_pUndoStack = new QUndoStack(this);
ui->actionUndo = m_pUndoStack->createUndoAction(this, tr("撤销"));
ui->actionUndo->setIcon(QIcon::fromTheme(QString::fromUtf8("edit-undo")));
ui->actionUndo->setShortcuts(QKeySequence::Undo);
ui->actionRedo = m_pUndoStack->createRedoAction(this, tr("重做"));
ui->actionRedo->setIcon(QIcon::fromTheme(QString::fromUtf8("edit-redo")));
ui->actionRedo->setShortcuts(QKeySequence::Redo);
ui->toolBar->addAction(ui->actionUndo);
ui->toolBar->addAction(ui->actionRedo);
ui->actionUndo->setEnabled(m_pUndoStack->canUndo());
ui->actionRedo->setEnabled(m_pUndoStack->canRedo());
ui->actionDelete->setShortcut(QKeySequence::Delete);
connect(ui->actionDelete, SIGNAL(triggered()), this, SLOT(onSignal_deleteItem()));
} }
void CMainWindow::onSignal_addItem(QGraphicsItem* item)
void CMainWindow::createPerspectiveUi()
{ {
SavePerspectiveAction = new QAction("Create Perspective", this); QUndoCommand* addItemCommand = new AddItemCommand(item, item->scene());
connect(SavePerspectiveAction, SIGNAL(triggered()), SLOT(savePerspective())); m_pUndoStack->push(addItemCommand);
PerspectiveListAction = new QWidgetAction(this);
PerspectiveComboBox = new QComboBox(this);
PerspectiveComboBox->setSizeAdjustPolicy(QComboBox::AdjustToContents);
PerspectiveComboBox->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred);
connect(PerspectiveComboBox, SIGNAL(currentTextChanged(const QString&)),
DockManager, SLOT(openPerspective(const QString&)));
PerspectiveListAction->setDefaultWidget(PerspectiveComboBox);
ui->toolBar->addSeparator();
ui->toolBar->addAction(PerspectiveListAction);
ui->toolBar->addAction(SavePerspectiveAction);
} }
void CMainWindow::onSignal_deleteItem()
void CMainWindow::savePerspective()
{
QString PerspectiveName = QInputDialog::getText(this, "Save Perspective", "Enter unique name:");
if (PerspectiveName.isEmpty())
{ {
QGraphicsScene* scene = m_pDrawingPanel->getQGraphicsScene();
if (scene && scene->selectedItems().isEmpty())
return; return;
QUndoCommand* deleteItemCommand = new DeleteItemCommand(scene);
m_pUndoStack->push(deleteItemCommand); //push时会自动调用一次command的redo函数
} }
DockManager->addPerspective(PerspectiveName);
QSignalBlocker Blocker(PerspectiveComboBox);
PerspectiveComboBox->clear();
PerspectiveComboBox->addItems(DockManager->perspectiveNames());
PerspectiveComboBox->setCurrentText(PerspectiveName);
}
//============================================================================
void CMainWindow::closeEvent(QCloseEvent* event)
{
// Delete dock manager here to delete all floating widgets. This ensures
// that all top level windows of the dock manager are properly closed
DockManager->deleteLater();
QMainWindow::closeEvent(event);
}

View File

@ -0,0 +1,64 @@
#include "operationCommand.h"
#include <QGraphicsItem>
AddItemCommand::AddItemCommand(QGraphicsItem* item, QGraphicsScene* scene, QUndoCommand* parent)
: QUndoCommand(parent)
{
m_pItem = item;
m_itemPos = item->pos();
m_pGraphicsScene = scene;
}
AddItemCommand::~AddItemCommand()
{
}
void AddItemCommand::undo()
{
m_pGraphicsScene->removeItem(m_pItem);
m_pGraphicsScene->update();
}
void AddItemCommand::redo()
{
if(m_pItem->scene()) //因为添加图元后同步创建一条该指令平且在push进入stack的时候redo会被触发一次因此这里加判断防止重复操作
return;
m_pGraphicsScene->addItem(m_pItem);
m_pItem->setPos(m_itemPos);
m_pGraphicsScene->update();
}
DeleteItemCommand::DeleteItemCommand(QGraphicsScene* scene, QUndoCommand* parent)
: QUndoCommand(parent)
{
m_pGraphicsScene = scene;
m_listItem = scene->selectedItems();
}
DeleteItemCommand::~DeleteItemCommand()
{
}
void DeleteItemCommand::undo()
{
foreach(QGraphicsItem* item, m_listItem)
{
QGraphicsItemGroup* group = dynamic_cast<QGraphicsItemGroup*>(item->parentItem());
if(!group)
{
m_pGraphicsScene->addItem(item);
}
}
m_pGraphicsScene->update();
}
void DeleteItemCommand::redo()
{
foreach(QGraphicsItem* item, m_listItem)
{
QGraphicsItemGroup* group = dynamic_cast<QGraphicsItemGroup*>(item->parentItem());
if(!group)
{
m_pGraphicsScene->removeItem(item); //remove即可不要delete因为会影响撤回undo操作
}
}
m_pGraphicsScene->update();
}

View File

@ -80,6 +80,7 @@ void CreatingSelector::mouseReleaseEvent(QGraphicsSceneMouseEvent* event, Design
else if (m_pCreatingItem && ms_ptMouseLast != ms_ptMouseDown) else if (m_pCreatingItem && ms_ptMouseLast != ms_ptMouseDown)
{ {
m_pCreatingItem->updateCoordinate(); m_pCreatingItem->updateCoordinate();
emit scene->signalAddItem(m_pCreatingItem);
} }
ms_nDragHandle = H_none; ms_nDragHandle = H_none;

View File

@ -7,7 +7,7 @@
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>1284</width> <width>1284</width>
<height>757</height> <height>756</height>
</rect> </rect>
</property> </property>
<property name="windowTitle"> <property name="windowTitle">
@ -60,8 +60,6 @@
<addaction name="actionZoomFit"/> <addaction name="actionZoomFit"/>
<addaction name="actionGrid"/> <addaction name="actionGrid"/>
<addaction name="separator"/> <addaction name="separator"/>
<addaction name="actionUndo"/>
<addaction name="actionRedo"/>
</widget> </widget>
<action name="actionNew"> <action name="actionNew">
<property name="icon"> <property name="icon">
@ -224,9 +222,6 @@
<property name="toolTip"> <property name="toolTip">
<string>撤销</string> <string>撤销</string>
</property> </property>
<property name="menuRole">
<enum>QAction::MenuRole::NoRole</enum>
</property>
</action> </action>
<action name="actionRedo"> <action name="actionRedo">
<property name="icon"> <property name="icon">