Skip to content
This repository

Implemented Undo support in EventView #83

Merged
merged 1 commit into from about 2 years ago

3 participants

Nicholas Van Sickle Mike McQuaid Frank Osterfeld
Nicholas Van Sickle

No description provided.

Charm/Commands/CommandDeleteEvent.cpp
... ... @@ -24,10 +24,26 @@ bool CommandDeleteEvent::execute( ControllerInterface* controller )
24 24 return controller->deleteEvent( m_event );
25 25 }
26 26
  27 +bool CommandDeleteEvent::rollback(ControllerInterface *controller)
  28 +{
  29 + int oid = m_event.id();
1
Mike McQuaid
mikemcquaid added a note

oid and nid aren't great variable names. oldId and newId (I assume that's what you mean)?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Charm/Commands/CommandRelayCommand.cpp
... ... @@ -12,7 +12,7 @@
12 12 }
13 13
14 14 CommandRelayCommand::~CommandRelayCommand()
15   -{
  15 +{
1
Mike McQuaid
mikemcquaid added a note

Unnecessary whitespace change

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Mike McQuaid mikemcquaid commented on the diff
Charm/TasksView.cpp
... ... @@ -420,7 +420,6 @@ void TasksView::configureUi()
420 420 void TasksView::commitCommand( CharmCommand* command )
421 421 {
422 422 command->finalize();
423   - delete command;
2
Mike McQuaid
mikemcquaid added a note

Where are the command deletions happening now?

It's handled by the QUndoStack they're pushed to

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Charm/EventView.cpp
... ... @@ -61,6 +63,24 @@
61 63 // SLOT( slotCommitTimeout() ) );
62 64 // m_commitTimer.setSingleShot( true );
63 65
  66 + m_actionUndo.setText(tr("Undo"));
1
Mike McQuaid
mikemcquaid added a note

Inconsistent indentation

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Charm/EventView.cpp
((4 lines not shown))
  372 +void EventView::slotUndoTextChanged(const QString &text)
  373 +{
  374 + m_actionUndo.setText(tr("Undo %1").arg(text));
  375 +}
  376 +
  377 +void EventView::slotRedoTextChanged(const QString &text)
  378 +{
  379 + m_actionRedo.setText(tr("Redo %1").arg(text));
  380 +}
  381 +
  382 +void EventView::slotEventIdChanged(int oid, int nid)
  383 +{
  384 + foreach(QObject* o, m_undoStack->children()) {
  385 + UndoCharmCommandWrapper* w = dynamic_cast<UndoCharmCommandWrapper*>(o);
  386 + Q_ASSERT(w);
  387 + w->command()->eventIdChanged(oid, nid);
1
Mike McQuaid
mikemcquaid added a note

w is not a great variable name.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Charm/EventView.cpp
... ... @@ -338,6 +369,25 @@ void EventView::slotUpdateCurrent()
338 369 slotUpdateTotal();
339 370 }
340 371
  372 +void EventView::slotUndoTextChanged(const QString &text)
  373 +{
  374 + m_actionUndo.setText(tr("Undo %1").arg(text));
  375 +}
  376 +
  377 +void EventView::slotRedoTextChanged(const QString &text)
  378 +{
  379 + m_actionRedo.setText(tr("Redo %1").arg(text));
  380 +}
  381 +
  382 +void EventView::slotEventIdChanged(int oid, int nid)
  383 +{
  384 + foreach(QObject* o, m_undoStack->children()) {
  385 + UndoCharmCommandWrapper* w = dynamic_cast<UndoCharmCommandWrapper*>(o);
1
Mike McQuaid
mikemcquaid added a note

This could perhaps just be a QObject and use qobject_cast instead.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Charm/EventView.cpp
... ... @@ -338,6 +369,25 @@ void EventView::slotUpdateCurrent()
338 369 slotUpdateTotal();
339 370 }
340 371
  372 +void EventView::slotUndoTextChanged(const QString &text)
  373 +{
  374 + m_actionUndo.setText(tr("Undo %1").arg(text));
  375 +}
  376 +
  377 +void EventView::slotRedoTextChanged(const QString &text)
  378 +{
  379 + m_actionRedo.setText(tr("Redo %1").arg(text));
  380 +}
  381 +
  382 +void EventView::slotEventIdChanged(int oid, int nid)
  383 +{
  384 + foreach(QObject* o, m_undoStack->children()) {
  385 + UndoCharmCommandWrapper* w = dynamic_cast<UndoCharmCommandWrapper*>(o);
  386 + Q_ASSERT(w);
1
Mike McQuaid
mikemcquaid added a note

I'd make this a check in release mode too to avoid dereferencing the null pointer (which will just crash anyway making the assert fairly pointless)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Charm/EventView.cpp
... ... @@ -417,17 +467,19 @@ void EventView::slotEditEvent( const Event& event )
417 467 EventEditor editor( event, this );
418 468 if( editor.exec() ) {
419 469 Event newEvent = editor.eventResult();
  470 +
1
Mike McQuaid
mikemcquaid added a note

Unnecessary whitespace change

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Charm/EventView.cpp
... ... @@ -435,7 +487,7 @@ void EventView::slotEditEvent( const Event& event )
435 487 void EventView::slotEditEventCompleted( const Event& event )
436 488 {
437 489 CommandModifyEvent* command =
438   - new CommandModifyEvent( event, this );
  490 + new CommandModifyEvent( event, event, this );
1
Mike McQuaid
mikemcquaid added a note

Not that it's incorrect but it seems strange to pass the same argument twice.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Charm/EventView.h
((14 lines not shown))
80 88 QList<NamedTimeSpan> m_timeSpans;
81 89 Event m_event;
82 90 EventModelFilter* m_model;
  91 + QAction m_actionUndo;
1
Mike McQuaid
mikemcquaid added a note

Indentation.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Charm/ModelConnector.cpp
... ... @@ -64,9 +63,9 @@ void ModelConnector::slotMakeAndActivateEvent( const Task& task )
64 63 VIEW.sendCommand( command );
65 64 }
66 65
67   -void ModelConnector::slotRequestEventModification( const Event& event )
  66 +void ModelConnector::slotRequestEventModification( const Event& event, const Event& old )
1
Mike McQuaid
mikemcquaid added a note

Old what? Better variable name would make this a bit more readable.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Charm/UndoCharmCommandWrapper.cpp
((6 lines not shown))
  6 + setText(command->description());
  7 +}
  8 +
  9 +void UndoCharmCommandWrapper::undo()
  10 +{
  11 + m_command->requestRollback();
  12 +}
  13 +
  14 +void UndoCharmCommandWrapper::redo()
  15 +{
  16 + m_command->requestExecute();
  17 +}
  18 +
  19 +CharmCommand *UndoCharmCommandWrapper::command()
  20 +{
  21 + return m_command;
3
Mike McQuaid
mikemcquaid added a note

Considering this is just a wrapper I'd be tempted to just make m_command public. @frankosterfeld may disagree :)

From a design standpoint it's pretty marginal either way, I think. I like having the getter abstraction there just in case, but it's pretty unlikely something would change.

Frank Osterfeld Owner

Method should be const

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Core/CharmCommand.cpp
((9 lines not shown))
21 27 CommandEmitterInterface* CharmCommand::owner() const
22 28 {
23 29 return m_owner;
24 30 }
25 31
  32 +void CharmCommand::requestExecute()
  33 +{
  34 + emit emitExecute(this);
  35 +}
  36 +
  37 +void CharmCommand::requestRollback()
  38 +{
  39 + emit emitRollback(this);
  40 +}
  41 +
  42 +void CharmCommand::requestSlotEventIdChanged(int oid, int nid)
1
Mike McQuaid
mikemcquaid added a note

Bit of a confusing method name?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Mike McQuaid mikemcquaid commented on the diff
Core/CharmDataModel.cpp
... ... @@ -424,9 +424,10 @@ void CharmDataModel::endEventRequested( const Task& task )
424 424
425 425 Q_ASSERT( eventId != 0 );
426 426 Event& event = findEvent( eventId );
  427 + Event old = event;
3
Mike McQuaid
mikemcquaid added a note

Could this be a reference?

It could not, the next line I call event.setEndDateTime which modifies the event, old is deliberately copy constructed

Mike McQuaid
mikemcquaid added a note

Cool, just checking.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Core/Controller.h
... ... @@ -43,8 +44,8 @@ class Controller : public QObject,
43 44 void updateModelEventsAndTasks();
44 45
45 46 public slots:
46   -
1
Mike McQuaid
mikemcquaid added a note

Whitespace.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Nicholas Van Sickle NicholasVanSickle commented on the diff
Charm/UndoCharmCommandWrapper.cpp
((9 lines not shown))
  9 +UndoCharmCommandWrapper::~UndoCharmCommandWrapper()
  10 +{
  11 + delete m_command;
  12 +}
  13 +
  14 +void UndoCharmCommandWrapper::undo()
  15 +{
  16 + m_command->requestRollback();
  17 +}
  18 +
  19 +void UndoCharmCommandWrapper::redo()
  20 +{
  21 + m_command->requestExecute();
  22 +}
  23 +
  24 +CharmCommand *UndoCharmCommandWrapper::command() const
1

Method is now const

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Mike McQuaid

Tested and merged.

Mike McQuaid mikemcquaid merged commit bb9d778 into from
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Showing 1 unique commit by 1 author.

Jun 04, 2012
Nicholas Van Sickle NicholasVanSickle Implemented Undo support in EventView 79c2833
This page is out of date. Refresh to see the latest.

Showing 44 changed files with 334 additions and 43 deletions. Show diff stats Hide diff stats

  1. +2 0  Charm/Application.cpp
  2. +1 0  Charm/CMakeLists.txt
  3. +8 1 Charm/CharmWindow.cpp
  4. +1 0  Charm/CharmWindow.h
  5. +1 1  Charm/Commands/CommandAddTask.cpp
  6. +17 1 Charm/Commands/CommandDeleteEvent.cpp
  7. +4 0 Charm/Commands/CommandDeleteEvent.h
  8. +1 1  Charm/Commands/CommandDeleteTask.cpp
  9. +1 1  Charm/Commands/CommandExportToXml.cpp
  10. +1 1  Charm/Commands/CommandImportFromXml.cpp
  11. +1 1  Charm/Commands/CommandMakeAndActivateEvent.cpp
  12. +28 2 Charm/Commands/CommandMakeEvent.cpp
  13. +5 0 Charm/Commands/CommandMakeEvent.h
  14. +17 2 Charm/Commands/CommandModifyEvent.cpp
  15. +6 1 Charm/Commands/CommandModifyEvent.h
  16. +1 1  Charm/Commands/CommandModifyTask.cpp
  17. +7 1 Charm/Commands/CommandRelayCommand.cpp
  18. +1 0  Charm/Commands/CommandRelayCommand.h
  19. +1 1  Charm/Commands/CommandSetAllTasks.cpp
  20. +0 1  Charm/EventModelAdapter.cpp
  21. +62 9 Charm/EventView.cpp
  22. +11 1 Charm/EventView.h
  23. +2 0  Charm/EventWindow.cpp
  24. +1 0  Charm/EventWindow.h
  25. +4 5 Charm/ModelConnector.cpp
  26. +1 1  Charm/ModelConnector.h
  27. +1 2  Charm/TaskModelAdapter.cpp
  28. +0 1  Charm/TasksView.cpp
  29. +1 0  Charm/TasksView.h
  30. +7 0 Charm/TasksWindow.cpp
  31. +2 0  Charm/TasksWindow.h
  32. +2 1  Charm/TimeTrackingView/TimeTrackingWindow.cpp
  33. +1 0  Charm/TimeTrackingView/TimeTrackingWindow.h
  34. +27 0 Charm/UndoCharmCommandWrapper.cpp
  35. +25 0 Charm/UndoCharmCommandWrapper.h
  36. +2 0  Charm/ViewHelpers.cpp
  37. +23 2 Core/CharmCommand.cpp
  38. +19 1 Core/CharmCommand.h
  39. +6 3 Core/CharmDataModel.cpp
  40. +1 1  Core/CharmDataModel.h
  41. +24 0 Core/Controller.cpp
  42. +2 0  Core/Controller.h
  43. +4 0 Core/ControllerInterface.h
  44. +2 0  Core/ViewInterface.h
2  Charm/Application.cpp
@@ -103,6 +103,8 @@ Application::Application(int& argc, char** argv)
103 103 if ( window != &mainView() ) { // main view acts as the main relay
104 104 connect( window, SIGNAL( emitCommand( CharmCommand* ) ),
105 105 &mainView(), SLOT( sendCommand( CharmCommand* ) ) );
  106 + connect( window, SIGNAL( emitCommandRollback( CharmCommand* ) ),
  107 + &mainView(), SLOT( sendCommandRollback( CharmCommand* ) ) );
106 108 }
107 109 // save the configuration (configuration is managed by the application)
108 110 connect( window, SIGNAL(saveConfiguration() ),
1  Charm/CMakeLists.txt
@@ -40,6 +40,7 @@ SET(
40 40 Reports/ActivityReport.cpp
41 41 Reports/WeeklyTimesheet.cpp
42 42 Reports/ReportPreviewWindow.cpp
  43 + UndoCharmCommandWrapper.cpp
43 44 Commands/CommandRelayCommand.cpp
44 45 Commands/CommandModifyEvent.cpp
45 46 Commands/CommandDeleteEvent.cpp
9 Charm/CharmWindow.cpp
@@ -134,6 +134,14 @@ void CharmWindow::sendCommand( CharmCommand* cmd )
134 134 emit emitCommand( relay );
135 135 }
136 136
  137 +void CharmWindow::sendCommandRollback(CharmCommand *cmd)
  138 +{
  139 + cmd->prepare();
  140 + CommandRelayCommand* relay = new CommandRelayCommand( this );
  141 + relay->setCommand( cmd );
  142 + emit emitCommandRollback ( relay );
  143 +}
  144 +
137 145 void CharmWindow::handleShowHide( bool visible )
138 146 {
139 147 const QString text = visible ? tr( "Hide %1 Window" ).arg( m_windowName )
@@ -145,7 +153,6 @@ void CharmWindow::handleShowHide( bool visible )
145 153 void CharmWindow::commitCommand( CharmCommand* command )
146 154 {
147 155 command->finalize();
148   - delete command;
149 156 }
150 157
151 158 void CharmWindow::keyPressEvent( QKeyEvent* event )
1  Charm/CharmWindow.h
@@ -55,6 +55,7 @@ class CharmWindow : public QMainWindow,
55 55 /* reimpl */ void saveConfiguration();
56 56
57 57 public slots:
  58 + /* reimpl */ void sendCommandRollback( CharmCommand* );
58 59 /* reimpl */ void sendCommand( CharmCommand* );
59 60 /* reimpl */ void commitCommand( CharmCommand* );
60 61 void restore();
2  Charm/Commands/CommandAddTask.cpp
@@ -7,7 +7,7 @@
7 7 #include "CommandAddTask.h"
8 8
9 9 CommandAddTask::CommandAddTask( const Task& task, QObject* parent )
10   - : CharmCommand( parent )
  10 + : CharmCommand( tr("Add Task"), parent )
11 11 , m_task( task )
12 12 , m_success( false )
13 13 {
18 Charm/Commands/CommandDeleteEvent.cpp
@@ -3,7 +3,7 @@
3 3 #include "CommandDeleteEvent.h"
4 4
5 5 CommandDeleteEvent::CommandDeleteEvent( const Event& event, QObject* parent )
6   - : CharmCommand( parent )
  6 + : CharmCommand( tr("Delete Event"), parent )
7 7 , m_event( event )
8 8 {
9 9 }
@@ -24,10 +24,26 @@ bool CommandDeleteEvent::execute( ControllerInterface* controller )
24 24 return controller->deleteEvent( m_event );
25 25 }
26 26
  27 +bool CommandDeleteEvent::rollback(ControllerInterface *controller)
  28 +{
  29 + int oldId = m_event.id();
  30 + m_event = controller->cloneEvent(m_event);
  31 + int newId = m_event.id();
  32 + if(oldId != newId)
  33 + emit emitSlotEventIdChanged(oldId, newId);
  34 + return m_event.isValid();
  35 +}
  36 +
27 37 bool CommandDeleteEvent::finalize()
28 38 {
29 39 return true;
30 40 }
31 41
  42 +void CommandDeleteEvent::eventIdChanged(int oid, int nid)
  43 +{
  44 + if(m_event.id() == oid)
  45 + m_event.setId(nid);
  46 +}
  47 +
32 48 #include "CommandDeleteEvent.moc"
33 49
4 Charm/Commands/CommandDeleteEvent.h
@@ -14,8 +14,12 @@ class CommandDeleteEvent : public CharmCommand
14 14
15 15 bool prepare();
16 16 bool execute( ControllerInterface* );
  17 + bool rollback( ControllerInterface* );
17 18 bool finalize();
18 19
  20 +public slots:
  21 + virtual void eventIdChanged(int,int);
  22 +
19 23 private:
20 24 Event m_event;
21 25 };
2  Charm/Commands/CommandDeleteTask.cpp
@@ -8,7 +8,7 @@
8 8 #include "CommandDeleteTask.h"
9 9
10 10 CommandDeleteTask::CommandDeleteTask( const Task& task, QObject* parent )
11   - : CharmCommand( parent )
  11 + : CharmCommand( tr("Delete Task"), parent )
12 12 , m_task( task )
13 13 , m_success( false )
14 14 {
2  Charm/Commands/CommandExportToXml.cpp
@@ -10,7 +10,7 @@
10 10 #include "CommandExportToXml.h"
11 11
12 12 CommandExportToXml::CommandExportToXml( QString filename, QObject* parent )
13   - : CharmCommand( parent )
  13 + : CharmCommand( tr("Export to XML"), parent )
14 14 , m_error( false )
15 15 , m_filename( filename )
16 16 {
2  Charm/Commands/CommandImportFromXml.cpp
@@ -9,7 +9,7 @@
9 9 #include "CommandImportFromXml.h"
10 10
11 11 CommandImportFromXml::CommandImportFromXml( QString filename, QObject* parent )
12   - : CharmCommand( parent )
  12 + : CharmCommand( tr("Import from XML"), parent )
13 13 , m_filename( filename )
14 14 {
15 15 }
2  Charm/Commands/CommandMakeAndActivateEvent.cpp
@@ -9,7 +9,7 @@
9 9
10 10 CommandMakeAndActivateEvent::CommandMakeAndActivateEvent( const Task& task,
11 11 QObject* parent )
12   - : CharmCommand( parent )
  12 + : CharmCommand( tr("Create Event"), parent )
13 13 , m_task( task )
14 14 {
15 15 }
30 Charm/Commands/CommandMakeEvent.cpp
@@ -8,14 +8,14 @@
8 8
9 9 CommandMakeEvent::CommandMakeEvent( const Task& task,
10 10 QObject* parent )
11   - : CharmCommand( parent )
  11 + : CharmCommand( tr("Create Event"), parent )
12 12 , m_task( task )
13 13 {
14 14 }
15 15
16 16 CommandMakeEvent::CommandMakeEvent( const Event& event,
17 17 QObject* parent )
18   - : CharmCommand( parent )
  18 + : CharmCommand( tr("Create Event"), parent )
19 19 , m_event( event )
20 20 {
21 21 }
@@ -33,6 +33,18 @@ bool CommandMakeEvent::prepare()
33 33
34 34 bool CommandMakeEvent::execute( ControllerInterface* controller )
35 35 {
  36 + m_rollback = false;
  37 +
  38 + if(m_event.id()) //if it already has an id, this is a redo operation
  39 + {
  40 + int oid = m_event.id();
  41 + m_event = controller->cloneEvent(m_event);
  42 + int nid = m_event.id();
  43 + if(oid != nid)
  44 + emit emitSlotEventIdChanged(oid, nid);
  45 + return m_event.isValid();
  46 + }
  47 +
36 48 Event event = controller->makeEvent( m_task );
37 49 if ( !event.isValid() )
38 50 return false;
@@ -58,8 +70,16 @@ bool CommandMakeEvent::execute( ControllerInterface* controller )
58 70 }
59 71 }
60 72
  73 +bool CommandMakeEvent::rollback(ControllerInterface *controller )
  74 +{
  75 + m_rollback = true;
  76 + return controller->deleteEvent(m_event);
  77 +}
  78 +
61 79 bool CommandMakeEvent::finalize()
62 80 {
  81 + if ( m_rollback )
  82 + return false;
63 83 if ( m_event.isValid() ) {
64 84 EventView* view = dynamic_cast<EventView*>( owner() );
65 85 if ( view )
@@ -71,4 +91,10 @@ bool CommandMakeEvent::finalize()
71 91 }
72 92 }
73 93
  94 +void CommandMakeEvent::eventIdChanged(int oid, int nid)
  95 +{
  96 + if(m_event.id() == oid)
  97 + m_event.setId(nid);
  98 +}
  99 +
74 100 #include "CommandMakeEvent.moc"
5 Charm/Commands/CommandMakeEvent.h
@@ -18,12 +18,17 @@ class CommandMakeEvent : public CharmCommand
18 18
19 19 bool prepare();
20 20 bool execute( ControllerInterface* );
  21 + bool rollback( ControllerInterface* );
21 22 bool finalize();
22 23
  24 +public slots:
  25 + virtual void eventIdChanged(int,int);
  26 +
23 27 Q_SIGNALS:
24 28 void finishedOk( const Event& );
25 29
26 30 private:
  31 + bool m_rollback; //don't show the event in finalize
27 32 Task m_task; // the task the new event should be assigned to
28 33 Event m_event; // the result, only valid after the event has been created
29 34 };
19 Charm/Commands/CommandModifyEvent.cpp
@@ -3,9 +3,10 @@
3 3
4 4 #include "CommandModifyEvent.h"
5 5
6   -CommandModifyEvent::CommandModifyEvent( const Event& event, QObject* parent )
7   - : CharmCommand( parent )
  6 +CommandModifyEvent::CommandModifyEvent( const Event& event, const Event& oldEvent, QObject* parent )
  7 + : CharmCommand( tr("Modify Event"), parent )
8 8 , m_event( event )
  9 + , m_oldEvent( oldEvent )
9 10 {
10 11 }
11 12
@@ -25,11 +26,25 @@ bool CommandModifyEvent::execute( ControllerInterface* controller )
25 26 return controller->modifyEvent( m_event );
26 27 }
27 28
  29 +bool CommandModifyEvent::rollback(ControllerInterface *controller)
  30 +{
  31 + return controller->modifyEvent( m_oldEvent );
  32 +}
  33 +
28 34 bool CommandModifyEvent::finalize()
29 35 {
30 36 return true;
31 37 }
32 38
  39 +void CommandModifyEvent::eventIdChanged(int oid, int nid)
  40 +{
  41 + if(m_event.id() == oid)
  42 + {
  43 + m_event.setId(nid);
  44 + m_oldEvent.setId(nid);
  45 + }
  46 +}
  47 +
33 48 #include "CommandModifyEvent.moc"
34 49
35 50
7 Charm/Commands/CommandModifyEvent.h
@@ -9,15 +9,20 @@ class CommandModifyEvent : public CharmCommand
9 9 Q_OBJECT
10 10
11 11 public:
12   - explicit CommandModifyEvent( const Event&, QObject* parent = 0 );
  12 + explicit CommandModifyEvent( const Event&, const Event&, QObject* parent = 0 );
13 13 ~CommandModifyEvent();
14 14
15 15 bool prepare();
16 16 bool execute( ControllerInterface* );
  17 + bool rollback( ControllerInterface* );
17 18 bool finalize();
18 19
  20 +public slots:
  21 + virtual void eventIdChanged(int,int);
  22 +
19 23 private:
20 24 Event m_event;
  25 + Event m_oldEvent;
21 26 };
22 27
23 28 #endif
2  Charm/Commands/CommandModifyTask.cpp
@@ -7,7 +7,7 @@
7 7 #include "CommandModifyTask.h"
8 8
9 9 CommandModifyTask::CommandModifyTask( const Task& task, QObject* parent )
10   - : CharmCommand( parent )
  10 + : CharmCommand( tr("Edit Task"), parent )
11 11 , m_task( task )
12 12 , m_success( false )
13 13 {
8 Charm/Commands/CommandRelayCommand.cpp
@@ -4,7 +4,7 @@
4 4 #include "CommandRelayCommand.h"
5 5
6 6 CommandRelayCommand::CommandRelayCommand( QObject* parent )
7   - : CharmCommand( parent )
  7 + : CharmCommand( tr("Relay"), parent )
8 8 , m_payload( 0 )
9 9 { // as long as Charm is single-threaded, this does not do anything,
10 10 // because there will be no repaint
@@ -33,8 +33,14 @@ bool CommandRelayCommand::execute( ControllerInterface* controller )
33 33 return m_payload->execute( controller );
34 34 }
35 35
  36 +bool CommandRelayCommand::rollback( ControllerInterface* controller )
  37 +{
  38 + return m_payload->rollback( controller );
  39 +}
  40 +
36 41 bool CommandRelayCommand::finalize()
37 42 {
  43 + QApplication::restoreOverrideCursor();
38 44 m_payload->owner()->commitCommand( m_payload );
39 45 return true;
40 46 }
1  Charm/Commands/CommandRelayCommand.h
@@ -22,6 +22,7 @@ class CommandRelayCommand : public CharmCommand
22 22
23 23 bool prepare();
24 24 bool execute( ControllerInterface* );
  25 + bool rollback( ControllerInterface* );
25 26 bool finalize();
26 27
27 28 private:
2  Charm/Commands/CommandSetAllTasks.cpp
@@ -7,7 +7,7 @@
7 7 #include "CommandSetAllTasks.h"
8 8
9 9 CommandSetAllTasks::CommandSetAllTasks( const TaskList& tasks, QObject* parent )
10   - : CharmCommand( parent )
  10 + : CharmCommand( tr("Import Tasks"), parent )
11 11 , m_tasks( tasks )
12 12 , m_success( false )
13 13 {
1  Charm/EventModelAdapter.cpp
@@ -105,7 +105,6 @@ void EventModelAdapter::eventDeactivated( EventId id )
105 105 void EventModelAdapter::commitCommand( CharmCommand* command )
106 106 {
107 107 command->finalize();
108   - delete command;
109 108 }
110 109
111 110 const Event& EventModelAdapter::eventForIndex( const QModelIndex& index ) const
71 Charm/EventView.cpp
@@ -31,6 +31,8 @@
31 31 EventView::EventView( QToolBar* toolBar, QWidget* parent )
32 32 : QWidget( parent )
33 33 , m_model( 0 )
  34 + , m_actionUndo( this )
  35 + , m_actionRedo( this )
34 36 , m_actionNewEvent( this )
35 37 , m_actionEditEvent( this )
36 38 , m_actionDeleteEvent( this )
@@ -61,6 +63,24 @@ EventView::EventView( QToolBar* toolBar, QWidget* parent )
61 63 // SLOT( slotCommitTimeout() ) );
62 64 // m_commitTimer.setSingleShot( true );
63 65
  66 + m_actionUndo.setText(tr("Undo"));
  67 + m_actionUndo.setToolTip(tr("Undo the latest change"));
  68 + m_actionUndo.setShortcut(QKeySequence::Undo);
  69 + m_actionUndo.setEnabled(false);
  70 +
  71 + m_actionRedo.setText(tr("Redo"));
  72 + m_actionRedo.setToolTip(tr("Redo the last undone change."));
  73 + m_actionRedo.setShortcut(QKeySequence::Redo);
  74 + m_actionRedo.setEnabled(false);
  75 +
  76 + m_undoStack = new QUndoStack(this);
  77 + connect(m_undoStack, SIGNAL(canUndoChanged(bool)), &m_actionUndo, SLOT(setEnabled(bool)));
  78 + connect(m_undoStack, SIGNAL(undoTextChanged(QString)), this, SLOT(slotUndoTextChanged(QString)));
  79 + connect(&m_actionUndo, SIGNAL(triggered()), m_undoStack, SLOT(undo()));
  80 +
  81 + connect(m_undoStack, SIGNAL(canRedoChanged(bool)), &m_actionRedo, SLOT(setEnabled(bool)));
  82 + connect(m_undoStack, SIGNAL(redoTextChanged(QString)), this, SLOT(slotRedoTextChanged(QString)));
  83 + connect(&m_actionRedo, SIGNAL(triggered()), m_undoStack, SLOT(redo()));
64 84
65 85 m_actionNewEvent.setText( tr( "New Event..." ) );
66 86 m_actionNewEvent.setToolTip( tr( "Create a new Event" ) );
@@ -122,6 +142,9 @@ void EventView::delayedInitialization()
122 142
123 143 void EventView::populateEditMenu( QMenu* menu )
124 144 {
  145 + menu->addAction( &m_actionUndo );
  146 + menu->addAction( &m_actionRedo );
  147 + menu->addSeparator();
125 148 menu->addAction( &m_actionNewEvent );
126 149 menu->addAction( &m_actionEditEvent );
127 150 menu->addAction( &m_actionDeleteEvent );
@@ -165,7 +188,6 @@ void EventView::reject()
165 188 void EventView::commitCommand( CharmCommand* command )
166 189 {
167 190 command->finalize();
168   - delete command;
169 191 }
170 192
171 193 void EventView::slotCurrentItemChanged( const QModelIndex& start,
@@ -191,6 +213,15 @@ void EventView::setCurrentEvent( const Event& event )
191 213 m_event = event;
192 214 }
193 215
  216 +void EventView::stageCommand(CharmCommand *command)
  217 +{
  218 + UndoCharmCommandWrapper* undoCommand = new UndoCharmCommandWrapper(command);
  219 + connect(command, SIGNAL(emitExecute(CharmCommand*)), this, SIGNAL(emitCommand(CharmCommand*)));
  220 + connect(command, SIGNAL(emitRollback(CharmCommand*)), this, SIGNAL(emitCommandRollback(CharmCommand*)));
  221 + connect(command, SIGNAL(emitSlotEventIdChanged(int,int)), this, SLOT(slotEventIdChanged(int,int)));
  222 + m_undoStack->push(undoCommand);
  223 +}
  224 +
194 225 void EventView::slotNewEvent()
195 226 {
196 227 SelectTaskDialog dialog( this );
@@ -223,7 +254,7 @@ void EventView::slotDeleteEvent()
223 254 == QMessageBox::Yes ) {
224 255 CommandDeleteEvent* command = new CommandDeleteEvent( m_event, this );
225 256 command->prepare();
226   - emitCommand( command );
  257 + stageCommand( command );
227 258 }
228 259 }
229 260
@@ -338,6 +369,25 @@ void EventView::slotUpdateCurrent()
338 369 slotUpdateTotal();
339 370 }
340 371
  372 +void EventView::slotUndoTextChanged(const QString &text)
  373 +{
  374 + m_actionUndo.setText(tr("Undo %1").arg(text));
  375 +}
  376 +
  377 +void EventView::slotRedoTextChanged(const QString &text)
  378 +{
  379 + m_actionRedo.setText(tr("Redo %1").arg(text));
  380 +}
  381 +
  382 +void EventView::slotEventIdChanged(int oldId, int newId)
  383 +{
  384 + foreach(QObject* o, m_undoStack->children()) {
  385 + UndoCharmCommandWrapper* wrapper = dynamic_cast<UndoCharmCommandWrapper*>(o);
  386 + Q_ASSERT(wrapper);
  387 + wrapper->command()->eventIdChanged(oldId, newId);
  388 + }
  389 +}
  390 +
341 391 void EventView::slotUpdateTotal()
342 392 { // what matching signal does the proxy emit?
343 393 int seconds = m_model->totalDuration();
@@ -421,23 +471,26 @@ void EventView::slotEditEvent( const Event& event )
421 471 CommandMakeEvent* command =
422 472 new CommandMakeEvent( newEvent, this );
423 473 connect( command, SIGNAL( finishedOk( const Event& ) ),
424   - this, SLOT( slotEditEventCompleted( const Event& ) ),
  474 + this, SLOT( slotEditNewEventCompleted( const Event& ) ),
425 475 Qt::QueuedConnection );
426   - emitCommand( command );
  476 + stageCommand( command );
427 477 return;
428   -
429 478 } else {
430   - slotEditEventCompleted( newEvent );
  479 + CommandModifyEvent* command =
  480 + new CommandModifyEvent( newEvent, event, this );
  481 + stageCommand( command );
431 482 }
432 483 }
433 484 }
434 485
435   -void EventView::slotEditEventCompleted( const Event& event )
  486 +void EventView::slotEditNewEventCompleted( const Event& event )
436 487 {
  488 + // make event editor finished, bypass the undo stack to set its contents
  489 + // undo will just target CommandMakeEvent instead
437 490 CommandModifyEvent* command =
438   - new CommandModifyEvent( event, this );
  491 + new CommandModifyEvent( event, event, this );
439 492 emitCommand( command );
  493 + delete command;
440 494 }
441 495
442   -
443 496 #include "EventView.moc"
12 Charm/EventView.h
@@ -3,12 +3,14 @@
3 3
4 4 #include <QWidget>
5 5 #include <QAction>
  6 +#include <QUndoStack>
6 7
7 8 #include "Core/Event.h"
8 9 #include "Core/TimeSpans.h"
9 10 #include "Core/CommandEmitterInterface.h"
10 11
11 12 #include "ViewModeInterface.h"
  13 +#include "UndoCharmCommandWrapper.h"
12 14
13 15 class QModelIndex;
14 16
@@ -49,6 +51,7 @@ class EventView : public QWidget,
49 51 signals:
50 52 void visible( bool );
51 53 void emitCommand( CharmCommand* );
  54 + void emitCommandRollback( CharmCommand* );
52 55
53 56 public slots:
54 57 void commitCommand( CharmCommand* );
@@ -61,7 +64,7 @@ private slots:
61 64 void slotEventDoubleClicked( const QModelIndex& );
62 65 void slotEditEvent();
63 66 void slotEditEvent( const Event& );
64   - void slotEditEventCompleted( const Event& );
  67 + void slotEditNewEventCompleted( const Event& );
65 68 void slotCurrentItemChanged( const QModelIndex&, const QModelIndex& );
66 69 void slotContextMenuRequested( const QPoint& );
67 70 void slotNextEvent();
@@ -72,14 +75,21 @@ private slots:
72 75 void slotEventDeactivated( EventId );
73 76 void slotUpdateTotal();
74 77 void slotUpdateCurrent();
  78 + void slotUndoTextChanged(const QString&);
  79 + void slotRedoTextChanged(const QString&);
  80 + void slotEventIdChanged(int oldId, int newId);
75 81
76 82 private:
77 83 Event newSettings();
78 84 void setCurrentEvent( const Event& );
  85 + void stageCommand( CharmCommand* );
79 86
  87 + QUndoStack* m_undoStack;
80 88 QList<NamedTimeSpan> m_timeSpans;
81 89 Event m_event;
82 90 EventModelFilter* m_model;
  91 + QAction m_actionUndo;
  92 + QAction m_actionRedo;
83 93 QAction m_actionNewEvent;
84 94 QAction m_actionEditEvent;
85 95 QAction m_actionDeleteEvent;
2  Charm/EventWindow.cpp
@@ -18,6 +18,8 @@ EventWindow::EventWindow( QWidget* parent )
18 18 setSizePolicy( QSizePolicy::Preferred, QSizePolicy::Expanding );
19 19 connect( m_eventView, SIGNAL( emitCommand( CharmCommand* ) ),
20 20 SIGNAL( emitCommand( CharmCommand* ) ) );
  21 + connect( m_eventView, SIGNAL( emitCommandRollback( CharmCommand* ) ),
  22 + SIGNAL( emitCommandRollback( CharmCommand* ) ) );
21 23 }
22 24
23 25 EventWindow::~EventWindow()
1  Charm/EventWindow.h
@@ -25,6 +25,7 @@ public slots:
25 25
26 26 signals:
27 27 /* reimpl */ void emitCommand( CharmCommand* );
  28 + /* reimpl */ void emitCommandRollback( CharmCommand* );
28 29 /* reimpl */ void quit();
29 30
30 31 private:
9 Charm/ModelConnector.cpp
@@ -14,8 +14,8 @@ ModelConnector::ModelConnector()
14 14 {
15 15 connect( &m_dataModel, SIGNAL( makeAndActivateEvent( const Task& ) ),
16 16 SLOT( slotMakeAndActivateEvent( const Task& ) ) );
17   - connect( &m_dataModel, SIGNAL( requestEventModification( const Event& ) ),
18   - SLOT( slotRequestEventModification( const Event& ) ) );
  17 + connect( &m_dataModel, SIGNAL( requestEventModification( const Event&, const Event& ) ),
  18 + SLOT( slotRequestEventModification( const Event&, const Event& ) ) );
19 19 connect( &m_dataModel, SIGNAL( sysTrayUpdate( const QString&, bool ) ),
20 20 SLOT( slotSysTrayUpdate( const QString&, bool ) ) );
21 21 connect( &m_iconTimer, SIGNAL( timeout() ),
@@ -53,7 +53,6 @@ void ModelConnector::commitCommand( CharmCommand* command )
53 53 << command->metaObject()->className()
54 54 << "command has failed";
55 55 }
56   - delete command;
57 56 }
58 57
59 58 void ModelConnector::slotMakeAndActivateEvent( const Task& task )
@@ -64,9 +63,9 @@ void ModelConnector::slotMakeAndActivateEvent( const Task& task )
64 63 VIEW.sendCommand( command );
65 64 }
66 65
67   -void ModelConnector::slotRequestEventModification( const Event& event )
  66 +void ModelConnector::slotRequestEventModification( const Event& newEvent, const Event& oldEvent )
68 67 {
69   - CommandModifyEvent* command = new CommandModifyEvent( event, this );
  68 + CommandModifyEvent* command = new CommandModifyEvent( newEvent, oldEvent, this );
70 69 VIEW.sendCommand( command );
71 70 }
72 71
2  Charm/ModelConnector.h
@@ -26,7 +26,7 @@ class ModelConnector : public QObject,
26 26
27 27 public slots:
28 28 void slotMakeAndActivateEvent( const Task& );
29   - void slotRequestEventModification( const Event& );
  29 + void slotRequestEventModification(const Event&newEvent, const Event& oldEvent);
30 30 void slotSysTrayUpdate( const QString&, bool );
31 31 void slotSysTrayIconUpdate();
32 32
3  Charm/TaskModelAdapter.cpp
@@ -175,7 +175,7 @@ bool TaskModelAdapter::setData( const QModelIndex & index, const QVariant & valu
175 175 QString comment = value.toString();
176 176 Event event( old );
177 177 event.setComment( comment );
178   - CommandModifyEvent* command = new CommandModifyEvent( event, this );
  178 + CommandModifyEvent* command = new CommandModifyEvent( event, old, this );
179 179 VIEW.sendCommand( command );
180 180 return true;
181 181 } else if ( role == Qt::CheckStateRole ) {
@@ -349,7 +349,6 @@ void TaskModelAdapter::commitCommand( CharmCommand* command )
349 349 {
350 350 Q_ASSERT( command->owner() == this );
351 351 command->finalize();
352   - delete command;
353 352 }
354 353
355 354 #include "TaskModelAdapter.moc"
1  Charm/TasksView.cpp
@@ -420,7 +420,6 @@ void TasksView::configureUi()
420 420 void TasksView::commitCommand( CharmCommand* command )
421 421 {
422 422 command->finalize();
423   - delete command;
424 423 }
425 424
426 425 void TasksView::slotEventActivated( EventId )
1  Charm/TasksView.h
@@ -45,6 +45,7 @@ public Q_SLOTS:
45 45 // FIXME connect to MainWindow
46 46 void saveConfiguration();
47 47 void emitCommand( CharmCommand* );
  48 + void emitCommandRollback( CharmCommand* );
48 49
49 50 private slots:
50 51 void actionNewTask();
7 Charm/TasksWindow.cpp
@@ -15,6 +15,8 @@ TasksWindow::TasksWindow( QWidget* parent )
15 15 setSizePolicy( QSizePolicy::Preferred, QSizePolicy::Expanding );
16 16 connect( m_tasksView, SIGNAL( emitCommand( CharmCommand* ) ),
17 17 SIGNAL( emitCommand( CharmCommand* ) ) );
  18 + connect( m_tasksView, SIGNAL( emitCommandRollback( CharmCommand* ) ),
  19 + SIGNAL( emitCommandRollback( CharmCommand* ) ) );
18 20 connect( m_tasksView, SIGNAL( saveConfiguration() ),
19 21 SIGNAL( saveConfiguration() ) );
20 22 }
@@ -55,6 +57,11 @@ void TasksWindow::sendCommand( CharmCommand* )
55 57 Q_ASSERT( false ); // should not be called
56 58 }
57 59
  60 +void TasksWindow::sendCommandRollback( CharmCommand* )
  61 +{
  62 + Q_ASSERT( false ); // should not be called
  63 +}
  64 +
58 65 void TasksWindow::commitCommand( CharmCommand* )
59 66 {
60 67 }
2  Charm/TasksWindow.h
@@ -15,6 +15,7 @@ class TasksWindow : public CharmWindow
15 15
16 16 /* reimpl */ void stateChanged( State previous );
17 17 /* reimpl */ void sendCommand( CharmCommand* );
  18 + /* reimpl */ void sendCommandRollback( CharmCommand* );
18 19 /* reimpl */ void commitCommand( CharmCommand* );
19 20
20 21 // restore the view
@@ -28,6 +29,7 @@ public slots:
28 29
29 30 signals:
30 31 /* reimpl */ void emitCommand( CharmCommand* );
  32 + /* reimpl */ void emitCommandRollback( CharmCommand* );
31 33 /* reimpl */ void quit();
32 34
33 35 private:
3  Charm/TimeTrackingView/TimeTrackingWindow.cpp
@@ -458,10 +458,11 @@ void TimeTrackingWindow::maybeIdle()
458 458 Q_FOREACH ( EventId eventId, activeEvents ) {
459 459 Event event = DATAMODEL->eventForId( eventId );
460 460 if ( event.isValid() ) {
  461 + Event old = event;
461 462 QDateTime start = period.first; // initializes a valid QDateTime
462 463 event.setEndDateTime( qMax( event.startDateTime(), start ) );
463 464 Q_ASSERT( event.isValid() );
464   - CommandModifyEvent* cmd = new CommandModifyEvent( event, this );
  465 + CommandModifyEvent* cmd = new CommandModifyEvent( event, old, this );
465 466 emit emitCommand( cmd );
466 467 }
467 468 }
1  Charm/TimeTrackingView/TimeTrackingWindow.h
@@ -75,6 +75,7 @@ private slots:
75 75
76 76 signals:
77 77 void emitCommand( CharmCommand* );
  78 + void emitCommandRollback( CharmCommand* );
78 79
79 80 private:
80 81 void showPreview( ReportConfigurationDialog*, int result );
27 Charm/UndoCharmCommandWrapper.cpp
... ... @@ -0,0 +1,27 @@
  1 +#include "UndoCharmCommandWrapper.h"
  2 +
  3 +UndoCharmCommandWrapper::UndoCharmCommandWrapper(CharmCommand* command)
  4 + : m_command(command)
  5 +{
  6 + setText(command->description());
  7 +}
  8 +
  9 +UndoCharmCommandWrapper::~UndoCharmCommandWrapper()
  10 +{
  11 + delete m_command;
  12 +}
  13 +
  14 +void UndoCharmCommandWrapper::undo()
  15 +{
  16 + m_command->requestRollback();
  17 +}
  18 +
  19 +void UndoCharmCommandWrapper::redo()
  20 +{
  21 + m_command->requestExecute();
  22 +}
  23 +
  24 +CharmCommand *UndoCharmCommandWrapper::command() const
  25 +{
  26 + return m_command;
  27 +}
25 Charm/UndoCharmCommandWrapper.h
... ... @@ -0,0 +1,25 @@
  1 +#ifndef UNDOCHARMCOMMANDWRAPPER_H
  2 +#define UNDOCHARMCOMMANDWRAPPER_H
  3 +
  4 +#include <QUndoCommand>
  5 +
  6 +#include "Core/CharmCommand.h"
  7 +
  8 +/**
  9 + Thin wrapper for CharmCommand -> QUndoCommand
  10 +
  11 + It simply forwards the command text and emits signals for commit/rollback on undo/redo
  12 + **/
  13 +class UndoCharmCommandWrapper : public QUndoCommand
  14 +{
  15 +public:
  16 + UndoCharmCommandWrapper(CharmCommand* command);
  17 + virtual ~UndoCharmCommandWrapper();
  18 + virtual void undo();
  19 + virtual void redo();
  20 + CharmCommand* command() const;
  21 +private:
  22 + CharmCommand* m_command;
  23 +};
  24 +
  25 +#endif
2  Charm/ViewHelpers.cpp
@@ -8,6 +8,8 @@ void connectControllerAndView( Controller* controller, CharmWindow* view )
8 8 // make controller process commands send by the view:
9 9 QObject::connect( view, SIGNAL( emitCommand( CharmCommand* ) ),
10 10 controller, SLOT( executeCommand( CharmCommand* ) ) );
  11 + QObject::connect( view, SIGNAL( emitCommandRollback( CharmCommand* ) ),
  12 + controller, SLOT( rollbackCommand( CharmCommand* ) ) );
11 13 // make view receive done commands from the controller:
12 14 QObject::connect( controller, SIGNAL( commandCompleted( CharmCommand* ) ),
13 15 view, SLOT( commitCommand( CharmCommand* ) ) );
25 Core/CharmCommand.cpp
... ... @@ -1,8 +1,9 @@
1 1 #include "CommandEmitterInterface.h"
2 2 #include "CharmCommand.h"
3 3
4   -CharmCommand::CharmCommand( QObject* parent )
5   - : QObject( parent )
  4 +CharmCommand::CharmCommand( const QString& description, QObject *parent )
  5 + : QObject( parent ),
  6 + m_description(description)
6 7 {
7 8 CommandEmitterInterface* emitter = dynamic_cast<CommandEmitterInterface*>( parent );
8 9 if ( emitter ) {
@@ -18,9 +19,29 @@ CharmCommand::~CharmCommand()
18 19 {
19 20 }
20 21
  22 +QString CharmCommand::description() const
  23 +{
  24 + return m_description;
  25 +}
  26 +
21 27 CommandEmitterInterface* CharmCommand::owner() const
22 28 {
23 29 return m_owner;
24 30 }
25 31
  32 +void CharmCommand::requestExecute()
  33 +{
  34 + emit emitExecute(this);
  35 +}
  36 +
  37 +void CharmCommand::requestRollback()
  38 +{
  39 + emit emitRollback(this);
  40 +}
  41 +
  42 +void CharmCommand::requestSlotEventIdChanged(int oldId, int newId)
  43 +{
  44 + emit emitSlotEventIdChanged(oldId,newId);
  45 +}
  46 +
26 47 #include "CharmCommand.moc"
20 Core/CharmCommand.h
@@ -38,19 +38,37 @@ class CharmCommand : public QObject
38 38 Q_OBJECT
39 39
40 40 public:
41   - explicit CharmCommand( QObject* parent = 0 );
  41 + explicit CharmCommand( const QString& description, QObject* parent = 0 );
42 42 virtual ~CharmCommand();
43 43
  44 + QString description() const;
  45 +
44 46 virtual bool prepare() = 0;
45 47 virtual bool execute( ControllerInterface* controller ) = 0;
  48 + virtual bool rollback( ControllerInterface* controller ) { return false; }
46 49 virtual bool finalize() = 0;
47 50
48 51 CommandEmitterInterface* owner() const;
49 52
  53 + //used by UndoCharmCommandWrapper to forward signal firing
  54 + //forwards to emitExecute/emitRollback/emitRequestSlotEventIdChanged
  55 + void requestExecute();
  56 + void requestRollback();
  57 + void requestSlotEventIdChanged(int oldId, int newId);
  58 +
  59 + //notify CharmCommands in a QUndoStack that an event ID has changed
  60 + virtual void eventIdChanged(int,int){}
  61 +
  62 +signals:
  63 + void emitExecute(CharmCommand*);
  64 + void emitRollback(CharmCommand*);
  65 + void emitSlotEventIdChanged(int,int);
  66 +
50 67 private:
51 68 CharmCommand( const CharmCommand& ); // disallow copying
52 69
53 70 CommandEmitterInterface* m_owner;
  71 + const QString m_description;
54 72 };
55 73
56 74 #endif
9 Core/CharmDataModel.cpp
@@ -424,9 +424,10 @@ void CharmDataModel::endEventRequested( const Task& task )
424 424
425 425 Q_ASSERT( eventId != 0 );
426 426 Event& event = findEvent( eventId );
  427 + Event old = event;
427 428 event.setEndDateTime( QDateTime::currentDateTime() );
428 429
429   - emit requestEventModification( event );
  430 + emit requestEventModification( event, old );
430 431
431 432 if ( m_activeEventIds.isEmpty() ) m_timer.stop();
432 433 updateToolTip();
@@ -444,9 +445,10 @@ void CharmDataModel::endAllEventsRequested()
444 445
445 446 Q_ASSERT( eventId != 0 );
446 447 Event& event = findEvent( eventId );
  448 + Event old = event;
447 449 event.setEndDateTime( currentDateTime );
448 450
449   - emit requestEventModification( event );
  451 + emit requestEventModification( event, old );
450 452 }
451 453
452 454 m_timer.stop();
@@ -459,9 +461,10 @@ void CharmDataModel::eventUpdateTimerEvent()
459 461 // Not a ref (Event &), since we want to diff "old event"
460 462 // and "new event" in *Adapter::eventModified
461 463 Event event = findEvent( id );
  464 + Event old = event;
462 465 event.setEndDateTime( QDateTime::currentDateTime() );
463 466
464   - emit requestEventModification( event );
  467 + emit requestEventModification( event, old );
465 468 }
466 469 updateToolTip();
467 470 }
2  Core/CharmDataModel.h
@@ -99,7 +99,7 @@ class CharmDataModel : public QObject
99 99 // these need to be implemented in the respective application to
100 100 // be able to track time:
101 101 void makeAndActivateEvent( const Task& );
102   - void requestEventModification( const Event& );
  102 + void requestEventModification( const Event&, const Event& );
103 103 void sysTrayUpdate( const QString&, bool );
104 104
105 105 public slots: