File indexing completed on 2024-04-21 15:38:54

0001 /***************************************************************************
0002  *   Copyright (C) 2005-2014 by Linuxstopmotion contributors;              *
0003  *   see the AUTHORS file for details.                                     *
0004  *                                                                         *
0005  *   This program is free software; you can redistribute it and/or modify  *
0006  *   it under the terms of the GNU General Public License as published by  *
0007  *   the Free Software Foundation; either version 2 of the License, or     *
0008  *   (at your option) any later version.                                   *
0009  *                                                                         *
0010  *   This program is distributed in the hope that it will be useful,       *
0011  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
0012  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
0013  *   GNU General Public License for more details.                          *
0014  *                                                                         *
0015  *   You should have received a copy of the GNU General Public License     *
0016  *   along with this program; if not, write to the                         *
0017  *   Free Software Foundation, Inc.,                                       *
0018  *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
0019  ***************************************************************************/
0020 #include "config.h"
0021 #include "src/domain/domainfacade.h"
0022 
0023 #ifdef QTGUI
0024 #include "presentation/frontends/qtfrontend/qtfrontend.h"
0025 #endif
0026 
0027 #include "presentation/frontends/nonguifrontend/nonguifrontend.h"
0028 #include "src/foundation/preferencestool.h"
0029 #include "src/domain/animation/workspacefile.h"
0030 #include "uiexception.h"
0031 
0032 #include <unistd.h>
0033 #include <stdio.h>
0034 #include <string.h>
0035 #include <sys/stat.h>
0036 #include <stddef.h>
0037 #include <errno.h>
0038 #include <exception>
0039 #include <iostream>
0040 
0041 class CouldNotInitializeRecoveryFiles : public std::exception {
0042     int error;
0043     char buffer[1024];
0044 public:
0045     CouldNotInitializeRecoveryFiles(int err) : error(err) {
0046         snprintf(buffer, sizeof(buffer),
0047                 "Could not initialize recovery files (%s)."
0048                 " You need permission to read and write in a ~/.stopmotion"
0049                 " directory.", strerror(err));
0050     }
0051     const char* what() const throw() {
0052         return buffer;
0053     }
0054 };
0055 
0056 class RecoveryIncompleteException : public std::exception {
0057     char buffer[1024];
0058 public:
0059     RecoveryIncompleteException(const char* filename) {
0060         snprintf(buffer, sizeof(buffer),
0061                 "Failed to recover previous project from command log file %s."
0062                 " Perhaps the file is corrupt or you don't have permission"
0063                 " to read it.", filename);
0064     }
0065     const char* what() const throw() {
0066         return buffer;
0067     }
0068 };
0069 
0070 /**
0071  * Recover the project. An exception will be throw if recovery fails.
0072  */
0073 void recover(DomainFacade *facadePtr) {
0074     struct stat st;
0075     WorkspaceFile commandLog(WorkspaceFile::commandLogFile);
0076     bool commandLogExists = 0 <= stat(commandLog.path(), &st);
0077     WorkspaceFile currentDat(WorkspaceFile::currentModelFile);
0078     if (stat(currentDat.path(), &st) < 0) {
0079         WorkspaceFile newDat(WorkspaceFile::newModelFile);
0080         if (stat(newDat.path(), &st) < 0) {
0081             if (!commandLogExists) {
0082                 // None of the files are present; clear and start afresh
0083                 WorkspaceFile::clear();
0084             }
0085         } else {
0086             // Program must have crashed in the middle of saving.
0087             if (unlink(commandLog.path()) < 0 && errno != ENOENT) {
0088                 throw CouldNotInitializeRecoveryFiles(errno);
0089             }
0090             commandLogExists = false;
0091             if (!facadePtr->loadProject(newDat.path(), 0)) {
0092                 throw RecoveryIncompleteException(newDat.path());
0093             }
0094         }
0095     } else {
0096         Preference projectFile("projectFile");
0097         if (!facadePtr->loadProject(currentDat.path(), projectFile.get())) {
0098             throw RecoveryIncompleteException(currentDat.path());
0099         }
0100     }
0101     if (commandLogExists) {
0102         facadePtr->replayCommandLog(commandLog.path());
0103     }
0104 }
0105 
0106 int main(int argc, char **argv) {
0107     int ret = 1;
0108 
0109     DomainFacade *facadePtr = DomainFacade::getFacade();
0110 
0111     // if program is started with --nonGUI
0112     if ( argc > 1 && strcmp(argv[1], "--nonGUI") == 0 ) {
0113         NonGUIFrontend nonGUIFrontend(facadePtr);
0114         try {
0115             recover(facadePtr);
0116             facadePtr->registerFrontend(&nonGUIFrontend);
0117             ret = nonGUIFrontend.run(argc, argv);
0118         } catch (std::exception& e) {
0119             std::cerr << e.what();
0120         }
0121     }
0122     else {
0123 #ifdef QTGUI
0124         QtFrontend qtFrontend(argc, argv);
0125         qtFrontend.processEvents();
0126         try {
0127             facadePtr->registerFrontend(&qtFrontend);
0128             recover(facadePtr);
0129             qtFrontend.setUndoRedoEnabled();
0130             facadePtr->initializeCommandLoggerFile();
0131             if (argc > 1 && access(argv[1], R_OK) == 0) {
0132                 qtFrontend.openProject(argv[1]);
0133                 facadePtr->setMostRecentProject();
0134             }
0135             ret = qtFrontend.run(argc, argv);
0136         } catch (UiException& e) {
0137             qtFrontend.handleException(e);
0138         } catch (std::exception& e) {
0139             UiException uie(UiException::ArbitraryError, e.what());
0140             qtFrontend.handleException(uie);
0141         }
0142 #endif
0143     }
0144 
0145     delete facadePtr;
0146     facadePtr = NULL;
0147     return ret;
0148 }