Developer Documentation
BackupPlugin.cc
1 /*===========================================================================*\
2 * *
3 * OpenFlipper *
4  * Copyright (c) 2001-2015, RWTH-Aachen University *
5  * Department of Computer Graphics and Multimedia *
6  * All rights reserved. *
7  * www.openflipper.org *
8  * *
9  *---------------------------------------------------------------------------*
10  * This file is part of OpenFlipper. *
11  *---------------------------------------------------------------------------*
12  * *
13  * Redistribution and use in source and binary forms, with or without *
14  * modification, are permitted provided that the following conditions *
15  * are met: *
16  * *
17  * 1. Redistributions of source code must retain the above copyright notice, *
18  * this list of conditions and the following disclaimer. *
19  * *
20  * 2. Redistributions in binary form must reproduce the above copyright *
21  * notice, this list of conditions and the following disclaimer in the *
22  * documentation and/or other materials provided with the distribution. *
23  * *
24  * 3. Neither the name of the copyright holder nor the names of its *
25  * contributors may be used to endorse or promote products derived from *
26  * this software without specific prior written permission. *
27  * *
28  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS *
29  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED *
30  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
31  * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER *
32  * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, *
33  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, *
34  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR *
35  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF *
36  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING *
37  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS *
38  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *
39 * *
40 \*===========================================================================*/
41 
42 
43 
44 #include "BackupPlugin.hh"
45 
48 
49 #include "GroupBackup.hh"
50 
51 #include <QLabel>
52 #include <QHBoxLayout>
53 
54 //-----------------------------------------------------------------------------
55 BackupPlugin::BackupPlugin():
56 globalBackup_(),
57 backupMenu_(0),
58 backupsEnabledAction_(0),
59 undoMenuAction_(0),
60 redoMenuAction_(0),
61 undoToolAction_(0),
62 redoToolAction_(0),
63 undoContextAction_(0),
64 redoContextAction_(0),
65 maxBackupSpinBox_(0)
66 {
67 
68 }
69 
70 //-----------------------------------------------------------------------------
71 
72 void BackupPlugin::initializePlugin()
73 {
74  int maxBackups = OpenFlipperSettings().value("BackupPlugin/MaxBackups",static_cast<unsigned>(globalBackup_.maxBackups())).toInt();
75  globalBackup_.setMaxBackups(maxBackups);
76 
77  std::cerr << "Setting OpenFlipper Option 2 " << OpenFlipperSettings().value("BackupPlugin/EnableBackups",true).toBool() << std::endl;
78  OpenFlipper::Options::enableBackup(OpenFlipperSettings().value("BackupPlugin/EnableBackups",true).toBool());
79 }
80 
81 //-----------------------------------------------------------------------------
82 
83 void BackupPlugin::pluginsInitialized() {
84 
85  // Create Backup menu
86  emit getMenubarMenu(tr("&Backup"), backupMenu_, true );
87 
88  if ( OpenFlipper::Options::gui() ) {
89  //construct the menu
90  backupsEnabledAction_ = new QAction("Backups Enabled",0);
91  backupsEnabledAction_->setCheckable(true);
92  backupsEnabledAction_->setChecked(OpenFlipper::Options::backupEnabled());
93  connect (backupsEnabledAction_, SIGNAL(triggered(bool)), this, SLOT(slotEnableDisableBackups()) );
94 
95  undoMenuAction_ = new QAction(tr("&Undo"), this);
96  undoMenuAction_->setEnabled(false);
97  undoMenuAction_->setStatusTip(tr("Undo the last action."));
98  undoMenuAction_->setIcon(QIcon(OpenFlipper::Options::iconDirStr()+OpenFlipper::Options::dirSeparator()+"edit-undo.png") );
99  connect(undoMenuAction_, SIGNAL(triggered()), this, SIGNAL( undo() ) );
100 
101  redoMenuAction_ = new QAction(tr("&Redo"), this);
102  redoMenuAction_->setEnabled(false);
103  redoMenuAction_->setStatusTip(tr("Redo the last action"));
104  redoMenuAction_->setIcon(QIcon(OpenFlipper::Options::iconDirStr()+OpenFlipper::Options::dirSeparator()+"edit-redo.png") );
105  connect(redoMenuAction_, SIGNAL(triggered()), this, SIGNAL( redo() ) );
106 
107  backupMenu_->addAction(undoMenuAction_);
108  backupMenu_->addAction(redoMenuAction_);
109  backupMenu_->addSeparator();
110  backupMenu_->addAction(backupsEnabledAction_);
111 
112  // Add a backup Toolbar
113  QToolBar* toolbar = new QToolBar("Backup Toolbar");
114 
115  //Undo
116  undoToolAction_ = new QAction(tr("&Undo"), this);
117  undoToolAction_->setEnabled(false);
118  undoToolAction_->setStatusTip(tr("Undo the last action."));
119  undoToolAction_->setIcon(QIcon(OpenFlipper::Options::iconDirStr()+OpenFlipper::Options::dirSeparator()+"edit-undo.png") );
120  connect(undoToolAction_, SIGNAL(triggered()), this, SIGNAL( undo() ) );
121  toolbar->addAction(undoToolAction_);
122 
123  //Redo
124  redoToolAction_ = new QAction(tr("&Redo"), this);
125  redoToolAction_->setEnabled(false);
126  redoToolAction_->setStatusTip(tr("Redo the last action"));
127  redoToolAction_->setIcon(QIcon(OpenFlipper::Options::iconDirStr()+OpenFlipper::Options::dirSeparator()+"edit-redo.png") );
128  connect(redoToolAction_, SIGNAL(triggered()), this, SIGNAL( redo() ) );
129  toolbar->addAction(redoToolAction_);
130 
131  emit addToolbar( toolbar );
132 
133  //the release event does not contain the modifier
134  emit registerKey(Qt::Key_Z, Qt::ControlModifier, tr("Undo Action"));
135  emit registerKey(Qt::Key_Z, (Qt::ControlModifier | Qt::ShiftModifier), tr("Redo Action"));
136 
137  //add actions for the context menu
138  undoContextAction_ = new QAction(tr("&Undo"), this);
139  undoContextAction_->setEnabled(false);
140  undoContextAction_->setStatusTip(tr("Undo the last action."));
141  undoContextAction_->setIcon(QIcon(OpenFlipper::Options::iconDirStr()+OpenFlipper::Options::dirSeparator()+"edit-undo.png") );
142  connect(undoContextAction_, SIGNAL(triggered()), this, SLOT(slotObjectUndo()) );
143  emit addContextMenuItem(undoContextAction_, DATA_ALL, CONTEXTOBJECTMENU);
144 
145  redoContextAction_ = new QAction(tr("&Redo"), this);
146  redoContextAction_->setEnabled(false);
147  redoContextAction_->setStatusTip(tr("Redo the last action"));
148  redoContextAction_->setIcon(QIcon(OpenFlipper::Options::iconDirStr()+OpenFlipper::Options::dirSeparator()+"edit-redo.png") );
149  connect(redoContextAction_, SIGNAL(triggered()), this, SLOT(slotObjectRedo()) );
150  emit addContextMenuItem(redoContextAction_, DATA_ALL, CONTEXTOBJECTMENU);
151 
152  //update option widget since it is created earlier
153  if (maxBackupSpinBox_)
154  maxBackupSpinBox_->setValue(globalBackup_.maxBackups());
155 
156  }
157 
158 //createBackup(int _objectId, QString _name, UpdateType _type= UPDATE_ALL)
159  emit setSlotDescription("createBackup(int,QString)", tr("Creates a backup which can be restored via undo."),
160  QString("objectId,name").split(","), QString("Id of the object,name of the backup").split(","));
161  emit setSlotDescription("createBackup(int,QString,UpdateType)", tr("Creates a backup which can be restored via undo."),
162  QString("objectId,name,type").split(","), QString("Id of the object,name of the backup,updatetypes which are changed").split(","));
163 }
164 
165 //-----------------------------------------------------------------------------
166 
167 void BackupPlugin::slotAllCleared(){
168  globalBackup_.clear();
169  updateButtons();
170 }
171 
172 //-----------------------------------------------------------------------------
173 
174 void BackupPlugin::updateButtons() {
175 
176  if ( globalBackup_.undoAvailable() ){
177  undoMenuAction_->setText( tr("Undo '%1'").arg( globalBackup_.undoName() ) );
178  undoMenuAction_->setEnabled(true);
179  undoToolAction_->setText( tr("Undo '%1'").arg( globalBackup_.undoName() ) );
180  undoToolAction_->setEnabled(true);
181  } else {
182  undoMenuAction_->setText( tr("Undo") );
183  undoMenuAction_->setEnabled(false);
184  undoToolAction_->setText( tr("Undo") );
185  undoToolAction_->setEnabled(false);
186  }
187 
188  if ( globalBackup_.redoAvailable() ){
189  redoMenuAction_->setText( tr("Redo '%1'").arg( globalBackup_.redoName() ) );
190  redoMenuAction_->setEnabled(true);
191  redoToolAction_->setText( tr("Redo '%1'").arg( globalBackup_.redoName() ) );
192  redoToolAction_->setEnabled(true);
193  } else {
194  redoMenuAction_->setText( tr("Redo") );
195  redoMenuAction_->setEnabled(false);
196  redoToolAction_->setText( tr("Redo") );
197  redoToolAction_->setEnabled(false);
198  }
199 
200  backupsEnabledAction_->setChecked( OpenFlipper::Options::backupEnabled() );
201 }
202 
203 //-----------------------------------------------------------------------------
204 
206  OpenFlipper::Options::enableBackup(backupsEnabledAction_->isChecked());
207  std::cerr << "Setting OpenFlipper Option 1 " << backupsEnabledAction_->isChecked() << std::endl;
208  OpenFlipperSettings().setValue("BackupPlugin/EnableBackups", backupsEnabledAction_->isChecked());
209 }
210 
211 //-----------------------------------------------------------------------------
212 
213 void BackupPlugin::slotKeyEvent( QKeyEvent* _event ){
214  switch (_event->key())
215  {
216  case Qt::Key_Z :
217  if ( _event->modifiers() == Qt::ControlModifier )
218  emit undo();
219  else if ( _event->modifiers() == (Qt::ControlModifier | Qt::ShiftModifier) )
220  emit redo();
221  break;
222  default:
223  break;
224  }
225 }
226 
227 //-----------------------------------------------------------------------------
228 
229 void BackupPlugin::objectDeleted(int _objectid) {
230  globalBackup_.eraseBackups(_objectid);
231  updateButtons();
232 }
233 
234 //-----------------------------------------------------------------------------
235 
236 void BackupPlugin::slotUpdateContextMenu( int _objectId ){
237 
238  //disable everything
239  undoContextAction_->setText( tr("Undo") );
240  undoContextAction_->setEnabled(false);
241  redoContextAction_->setText( tr("Redo") );
242  redoContextAction_->setEnabled(false);
243 
244  //get backup data
245  BaseObjectData* object = 0;
246  PluginFunctions::getObject(_objectId, object);
247 
248  if ( object != 0 ){
249 
250  if ( object->hasObjectData( OBJECT_BACKUPS ) ){
251 
252  //get backup object data
253  BackupData* backupData = dynamic_cast< BackupData* >(object->objectData(OBJECT_BACKUPS));
254 
255  if ( backupData->undoAvailable() ){
256  undoContextAction_->setData(_objectId);
257  undoContextAction_->setText( tr("Undo '%1'").arg( backupData->undoName() ) );
258  undoContextAction_->setEnabled( !backupData->undoBlocked() );
259  }
260 
261  if ( backupData->redoAvailable() ){
262  redoContextAction_->setData(_objectId);
263  redoContextAction_->setText( tr("Redo '%1'").arg( backupData->redoName() ) );
264  redoContextAction_->setEnabled( !backupData->redoBlocked() );
265  }
266  }
267  }
268 
269 }
270 
271 //-----------------------------------------------------------------------------
272 
273 void BackupPlugin::slotObjectUndo(){
274 
275  int id = undoContextAction_->data().toInt();
276  emit undo(id);
277 }
278 
279 //-----------------------------------------------------------------------------
280 
281 void BackupPlugin::slotObjectRedo(){
282 
283  int id = undoContextAction_->data().toInt();
284  emit redo(id);
285 }
286 
287 //-----------------------------------------------------------------------------
288 
289 void BackupPlugin::slotCreateBackup( int _objectid, QString _name, UpdateType _type){
290 
291  if ( !OpenFlipper::Options::backupEnabled() )
292  return;
293 
294  BaseObjectData* object;
295 
296  if ( !PluginFunctions::getObject(_objectid,object) ){
297  emit log(LOGWARN,"Unable to find backup object with id " + QString::number(_objectid));
298  return;
299  }
300 
301  //tell TypePlugin to Backup
302  emit generateBackup( _objectid, _name, _type );
303 
304  //add global backup
305  IdList groupIds;
306  groupIds.push_back( _objectid );
307 
308  bool skipBackup = false;
309 
310  if ( globalBackup_.undoAvailable() ){
311  //skip 'Original Object' Backups in global view
312  BackupData* backupData = dynamic_cast< BackupData* >(object->objectData(OBJECT_BACKUPS));
313 
314  if ( backupData != 0 )
315  skipBackup = !backupData->undoAvailable();
316  }
317 
318  if ( !skipBackup ){
319  GroupBackup* backup = new GroupBackup(groupIds, _name);
320  globalBackup_.storeBackup( backup );
321  }
322 
323  updateButtons();
324  emit log(LOGOUT,"Created backup for " + QString::number(_objectid)+ " , Name : '" + _name + "'" );
325 }
326 
327 //-----------------------------------------------------------------------------
328 
329 void BackupPlugin::slotCreateBackup( IdList _objectids , QString _name, std::vector<UpdateType> _types){
330 
331  if ( !OpenFlipper::Options::backupEnabled() )
332  return;
333 
334  IdList groupIds;
335 
336  if ( _objectids.size() != _types.size() ){
337  emit log(LOGWARN,"Unable to create backup sizes of ids and updateTypes do not match!");
338  return;
339  }
340 
341  //generate backups on all objects
342  for (unsigned int i=0; i < _objectids.size(); ++i){
343 
344  BaseObjectData* object;
345 
346  if ( !PluginFunctions::getObject(_objectids[i],object) ){
347  emit log(LOGWARN,"Unable to find backup object with id " + QString::number(_objectids[i]));
348  continue;
349  }
350 
351  //tell TypePlugin to generate a backup
352  emit generateBackup( _objectids[i], _name, _types[i] );
353  groupIds.push_back( _objectids[i] );
354  }
355 
356  //add global backup
357  if ( ! groupIds.empty() ){
358 
359  GroupBackup* backup = new GroupBackup(groupIds, _name);
360  globalBackup_.storeBackup( backup );
361 
362  updateButtons();
363  emit log(LOGOUT,"Created grouped backup, Name : '" + _name + "'" );
364  }
365 }
366 
367 //-----------------------------------------------------------------------------
368 
369 void BackupPlugin::slotUndo(int _objectid){
370 
371  emit aboutToRestore(_objectid);
372  globalBackup_.undo(_objectid);
373  emit restored(_objectid);
374  emit updatedObject(_objectid, UPDATE_ALL);
375 
376  updateButtons();
377 }
378 
379 //-----------------------------------------------------------------------------
380 
381 void BackupPlugin::slotUndo(){
382  GroupBackup* group = dynamic_cast< GroupBackup* >( globalBackup_.currentState() );
383 
384  if (group) {
385  IdList ids = group->objectIDs();
386  IdList::const_iterator it, end;
387  for (it = ids.begin(), end = ids.end(); it != end; ++it)
388  emit aboutToRestore(*it);
389 
390  globalBackup_.undo();
391 
392  for (unsigned int i=0; i < group->objectIDs().size(); i++)
393  {
394  emit restored(group->objectIDs()[i]);
395  emit updatedObject(group->objectIDs()[i], UPDATE_ALL);
396  }
397 
398  updateButtons();
399  } else
400  emit log(LOGWARN,"Unable to find the current GroupBackup");
401 }
402 
403 //-----------------------------------------------------------------------------
404 
405 void BackupPlugin::slotRedo(int _objectid){
406 
407  emit aboutToRestore(_objectid);
408  globalBackup_.redo(_objectid);
409  emit restored(_objectid);
410  emit updatedObject(_objectid, UPDATE_ALL);
411 
412  updateButtons();
413 }
414 
415 //-----------------------------------------------------------------------------
416 
417 void BackupPlugin::slotRedo(){
418  globalBackup_.redo();
419 
420  GroupBackup* group = dynamic_cast< GroupBackup* >( globalBackup_.currentState() );
421 
422  if ( group != 0)
423  for (unsigned int i=0; i < group->objectIDs().size(); i++)
424  {
425  emit restored(group->objectIDs()[i]);
426  emit updatedObject(group->objectIDs()[i], UPDATE_ALL);
427  }
428 
429  updateButtons();
430 }
431 
432 //-----------------------------------------------------------------------------
433 
434 void BackupPlugin::createBackup(int _objectId, QString _name, UpdateType _type)
435 {
436  slotCreateBackup(_objectId,_name,_type);
437 }
438 
439 //-----------------------------------------------------------------------------
440 
441 bool BackupPlugin::initializeOptionsWidget(QWidget*& _widget)
442 {
443  QLabel* maxBackupLabel = new QLabel();
444  maxBackupLabel->setText(tr("Max. saved backups: "));
445  maxBackupSpinBox_ = new QSpinBox();
446  maxBackupSpinBox_->setValue(globalBackup_.maxBackups());
447  maxBackupSpinBox_->setRange(0,100);
448 
449  QHBoxLayout* layout = new QHBoxLayout();
450  layout->addWidget(maxBackupLabel);
451  layout->addWidget(maxBackupSpinBox_);
452 
453  QWidget* baseWidget = new QWidget();
454  baseWidget->setLayout(layout);
455  _widget = baseWidget;
456 
457  return true;
458 }
459 
460 //-----------------------------------------------------------------------------
461 
462 void BackupPlugin::applyOptions()
463 {
464  int maxBackups = maxBackupSpinBox_->value();
465  globalBackup_.setMaxBackups(maxBackups);
466  OpenFlipperSettings().setValue("BackupPlugin/MaxBackups", maxBackups);
467 }
468 
469 
const UpdateType UPDATE_ALL(UpdateTypeSet(1))
Identifier for all updates.
bool redoAvailable()
return if a redo backup is available
Definition: BackupData.cc:189
bool undoBlocked()
return if an undo backup is blocked
Definition: BackupData.cc:195
bool getObject(const int _identifier, BaseObject *&_object)
Get the object which has the given identifier.
QString redoName()
return the name of the next redo backup
Definition: BackupData.cc:143
Class that encapsulates simultaneous backups on multiple objects.
Definition: GroupBackup.hh:52
std::vector< int > IdList
Standard Type for id Lists used for scripting.
Definition: DataTypes.hh:181
Abstract class that is used to store backups.
Definition: BackupData.hh:57
QVariant value(const QString &key, const QVariant &defaultValue=QVariant()) const
void createBackup(int _objectId, QString _name, UpdateType _type=UPDATE_ALL)
Tell Backup Plugin to create a backup.
void slotEnableDisableBackups()
Backups enabled or disabled checkbox.
Update type class.
Definition: UpdateType.hh:59
bool redoBlocked()
return if a redo backup is blocked
Definition: BackupData.cc:205
QString undoName()
return the name of the next undo backup
Definition: BackupData.cc:133
bool undoAvailable()
return if an undo backup is available
Definition: BackupData.cc:183
void setValue(const QString &key, const QVariant &value)
Wrapper function which makes it possible to enable Debugging output with -DOPENFLIPPER_SETTINGS_DEBUG...
bool hasObjectData(QString _dataName)
Checks if object data with given name is available.
Definition: BaseObject.cc:795
DLLEXPORT OpenFlipperQSettings & OpenFlipperSettings()
QSettings object containing all program settings of OpenFlipper.
The Menu will be shown when an object was picked.
const DataType DATA_ALL(UINT_MAX)
Identifier for all available objects.