Developer Documentation
Loading...
Searching...
No Matches
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//-----------------------------------------------------------------------------
55BackupPlugin::BackupPlugin():
56globalBackup_(),
57backupMenu_(0),
58backupsEnabledAction_(0),
59undoMenuAction_(0),
60redoMenuAction_(0),
61undoToolAction_(0),
62redoToolAction_(0),
63undoContextAction_(0),
64redoContextAction_(0),
65maxBackupSpinBox_(0)
66{
67
68}
69
70//-----------------------------------------------------------------------------
71
72void BackupPlugin::initializePlugin()
73{
74 int maxBackups = OpenFlipperSettings().value("BackupPlugin/MaxBackups",static_cast<unsigned>(globalBackup_.maxBackups())).toInt();
75 globalBackup_.setMaxBackups(maxBackups);
76
77 OpenFlipper::Options::enableBackup(OpenFlipperSettings().value("BackupPlugin/EnableBackups",true).toBool());
78}
79
80//-----------------------------------------------------------------------------
81
82void BackupPlugin::pluginsInitialized() {
83
84 // Create Backup menu
85 emit getMenubarMenu(tr("&Backup"), backupMenu_, true );
86
87 if ( OpenFlipper::Options::gui() ) {
88 //construct the menu
89 backupsEnabledAction_ = new QAction("Backups Enabled",0);
90 backupsEnabledAction_->setCheckable(true);
91 backupsEnabledAction_->setChecked(OpenFlipper::Options::backupEnabled());
92 connect (backupsEnabledAction_, SIGNAL(triggered(bool)), this, SLOT(slotEnableDisableBackups()) );
93
94 undoMenuAction_ = new QAction(tr("&Undo"), this);
95 undoMenuAction_->setEnabled(false);
96 undoMenuAction_->setStatusTip(tr("Undo the last action."));
97 undoMenuAction_->setIcon(QIcon(OpenFlipper::Options::iconDirStr()+OpenFlipper::Options::dirSeparator()+"edit-undo.png") );
98 connect(undoMenuAction_, SIGNAL(triggered()), this, SIGNAL( undo() ) );
99
100 redoMenuAction_ = new QAction(tr("&Redo"), this);
101 redoMenuAction_->setEnabled(false);
102 redoMenuAction_->setStatusTip(tr("Redo the last action"));
103 redoMenuAction_->setIcon(QIcon(OpenFlipper::Options::iconDirStr()+OpenFlipper::Options::dirSeparator()+"edit-redo.png") );
104 connect(redoMenuAction_, SIGNAL(triggered()), this, SIGNAL( redo() ) );
105
106 backupMenu_->addAction(undoMenuAction_);
107 backupMenu_->addAction(redoMenuAction_);
108 backupMenu_->addSeparator();
109 backupMenu_->addAction(backupsEnabledAction_);
110
111 // Add a backup Toolbar
112 QToolBar* toolbar = new QToolBar("Backup Toolbar");
113
114 //Undo
115 undoToolAction_ = new QAction(tr("&Undo"), this);
116 undoToolAction_->setEnabled(false);
117 undoToolAction_->setStatusTip(tr("Undo the last action."));
118 undoToolAction_->setIcon(QIcon(OpenFlipper::Options::iconDirStr()+OpenFlipper::Options::dirSeparator()+"edit-undo.png") );
119 connect(undoToolAction_, SIGNAL(triggered()), this, SIGNAL( undo() ) );
120 toolbar->addAction(undoToolAction_);
121
122 //Redo
123 redoToolAction_ = new QAction(tr("&Redo"), this);
124 redoToolAction_->setEnabled(false);
125 redoToolAction_->setStatusTip(tr("Redo the last action"));
126 redoToolAction_->setIcon(QIcon(OpenFlipper::Options::iconDirStr()+OpenFlipper::Options::dirSeparator()+"edit-redo.png") );
127 connect(redoToolAction_, SIGNAL(triggered()), this, SIGNAL( redo() ) );
128 toolbar->addAction(redoToolAction_);
129
130 emit addToolbar( toolbar );
131
132 //the release event does not contain the modifier
133 emit registerKey(Qt::Key_Z, Qt::ControlModifier, tr("Undo Action"));
134 emit registerKey(Qt::Key_Z, (Qt::ControlModifier | Qt::ShiftModifier), tr("Redo Action"));
135
136 //add actions for the context menu
137 undoContextAction_ = new QAction(tr("&Undo"), this);
138 undoContextAction_->setEnabled(false);
139 undoContextAction_->setStatusTip(tr("Undo the last action."));
140 undoContextAction_->setIcon(QIcon(OpenFlipper::Options::iconDirStr()+OpenFlipper::Options::dirSeparator()+"edit-undo.png") );
141 connect(undoContextAction_, SIGNAL(triggered()), this, SLOT(slotObjectUndo()) );
142 emit addContextMenuItem(undoContextAction_, DATA_ALL, CONTEXTOBJECTMENU);
143
144 redoContextAction_ = new QAction(tr("&Redo"), this);
145 redoContextAction_->setEnabled(false);
146 redoContextAction_->setStatusTip(tr("Redo the last action"));
147 redoContextAction_->setIcon(QIcon(OpenFlipper::Options::iconDirStr()+OpenFlipper::Options::dirSeparator()+"edit-redo.png") );
148 connect(redoContextAction_, SIGNAL(triggered()), this, SLOT(slotObjectRedo()) );
149 emit addContextMenuItem(redoContextAction_, DATA_ALL, CONTEXTOBJECTMENU);
150
151 //update option widget since it is created earlier
152 if (maxBackupSpinBox_)
153 maxBackupSpinBox_->setValue(globalBackup_.maxBackups());
154
155 }
156
157//createBackup(int _objectId, QString _name, UpdateType _type= UPDATE_ALL)
158 emit setSlotDescription("createBackup(int,QString)", tr("Creates a backup which can be restored via undo."),
159 QString("objectId,name").split(","), QString("Id of the object,name of the backup").split(","));
160 emit setSlotDescription("createBackup(int,QString,UpdateType)", tr("Creates a backup which can be restored via undo."),
161 QString("objectId,name,type").split(","), QString("Id of the object,name of the backup,updatetypes which are changed").split(","));
162}
163
164//-----------------------------------------------------------------------------
165
166void BackupPlugin::slotAllCleared(){
167 globalBackup_.clear();
168 updateButtons();
169}
170
171//-----------------------------------------------------------------------------
172
173void BackupPlugin::updateButtons() {
174
175 if ( globalBackup_.undoAvailable() ){
176 undoMenuAction_->setText( tr("Undo '%1'").arg( globalBackup_.undoName() ) );
177 undoMenuAction_->setEnabled(true);
178 undoToolAction_->setText( tr("Undo '%1'").arg( globalBackup_.undoName() ) );
179 undoToolAction_->setEnabled(true);
180 } else {
181 undoMenuAction_->setText( tr("Undo") );
182 undoMenuAction_->setEnabled(false);
183 undoToolAction_->setText( tr("Undo") );
184 undoToolAction_->setEnabled(false);
185 }
186
187 if ( globalBackup_.redoAvailable() ){
188 redoMenuAction_->setText( tr("Redo '%1'").arg( globalBackup_.redoName() ) );
189 redoMenuAction_->setEnabled(true);
190 redoToolAction_->setText( tr("Redo '%1'").arg( globalBackup_.redoName() ) );
191 redoToolAction_->setEnabled(true);
192 } else {
193 redoMenuAction_->setText( tr("Redo") );
194 redoMenuAction_->setEnabled(false);
195 redoToolAction_->setText( tr("Redo") );
196 redoToolAction_->setEnabled(false);
197 }
198
199 backupsEnabledAction_->setChecked( OpenFlipper::Options::backupEnabled() );
200}
201
202//-----------------------------------------------------------------------------
203
205 OpenFlipper::Options::enableBackup(backupsEnabledAction_->isChecked());
206 std::cerr << "Setting OpenFlipper Option 1 " << backupsEnabledAction_->isChecked() << std::endl;
207 OpenFlipperSettings().setValue("BackupPlugin/EnableBackups", backupsEnabledAction_->isChecked());
208}
209
210//-----------------------------------------------------------------------------
211
212void BackupPlugin::slotKeyEvent( QKeyEvent* _event ){
213 switch (_event->key())
214 {
215 case Qt::Key_Z :
216 if ( _event->modifiers() == Qt::ControlModifier )
217 emit undo();
218 else if ( _event->modifiers() == (Qt::ControlModifier | Qt::ShiftModifier) )
219 emit redo();
220 break;
221 default:
222 break;
223 }
224}
225
226//-----------------------------------------------------------------------------
227
228void BackupPlugin::objectDeleted(int _objectid) {
229 globalBackup_.eraseBackups(_objectid);
230 updateButtons();
231}
232
233//-----------------------------------------------------------------------------
234
235void BackupPlugin::slotUpdateContextMenu( int _objectId ){
236
237 //disable everything
238 undoContextAction_->setText( tr("Undo") );
239 undoContextAction_->setEnabled(false);
240 redoContextAction_->setText( tr("Redo") );
241 redoContextAction_->setEnabled(false);
242
243 //get backup data
244 BaseObjectData* object = 0;
245 PluginFunctions::getObject(_objectId, object);
246
247 if ( object != 0 ){
248
249 if ( object->hasObjectData( OBJECT_BACKUPS ) ){
250
251 //get backup object data
252 BackupData* backupData = dynamic_cast< BackupData* >(object->objectData(OBJECT_BACKUPS));
253
254 if ( backupData->undoAvailable() ){
255 undoContextAction_->setData(_objectId);
256 undoContextAction_->setText( tr("Undo '%1'").arg( backupData->undoName() ) );
257 undoContextAction_->setEnabled( !backupData->undoBlocked() );
258 }
259
260 if ( backupData->redoAvailable() ){
261 redoContextAction_->setData(_objectId);
262 redoContextAction_->setText( tr("Redo '%1'").arg( backupData->redoName() ) );
263 redoContextAction_->setEnabled( !backupData->redoBlocked() );
264 }
265 }
266 }
267
268}
269
270//-----------------------------------------------------------------------------
271
272void BackupPlugin::slotObjectUndo(){
273
274 int id = undoContextAction_->data().toInt();
275 emit undo(id);
276}
277
278//-----------------------------------------------------------------------------
279
280void BackupPlugin::slotObjectRedo(){
281
282 int id = undoContextAction_->data().toInt();
283 emit redo(id);
284}
285
286//-----------------------------------------------------------------------------
287
288void BackupPlugin::slotCreateBackup( int _objectid, QString _name, UpdateType _type){
289
290 if ( !OpenFlipper::Options::backupEnabled() )
291 return;
292
293 BaseObjectData* object;
294
295 if ( !PluginFunctions::getObject(_objectid,object) ){
296 emit log(LOGWARN,"Unable to find backup object with id " + QString::number(_objectid));
297 return;
298 }
299
300 //tell TypePlugin to Backup
301 emit generateBackup( _objectid, _name, _type );
302
303 //add global backup
304 IdList groupIds;
305 groupIds.push_back( _objectid );
306
307 bool skipBackup = false;
308
309 if ( globalBackup_.undoAvailable() ){
310 //skip 'Original Object' Backups in global view
311 BackupData* backupData = dynamic_cast< BackupData* >(object->objectData(OBJECT_BACKUPS));
312
313 if ( backupData != 0 )
314 skipBackup = !backupData->undoAvailable();
315 }
316
317 if ( !skipBackup ){
318 GroupBackup* backup = new GroupBackup(groupIds, _name);
319 globalBackup_.storeBackup( backup );
320 }
321
322 updateButtons();
323 emit log(LOGOUT,"Created backup for " + QString::number(_objectid)+ " , Name : '" + _name + "'" );
324}
325
326//-----------------------------------------------------------------------------
327
328void BackupPlugin::slotCreateBackup( IdList _objectids , QString _name, std::vector<UpdateType> _types){
329
330 if ( !OpenFlipper::Options::backupEnabled() )
331 return;
332
333 IdList groupIds;
334
335 if ( _objectids.size() != _types.size() ){
336 emit log(LOGWARN,"Unable to create backup sizes of ids and updateTypes do not match!");
337 return;
338 }
339
340 //generate backups on all objects
341 for (unsigned int i=0; i < _objectids.size(); ++i){
342
343 BaseObjectData* object;
344
345 if ( !PluginFunctions::getObject(_objectids[i],object) ){
346 emit log(LOGWARN,"Unable to find backup object with id " + QString::number(_objectids[i]));
347 continue;
348 }
349
350 //tell TypePlugin to generate a backup
351 emit generateBackup( _objectids[i], _name, _types[i] );
352 groupIds.push_back( _objectids[i] );
353 }
354
355 //add global backup
356 if ( ! groupIds.empty() ){
357
358 GroupBackup* backup = new GroupBackup(groupIds, _name);
359 globalBackup_.storeBackup( backup );
360
361 updateButtons();
362 emit log(LOGOUT,"Created grouped backup, Name : '" + _name + "'" );
363 }
364}
365
366//-----------------------------------------------------------------------------
367
368void BackupPlugin::slotUndo(int _objectid){
369
370 emit aboutToRestore(_objectid);
371 globalBackup_.undo(_objectid);
372 emit restored(_objectid);
373 emit updatedObject(_objectid, UPDATE_ALL);
374
375 updateButtons();
376}
377
378//-----------------------------------------------------------------------------
379
380void BackupPlugin::slotUndo(){
381 GroupBackup* group = dynamic_cast< GroupBackup* >( globalBackup_.currentState() );
382
383 if (group) {
384 IdList ids = group->objectIDs();
385 IdList::const_iterator it, end;
386 for (it = ids.begin(), end = ids.end(); it != end; ++it)
387 emit aboutToRestore(*it);
388
389 globalBackup_.undo();
390
391 for (unsigned int i=0; i < group->objectIDs().size(); i++)
392 {
393 emit restored(group->objectIDs()[i]);
394 emit updatedObject(group->objectIDs()[i], UPDATE_ALL);
395 }
396
397 updateButtons();
398 } else
399 emit log(LOGWARN,"Unable to find the current GroupBackup");
400}
401
402//-----------------------------------------------------------------------------
403
404void BackupPlugin::slotRedo(int _objectid){
405
406 emit aboutToRestore(_objectid);
407 globalBackup_.redo(_objectid);
408 emit restored(_objectid);
409 emit updatedObject(_objectid, UPDATE_ALL);
410
411 updateButtons();
412}
413
414//-----------------------------------------------------------------------------
415
416void BackupPlugin::slotRedo(){
417 globalBackup_.redo();
418
419 GroupBackup* group = dynamic_cast< GroupBackup* >( globalBackup_.currentState() );
420
421 if ( group != 0)
422 for (unsigned int i=0; i < group->objectIDs().size(); i++)
423 {
424 emit restored(group->objectIDs()[i]);
425 emit updatedObject(group->objectIDs()[i], UPDATE_ALL);
426 }
427
428 updateButtons();
429}
430
431//-----------------------------------------------------------------------------
432
433void BackupPlugin::createBackup(int _objectId, const QString& _name, UpdateType _type)
434{
435 slotCreateBackup(_objectId,_name,_type);
436}
437
438//-----------------------------------------------------------------------------
439
440bool BackupPlugin::initializeOptionsWidget(QWidget*& _widget)
441{
442 QLabel* maxBackupLabel = new QLabel();
443 maxBackupLabel->setText(tr("Max. saved backups: "));
444 maxBackupSpinBox_ = new QSpinBox();
445 maxBackupSpinBox_->setValue(globalBackup_.maxBackups());
446 maxBackupSpinBox_->setRange(0,100);
447
448 QHBoxLayout* layout = new QHBoxLayout();
449 layout->addWidget(maxBackupLabel);
450 layout->addWidget(maxBackupSpinBox_);
451
452 QWidget* baseWidget = new QWidget();
453 baseWidget->setLayout(layout);
454 _widget = baseWidget;
455
456 return true;
457}
458
459//-----------------------------------------------------------------------------
460
461void BackupPlugin::applyOptions()
462{
463 int maxBackups = maxBackupSpinBox_->value();
464 globalBackup_.setMaxBackups(maxBackups);
465 OpenFlipperSettings().setValue("BackupPlugin/MaxBackups", maxBackups);
466}
467
468void BackupPlugin::createBackupSimple(int _objectId, const QString& _name) {
469 createBackup(_objectId, _name);
470}
@ CONTEXTOBJECTMENU
The Menu will be shown when an object was picked.
const DataType DATA_ALL(UINT_MAX)
Identifier for all available objects.
std::vector< int > IdList
Standard Type for id Lists used for scripting.
Definition DataTypes.hh:181
@ LOGWARN
@ LOGOUT
Abstract class that is used to store backups.
Definition BackupData.hh:58
void setMaxBackups(size_t _max)
set the maximum of saved backups
Definition BackupData.cc:65
size_t maxBackups()
return the maximum of backups which are saved
Definition BackupData.cc:58
BaseBackup * currentState()
return the current state
bool undoAvailable()
return if an undo backup is available
void storeBackup(BaseBackup *_backup)
store a backup
Definition BackupData.cc:72
bool redoAvailable()
return if a redo backup is available
void clear()
remove all backups
bool redoBlocked()
return if a redo backup is blocked
bool undoBlocked()
return if an undo backup is blocked
QString redoName()
return the name of the next redo backup
QString undoName()
return the name of the next undo backup
void slotEnableDisableBackups()
Backups enabled or disabled checkbox.
QMenu * backupMenu_
The backup Menu.
bool hasObjectData(QString _dataName)
Checks if object data with given name is available.
Class that encapsulates simultaneous backups on multiple objects.
void undo()
perform an undo if possible
Definition GroupData.cc:69
void eraseBackups(int _objectid)
erase all backups containing given id
Definition GroupData.cc:309
void redo()
perform an redo if possible
Definition GroupData.cc:118
QVariant value(const QString &key, const QVariant &defaultValue=QVariant()) const
void setValue(const QString &key, const QVariant &value)
Wrapper function which makes it possible to enable Debugging output with -DOPENFLIPPER_SETTINGS_DEBUG...
Update type class.
Definition UpdateType.hh:59
const UpdateType UPDATE_ALL(UpdateTypeSet(1))
Identifier for all updates.
bool getObject(const int _identifier, BaseObject *&_object)
Get the object which has the given identifier.