summaryrefslogtreecommitdiff
path: root/src/main-view/UndoCommands.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/main-view/UndoCommands.cpp')
-rw-r--r--src/main-view/UndoCommands.cpp322
1 files changed, 322 insertions, 0 deletions
diff --git a/src/main-view/UndoCommands.cpp b/src/main-view/UndoCommands.cpp
new file mode 100644
index 0000000..349b2a7
--- /dev/null
+++ b/src/main-view/UndoCommands.cpp
@@ -0,0 +1,322 @@
+#include "UndoCommands.h"
+#include "DictTableModel.h"
+#include "DictTableView.h"
+#include "../dictionary/Dictionary.h"
+#include "../dictionary/DicRecord.h"
+#include "../main-view/MainWindow.h"
+#include "../main-view/CardFilterModel.h"
+
+UndoRecordCmd::UndoRecordCmd( const MainWindow* aMainWin ):
+ m_mainWindow( aMainWin )
+ {
+ }
+
+const DictTableView* UndoRecordCmd::getCurView()
+ {
+ if( !m_mainWindow )
+ return NULL;
+ const DictTableView* dictView = m_mainWindow->getCurDictView(); // May be proxy view
+ return dictView;
+ }
+
+CardFilterModel* UndoRecordCmd::getProxyModel( const DictTableView* aCurDictView )
+ {
+ CardFilterModel* proxyModel = qobject_cast<CardFilterModel*>( aCurDictView->model() );
+ return proxyModel;
+ }
+
+void UndoRecordCmd::insertRows( QList<int> aRowNumbers )
+ {
+ const DictTableView* dictView = getCurView();
+ CardFilterModel* proxyModel = getProxyModel( dictView );
+
+ // Insert rows by positions in the direct order
+ foreach( int row, aRowNumbers )
+ {
+ if( proxyModel )
+ proxyModel->addFilterRow( row );
+ m_dictModel->insertRows( row, 1 );
+ }
+ }
+
+void UndoRecordCmd::setRecords( QMap<int, DicRecord*> aRecords )
+ {
+ Dictionary* dict = const_cast<Dictionary*>( m_dictModel->dictionary() );
+ dict->disableRecordUpdates();
+
+ // Init rows by positions in the direct order
+ foreach( int row, aRecords.keys() )
+ {
+ QModelIndex index = m_dictModel->index( row, 0 );
+ DicRecord* record = aRecords.value( row );
+ m_dictModel->setData( index, QVariant::fromValue( *record ), DictTableModel::DicRecordRole );
+ }
+ dict->enableRecordUpdates();
+ }
+
+void UndoRecordCmd::removeRows( QList<int> aRowNumbers )
+ {
+ const DictTableView* dictView = m_mainWindow->getCurDictView(); // May be proxy view
+ CardFilterModel* proxyModel = getProxyModel( dictView );
+ Dictionary* dict = const_cast<Dictionary*>( m_dictModel->dictionary() );
+ dict->disableRecordUpdates();
+
+ // Remove records by ranges from back
+ QListIterator<int> i( aRowNumbers );
+ i.toBack();
+ while( i.hasPrevious() )
+ {
+ int pos = i.previous();
+ if( proxyModel )
+ proxyModel->removeFilterRow( pos );
+ m_dictModel->removeRows( pos, 1 );
+ }
+ dict->enableRecordUpdates();
+ }
+
+
+/** Selects rows in the list.
+ * Sets the first row in the list as current.
+ */
+void UndoRecordCmd::selectRows( QList<int> aRowNumbers )
+ {
+ const DictTableView* dictView = m_mainWindow->getCurDictView(); // May be proxy view
+ CardFilterModel* proxyModel = getProxyModel( dictView );
+ int topRow = aRowNumbers.first();
+ if( topRow > m_dictModel->rowCount() - 1 ) // don't go beyond table boundaries
+ topRow = m_dictModel->rowCount() - 1;
+ QModelIndex topIndex = m_dictModel->index( topRow, 0, QModelIndex() );
+ QItemSelectionModel* selectionModel = dictView->selectionModel();
+ selectionModel->clear();
+ foreach( int row, aRowNumbers )
+ {
+ if( row > m_dictModel->rowCount() - 1 ) // don't go beyond table boundaries
+ row = m_dictModel->rowCount() - 1;
+ QModelIndex index = m_dictModel->index( row, 0, QModelIndex() );
+ if( proxyModel )
+ {
+ index = proxyModel->mapFromSource( index );
+ if( !index.isValid() )
+ continue;
+ }
+ selectionModel->setCurrentIndex( index, QItemSelectionModel::Select | QItemSelectionModel::Rows );
+ }
+ if( proxyModel )
+ topIndex = proxyModel->mapFromSource( topIndex );
+ if( topIndex.isValid() )
+ selectionModel->setCurrentIndex( topIndex, QItemSelectionModel::Current );
+ }
+
+void UndoRecordCmd::selectRow( int aRow )
+ {
+ QList<int> list;
+ list << aRow;
+ selectRows( list );
+ }
+
+//==============================================================================================================
+
+InsertRecordsCmd::InsertRecordsCmd( const MainWindow* aMainWin):
+ UndoRecordCmd( aMainWin )
+ {
+ const DictTableView* dictView = getCurView();
+ m_dictModel = dictView->dicTableModel(); // Always original model
+
+ // If no selection, insert 1 row in the end
+ int pos = m_dictModel->rowCount();
+ int rowsNum = 1;
+ QModelIndexList selectedRows = dictView->selectionModel()->selectedRows();
+ if( !selectedRows.isEmpty() )
+ // Insert number of rows equal to the selected rows
+ {
+ QAbstractProxyModel* proxyModel = qobject_cast<QAbstractProxyModel*>( dictView->model() );
+ if( proxyModel )
+ { // convert selection to source indexes
+ QModelIndexList list;
+ foreach( QModelIndex index, selectedRows )
+ list << proxyModel->mapToSource( index );
+ selectedRows = list;
+ }
+
+ qSort( selectedRows ); // to find the top row
+ pos = selectedRows.first().row();
+ rowsNum = selectedRows.size();
+ }
+ for( int r = pos; r < pos + rowsNum; r++ )
+ m_rowNumbers << r;
+
+ updateText();
+ }
+
+void InsertRecordsCmd::updateText()
+ {
+ setText(QObject::tr("Insert %n record(s)", "Undo action of inserting records", m_rowNumbers.size() ));
+ }
+
+void InsertRecordsCmd::redo()
+ {
+ insertRows( m_rowNumbers );
+ selectRows( m_rowNumbers );
+ }
+
+void InsertRecordsCmd::undo()
+ {
+ removeRows( m_rowNumbers );
+ selectRow( m_rowNumbers.first() );
+ }
+
+bool InsertRecordsCmd::mergeWith( const QUndoCommand* command )
+ {
+ const InsertRecordsCmd* otherInsertCmd = static_cast<const InsertRecordsCmd*>( command );
+ if( !otherInsertCmd )
+ return false;
+ if( otherInsertCmd->m_dictModel != m_dictModel )
+ return false;
+
+ // Find where to insert the other row numbers
+ int otherFirstRow = otherInsertCmd->m_rowNumbers.first();
+ int otherRowsNum = otherInsertCmd->m_rowNumbers.size();
+ int i = 0;
+ for( i = 0; i < m_rowNumbers.size(); i++ )
+ if( otherFirstRow <= m_rowNumbers[i] )
+ break;
+ int insertPos = i;
+ // Increment this row numbers by the number of other rows, after the insertion point
+ for( int i = insertPos; i < m_rowNumbers.size(); i++ )
+ m_rowNumbers[i] += otherRowsNum;
+ // Do the insertion of other rows
+ for( int i = 0; i < otherRowsNum; i++ )
+ m_rowNumbers.insert( insertPos + i, otherInsertCmd->m_rowNumbers[i] );
+
+ updateText();
+ return true;
+ }
+
+//==============================================================================================================
+
+RemoveRecordsCmd::RemoveRecordsCmd( const MainWindow* aMainWin ):
+ UndoRecordCmd( aMainWin )
+ {
+ const DictTableView* dictView = getCurView();
+ m_dictModel = dictView->dicTableModel(); // Always original model
+
+ int recordsNum = 0;
+ QModelIndexList selectedRows = dictView->selectionModel()->selectedRows();
+ QAbstractProxyModel* proxyModel = qobject_cast<QAbstractProxyModel*>( dictView->model() );
+ if( proxyModel )
+ { // convert selection to source indexes
+ QModelIndexList list;
+ foreach( QModelIndex index, selectedRows )
+ list << proxyModel->mapToSource( index );
+ selectedRows = list;
+ }
+
+ foreach( QModelIndex index, selectedRows )
+ {
+ int row = index.row();
+ DicRecord record = index.data( DictTableModel::DicRecordRole ).value<DicRecord>();
+ Q_ASSERT( !index.data( DictTableModel::DicRecordRole ).isNull() );
+ m_records.insert( row, new DicRecord( record ) );
+ recordsNum++;
+ }
+ setText(QObject::tr( "Remove %n record(s)", "Undo action of removing records", recordsNum ));
+ }
+
+RemoveRecordsCmd::~RemoveRecordsCmd()
+ {
+ qDeleteAll( m_records );
+ }
+
+void RemoveRecordsCmd::redo()
+ {
+ removeRows( m_records.keys() );
+ selectRow( m_records.keys().first() );
+ }
+
+void RemoveRecordsCmd::undo()
+ {
+ insertRows( m_records.keys() );
+ setRecords( m_records );
+ selectRows( m_records.keys() );
+ }
+
+//==============================================================================================================
+
+EditRecordCmd::EditRecordCmd( QAbstractItemModel* aTableModel, const QModelIndex& aIndex, const QVariant& aValue ):
+ m_dictModel( aTableModel ), m_insertedRow( -1 )
+ {
+ m_row = aIndex.row();
+ m_col = aIndex.column();
+ m_oldStr = aIndex.data( Qt::EditRole ).toString();
+ m_newStr = aValue.toString();
+ if( m_row == m_dictModel->rowCount() - 1 && m_col == m_dictModel->columnCount() - 1 )
+ m_insertedRow = m_dictModel->rowCount();
+ QString editStr = m_newStr;
+ if( editStr.length() > MaxMenuEditStrLen )
+ editStr = editStr.left( MaxMenuEditStrLen ) + QChar( 8230 );
+ setText( QObject::tr( "Edit \"%1\"", "Undo action of editing a record").arg( editStr ) );
+ }
+
+void EditRecordCmd::redo()
+ {
+ QModelIndex index = m_dictModel->index( m_row, m_col );
+ m_dictModel->setData( index, m_newStr, Qt::EditRole );
+ if( m_insertedRow > -1 )
+ m_dictModel->insertRows( m_insertedRow, 1 );
+ }
+
+void EditRecordCmd::undo()
+ {
+ if( m_insertedRow > -1 )
+ m_dictModel->removeRows( m_insertedRow, 1 );
+ QModelIndex index = m_dictModel->index( m_row, m_col );
+ m_dictModel->setData( index, m_oldStr, Qt::EditRole );
+ }
+
+//==============================================================================================================
+
+PasteRecordsCmd::PasteRecordsCmd( QList<DicRecord*> aRecords, const MainWindow* aMainWin ):
+ UndoRecordCmd( aMainWin )
+ {
+ const DictTableView* dictView = getCurView();
+ m_dictModel = dictView->dicTableModel(); // Always original model
+
+ // Find position where to insert records
+ // Paste above selection. If no selection -> paste in the end of dictionary
+ QModelIndexList selectedRows = dictView->selectionModel()->selectedRows();
+ int pastePos = m_dictModel->rowCount();
+ if( !selectedRows.isEmpty() )
+ {
+ qSort( selectedRows );
+ QModelIndex posIndex = selectedRows.first();
+
+ // If proxy view, convert position to source index
+ QAbstractProxyModel* proxyModel = qobject_cast<QAbstractProxyModel*>( dictView->model() );
+ if( proxyModel )
+ posIndex = proxyModel->mapToSource( posIndex );
+
+ pastePos = posIndex.row();
+ }
+ for( int i = 0; i < aRecords.size(); i++ )
+ m_records.insert( pastePos + i, aRecords.value( i ) );
+
+ setText(QObject::tr("Paste %n record(s)", "Undo action of pasting records", m_records.size() ));
+ }
+
+PasteRecordsCmd::~PasteRecordsCmd()
+ {
+ qDeleteAll( m_records.values() );
+ }
+
+void PasteRecordsCmd::redo()
+ {
+ insertRows( m_records.keys() );
+ setRecords( m_records );
+ selectRows( m_records.keys() );
+ }
+
+void PasteRecordsCmd::undo()
+ {
+ removeRows( m_records.keys() );
+ selectRow( m_records.keys().first() );
+ }