diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp
index cc42105..b5805b1 100644
--- a/src/mainwindow.cpp
+++ b/src/mainwindow.cpp
@@ -112,6 +112,16 @@ MainWindow::MainWindow( bool enablePrint )
m_menuEdit = menuBar()->addMenu( tr( "Edit", "Menu item \"Edit\"" ) );
+ m_actionUndo = m_menuEdit->addAction( tr( "Undo", "Menu item \"Undo\"" ),
+ this,
+ SLOT(onMenuUndo()),
+ QKeySequence( Qt::CTRL + Qt::Key_Z ) );
+
+ m_actionRedo = m_menuEdit->addAction( tr( "Redo", "Menu item \"Redo\"" ),
+ this,
+ SLOT(onMenuRedo()),
+ QKeySequence( Qt::CTRL + Qt::Key_R ) );
+
m_actionCopy = m_menuEdit->addAction( tr( "Copy", "Menu item \"Copy\"" ),
this,
SLOT(onMenuCopy()),
@@ -244,10 +254,11 @@ void MainWindow::onMenuNewLabel( int mode )
{
QCDView *newView = new QCDView;
QCDScene *scene = new QCDScene( newView );
- scene->setLabelMode( LabelMode( mode ) );
+ scene->start( LabelMode( mode ) );
newView->setScene( scene );
scene->setName();
connect( scene, SIGNAL(selectionChanged()), this, SLOT(updateMenu()) );
+ connect( scene, SIGNAL(changed()), this, SLOT(updateMenu()) );
QMdiSubWindow *subWindow = m_mdiArea->addSubWindow( newView );
subWindow->show();
@@ -311,6 +322,7 @@ void MainWindow::onMenuOpen()
return;
}
connect( scene, SIGNAL(selectionChanged()), this, SLOT(updateMenu()) );
+ connect( scene, SIGNAL(changed()), this, SLOT(updateMenu()) );
QMdiSubWindow *subWindow = m_mdiArea->addSubWindow( newView );
subWindow->show();
@@ -377,6 +389,20 @@ void MainWindow::onMenuPrint()
}
}
+void MainWindow::onMenuUndo()
+{
+ QCDScene *scene = getScene( m_mdiArea );
+ if( scene )
+ scene->undo();
+}
+
+void MainWindow::onMenuRedo()
+{
+ QCDScene *scene = getScene( m_mdiArea );
+ if( scene )
+ scene->redo();
+}
+
void MainWindow::onMenuCopy()
{
QCDScene *scene = getScene( m_mdiArea );
@@ -403,7 +429,7 @@ void MainWindow::onMenuAbout()
QMessageBox::about( this,
tr( "About" ),
tr( "
qlscribe - Qt lisghtScribe
"
- "release 0.9 $Revision$
"
+ "prerelease 0.10 $Revision$
"
"visit project at home page "
"qlscribe.sourceforge.net
" ) );
}
@@ -425,10 +451,15 @@ void MainWindow::updateMenu()
m_menuInsert->setEnabled( scene );
if( !scene ) {
+ m_actionUndo->setEnabled( false );
+ m_actionRedo->setEnabled( false );
m_actionCopy->setEnabled( false );
m_actionCut->setEnabled( false );
m_actionPaste->setEnabled( false );
} else {
+ m_actionUndo->setEnabled( scene->canUndo() );
+ m_actionRedo->setEnabled( scene->canRedo() );
+
const QMimeData *mdata = QApplication::clipboard()->mimeData();
m_actionPaste->setEnabled( mdata && mdata->hasFormat( itemMimeType ) );
diff --git a/src/mainwindow.h b/src/mainwindow.h
index 56e54db..b2faa6b 100644
--- a/src/mainwindow.h
+++ b/src/mainwindow.h
@@ -48,6 +48,8 @@ private slots:
void onMenuProperties();
void onMenuPrintPreview();
void onMenuPrint();
+ void onMenuUndo();
+ void onMenuRedo();
void onMenuCopy();
void onMenuCut();
void onMenuPaste();
@@ -72,6 +74,8 @@ private:
QAction *m_actionLabelProperties;
QAction *m_actionPrint;
QAction *m_actionPrintPreview;
+ QAction *m_actionUndo;
+ QAction *m_actionRedo;
QAction *m_actionCopy;
QAction *m_actionCut;
QAction *m_actionPaste;
diff --git a/src/qcdscene.cpp b/src/qcdscene.cpp
index 612acc3..85b55d1 100644
--- a/src/qcdscene.cpp
+++ b/src/qcdscene.cpp
@@ -39,10 +39,13 @@ QCDScene::QCDScene( QObject * parent )
: QGraphicsScene( parent ),
m_index( 0 ),
m_saved( true ),
+ m_itemMoved( false ),
m_labelMode( modeFull ),
- m_cdColor( Qt::white )
+ m_cdColor( Qt::white ),
+ m_undoPosition( m_undoBuffer.end() )
{
setSceneRect( -60.0, -60.0, 60.0 * 2, 60.0 * 2 );
+
}
//#include
@@ -70,6 +73,12 @@ void QCDScene::replace( const QString2String &strings )
}
}
+void QCDScene::start( LabelMode mode )
+{
+ setLabelMode( mode );
+ pushUndo();
+}
+
bool QCDScene::load( const QString &fileName, QString *errMessage )
{
QFile file( fileName );
@@ -94,9 +103,12 @@ bool QCDScene::load( const QString &fileName, QString *errMessage )
m_fileName = fileName;
m_saved = true;
setName();
+
+ pushUndo();
return true;
}
+
bool QCDScene::save()
{
QFile file( m_fileName );
@@ -143,10 +155,32 @@ void QCDScene::setName()
updateTitles();
}
-void QCDScene::setChanged()
+void QCDScene::setChanged( bool undo )
{
m_saved = false;
updateTitles();
+
+ if( undo && m_undoPosition != m_undoBuffer.end() )
+ pushUndo();
+
+ emit changed();
+}
+
+void QCDScene::pushUndo()
+{
+ if( canRedo() ) {
+ UndoBuffer::iterator pos = m_undoBuffer.begin() + 1 + ( m_undoPosition - m_undoBuffer.begin() );
+ m_undoBuffer.erase( pos, m_undoBuffer.end() );
+ }
+
+ QString data;
+ QXmlStreamWriter writer( &data );
+ write( writer );
+ m_undoBuffer.push_back( data );
+ if( m_undoBuffer.size() > 20 )
+ m_undoBuffer.pop_front();
+
+ m_undoPosition = m_undoBuffer.end() - 1;
}
void QCDScene::updateTitles() const
@@ -330,6 +364,16 @@ void QCDScene::contextMenuEvent( QGraphicsSceneContextMenuEvent *mouseEvent )
menu.exec( mouseEvent->screenPos() );
}
+void QCDScene::mouseReleaseEvent ( QGraphicsSceneMouseEvent *mouseEvent )
+{
+ if( m_itemMoved ) {
+ setChanged();
+ m_itemMoved = false;
+ }
+
+ QGraphicsScene::mouseReleaseEvent( mouseEvent );
+}
+
void QCDScene::onMenuEdit()
{
QList list = selectedItems();
@@ -387,4 +431,37 @@ void QCDScene::sendItemTo( bool front )
zValue = item->zValue() - 0.1;
}
selectedItem->setZValue( zValue );
+ setChanged();
+}
+
+bool QCDScene::canUndo() const
+{
+ return m_undoPosition - m_undoBuffer.begin() > 0;
+}
+
+bool QCDScene::canRedo() const
+{
+ return m_undoBuffer.end() - m_undoPosition > 1;
+}
+
+void QCDScene::unredo( bool undo )
+{
+ if( undo ) {
+ if( !canUndo() )
+ return;
+ --m_undoPosition;
+ } else {
+ if( !canRedo() )
+ return;
+ ++m_undoPosition;
+ }
+
+ try {
+ clear();
+ QXmlStreamReader reader( *m_undoPosition );
+ read( reader );
+ }
+ catch(...) {
+ }
+ setChanged( false );
}
diff --git a/src/qcdscene.h b/src/qcdscene.h
index 6a863b5..c0a6c9e 100644
--- a/src/qcdscene.h
+++ b/src/qcdscene.h
@@ -44,13 +44,19 @@ public:
bool isSaved() const { return m_saved; }
bool isUnnamed() const { return m_fileName.isEmpty(); }
+ bool canUndo() const;
+ bool canRedo() const;
- void setChanged();
+ void itemMoved() { m_itemMoved = true; }
+ void setChanged( bool undo = true );
void setName();
+ void start( LabelMode mode );
bool load( const QString &fileName, QString *errMessage = 0 );
void replace( const QString2String &strings );
bool save();
bool saveAs( const QString &fileName );
+ void undo() { unredo( true ); }
+ void redo() { unredo( false ); }
void putItemToClipboard( bool move );
void getItemFromClipboard();
@@ -59,8 +65,12 @@ public:
void redrawViews() const;
QString name() const { return m_name; }
+signals:
+ void changed();
+
protected:
virtual void contextMenuEvent( QGraphicsSceneContextMenuEvent *contextMenuEvent );
+ virtual void mouseReleaseEvent ( QGraphicsSceneMouseEvent *mouseEvent );
private slots:
void onMenuEdit();
@@ -75,14 +85,21 @@ private:
bool readItem( QXmlStreamReader &reader );
void read( QXmlStreamReader &reader );
void sendItemTo( bool front );
+ void pushUndo();
+ void unredo( bool undo );
private:
- QString m_name;
- QString m_fileName;
- int m_index;
- bool m_saved;
- LabelMode m_labelMode;
- QColor m_cdColor;
+ typedef QList UndoBuffer;
+
+ QString m_name;
+ QString m_fileName;
+ int m_index;
+ bool m_saved;
+ bool m_itemMoved;
+ LabelMode m_labelMode;
+ QColor m_cdColor;
+ UndoBuffer m_undoBuffer;
+ UndoBuffer::const_iterator m_undoPosition;
};
#endif //QCDSCENE_H
diff --git a/src/qlightpixmapitem.cpp b/src/qlightpixmapitem.cpp
index fce08c7..034a0c2 100644
--- a/src/qlightpixmapitem.cpp
+++ b/src/qlightpixmapitem.cpp
@@ -32,7 +32,7 @@ QLightPixmapItem::QLightPixmapItem()
QVariant QLightPixmapItem::itemChange( GraphicsItemChange change, const QVariant & value )
{
if( scene() && change == ItemPositionHasChanged )
- static_cast( scene() )->setChanged();
+ static_cast( scene() )->itemMoved();
return value;
}
diff --git a/src/qlightroundtextitem.cpp b/src/qlightroundtextitem.cpp
index b9e23ed..148d7ff 100644
--- a/src/qlightroundtextitem.cpp
+++ b/src/qlightroundtextitem.cpp
@@ -233,7 +233,7 @@ void QLightRoundTextItem::paint( QPainter *painter, const QStyleOptionGraphicsIt
QVariant QLightRoundTextItem::itemChange( GraphicsItemChange change, const QVariant & value )
{
if( scene() && change == ItemPositionHasChanged )
- static_cast( scene() )->setChanged();
+ static_cast( scene() )->itemMoved();
return value;
}
diff --git a/src/qlighttextitem.cpp b/src/qlighttextitem.cpp
index 6b89672..0f05cab 100644
--- a/src/qlighttextitem.cpp
+++ b/src/qlighttextitem.cpp
@@ -33,7 +33,7 @@ QLightTextItem::QLightTextItem()
QVariant QLightTextItem::itemChange( GraphicsItemChange change, const QVariant & value )
{
if( scene() && change == ItemPositionHasChanged )
- static_cast( scene() )->setChanged();
+ static_cast( scene() )->itemMoved();
return value;
}