diff --git a/src/README.md b/src/README.md index 51c9e6046..b27434d8e 100644 --- a/src/README.md +++ b/src/README.md @@ -59,6 +59,9 @@ because they don't depend on any other component. # Debugging Tricks -On Windows, you can use F5 to show the amount of used memory. Also -`Ctrl+Shift+Q` crashes the application in case that you want to test -the anticrash feature or your need a memory dump file. +* On Windows, you can use F5 to show the amount of used memory. +* On debug mode (when `_DEBUG` is defined), `Ctrl+Alt+Shift+Q` crashes + the application in case that you want to test the anticrash feature + or your need a memory dump file. +* On debug mode, you can use `Ctrl+Alt+Shift+R` to recover the active + document from the data recovery store. diff --git a/src/app/app.cpp b/src/app/app.cpp index 1abb084bb..b2c7167a6 100644 --- a/src/app/app.cpp +++ b/src/app/app.cpp @@ -129,6 +129,7 @@ public: void deleteDataRecovery() { #ifdef ENABLE_DATA_RECOVERY delete m_recovery; + m_recovery = nullptr; #endif } @@ -845,6 +846,11 @@ Preferences& App::preferences() const return m_coreModules->m_preferences; } +crash::DataRecovery* App::dataRecovery() const +{ + return m_modules->recovery(); +} + void App::showNotification(INotificationDelegate* del) { m_mainWindow->showNotification(del); diff --git a/src/app/app.h b/src/app/app.h index ebd520e39..6d4acb874 100644 --- a/src/app/app.h +++ b/src/app/app.h @@ -42,6 +42,10 @@ namespace app { class Timeline; class Workspace; + namespace crash { + class DataRecovery; + } + namespace tools { class ActiveToolManager; class Tool; @@ -78,6 +82,7 @@ namespace app { ContextBar* contextBar() const; Timeline* timeline() const; Preferences& preferences() const; + crash::DataRecovery* dataRecovery() const; AppBrushes& brushes() { ASSERT(m_brushes.get()); diff --git a/src/app/crash/data_recovery.h b/src/app/crash/data_recovery.h index b2b4dfa34..51a2924e3 100644 --- a/src/app/crash/data_recovery.h +++ b/src/app/crash/data_recovery.h @@ -1,5 +1,5 @@ // Aseprite -// Copyright (C) 2001-2015 David Capello +// Copyright (C) 2001-2016 David Capello // // This program is distributed under the terms of // the End-User License Agreement for Aseprite. @@ -28,6 +28,8 @@ namespace crash { DataRecovery(doc::Context* context); ~DataRecovery(); + Session* activeSession() { return m_inProgress.get(); } + // Returns the list of sessions that can be recovered. const Sessions& sessions() { return m_sessions; } diff --git a/src/app/crash/session.cpp b/src/app/crash/session.cpp index fd076d784..6925c0c58 100644 --- a/src/app/crash/session.cpp +++ b/src/app/crash/session.cpp @@ -25,6 +25,7 @@ #include "base/process.h" #include "base/split_string.h" #include "base/string.h" +#include "base/unique_ptr.h" namespace app { namespace crash { @@ -173,6 +174,17 @@ void Session::restoreBackup(Backup* backup) } } +void Session::restoreBackupById(const ObjectId id) +{ + std::string docDir = base::join_path(m_path, base::convert_to(int(id))); + if (!base::is_directory(docDir)) + return; + + base::UniquePtr backup(new Backup(docDir)); + if (backup) + restoreBackup(backup.get()); +} + void Session::restoreRawImages(Backup* backup, RawImagesAs as) { Console console; diff --git a/src/app/crash/session.h b/src/app/crash/session.h index 354ecc7c5..ac9b9b667 100644 --- a/src/app/crash/session.h +++ b/src/app/crash/session.h @@ -12,6 +12,7 @@ #include "base/disable_copying.h" #include "base/process.h" #include "base/shared_ptr.h" +#include "doc/object_id.h" #include #include @@ -52,6 +53,7 @@ namespace crash { void removeDocument(app::Document* doc); void restoreBackup(Backup* backup); + void restoreBackupById(const doc::ObjectId id); void restoreRawImages(Backup* backup, RawImagesAs as); void deleteBackup(Backup* backup); diff --git a/src/app/modules/gui.cpp b/src/app/modules/gui.cpp index 5ab764a04..615856a27 100644 --- a/src/app/modules/gui.cpp +++ b/src/app/modules/gui.cpp @@ -15,7 +15,6 @@ #include "app/console.h" #include "app/document.h" #include "app/ini_file.h" -#include "app/modules/editors.h" #include "app/modules/gfx.h" #include "app/modules/gui.h" #include "app/modules/palettes.h" @@ -47,6 +46,11 @@ #include #include +#if defined(_DEBUG) && defined(ENABLE_DATA_RECOVERY) +#include "app/crash/data_recovery.h" +#include "app/modules/editors.h" +#endif + namespace app { using namespace gfx; @@ -372,14 +376,30 @@ bool CustomizedGuiManager::onProcessMessage(Message* msg) case kKeyDownMessage: { #ifdef _DEBUG - // Left Shift+Ctrl+Q generates a crash (useful to test the anticrash feature) + // Ctrl+Shift+Q generates a crash (useful to test the anticrash feature) if (msg->ctrlPressed() && msg->shiftPressed() && static_cast(msg)->scancode() == kKeyQ) { int* p = nullptr; *p = 0; } -#endif + +#ifdef ENABLE_DATA_RECOVERY + // Ctrl+Shift+R recover active sprite from the backup store + if (msg->ctrlPressed() && + msg->shiftPressed() && + static_cast(msg)->scancode() == kKeyR && + App::instance()->dataRecovery() && + App::instance()->dataRecovery()->activeSession() && + current_editor && + current_editor->document()) { + App::instance() + ->dataRecovery() + ->activeSession() + ->restoreBackupById(current_editor->document()->id()); + } +#endif // ENABLE_DATA_RECOVERY +#endif // _DEBUG // Call base impl to check if there is a foreground window as // top level that needs keys. (In this way we just do not