Started adding undo/redo framework.
This commit is contained in:
@@ -51,6 +51,7 @@ set (glabels_sources
|
|||||||
TemplatePicker.cpp
|
TemplatePicker.cpp
|
||||||
TemplatePickerItem.cpp
|
TemplatePickerItem.cpp
|
||||||
TextNode.cpp
|
TextNode.cpp
|
||||||
|
UndoRedoModel.cpp
|
||||||
XmlLabelCreator.cpp
|
XmlLabelCreator.cpp
|
||||||
XmlLabelParser.cpp
|
XmlLabelParser.cpp
|
||||||
)
|
)
|
||||||
@@ -87,6 +88,7 @@ set (glabels_qobject_headers
|
|||||||
SimplePreview.h
|
SimplePreview.h
|
||||||
StartupWizard.h
|
StartupWizard.h
|
||||||
TemplatePicker.h
|
TemplatePicker.h
|
||||||
|
UndoRedoModel.h
|
||||||
)
|
)
|
||||||
|
|
||||||
set (glabels_forms
|
set (glabels_forms
|
||||||
|
|||||||
+10
-1
@@ -28,6 +28,7 @@
|
|||||||
#include "LabelModel.h"
|
#include "LabelModel.h"
|
||||||
#include "LabelModelObject.h"
|
#include "LabelModelObject.h"
|
||||||
#include "LabelModelBoxObject.h"
|
#include "LabelModelBoxObject.h"
|
||||||
|
#include "UndoRedoModel.h"
|
||||||
#include "Settings.h"
|
#include "Settings.h"
|
||||||
#include "Cursors.h"
|
#include "Cursors.h"
|
||||||
|
|
||||||
@@ -81,6 +82,7 @@ LabelEditor::LabelEditor( QScrollArea* scrollArea, QWidget* parent )
|
|||||||
mState = IdleState;
|
mState = IdleState;
|
||||||
|
|
||||||
mModel = 0;
|
mModel = 0;
|
||||||
|
mUndoRedoModel = 0;
|
||||||
mMarkupVisible = true;
|
mMarkupVisible = true;
|
||||||
mGridVisible = true;
|
mGridVisible = true;
|
||||||
mGridSpacing = 18;
|
mGridSpacing = 18;
|
||||||
@@ -127,9 +129,10 @@ LabelEditor::qridVisible() const
|
|||||||
/// Model Parameter Setter
|
/// Model Parameter Setter
|
||||||
///
|
///
|
||||||
void
|
void
|
||||||
LabelEditor::setModel( LabelModel* model )
|
LabelEditor::setModel( LabelModel* model, UndoRedoModel* undoRedoModel )
|
||||||
{
|
{
|
||||||
mModel = model;
|
mModel = model;
|
||||||
|
mUndoRedoModel = undoRedoModel;
|
||||||
|
|
||||||
if ( model )
|
if ( model )
|
||||||
{
|
{
|
||||||
@@ -571,6 +574,7 @@ LabelEditor::mouseMoveEvent( QMouseEvent* event )
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case ArrowMove:
|
case ArrowMove:
|
||||||
|
mUndoRedoModel->checkpoint( tr("Move") );
|
||||||
mModel->moveSelection( (xWorld - mMoveLastX),
|
mModel->moveSelection( (xWorld - mMoveLastX),
|
||||||
(yWorld - mMoveLastY) );
|
(yWorld - mMoveLastY) );
|
||||||
mMoveLastX = xWorld;
|
mMoveLastX = xWorld;
|
||||||
@@ -867,22 +871,27 @@ LabelEditor::keyPressEvent( QKeyEvent* event )
|
|||||||
{
|
{
|
||||||
|
|
||||||
case Qt::Key_Left:
|
case Qt::Key_Left:
|
||||||
|
mUndoRedoModel->checkpoint( tr("Move") );
|
||||||
mModel->moveSelection( -mStepSize, glabels::Distance(0) );
|
mModel->moveSelection( -mStepSize, glabels::Distance(0) );
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case Qt::Key_Up:
|
case Qt::Key_Up:
|
||||||
|
mUndoRedoModel->checkpoint( tr("Move") );
|
||||||
mModel->moveSelection( glabels::Distance(0), -mStepSize );
|
mModel->moveSelection( glabels::Distance(0), -mStepSize );
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case Qt::Key_Right:
|
case Qt::Key_Right:
|
||||||
|
mUndoRedoModel->checkpoint( tr("Move") );
|
||||||
mModel->moveSelection( mStepSize, glabels::Distance(0) );
|
mModel->moveSelection( mStepSize, glabels::Distance(0) );
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case Qt::Key_Down:
|
case Qt::Key_Down:
|
||||||
|
mUndoRedoModel->checkpoint( tr("Move") );
|
||||||
mModel->moveSelection( glabels::Distance(0), mStepSize );
|
mModel->moveSelection( glabels::Distance(0), mStepSize );
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case Qt::Key_Delete:
|
case Qt::Key_Delete:
|
||||||
|
mUndoRedoModel->checkpoint( tr("Delete") );
|
||||||
mModel->deleteSelection();
|
mModel->deleteSelection();
|
||||||
setCursor( Qt::ArrowCursor );
|
setCursor( Qt::ArrowCursor );
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -31,6 +31,7 @@
|
|||||||
// Forward References
|
// Forward References
|
||||||
class LabelModel;
|
class LabelModel;
|
||||||
class LabelModelObject;
|
class LabelModelObject;
|
||||||
|
class UndoRedoModel;
|
||||||
class Handle;
|
class Handle;
|
||||||
|
|
||||||
|
|
||||||
@@ -72,7 +73,7 @@ public:
|
|||||||
// Model
|
// Model
|
||||||
/////////////////////////////////////
|
/////////////////////////////////////
|
||||||
public:
|
public:
|
||||||
void setModel( LabelModel* model );
|
void setModel( LabelModel* model, UndoRedoModel* undoRedoModel );
|
||||||
|
|
||||||
|
|
||||||
/////////////////////////////////////
|
/////////////////////////////////////
|
||||||
@@ -184,6 +185,7 @@ private:
|
|||||||
glabels::Distance mStepSize;
|
glabels::Distance mStepSize;
|
||||||
|
|
||||||
LabelModel* mModel;
|
LabelModel* mModel;
|
||||||
|
UndoRedoModel* mUndoRedoModel;
|
||||||
|
|
||||||
State mState;
|
State mState;
|
||||||
|
|
||||||
|
|||||||
+39
-7
@@ -44,6 +44,7 @@
|
|||||||
#include "PrintView.h"
|
#include "PrintView.h"
|
||||||
#include "LabelModel.h"
|
#include "LabelModel.h"
|
||||||
#include "LabelModelBoxObject.h"
|
#include "LabelModelBoxObject.h"
|
||||||
|
#include "UndoRedoModel.h"
|
||||||
#include "Icons.h"
|
#include "Icons.h"
|
||||||
#include "File.h"
|
#include "File.h"
|
||||||
#include "Help.h"
|
#include "Help.h"
|
||||||
@@ -163,8 +164,10 @@ LabelModel* MainWindow::model() const
|
|||||||
void MainWindow::setModel( LabelModel *label )
|
void MainWindow::setModel( LabelModel *label )
|
||||||
{
|
{
|
||||||
mModel = label;
|
mModel = label;
|
||||||
mPropertiesView->setModel( mModel );
|
mUndoRedoModel = new UndoRedoModel( mModel );
|
||||||
mLabelEditor->setModel( mModel );
|
|
||||||
|
mPropertiesView->setModel( mModel, mUndoRedoModel );
|
||||||
|
mLabelEditor->setModel( mModel, mUndoRedoModel );
|
||||||
mObjectEditor->setModel( mModel );
|
mObjectEditor->setModel( mModel );
|
||||||
mPrintView->setModel( mModel );
|
mPrintView->setModel( mModel );
|
||||||
|
|
||||||
@@ -180,6 +183,7 @@ void MainWindow::setModel( LabelModel *label )
|
|||||||
connect( mModel, SIGNAL(modifiedChanged()), this, SLOT(onModifiedChanged()) );
|
connect( mModel, SIGNAL(modifiedChanged()), this, SLOT(onModifiedChanged()) );
|
||||||
connect( mModel, SIGNAL(selectionChanged()), this, SLOT(onSelectionChanged()) );
|
connect( mModel, SIGNAL(selectionChanged()), this, SLOT(onSelectionChanged()) );
|
||||||
connect( mModel, SIGNAL(changed()), this, SLOT(onLabelChanged()) );
|
connect( mModel, SIGNAL(changed()), this, SLOT(onLabelChanged()) );
|
||||||
|
connect( mUndoRedoModel, SIGNAL(changed()), this, SLOT(onUndoRedoChanged()) );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -726,8 +730,8 @@ void MainWindow::setDocVerbsEnabled( bool enabled )
|
|||||||
{
|
{
|
||||||
fileSaveAction->setEnabled( enabled );
|
fileSaveAction->setEnabled( enabled );
|
||||||
fileSaveAsAction->setEnabled( enabled );
|
fileSaveAsAction->setEnabled( enabled );
|
||||||
editUndoAction->setEnabled( enabled );
|
editUndoAction->setEnabled( enabled && mUndoRedoModel->canUndo() );
|
||||||
editRedoAction->setEnabled( enabled );
|
editRedoAction->setEnabled( enabled && mUndoRedoModel->canRedo() );
|
||||||
editDeleteAction->setEnabled( enabled );
|
editDeleteAction->setEnabled( enabled );
|
||||||
editSelectAllAction->setEnabled( enabled );
|
editSelectAllAction->setEnabled( enabled );
|
||||||
editUnSelectAllAction->setEnabled( enabled );
|
editUnSelectAllAction->setEnabled( enabled );
|
||||||
@@ -979,7 +983,7 @@ void MainWindow::fileExit()
|
|||||||
///
|
///
|
||||||
void MainWindow::editUndo()
|
void MainWindow::editUndo()
|
||||||
{
|
{
|
||||||
qDebug() << "ACTION: edit->Undo";
|
mUndoRedoModel->undo();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -988,7 +992,7 @@ void MainWindow::editUndo()
|
|||||||
///
|
///
|
||||||
void MainWindow::editRedo()
|
void MainWindow::editRedo()
|
||||||
{
|
{
|
||||||
qDebug() << "ACTION: edit->Redo";
|
mUndoRedoModel->redo();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -997,6 +1001,7 @@ void MainWindow::editRedo()
|
|||||||
///
|
///
|
||||||
void MainWindow::editCut()
|
void MainWindow::editCut()
|
||||||
{
|
{
|
||||||
|
mUndoRedoModel->checkpoint( tr("Cut") );
|
||||||
mModel->cutSelection();
|
mModel->cutSelection();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1006,6 +1011,7 @@ void MainWindow::editCut()
|
|||||||
///
|
///
|
||||||
void MainWindow::editCopy()
|
void MainWindow::editCopy()
|
||||||
{
|
{
|
||||||
|
// Non-destructive -- do not checkpoint.
|
||||||
mModel->copySelection();
|
mModel->copySelection();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1015,6 +1021,7 @@ void MainWindow::editCopy()
|
|||||||
///
|
///
|
||||||
void MainWindow::editPaste()
|
void MainWindow::editPaste()
|
||||||
{
|
{
|
||||||
|
mUndoRedoModel->checkpoint( tr("Paste") );
|
||||||
mModel->paste();
|
mModel->paste();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1024,6 +1031,7 @@ void MainWindow::editPaste()
|
|||||||
///
|
///
|
||||||
void MainWindow::editDelete()
|
void MainWindow::editDelete()
|
||||||
{
|
{
|
||||||
|
mUndoRedoModel->checkpoint( tr("Delete") );
|
||||||
mModel->deleteSelection();
|
mModel->deleteSelection();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1151,6 +1159,7 @@ void MainWindow::objectsCreateText()
|
|||||||
///
|
///
|
||||||
void MainWindow::objectsCreateBox()
|
void MainWindow::objectsCreateBox()
|
||||||
{
|
{
|
||||||
|
mUndoRedoModel->checkpoint( tr("Create Box") );
|
||||||
mLabelEditor->createBoxMode();
|
mLabelEditor->createBoxMode();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1196,6 +1205,7 @@ void MainWindow::objectsCreateBarcode()
|
|||||||
///
|
///
|
||||||
void MainWindow::objectsOrderRaise()
|
void MainWindow::objectsOrderRaise()
|
||||||
{
|
{
|
||||||
|
mUndoRedoModel->checkpoint( tr("Bring To Front") );
|
||||||
mModel->raiseSelectionToTop();
|
mModel->raiseSelectionToTop();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1205,6 +1215,7 @@ void MainWindow::objectsOrderRaise()
|
|||||||
///
|
///
|
||||||
void MainWindow::objectsOrderLower()
|
void MainWindow::objectsOrderLower()
|
||||||
{
|
{
|
||||||
|
mUndoRedoModel->checkpoint( tr("Send To Back") );
|
||||||
mModel->lowerSelectionToBottom();
|
mModel->lowerSelectionToBottom();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1214,6 +1225,7 @@ void MainWindow::objectsOrderLower()
|
|||||||
///
|
///
|
||||||
void MainWindow::objectsXformRotateLeft()
|
void MainWindow::objectsXformRotateLeft()
|
||||||
{
|
{
|
||||||
|
mUndoRedoModel->checkpoint( tr("Rotate Left") );
|
||||||
mModel->rotateSelectionLeft();
|
mModel->rotateSelectionLeft();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1223,6 +1235,7 @@ void MainWindow::objectsXformRotateLeft()
|
|||||||
///
|
///
|
||||||
void MainWindow::objectsXformRotateRight()
|
void MainWindow::objectsXformRotateRight()
|
||||||
{
|
{
|
||||||
|
mUndoRedoModel->checkpoint( tr("Rotate Right") );
|
||||||
mModel->rotateSelectionRight();
|
mModel->rotateSelectionRight();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1232,6 +1245,7 @@ void MainWindow::objectsXformRotateRight()
|
|||||||
///
|
///
|
||||||
void MainWindow::objectsXformFlipHoriz()
|
void MainWindow::objectsXformFlipHoriz()
|
||||||
{
|
{
|
||||||
|
mUndoRedoModel->checkpoint( tr("Flip Horizontally") );
|
||||||
mModel->flipSelectionHoriz();
|
mModel->flipSelectionHoriz();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1241,6 +1255,7 @@ void MainWindow::objectsXformFlipHoriz()
|
|||||||
///
|
///
|
||||||
void MainWindow::objectsXformFlipVert()
|
void MainWindow::objectsXformFlipVert()
|
||||||
{
|
{
|
||||||
|
mUndoRedoModel->checkpoint( tr("Flip Vertically") );
|
||||||
mModel->flipSelectionVert();
|
mModel->flipSelectionVert();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1250,6 +1265,7 @@ void MainWindow::objectsXformFlipVert()
|
|||||||
///
|
///
|
||||||
void MainWindow::objectsAlignLeft()
|
void MainWindow::objectsAlignLeft()
|
||||||
{
|
{
|
||||||
|
mUndoRedoModel->checkpoint( tr("Align Left") );
|
||||||
mModel->alignSelectionLeft();
|
mModel->alignSelectionLeft();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1259,6 +1275,7 @@ void MainWindow::objectsAlignLeft()
|
|||||||
///
|
///
|
||||||
void MainWindow::objectsAlignHCenter()
|
void MainWindow::objectsAlignHCenter()
|
||||||
{
|
{
|
||||||
|
mUndoRedoModel->checkpoint( tr("Align Center") );
|
||||||
mModel->alignSelectionHCenter();
|
mModel->alignSelectionHCenter();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1268,6 +1285,7 @@ void MainWindow::objectsAlignHCenter()
|
|||||||
///
|
///
|
||||||
void MainWindow::objectsAlignRight()
|
void MainWindow::objectsAlignRight()
|
||||||
{
|
{
|
||||||
|
mUndoRedoModel->checkpoint( tr("Align Right") );
|
||||||
mModel->alignSelectionRight();
|
mModel->alignSelectionRight();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1277,6 +1295,7 @@ void MainWindow::objectsAlignRight()
|
|||||||
///
|
///
|
||||||
void MainWindow::objectsAlignTop()
|
void MainWindow::objectsAlignTop()
|
||||||
{
|
{
|
||||||
|
mUndoRedoModel->checkpoint( tr("Align Top") );
|
||||||
mModel->alignSelectionTop();
|
mModel->alignSelectionTop();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1286,6 +1305,7 @@ void MainWindow::objectsAlignTop()
|
|||||||
///
|
///
|
||||||
void MainWindow::objectsAlignVCenter()
|
void MainWindow::objectsAlignVCenter()
|
||||||
{
|
{
|
||||||
|
mUndoRedoModel->checkpoint( tr("Align Middle") );
|
||||||
mModel->alignSelectionVCenter();
|
mModel->alignSelectionVCenter();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1295,6 +1315,7 @@ void MainWindow::objectsAlignVCenter()
|
|||||||
///
|
///
|
||||||
void MainWindow::objectsAlignBottom()
|
void MainWindow::objectsAlignBottom()
|
||||||
{
|
{
|
||||||
|
mUndoRedoModel->checkpoint( tr("Align Bottom") );
|
||||||
mModel->alignSelectionBottom();
|
mModel->alignSelectionBottom();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1304,6 +1325,7 @@ void MainWindow::objectsAlignBottom()
|
|||||||
///
|
///
|
||||||
void MainWindow::objectsCenterHoriz()
|
void MainWindow::objectsCenterHoriz()
|
||||||
{
|
{
|
||||||
|
mUndoRedoModel->checkpoint( tr("Center Horizontally") );
|
||||||
mModel->centerSelectionHoriz();
|
mModel->centerSelectionHoriz();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1313,6 +1335,7 @@ void MainWindow::objectsCenterHoriz()
|
|||||||
///
|
///
|
||||||
void MainWindow::objectsCenterVert()
|
void MainWindow::objectsCenterVert()
|
||||||
{
|
{
|
||||||
|
mUndoRedoModel->checkpoint( tr("Center Vertically") );
|
||||||
mModel->centerSelectionVert();
|
mModel->centerSelectionVert();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1416,5 +1439,14 @@ void MainWindow::onSelectionChanged()
|
|||||||
///
|
///
|
||||||
void MainWindow::onLabelChanged()
|
void MainWindow::onLabelChanged()
|
||||||
{
|
{
|
||||||
/* @TODO: update undo/redo verbs. */
|
}
|
||||||
|
|
||||||
|
|
||||||
|
///
|
||||||
|
/// Undo/Redo changed handler
|
||||||
|
///
|
||||||
|
void MainWindow::onUndoRedoChanged()
|
||||||
|
{
|
||||||
|
editUndoAction->setEnabled( mUndoRedoModel->canUndo() );
|
||||||
|
editRedoAction->setEnabled( mUndoRedoModel->canRedo() );
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -37,6 +37,7 @@ class QScrollArea;
|
|||||||
|
|
||||||
// Forward References
|
// Forward References
|
||||||
class LabelModel;
|
class LabelModel;
|
||||||
|
class UndoRedoModel;
|
||||||
class PropertiesView;
|
class PropertiesView;
|
||||||
class LabelEditor;
|
class LabelEditor;
|
||||||
class ObjectEditor;
|
class ObjectEditor;
|
||||||
@@ -148,6 +149,7 @@ private slots:
|
|||||||
void onModifiedChanged();
|
void onModifiedChanged();
|
||||||
void onSelectionChanged();
|
void onSelectionChanged();
|
||||||
void onLabelChanged();
|
void onLabelChanged();
|
||||||
|
void onUndoRedoChanged();
|
||||||
|
|
||||||
|
|
||||||
/////////////////////////////////////
|
/////////////////////////////////////
|
||||||
@@ -204,9 +206,11 @@ private:
|
|||||||
QToolBar* fileToolBar;
|
QToolBar* fileToolBar;
|
||||||
QToolBar* editorToolBar;
|
QToolBar* editorToolBar;
|
||||||
|
|
||||||
|
LabelModel* mModel;
|
||||||
|
UndoRedoModel* mUndoRedoModel;
|
||||||
|
|
||||||
QListWidget* mContents;
|
QListWidget* mContents;
|
||||||
QStackedWidget* mPages;
|
QStackedWidget* mPages;
|
||||||
LabelModel* mModel;
|
|
||||||
PropertiesView* mPropertiesView;
|
PropertiesView* mPropertiesView;
|
||||||
QScrollArea* mLabelEditorScrollArea;
|
QScrollArea* mLabelEditorScrollArea;
|
||||||
LabelEditor* mLabelEditor;
|
LabelEditor* mLabelEditor;
|
||||||
|
|||||||
@@ -21,6 +21,7 @@
|
|||||||
#include "PropertiesView.h"
|
#include "PropertiesView.h"
|
||||||
|
|
||||||
#include "LabelModel.h"
|
#include "LabelModel.h"
|
||||||
|
#include "UndoRedoModel.h"
|
||||||
#include "Settings.h"
|
#include "Settings.h"
|
||||||
|
|
||||||
#include "libglabels/Db.h"
|
#include "libglabels/Db.h"
|
||||||
@@ -55,9 +56,10 @@ PropertiesView::~PropertiesView()
|
|||||||
///
|
///
|
||||||
/// Set Model
|
/// Set Model
|
||||||
///
|
///
|
||||||
void PropertiesView::setModel( LabelModel* model )
|
void PropertiesView::setModel( LabelModel* model, UndoRedoModel* undoRedoModel )
|
||||||
{
|
{
|
||||||
mModel = model;
|
mModel = model;
|
||||||
|
mUndoRedoModel = undoRedoModel;
|
||||||
|
|
||||||
connect( mModel, SIGNAL(sizeChanged()), this, SLOT(onLabelSizeChanged()) );
|
connect( mModel, SIGNAL(sizeChanged()), this, SLOT(onLabelSizeChanged()) );
|
||||||
|
|
||||||
@@ -171,11 +173,13 @@ void PropertiesView::onFormChanged()
|
|||||||
}
|
}
|
||||||
else if ( frame->w() > frame->h() )
|
else if ( frame->w() > frame->h() )
|
||||||
{
|
{
|
||||||
|
mUndoRedoModel->checkpoint( tr("Product Orientation") );
|
||||||
int index = orientationCombo->currentIndex();
|
int index = orientationCombo->currentIndex();
|
||||||
mModel->setRotate( index == 1 );
|
mModel->setRotate( index == 1 );
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
mUndoRedoModel->checkpoint( tr("Product Orientation") );
|
||||||
int index = orientationCombo->currentIndex();
|
int index = orientationCombo->currentIndex();
|
||||||
mModel->setRotate( index == 0 );
|
mModel->setRotate( index == 0 );
|
||||||
}
|
}
|
||||||
@@ -193,6 +197,8 @@ void PropertiesView::onChangeProductButtonClicked()
|
|||||||
const glabels::Template* tmplate = selectProductDialog.tmplate();
|
const glabels::Template* tmplate = selectProductDialog.tmplate();
|
||||||
if ( tmplate )
|
if ( tmplate )
|
||||||
{
|
{
|
||||||
|
mUndoRedoModel->checkpoint( tr("Change Product") );
|
||||||
|
|
||||||
mModel->setTmplate( tmplate );
|
mModel->setTmplate( tmplate );
|
||||||
|
|
||||||
// Don't rotate circular or round labels
|
// Don't rotate circular or round labels
|
||||||
|
|||||||
@@ -25,7 +25,9 @@
|
|||||||
|
|
||||||
#include "libglabels/Units.h"
|
#include "libglabels/Units.h"
|
||||||
|
|
||||||
class LabelModel; // Forward reference
|
// Forward references
|
||||||
|
class LabelModel;
|
||||||
|
class UndoRedoModel;
|
||||||
|
|
||||||
|
|
||||||
///
|
///
|
||||||
@@ -47,7 +49,7 @@ public:
|
|||||||
/////////////////////////////////
|
/////////////////////////////////
|
||||||
// Public methods
|
// Public methods
|
||||||
/////////////////////////////////
|
/////////////////////////////////
|
||||||
void setModel( LabelModel* model );
|
void setModel( LabelModel* model, UndoRedoModel* undoRedoModel );
|
||||||
|
|
||||||
|
|
||||||
/////////////////////////////////
|
/////////////////////////////////
|
||||||
@@ -65,6 +67,7 @@ private slots:
|
|||||||
/////////////////////////////////
|
/////////////////////////////////
|
||||||
private:
|
private:
|
||||||
LabelModel* mModel;
|
LabelModel* mModel;
|
||||||
|
UndoRedoModel* mUndoRedoModel;
|
||||||
glabels::Units mUnits;
|
glabels::Units mUnits;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -0,0 +1,255 @@
|
|||||||
|
/* UndoRedoModel.cpp
|
||||||
|
*
|
||||||
|
* Copyright (C) 2016 Jim Evins <evins@snaught.com>
|
||||||
|
*
|
||||||
|
* This file is part of gLabels-qt.
|
||||||
|
*
|
||||||
|
* gLabels-qt is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* gLabels-qt 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
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with gLabels-qt. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "UndoRedoModel.h"
|
||||||
|
|
||||||
|
#include "LabelModel.h"
|
||||||
|
|
||||||
|
|
||||||
|
///
|
||||||
|
/// Constructor
|
||||||
|
///
|
||||||
|
UndoRedoModel::UndoRedoModel( LabelModel* model )
|
||||||
|
{
|
||||||
|
mModel = model;
|
||||||
|
mNewSelection = true;
|
||||||
|
|
||||||
|
connect( model, SIGNAL(selectionChanged()), this, SLOT(onSelectionChanged()) );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
///
|
||||||
|
/// Destructor
|
||||||
|
///
|
||||||
|
UndoRedoModel::~UndoRedoModel()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
///
|
||||||
|
/// Checkpoint
|
||||||
|
///
|
||||||
|
void UndoRedoModel::checkpoint( const QString& description )
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// Do not perform consecutive checkpoints that are identical.
|
||||||
|
// E.g. moving an object by dragging, would produce a large number
|
||||||
|
// of incremental checkpoints -- what we really want is a single
|
||||||
|
// checkpoint so that we can undo the entire dragging effort with
|
||||||
|
// one "undo"
|
||||||
|
//
|
||||||
|
if ( mNewSelection || (description != mLastDescription) )
|
||||||
|
{
|
||||||
|
|
||||||
|
/* Sever old redo "thread" */
|
||||||
|
mRedoStack.clear();
|
||||||
|
|
||||||
|
/* Save state onto undo stack. */
|
||||||
|
State* stateNow = new State( mModel, description );
|
||||||
|
mUndoStack.push( stateNow );
|
||||||
|
|
||||||
|
/* Track consecutive checkpoints. */
|
||||||
|
mNewSelection = false;
|
||||||
|
mLastDescription = description;
|
||||||
|
|
||||||
|
emit changed();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
///
|
||||||
|
/// Undo
|
||||||
|
///
|
||||||
|
void UndoRedoModel::undo()
|
||||||
|
{
|
||||||
|
State* oldState = mUndoStack.pop();
|
||||||
|
State* stateNow = new State( mModel, oldState->description );
|
||||||
|
|
||||||
|
mRedoStack.push( stateNow );
|
||||||
|
|
||||||
|
mModel->restore( oldState->model );
|
||||||
|
delete oldState;
|
||||||
|
|
||||||
|
mNewSelection = true;
|
||||||
|
|
||||||
|
emit changed();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
///
|
||||||
|
/// Redo
|
||||||
|
///
|
||||||
|
void UndoRedoModel::redo()
|
||||||
|
{
|
||||||
|
State* oldState = mRedoStack.pop();
|
||||||
|
State* stateNow = new State( mModel, oldState->description );
|
||||||
|
|
||||||
|
mUndoStack.push( stateNow );
|
||||||
|
|
||||||
|
mModel->restore( oldState->model );
|
||||||
|
delete oldState;
|
||||||
|
|
||||||
|
mNewSelection = true;
|
||||||
|
|
||||||
|
emit changed();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
///
|
||||||
|
/// Can we undo?
|
||||||
|
///
|
||||||
|
bool UndoRedoModel::canUndo() const
|
||||||
|
{
|
||||||
|
return !mUndoStack.isEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
///
|
||||||
|
/// Can we redo?
|
||||||
|
///
|
||||||
|
bool UndoRedoModel::canRedo() const
|
||||||
|
{
|
||||||
|
return !mRedoStack.isEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
///
|
||||||
|
/// Undo description
|
||||||
|
///
|
||||||
|
QString UndoRedoModel::undoDescription() const
|
||||||
|
{
|
||||||
|
if ( canUndo() )
|
||||||
|
{
|
||||||
|
return mUndoStack.topState()->description;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
///
|
||||||
|
/// Redo description
|
||||||
|
///
|
||||||
|
QString UndoRedoModel::redoDescription() const
|
||||||
|
{
|
||||||
|
if ( canRedo() )
|
||||||
|
{
|
||||||
|
return mRedoStack.topState()->description;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
///
|
||||||
|
/// Selection changed handler
|
||||||
|
///
|
||||||
|
void UndoRedoModel::onSelectionChanged()
|
||||||
|
{
|
||||||
|
mNewSelection = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
///
|
||||||
|
/// State constructor
|
||||||
|
///
|
||||||
|
UndoRedoModel::State::State( LabelModel* model, const QString& description )
|
||||||
|
{
|
||||||
|
this->model = model->save();
|
||||||
|
this->description = description;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
///
|
||||||
|
/// State destructor
|
||||||
|
///
|
||||||
|
UndoRedoModel::State::~State()
|
||||||
|
{
|
||||||
|
delete model;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
///
|
||||||
|
/// Stack constructor
|
||||||
|
///
|
||||||
|
UndoRedoModel::Stack::Stack()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
///
|
||||||
|
/// Stack destructor
|
||||||
|
///
|
||||||
|
UndoRedoModel::Stack::~Stack()
|
||||||
|
{
|
||||||
|
clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
///
|
||||||
|
/// Push state onto stack
|
||||||
|
///
|
||||||
|
void UndoRedoModel::Stack::push( UndoRedoModel::State* state )
|
||||||
|
{
|
||||||
|
list.push_front( state );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
///
|
||||||
|
/// Pop state from stack
|
||||||
|
///
|
||||||
|
UndoRedoModel::State* UndoRedoModel::Stack::pop()
|
||||||
|
{
|
||||||
|
return list.takeFirst();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
///
|
||||||
|
/// Peek at state at top of stack
|
||||||
|
///
|
||||||
|
const UndoRedoModel::State* UndoRedoModel::Stack::topState() const
|
||||||
|
{
|
||||||
|
return list.first();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
///
|
||||||
|
/// Is stack empty?
|
||||||
|
///
|
||||||
|
bool UndoRedoModel::Stack::isEmpty() const
|
||||||
|
{
|
||||||
|
return list.isEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
///
|
||||||
|
/// Clear stack
|
||||||
|
///
|
||||||
|
void UndoRedoModel::Stack::clear()
|
||||||
|
{
|
||||||
|
while ( !isEmpty() )
|
||||||
|
{
|
||||||
|
delete pop();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,119 @@
|
|||||||
|
/* UndoRedoModel.h
|
||||||
|
*
|
||||||
|
* Copyright (C) 2016 Jim Evins <evins@snaught.com>
|
||||||
|
*
|
||||||
|
* This file is part of gLabels-qt.
|
||||||
|
*
|
||||||
|
* gLabels-qt is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* gLabels-qt 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
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with gLabels-qt. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef UndoRedoModel_h
|
||||||
|
#define UndoRedoModel_h
|
||||||
|
|
||||||
|
#include <QObject>
|
||||||
|
#include <QString>
|
||||||
|
#include <QList>
|
||||||
|
|
||||||
|
class LabelModel;
|
||||||
|
|
||||||
|
|
||||||
|
///
|
||||||
|
/// UndoRedoModel
|
||||||
|
///
|
||||||
|
struct UndoRedoModel : QObject
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
|
||||||
|
/////////////////////////////////
|
||||||
|
// Life Cycle
|
||||||
|
/////////////////////////////////
|
||||||
|
public:
|
||||||
|
UndoRedoModel( LabelModel* model );
|
||||||
|
virtual ~UndoRedoModel();
|
||||||
|
|
||||||
|
|
||||||
|
/////////////////////////////////
|
||||||
|
// Public Methods
|
||||||
|
/////////////////////////////////
|
||||||
|
public:
|
||||||
|
void checkpoint( const QString& description );
|
||||||
|
void undo();
|
||||||
|
void redo();
|
||||||
|
bool canUndo() const;
|
||||||
|
bool canRedo() const;
|
||||||
|
QString undoDescription() const;
|
||||||
|
QString redoDescription() const;
|
||||||
|
|
||||||
|
|
||||||
|
/////////////////////////////////
|
||||||
|
// Slots
|
||||||
|
/////////////////////////////////
|
||||||
|
private slots:
|
||||||
|
void onSelectionChanged();
|
||||||
|
|
||||||
|
|
||||||
|
/////////////////////////////////
|
||||||
|
// Signals
|
||||||
|
/////////////////////////////////
|
||||||
|
signals:
|
||||||
|
void changed();
|
||||||
|
|
||||||
|
|
||||||
|
/////////////////////////////////
|
||||||
|
// Private types
|
||||||
|
/////////////////////////////////
|
||||||
|
private:
|
||||||
|
class State
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
State( LabelModel* model, const QString& description );
|
||||||
|
~State();
|
||||||
|
|
||||||
|
LabelModel* model;
|
||||||
|
QString description;
|
||||||
|
};
|
||||||
|
|
||||||
|
class Stack
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Stack();
|
||||||
|
~Stack();
|
||||||
|
|
||||||
|
void push( State* state );
|
||||||
|
State* pop();
|
||||||
|
const State* topState() const;
|
||||||
|
bool isEmpty() const;
|
||||||
|
void clear();
|
||||||
|
|
||||||
|
private:
|
||||||
|
QList<State*> list;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/////////////////////////////////
|
||||||
|
// Private data
|
||||||
|
/////////////////////////////////
|
||||||
|
private:
|
||||||
|
LabelModel *mModel;
|
||||||
|
|
||||||
|
Stack mUndoStack;
|
||||||
|
Stack mRedoStack;
|
||||||
|
|
||||||
|
bool mNewSelection;
|
||||||
|
QString mLastDescription;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // UndoRedoModel_h
|
||||||
Reference in New Issue
Block a user