[doc_tool] Moved executing of external programms from Model to FSHelper
authorDaniel G <daniel@giritzer.eu>
Fri, 11 May 2018 00:39:01 +0000 (02:39 +0200)
committerDaniel G <daniel@giritzer.eu>
Fri, 11 May 2018 00:39:01 +0000 (02:39 +0200)
* Minor GUI fixes
* Code cleanup
* Use Variable for Log instead of hardcoded Log.txt (Model)

src/FSHelper.cxx
src/FSHelper.h
src/Model.cxx
src/Model.h
src/ModelIF.h
src/View.cxx
src/ViewFluid.cxx
src/ViewFluid.fld
src/main.cxx

index 979ee78..aa6e477 100644 (file)
 #include <fstream>
 #include <dirent.h>
 #include <sys/types.h>
+#include <unistd.h>
 #include <sys/stat.h>
 #include <cstring>
+#include <sstream>
 #include <algorithm>
 
+#ifndef _WIN32
+#include <sys/wait.h>
+#endif
+
 std::vector<FSHelper::File> FSHelper::listFiles(std::string const &src)
 {
     std::vector<File> retVal;
@@ -33,32 +39,31 @@ std::vector<FSHelper::File> FSHelper::listFiles(std::string const &src)
         closedir(dir);
     }
     else
-        throw std::string("Directory could not be opened!");
+        throw std::string("Directory could not be opened: " + src);
 
     return retVal;
 }
 
-bool FSHelper::copyFile(std::string const &src, std::string const &dest)
+void FSHelper::copyFile(std::string const &src, std::string const &dest)
 {
     std::ifstream srcStream(src, std::ios::in | std::ios_base::binary);
 
     if(!srcStream.good())
-        return false;
+        throw std::string("Failed to open input file: " + src);
 
     std::ofstream destStream(dest, std::ios::out |std::ios_base::binary);
 
     if(!destStream.good())
-        return false;
+        throw std::string("Failed to open output file: " + dest);
 
     destStream << srcStream.rdbuf();
 
     destStream.close();
     srcStream.close();
 
-    return true;
 }
 
-bool FSHelper::makeDir(std::string const& dir)
+void FSHelper::makeDir(std::string const& dir)
 {
     if(!dirExists(dir))
 #if defined(_WIN32)
@@ -66,48 +71,58 @@ bool FSHelper::makeDir(std::string const& dir)
 #else
         if(mkdir(dir.c_str(), S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH) < 0)
 #endif
-            return false;
+            throw std::string("Failed to create directory: " + dir);
 
-    return true;
 }
 
-bool FSHelper::createFile(std::string const& path)
+void FSHelper::createFile(std::string const& path)
 {
     std::ofstream file(path);
 
     if(!file.good())
-        return false;
+        throw std::string("Failed to create file: " + path);
 
     file.close();
-
-    return true;
 }
 
-bool FSHelper::copyFolder(std::string const &src, std::string const &dest)
+void FSHelper::copyDir(std::string const &src, std::string const &dest)
 {
     std::string from = addDirLastSlash(src);
     std::string to = addDirLastSlash(dest);
 
     if(!dirExists(addDirLastSlash(from)))
-        return false;
+        throw std::string("Source folder does not exist: " + from);
 
-    if(!makeDir(to))
-        return false;
+    try
+    {
+        makeDir(to);
+    }
+    catch(std::string& e)
+    {
+        throw std::string("Could not create destination folder: " + to);
+    }
 
     std::vector<File> files;
     if(!listFilesRecursive(from, files, true))
-        return false;
+        throw std::string("Could not fetch source folder content: " + from);
 
     std::vector<std::string> folders;
-    if(!listFoldersRecursive(from, folders, true))
-        return false;
+    if(!listDirsRecursive(from, folders, true))
+        throw std::string("Could not fetch source folder directory tree: " + from);
 
     // Erstelle Ordnerbaum
     for(auto folder : folders)
     {
         folder.replace(folder.find(from), from.length(), to);
-        if(!makeDir(addDirLastSlash(folder)))
-            return false;
+        try
+        {
+            makeDir(addDirLastSlash(folder));
+        }
+        catch(std::string& e)
+        {
+            throw std::string("Could not create directory tree in destination directory! Failed on: " + folder);
+        }
+
     }
 
     // Kopiere Dateien
@@ -118,14 +133,25 @@ bool FSHelper::copyFolder(std::string const &src, std::string const &dest)
 
         // ersetze Qellordner mit zielordner
         outFile.first.replace(outFile.first.find(from), from.length(), to);
-        if(!makeDir(addDirLastSlash(outFile.first)))
-            return false;
+        try
+        {
+            makeDir(addDirLastSlash(outFile.first));
+        }
+        catch(std::string& e)
+        {
+            throw std::string("Could not create subfolder in destination directory! Failed on: " + outFile.first);
+        }
 
-        if(!copyFile(inFile.first + inFile.second, outFile.first + outFile.second))
-            return false;
-    }
+        try
+        {
+            copyFile(inFile.first + inFile.second, outFile.first + outFile.second);
+        }
+        catch(std::string& e)
+        {
+            throw std::string("Could not copy file: " + inFile.first + inFile.second);
+        }
 
-    return true;
+    }
 }
 
 
@@ -178,7 +204,7 @@ std::string FSHelper::addDirLastSlash(std::string const& dir)
 
 std::string FSHelper::rmDirLastSlash(std::string const& dir)
 {
-    if(dir.back() == '\\' && dir.back() == '/')
+    if(dir.back() == '\\' || dir.back() == '/')
         return dir.substr(0, dir.size()-1);
     else
         return dir;
@@ -220,7 +246,7 @@ bool FSHelper::listFilesRecursive(const std::string& path, std::vector<FSHelper:
 }
 
 
-bool FSHelper::listFoldersRecursive(const std::string& path, std::vector<std::string>& folders,const bool showHiddenDirs)
+bool FSHelper::listDirsRecursive(const std::string& path, std::vector<std::string>& folders,const bool showHiddenDirs)
 {
     std::string dir = addDirLastSlash(path);
     DIR *dpdf;
@@ -240,7 +266,7 @@ bool FSHelper::listFoldersRecursive(const std::string& path, std::vector<std::st
             {
                 if(!(std::find(folders.begin(), folders.end(), dir+epdf->d_name) != folders.end()))
                     folders.push_back(addDirLastSlash(dir+epdf->d_name));
-                listFoldersRecursive(dir+epdf->d_name,folders, showHiddenDirs);
+                listDirsRecursive(dir+epdf->d_name,folders, showHiddenDirs);
             }
         }
     }
@@ -248,6 +274,21 @@ bool FSHelper::listFoldersRecursive(const std::string& path, std::vector<std::st
     return true;
 }
 
+std::string FSHelper::getCurrentWorkingDir()
+{
+    char temp[PATH_MAX];
+
+    if(getcwd(temp, PATH_MAX))
+#if defined(_WIN32)
+        return convertPathToWindows(temp);
+#else
+        return convertPathToUnix(temp);
+#endif
+
+    // leerer string bei fehler
+    return std::string("");
+}
+
 std::string FSHelper::convertPathToWindows(std::string dir)
 {
     std::replace(dir.begin(), dir.end(), '/', '\\');
@@ -259,3 +300,166 @@ std::string FSHelper::convertPathToUnix(std::string dir)
     std::replace(dir.begin(), dir.end(), '\\', '/');
     return dir;
 }
+
+std::string FSHelper::findExecutableInPath(std::string executable)
+{
+    std::string path = getenv("PATH");
+
+#if defined(_WIN32)
+    char delim = ';';
+#else
+    char delim = ':';
+#endif
+
+    std::vector<std::string> tokens;
+    std::string token;
+    std::istringstream tokenStream(path);
+    while (std::getline(tokenStream, token, delim))
+    {
+        if(fileExists(addDirLastSlash(token) + executable))
+            return addDirLastSlash(token) + executable;
+
+        if(fileExists(addDirLastSlash(token) + executable + ".exe"))
+            return addDirLastSlash(token) + executable + ".exe";
+    }
+    throw std::string("Executable not found in PATH!: " + executable);
+}
+
+void FSHelper::executeCommand(const std::string& path, const std::string& command, std::vector<std::string> params, std::string log)
+{
+
+    if((!path.empty()) && !dirExists(path))
+        throw std::string("Path does not exist: " + path);
+
+    if(!log.empty() && !fileExists(log))
+        createFile(log);
+
+    std::string execCommand = findExecutableInPath(command);
+
+#if defined(_WIN32)
+    std::string paramString;
+
+    for(auto curParam : params)
+        paramString = curParam + " ";
+
+    if(!log.empty())
+        paramString = paramString + " >> " + log;
+
+    // Benutze System, da CreateProcess nicht POSIX standardkonform ist
+    if(!path.empty())
+    {
+        // Laufwerkbuchstaben ermitteln
+        unsigned int ind = path.find_first_of(":");
+        if(ind ==  std::string::npos)
+            throw std::string("Illegal Path! Path does not cointain drive letter! :" + path);
+
+        std::string driveLetter = path.substr(0, ind+1);
+        system(std::string(driveLetter + " && cd " + path + " && " + execCommand + " " + paramString).c_str());
+    }
+    else
+        system(std::string(execCommand + " " + paramString).c_str());
+#else
+    // String vector zu char array
+    std::vector<char*> charParams;
+
+    if(!log.empty())
+        FILE* logFile = freopen(log.c_str(),"a",stdout);
+
+    // Falls DynLoader gesetzt ist dynloader erster parameter
+    // im array
+    if(!mLinuxDynLoader.empty())
+    {
+        char *pc = new char[mLinuxDynLoader.size()+1];
+        std::strcpy(pc, mLinuxDynLoader.c_str());
+        charParams.emplace_back(pc);
+        execCommand = mLinuxDynLoader;
+    }
+
+    // command muss auch immer im array gespeichert sein
+    char *pc = new char[findExecutableInPath(command).size()+1];
+    std::strcpy(pc, findExecutableInPath(command).c_str());
+    charParams.emplace_back(pc);
+
+    // vector zu char array convertieren
+    std::transform(params.begin(), params.end(), std::back_inserter(charParams),
+                   [](const std::string & s)
+
+    {
+        char *pc = new char[s.size()+1];
+        std::strcpy(pc, s.c_str());
+        return pc;
+        ;
+    });
+    charParams.emplace_back(nullptr); //Letztes element muss ein nullpointer sein
+
+    int status;
+    pid_t parent_pid;
+    pid_t child_pid;
+    parent_pid = getpid();
+
+    child_pid = fork();
+    switch(child_pid)
+    {
+    case -1:
+        //Fork Fehler
+        std::exit(EXIT_FAILURE);
+        break;
+
+    case 0:
+        if(!path.empty())
+            if(chdir(path.c_str())!=0)
+                std::exit(EXIT_FAILURE);
+
+        execvp(execCommand.c_str(), &charParams[0]);
+
+        // bei fehler Char array im Child freigeben
+        for(auto curParam : charParams)
+            delete [] curParam;
+
+        // Soll nicht erreicht werden. Falls ja
+        // Child prozess beenden
+        std::exit(EXIT_FAILURE);
+        break;
+
+    default:
+        // OK
+        break;
+    }
+
+    // Auf child warten
+    wait(&status);
+
+    // Char array freigeben
+    for(auto curParam : charParams)
+        delete [] curParam;
+
+    // Logfile schliessen
+    fcloseall();
+
+    if(!WIFEXITED(status))
+        throw std::string("Could not execute command: " + command);
+#endif
+}
+
+
+void FSHelper::setLinuxDynLoader(std::string Loader)
+{
+#ifndef _WIN32
+    if(!fileExists(Loader))
+        throw std::string("Specified Loader does not exist: " + Loader);
+#endif
+
+    mLinuxDynLoader = Loader;
+}
+
+
+std::string FSHelper::getLinuxDynLoader()
+{
+    return mLinuxDynLoader;
+}
+
+
+void FSHelper::removeLinuxDynLoader()
+{
+    mLinuxDynLoader.clear();
+}
index bcadeb6..abbd7f3 100644 (file)
@@ -17,7 +17,7 @@
 
 /////////////////////////////////////////////////
 /// \brief Diese Klasse beinhaltet Dateisystemfunktionen
-///        Basierend auf C++11 und POSIX standart und funktinieren
+///        Basierend auf C++11 und POSIX-1 standart und funktinieren
 ///        somit auf Windows und Linux.
 /////////////////////////////////////////////////
 class FSHelper : public Object
@@ -59,17 +59,21 @@ public:
 /// \brief Diese funktion kopiert eine Datei.
 /// \param src Quelldatei
 /// \param dest Zieldatei
-/// \return bool Bei Erfolg true, ansonsten false
 /////////////////////////////////////////////////
-    bool copyFile(std::string const &src, std::string const &dest);
+    void copyFile(std::string const &src, std::string const &dest);
 
 /////////////////////////////////////////////////
 /// \brief Diese funktion kopiert einen Ordner.
 /// \param src Quellordner
 /// \param dest Zielordner
-/// \return bool Bei Erfolg true, ansonsten false
 /////////////////////////////////////////////////
-    bool copyFolder(std::string const &src, std::string const &dest);
+    void copyDir(std::string const &src, std::string const &dest);
+
+/////////////////////////////////////////////////
+/// \brief Gibt aktuelles Arbeitsverzeichnis zurück.
+/// \return aktuelles Arbeitsverzeichnis.
+/////////////////////////////////////////////////
+    std::string getCurrentWorkingDir();
 
 /////////////////////////////////////////////////
 /// \brief Strenge Dateinamenüberprüfung. Überprüft
@@ -113,16 +117,14 @@ public:
 /////////////////////////////////////////////////
 /// \brief Erstellt einen Ordner.
 /// \param dir pfad des zu erstellenden Ordners.
-/// \return true bei erfolg, false bei fehler
 /////////////////////////////////////////////////
-    bool makeDir(std::string const& dir);
+    void makeDir(std::string const& dir);
 
 /////////////////////////////////////////////////
 /// \brief Erstellt eine Datei.
 /// \param dir pfad der zu erstellenden Datei.
-/// \return true bei erfolg, false bei fehler
 /////////////////////////////////////////////////
-    bool createFile(std::string const& path);
+    void createFile(std::string const& path);
 
 /////////////////////////////////////////////////
 /// \brief Diese funktion gibt alle Deteien eines
@@ -149,7 +151,54 @@ public:
 ///        false nein)
 /// \return true bei erfolg, false bei fehler
 /////////////////////////////////////////////////
-    bool listFoldersRecursive(const std::string& path, std::vector<std::string>& folders,const bool showHiddenDirs);
+    bool listDirsRecursive(const std::string& path, std::vector<std::string>& dirs,const bool showHiddenDirs);
+
+/////////////////////////////////////////////////
+/// \brief Diese funktion führt einen Befehl/ein Programm
+///        aus.
+/// \param path Pfad in dem der Befehl ausgeführt werden soll
+/// \param command Auszuführender Befehl
+/// \param params Bafehlsparameter
+/// \param log optional, Pfad zu einer datei, in der die Konsolenausgabe
+///        des Befehls geschrieben werden soll.
+/////////////////////////////////////////////////
+    void executeCommand(const std::string& path, const std::string& command, std::vector<std::string> params, std::string log = "");
+
+/////////////////////////////////////////////////
+/// \brief Diese funktion setzt einen Dynamischen
+///        Loader, der für das ausführen von Programmen
+///        mit executeCommand auf Linux Systemen
+///        verwendet werden soll.
+/// \param Loader Pfad zum Loader
+/////////////////////////////////////////////////
+    void setLinuxDynLoader(std::string Loader);
+
+/////////////////////////////////////////////////
+/// \brief Diese funktion gibt den gesetzten Loader
+///        retour.
+/// \return gesetzter Loader
+/////////////////////////////////////////////////
+    std::string getLinuxDynLoader();
+
+/////////////////////////////////////////////////
+/// \brief Diese funktion entfernt einen gesetzten Loader.
+///        Programme die mit executeCommand ausgeführt
+///        werden, verwenden dann den standard Loader
+///        des Systems.
+/////////////////////////////////////////////////
+    void removeLinuxDynLoader();
+
+/////////////////////////////////////////////////
+/// \brief Durchsucht PATH nach übergebenem Kommando.
+///        Gibt vollständigen Pfad zur Datei des Kommandos
+///        retour.
+/// \param executable Kommando dessen executable gesucht werden soll
+/// \return vollständiger Pfad zur executable.
+/////////////////////////////////////////////////
+    std::string findExecutableInPath(std::string executable);
+
+private:
+    std::string mLinuxDynLoader;
 
 };
 
index 4aac8f9..06b98cf 100644 (file)
@@ -71,11 +71,14 @@ void Model::throwXmlError(tinyxml2::XMLError error)
     }
 }
 
-Model::Model(std::string confDir)
+Model::Model(std::string confDir, FSHelper help, std::string log)
 {
+    mFSHelp = help;
+
     if(!mFSHelp.dirExists(confDir))
         throw std::string("Configuration directory not found!");
 
+    mLogFile = log;
     mConfDir = mFSHelp.addDirLastSlash(confDir);
 }
 
@@ -545,10 +548,6 @@ void Model::setOutPath(std::string outPath)
 
     mOutPath = mFSHelp.addDirLastSlash(outPath);
 
-    if(!mFSHelp.createFile(mOutPath + "Log.txt"))
-        throw std::string("Could not create log file!");
-
-
     // Lade text aus ev. existierenden Dateien
     for(auto curChapt : mChapters)
     {
@@ -574,18 +573,12 @@ void Model::generateDocument()
     if(!mFSHelp.dirExists(mOutPath))
         throw std::string("Output path not found! Please set an existing output directory.");
 
-    if(!mFSHelp.copyFile(mConfDir + "packages.tex", mOutPath + "packages.tex"))
-        throw std::string("Failed to copy packages.tex!");
-    if(!mFSHelp.copyFile(mConfDir + "doxygen.sty", mOutPath + "doxygen.sty"))
-        throw std::string("Failed to copy doxygen.sty!");
-    if(!mFSHelp.copyFile(mConfDir + "setup_doxygen.tex", mOutPath + "setup_doxygen.tex"))
-        throw std::string("Failed to copy setup_doxygen.tex!");
-    if(!mFSHelp.copyFile(mConfDir + "codesettings.tex", mOutPath + "codesettings.tex"))
-        throw std::string("Failed to copy codesettings.tex!");
-    if(!mFSHelp.copyFile(mConfDir + "main.tex", mOutPath + "main.tex"))
-        throw std::string("Failed to copy main.tex");
-    if(!mFSHelp.copyFile(mConfDir + "docsettings.tex", mOutPath + "docsettings.tex"))
-        throw std::string("Failed to copy docsettings.tex");
+    mFSHelp.copyFile(mConfDir + "packages.tex", mOutPath + "packages.tex");
+    mFSHelp.copyFile(mConfDir + "doxygen.sty", mOutPath + "doxygen.sty");
+    mFSHelp.copyFile(mConfDir + "setup_doxygen.tex", mOutPath + "setup_doxygen.tex");
+    mFSHelp.copyFile(mConfDir + "codesettings.tex", mOutPath + "codesettings.tex");
+    mFSHelp.copyFile(mConfDir + "main.tex", mOutPath + "main.tex");
+    mFSHelp.copyFile(mConfDir + "docsettings.tex", mOutPath + "docsettings.tex");
 
     // Öffne main.tex
     std::ofstream mainFile;
@@ -671,20 +664,15 @@ void Model::generateDocument()
 
     if(shouldGenDoxygen())
     {
-        if(!mFSHelp.copyFolder(mSourcePath, mOutPath + "src"))
-            throw std::string("Failed to copy sourcecode directory!");
-
-        if(!mFSHelp.copyFile(mConfDir + "doxyfile", mOutPath + "doxyfile"))
-            throw std::string("Failed to copy doxyfile!");
-
-        if(!mFSHelp.makeDir(mOutPath + "doxygen"))
-            throw std::string("Failed to create doxygen output directory!");
+        mFSHelp.copyDir(mSourcePath, mOutPath + "src");
+        mFSHelp.copyFile(mConfDir + "doxyfile", mOutPath + "doxyfile");
+        mFSHelp.makeDir(mOutPath + "doxygen");
 
         // Starte DoxyGen
-        system(std::string("cd " + mOutPath + " && doxygen " + mOutPath + "doxyfile >> " + mOutPath + "Log.txt").c_str());
+        std::vector<std::string> paramsDoxy = {mOutPath + "doxyfile"};
+        mFSHelp.executeCommand(mOutPath, "doxygen", paramsDoxy, mFSHelp.addDirLastSlash(mOutPath) + mLogFile);
 
-        if(!mFSHelp.copyFile(mOutPath + "doxygen/doxygen.sty", mOutPath + "doxygen.sty"))
-            throw std::string("Failed to copy doxygen.sty!");
+        mFSHelp.copyFile(mOutPath + "doxygen/doxygen.sty", mOutPath + "doxygen.sty");
 
         std::vector<FSHelper::File> doxyFiles;
         if(!mFSHelp.listFilesRecursive(mOutPath + "doxygen", doxyFiles, true))
@@ -742,8 +730,7 @@ void Model::generateDocument()
     // Füge Quellcode hinzu
     if(shouldAddSource())
     {
-        if(!mFSHelp.copyFolder(mSourcePath, mOutPath + "src"))
-            throw std::string("Failed to copy sourcecode directory!");
+        mFSHelp.copyDir(mSourcePath, mOutPath + "src");
 
         std::vector<FSHelper::File> sourceFiles;
         if(!mFSHelp.listFilesRecursive(mOutPath + "src", sourceFiles, true))
@@ -762,7 +749,7 @@ void Model::generateDocument()
 
             // Dateiendung cpp oder h
             if((x.second.substr(ind) == mSourceExtension) ||
-                    (x.second.substr(ind) == mHeaderExtension))
+               (x.second.substr(ind) == mHeaderExtension))
                 return false;
 
             // Alle anderen
@@ -773,14 +760,12 @@ void Model::generateDocument()
         // Nach namen sortieren (header vor cpp)
         std::sort(sourceFiles.begin(), sourceFiles.end(),
                   [](FSHelper::File left, FSHelper::File right)
-        {
-            return left.second > right.second;
-        }
+                    {
+                        return left.second > right.second;
+                    }
 
                  );
 
-
-
         std::ofstream out;
         out.open(mOutPath + "sourcefiles.tex", std::ios_base::out);
         if(out.good())
@@ -800,18 +785,18 @@ void Model::generateDocument()
     }
 
     if(shouldAddCoverSheet())
-        if(!mFSHelp.copyFile(mCoverSheet, mOutPath + "coversheet.pdf"))
-            throw std::string("Failed to copy cover sheet!");
+        mFSHelp.copyFile(mCoverSheet, mOutPath + "coversheet.pdf");
 
-    if(!mFSHelp.copyFolder(mConfDir + "resources", mOutPath + "resources"))
-        throw std::string("Failed to copy resource directory!");
+    mFSHelp.copyDir(mConfDir + "resources", mOutPath + "resources");
 
     mainFile << "\\end{document}" << std::endl;
     mainFile.close();
 
     //start dokument generierung
-    system(std::string("cd " + mOutPath + " && pdflatex -draftmode -interaction=nonstopmode main.tex >> " + mOutPath + "Log.txt").c_str());
-    system(std::string("cd " + mOutPath + " && pdflatex -interaction=nonstopmode main.tex >> " + mOutPath + "Log.txt").c_str());
+    std::vector<std::string> paramsDryRun = {"-draftmode", "-interaction=nonstopmode", "main.tex"};
+    std::vector<std::string> paramsGen = {"-interaction=nonstopmode", "main.tex"};
+    mFSHelp.executeCommand(mOutPath, "pdflatex", paramsDryRun, mFSHelp.addDirLastSlash(mOutPath) + mLogFile);
+    mFSHelp.executeCommand(mOutPath, "pdflatex", paramsGen, mFSHelp.addDirLastSlash(mOutPath) + mLogFile);
 }
 
 void Model::saveTemplFile()
@@ -1139,6 +1124,16 @@ void Model::setHeaderFileExtension(std::string fileExt)
     mHeaderExtension = fileExt;
 }
 
+void Model::setLogFile(std::string log)
+{
+    mLogFile = log;
+}
+
+std::string Model::getLogFile()
+{
+    return mLogFile;
+}
+
 void Model::setSourceFileExtension(std::string fileExt)
 {
     if(fileExt.empty())
index 72b7122..b6e6ba8 100644 (file)
@@ -30,8 +30,18 @@ class Model : public ModelIF
 {
 public:
 
-    Model(std::string confDir);
 
+    /////////////////////////////////////////////////
+    /// \brief Konstruktor für ein Model Objekt
+    /// \param confDir Ordner der die Konfigurationen beinhlatet.
+    /// \param help ein configuriertes FSHelper Objekt
+    /// \param log Name der logging Datei (Ohne Pfad!)
+    ///        Wird im Ausgabeordner gespeichert.
+    ///        (siehe getOutPath)
+    /////////////////////////////////////////////////
+    Model(std::string confDir, FSHelper help, std::string log);
+
+    // Destruktor
     virtual ~Model() = default;
 
     /////////////////////////////////////////////////
@@ -213,6 +223,11 @@ public:
     /////////////////////////////////////////////////
     void setSourceFileExtension(std::string fileExt);
 
+    /////////////////////////////////////////////////
+    /// \brief Setzt dateinamen (Ohne Pfad!) für loggng Datei.
+    /// \param log Dateiname der Logging Datei.
+    /////////////////////////////////////////////////
+    void setLogFile(std::string log);
     // ---------- Implementierung Interface ---------------
     std::list<std::string> getChapterNames() override;
     std::list<std::string> getAuthorNames() override;
@@ -240,10 +255,12 @@ public:
     std::string getCovSheet() override;
     Author::SPtr getSelAuthor() override;
     Chapter::SPtr getSelChapter() override;
+    std::string getLogFile() override;
 
 private:
     std::string mTemplFileString;
     std::string mOutPath;
+    std::string mLogFile;
     std::string mSourcePath;
     std::string mCoverSheet;
     std::string mConfDir;
index b230ebf..955cde3 100644 (file)
@@ -216,6 +216,13 @@ public:
     /////////////////////////////////////////////////
     virtual int getDepartmentY() = 0;
 
+    /////////////////////////////////////////////////
+    /// \brief Gibt Dateinamen (ohne Pfad!) der Logging
+    ///        Datei retour.
+    /// \return Dateiname der Logging Datei.
+    /////////////////////////////////////////////////
+    virtual std::string getLogFile() = 0;
+
 
 protected:
     ModelIF() = default;
index aa6862d..3dde325 100644 (file)
@@ -24,6 +24,13 @@ View::View(ControllerIF::SPtr contr, ModelIF::SPtr model)
 
 View::~View()
 {
+    win_doctool->hide();
+    win_chapt_add->hide();
+    win_settings->hide();
+    win_auth_coord->hide();
+    win_depart_coord->hide();
+    win_log_view->hide();
+
     // Ressourcen freigeben
     Fl::delete_widget(win_doctool);
     Fl::delete_widget(win_chapt_add);
@@ -310,7 +317,7 @@ void View::btn_next_cb(Fl_Button* btn, void* view)
         View* thisView = static_cast<View*>(view);
         thisView->saveBuffer();
         int selectedNum=1;
-        for (selectedNum =1 ; selectedNum<=thisView->br_chapters->size(); selectedNum++ )
+        for (selectedNum=1 ; selectedNum<=thisView->br_chapters->size(); selectedNum++ )
             if (thisView->br_chapters->selected(selectedNum)) break;
 
 
@@ -337,23 +344,36 @@ void View::btn_generate_cb(Fl_Button* btn, void* view)
     {
         View* thisView = static_cast<View*>(view);
         thisView->saveBuffer();
+        thisView->win_doctool->deactivate();
+        thisView->win_doctool->cursor(FL_CURSOR_WAIT);
+
+
+        Fl::check();
         thisView->mController->generateDocument();
 
-        if(thisView->mLogBuf->loadfile(std::string(thisView->mModel->getOutPath() + "Log.txt").c_str()) != 0)
+        if(thisView->mLogBuf->loadfile(std::string(thisView->mModel->getOutPath() + thisView->mModel->getLogFile()).c_str()) != 0)
             throw std::string("Error opening Logfile!");
 
         thisView->win_log_view->show();
+        thisView->win_doctool->activate();
+        thisView->win_doctool->cursor(FL_CURSOR_DEFAULT);
     }
     // ----------- Exception Handling ------------
     catch(std::string& e)
     {
         std::cerr << e << std::endl;
         fl_alert(e.c_str()); //Textbox mit fehlermeldung
+        View* thisView = static_cast<View*>(view);
+        thisView->win_doctool->activate();
+        thisView->win_doctool->cursor(FL_CURSOR_DEFAULT);
     }
     catch(...)
     {
         fl_alert("Unknown error occured!");
         std::cerr << "Unknown error occured!" << std::endl;
+        View* thisView = static_cast<View*>(view);
+        thisView->win_doctool->activate();
+        thisView->win_doctool->cursor(FL_CURSOR_DEFAULT);
     }
 }
 
@@ -402,11 +422,13 @@ void View::menu_open_template_cb(Fl_Menu_* menu, void* view)
         while(chooser.shown())
             Fl::wait();
 
-        // Abbruch gedrückt
         if ( chooser.value() != nullptr )
         {
             thisView->mController->setTemplate(chooser.value());
-            thisView->menu_out_dir->do_callback(nullptr);
+
+            while(thisView->mModel->getOutPath().empty())
+                thisView->menu_out_dir->do_callback(nullptr);
+
             thisView->activate();
         }
     }
@@ -908,6 +930,9 @@ void View::menu_new_templ_cb(Fl_Menu_* menu, void* view)
         View* thisView = static_cast<View*>(view);
         thisView->menu_out_dir->do_callback(nullptr);
 
+        if(thisView->mModel->getOutPath().empty())
+            throw std::string("An output directory has to be set!");
+
         menu_settings->do_callback(nullptr);
 
         // Warte bis benutzer einstellungen eingegeben hat
index 12528c5..7e9cb55 100644 (file)
@@ -28,6 +28,7 @@ output->value("Doc Tool\n\nFor a detailed usermanual please visit:"
               "\n\n[doc_tool] is based in part on the work of the"
               "\nFLTK Project (http://www.fltk.org).");
 }
+win.label("About");
 win.end();
 win.show();
 Fl::run();
@@ -156,15 +157,17 @@ ViewFluid::ViewFluid() {
       cb_author->align(Fl_Align(FL_ALIGN_TOP_LEFT));
       cb_author->deactivate();
     } // Fl_Choice* cb_author
-    { ti_name = new Fl_Input(80, 340, 110, 25, "Name:  ");
+    { ti_name = new Fl_Input(75, 340, 115, 25, "Name:");
       ti_name->box(FL_GTK_DOWN_BOX);
       ti_name->deactivate();
     } // Fl_Input* ti_name
     { ti_est_time = new Fl_Input(130, 370, 60, 25, "Estimated time:");
+      ti_est_time->tooltip("Time estimated by the author.");
       ti_est_time->box(FL_GTK_DOWN_BOX);
       ti_est_time->deactivate();
     } // Fl_Input* ti_est_time
-    { ti_needed_time = new Fl_Input(130, 400, 60, 25, "Needed time:   ");
+    { ti_needed_time = new Fl_Input(130, 400, 60, 25, "Needed time:");
+      ti_needed_time->tooltip("Time actually needed.");
       ti_needed_time->box(FL_GTK_DOWN_BOX);
       ti_needed_time->deactivate();
     } // Fl_Input* ti_needed_time
@@ -187,7 +190,7 @@ ViewFluid::ViewFluid() {
       ot_src_dir->box(FL_GTK_DOWN_BOX);
       ot_src_dir->deactivate();
     } // Fl_Output* ot_src_dir
-    { ot_cov_sheet = new Fl_Output(140, 560, 280, 25, "Cover Sheet:       ");
+    { ot_cov_sheet = new Fl_Output(140, 560, 280, 25, "Cover Sheet:");
       ot_cov_sheet->tooltip("Cover sheet .pdf file.");
       ot_cov_sheet->box(FL_GTK_DOWN_BOX);
       ot_cov_sheet->deactivate();
@@ -197,20 +200,20 @@ ViewFluid::ViewFluid() {
       menu_chapter->deactivate();
       menu_chapter->menu(menu_menu_chapter);
     } // Fl_Menu_Button* menu_chapter
-    { menu_author = new Fl_Menu_Button(25, 310, 165, 150);
+    { menu_author = new Fl_Menu_Button(25, 295, 165, 165);
       menu_author->box(FL_GTK_UP_BOX);
       menu_author->deactivate();
       menu_author->menu(menu_menu_author);
     } // Fl_Menu_Button* menu_author
-    { ti_doc_name = new Fl_Input(140, 470, 200, 25, "Document name: ");
+    { ti_doc_name = new Fl_Input(140, 470, 200, 25, "Document name:");
       ti_doc_name->box(FL_GTK_DOWN_BOX);
       ti_doc_name->deactivate();
     } // Fl_Input* ti_doc_name
-    { ti_department = new Fl_Input(140, 500, 200, 25, "Department:        ");
+    { ti_department = new Fl_Input(140, 500, 200, 25, "Department:");
       ti_department->box(FL_GTK_DOWN_BOX);
       ti_department->deactivate();
     } // Fl_Input* ti_department
-    { menu_department = new Fl_Menu_Button(25, 500, 315, 25);
+    { menu_department = new Fl_Menu_Button(60, 500, 280, 25);
       menu_department->box(FL_GTK_UP_BOX);
       menu_department->deactivate();
       menu_department->menu(menu_menu_department);
@@ -221,7 +224,7 @@ ViewFluid::ViewFluid() {
   { win_chapt_add = new Fl_Double_Window(415, 125, "Add Chapter");
     win_chapt_add->box(FL_GTK_DOWN_BOX);
     win_chapt_add->user_data((void*)(this));
-    { add_chapt_chaptname = new Fl_Input(150, 15, 225, 25, "Chapter Name:   ");
+    { add_chapt_chaptname = new Fl_Input(150, 15, 225, 25, "Chapter Name:");
       add_chapt_chaptname->box(FL_GTK_DOWN_BOX);
     } // Fl_Input* add_chapt_chaptname
     { add_chapt_fname = new Fl_Input(150, 50, 225, 25, "Output Filename:");
@@ -236,6 +239,7 @@ ViewFluid::ViewFluid() {
     win_settings->box(FL_GTK_DOWN_BOX);
     win_settings->user_data((void*)(this));
     { btn_save_settings = new Fl_Button(220, 325, 90, 25, "Save");
+      btn_save_settings->tooltip("Save settings.");
       btn_save_settings->box(FL_GTK_UP_BOX);
     } // Fl_Button* btn_save_settings
     { chb_gen_doxygen = new Fl_Check_Button(120, 70, 115, 25, "Generate Doxygen Chapter");
@@ -252,44 +256,54 @@ cument.");
       chb_add_covpage->down_box(FL_GTK_DOWN_BOX);
     } // Fl_Check_Button* chb_add_covpage
     { ti_doxy_chapt_name = new Fl_Input(120, 95, 190, 25, "Chapter Name:");
+      ti_doxy_chapt_name->tooltip("Name of doxygen chapter.");
       ti_doxy_chapt_name->box(FL_GTK_DOWN_BOX);
     } // Fl_Input* ti_doxy_chapt_name
     { ti_source_chapt_name = new Fl_Input(120, 140, 190, 25, "Chapter Name:");
+      ti_source_chapt_name->tooltip("Name of source code chapter.");
       ti_source_chapt_name->box(FL_GTK_DOWN_BOX);
     } // Fl_Input* ti_source_chapt_name
     { ti_settings_subject_name = new Fl_Input(115, 290, 100, 25, "Subject Name:");
+      ti_settings_subject_name->tooltip("Name of the document Subject.");
       ti_settings_subject_name->box(FL_GTK_DOWN_BOX);
     } // Fl_Input* ti_settings_subject_name
-    { new Fl_Box(0, 10, 350, 35, "Generation Settings");
+    { Fl_Box* o = new Fl_Box(0, 10, 350, 35, "Generation Settings");
+      o->tooltip("General generation settings used for document generation.");
     } // Fl_Box* o
-    { ti_location = new Fl_Input(115, 325, 100, 25, "Location:        ");
+    { ti_location = new Fl_Input(115, 325, 100, 25, "Location:");
+      ti_location->tooltip("Location of the Author.");
       ti_location->box(FL_GTK_DOWN_BOX);
     } // Fl_Input* ti_location
     { ti_header_ext = new Fl_Input(115, 220, 70, 25, "Header:");
+      ti_header_ext->tooltip("Header file extension (most probably .h)");
       ti_header_ext->box(FL_GTK_DOWN_BOX);
     } // Fl_Input* ti_header_ext
     { ti_src_ext = new Fl_Input(240, 220, 70, 25, "Source:");
+      ti_src_ext->tooltip("Source file extension (most probably .c/.cpp)");
       ti_src_ext->box(FL_GTK_DOWN_BOX);
     } // Fl_Input* ti_src_ext
-    { new Fl_Box(0, 185, 350, 20, "File Extension Settings");
+    { Fl_Box* o = new Fl_Box(0, 185, 350, 20, "File Extension Settings");
+      o->tooltip("Set file extension used by the C/C++ source files.");
     } // Fl_Box* o
-    { new Fl_Box(0, 250, 350, 35, "Document Settings");
+    { Fl_Box* o = new Fl_Box(0, 250, 350, 35, "Document Settings");
+      o->tooltip("Document Settings.");
     } // Fl_Box* o
     win_settings->end();
   } // Fl_Double_Window* win_settings
   { win_auth_coord = new Fl_Double_Window(200, 190, "Author coordinates");
+    win_auth_coord->tooltip("Coordinates to enter author information on Cover Sheet.");
     win_auth_coord->box(FL_GTK_DOWN_BOX);
     win_auth_coord->user_data((void*)(this));
     { btn_ok_author = new Fl_Button(50, 155, 105, 25, "Ok");
       btn_ok_author->box(FL_GTK_UP_BOX);
     } // Fl_Button* btn_ok_author
-    { vi_spenttime_x = new Fl_Value_Input(110, 85, 40, 25, "Time spent:      ");
+    { vi_spenttime_x = new Fl_Value_Input(110, 85, 40, 25, "Time spent:");
       vi_spenttime_x->box(FL_GTK_DOWN_BOX);
     } // Fl_Value_Input* vi_spenttime_x
     { vi_spenttime_y = new Fl_Value_Input(150, 85, 40, 25);
       vi_spenttime_y->box(FL_GTK_DOWN_BOX);
     } // Fl_Value_Input* vi_spenttime_y
-    { vi_authname_x = new Fl_Value_Input(110, 110, 40, 25, "Author name:   ");
+    { vi_authname_x = new Fl_Value_Input(110, 110, 40, 25, "Author name:");
       vi_authname_x->box(FL_GTK_DOWN_BOX);
     } // Fl_Value_Input* vi_authname_x
     { vi_authname_y = new Fl_Value_Input(150, 110, 40, 25);
@@ -301,7 +315,7 @@ cument.");
     { vi_esttime_y = new Fl_Value_Input(150, 60, 40, 25);
       vi_esttime_y->box(FL_GTK_DOWN_BOX);
     } // Fl_Value_Input* vi_esttime_y
-    { Fl_Box* o = new Fl_Box(20, 5, 175, 25, "Cover Page Coordinates");
+    { Fl_Box* o = new Fl_Box(20, 5, 175, 25, "Cover Sheet Coordinates");
       o->tooltip("These coordinates are used to fill in the values in the cover page .pdf.");
     } // Fl_Box* o
     { new Fl_Box(110, 35, 40, 25, "X");
@@ -326,7 +340,7 @@ cument.");
     { btn_ok_depart = new Fl_Button(70, 95, 105, 25, "Ok");
       btn_ok_depart->box(FL_GTK_UP_BOX);
     } // Fl_Button* btn_ok_depart
-    { Fl_Box* o = new Fl_Box(30, 5, 175, 25, "Department Coordinates");
+    { Fl_Box* o = new Fl_Box(30, 5, 175, 25, "Cover Sheet Coordinates");
       o->tooltip("These coordinates are used to fill in the values in the cover page .pdf.");
     } // Fl_Box* o
     win_depart_coord->end();
index bbafc4d..bb50803 100644 (file)
@@ -4,11 +4,11 @@ header_name {.h}
 code_name {.cxx}
 class ViewFluid {open
 } {
-  Function {ViewFluid()} {open selected protected
+  Function {ViewFluid()} {open protected
   } {
     Fl_Window win_doctool {
-      label {Doc Tool}
-      protected xywh {437 139 585 630} type Double box GTK_DOWN_BOX resizable hotspot size_range {585 555 0 0} visible
+      label {Doc Tool} open
+      protected xywh {319 138 585 630} type Double box GTK_DOWN_BOX resizable hotspot size_range {585 555 0 0} visible
     } {
       Fl_Group {} {
         protected xywh {200 45 365 575} resizable
@@ -70,7 +70,7 @@ class ViewFluid {open
         user_data this
         protected tooltip {Choose a chapter to write.} xywh {25 50 165 220} box GTK_UP_BOX align 1 deactivate
       }
-      Fl_Menu_Bar menu_bar {
+      Fl_Menu_Bar menu_bar {open
         protected xywh {0 0 585 20} box GTK_UP_BOX
       } {
         Submenu menu_file {
@@ -108,7 +108,7 @@ class ViewFluid {open
           }
         }
         Submenu menu_help {
-          label Help
+          label Help open
           protected xywh {10 10 100 20}
         } {
           MenuItem menu_open_about_dialog {
@@ -123,9 +123,10 @@ output->value("Doc Tool\\n\\nFor a detailed usermanual please visit:"
               "\\n\\n[doc_tool] is based in part on the work of the"
               "\\nFLTK Project (http://www.fltk.org).");
 }
+win.label("About");
 win.end();
 win.show();
-Fl::run();}
+Fl::run();} selected
             protected tooltip {Shows about text.} xywh {0 0 100 20}
             code0 {\#include <FL/Fl_Multiline_Output.H>}
           }
@@ -141,16 +142,16 @@ Fl::run();}
         protected tooltip {Select author to edit.} xywh {25 310 165 25} box GTK_UP_BOX down_box GTK_DOWN_BOX align 5 deactivate
       } {}
       Fl_Input ti_name {
-        label {Name:  }
-        protected xywh {80 340 110 25} box GTK_DOWN_BOX deactivate
+        label {Name:}
+        protected xywh {75 340 115 25} box GTK_DOWN_BOX deactivate
       }
       Fl_Input ti_est_time {
         label {Estimated time:}
-        protected xywh {130 370 60 25} box GTK_DOWN_BOX deactivate
+        protected tooltip {Time estimated by the author.} xywh {130 370 60 25} box GTK_DOWN_BOX deactivate
       }
       Fl_Input ti_needed_time {
-        label {Needed time:   }
-        protected xywh {130 400 60 25} box GTK_DOWN_BOX deactivate
+        label {Needed time:}
+        protected tooltip {Time actually needed.} xywh {130 400 60 25} box GTK_DOWN_BOX deactivate
       }
       Fl_Button btn_save_author {
         label {Save Author}
@@ -169,7 +170,7 @@ Fl::run();}
         protected tooltip {Directory containing Sourcecode.} xywh {140 530 280 25} box GTK_DOWN_BOX deactivate
       }
       Fl_Output ot_cov_sheet {
-        label {Cover Sheet:       }
+        label {Cover Sheet:}
         protected tooltip {Cover sheet .pdf file.} xywh {140 560 280 25} box GTK_DOWN_BOX deactivate
       }
       Fl_Menu_Button menu_chapter {
@@ -185,7 +186,7 @@ Fl::run();}
         }
       }
       Fl_Menu_Button menu_author {
-        protected xywh {25 310 165 150} box GTK_UP_BOX deactivate
+        protected xywh {25 295 165 165} box GTK_UP_BOX deactivate
       } {
         MenuItem menu_add_author {
           label {Remove author}
@@ -201,15 +202,15 @@ Fl::run();}
         }
       }
       Fl_Input ti_doc_name {
-        label {Document name: }
+        label {Document name:}
         protected xywh {140 470 200 25} box GTK_DOWN_BOX deactivate
       }
       Fl_Input ti_department {
-        label {Department:        }
+        label {Department:}
         protected xywh {140 500 200 25} box GTK_DOWN_BOX deactivate
       }
-      Fl_Menu_Button menu_department {open
-        protected xywh {25 500 315 25} box GTK_UP_BOX deactivate
+      Fl_Menu_Button menu_department {
+        protected xywh {60 500 280 25} box GTK_UP_BOX deactivate
       } {
         MenuItem menu_department_coord {
           label {Edit coordinates}
@@ -219,10 +220,10 @@ Fl::run();}
     }
     Fl_Window win_chapt_add {
       label {Add Chapter}
-      protected xywh {1 174 415 125} type Double box GTK_DOWN_BOX visible
+      protected xywh {1 171 415 125} type Double box GTK_DOWN_BOX visible
     } {
       Fl_Input add_chapt_chaptname {
-        label {Chapter Name:   }
+        label {Chapter Name:}
         protected xywh {150 15 225 25} box GTK_DOWN_BOX
       }
       Fl_Input add_chapt_fname {
@@ -235,12 +236,12 @@ Fl::run();}
       }
     }
     Fl_Window win_settings {
-      label Settings open
-      protected xywh {612 144 350 365} type Double box GTK_DOWN_BOX visible
+      label Settings
+      protected xywh {652 171 350 365} type Double box GTK_DOWN_BOX visible
     } {
       Fl_Button btn_save_settings {
         label Save
-        protected xywh {220 325 90 25} box GTK_UP_BOX
+        protected tooltip {Save settings.} xywh {220 325 90 25} box GTK_UP_BOX
       }
       Fl_Check_Button chb_gen_doxygen {
         label {Generate Doxygen Chapter}
@@ -256,58 +257,58 @@ Fl::run();}
       }
       Fl_Input ti_doxy_chapt_name {
         label {Chapter Name:}
-        protected xywh {120 95 190 25} box GTK_DOWN_BOX
+        protected tooltip {Name of doxygen chapter.} xywh {120 95 190 25} box GTK_DOWN_BOX
       }
       Fl_Input ti_source_chapt_name {
         label {Chapter Name:}
-        protected xywh {120 140 190 25} box GTK_DOWN_BOX
+        protected tooltip {Name of source code chapter.} xywh {120 140 190 25} box GTK_DOWN_BOX
       }
       Fl_Input ti_settings_subject_name {
         label {Subject Name:}
-        protected xywh {115 290 100 25} box GTK_DOWN_BOX
+        protected tooltip {Name of the document Subject.} xywh {115 290 100 25} box GTK_DOWN_BOX
       }
       Fl_Box {} {
         label {Generation Settings}
-        protected xywh {0 10 350 35}
+        protected tooltip {General generation settings used for document generation.} xywh {0 10 350 35}
       }
       Fl_Input ti_location {
-        label {Location:        }
-        protected xywh {115 325 100 25} box GTK_DOWN_BOX
+        label {Location:}
+        protected tooltip {Location of the Author.} xywh {115 325 100 25} box GTK_DOWN_BOX
       }
       Fl_Input ti_header_ext {
         label {Header:}
-        protected xywh {115 220 70 25} box GTK_DOWN_BOX
+        protected tooltip {Header file extension (most probably .h)} xywh {115 220 70 25} box GTK_DOWN_BOX
       }
       Fl_Input ti_src_ext {
         label {Source:}
-        protected xywh {240 220 70 25} box GTK_DOWN_BOX
+        protected tooltip {Source file extension (most probably .c/.cpp)} xywh {240 220 70 25} box GTK_DOWN_BOX
       }
       Fl_Box {} {
         label {File Extension Settings}
-        protected xywh {0 185 350 20}
+        protected tooltip {Set file extension used by the C/C++ source files.} xywh {0 185 350 20}
       }
       Fl_Box {} {
         label {Document Settings}
-        protected xywh {0 250 350 35}
+        protected tooltip {Document Settings.} xywh {0 250 350 35}
       }
     }
     Fl_Window win_auth_coord {
       label {Author coordinates}
-      protected xywh {67 591 200 190} type Double box GTK_DOWN_BOX visible
+      protected tooltip {Coordinates to enter author information on Cover Sheet.} xywh {64 588 200 190} type Double box GTK_DOWN_BOX visible
     } {
       Fl_Button btn_ok_author {
         label Ok
         protected xywh {50 155 105 25} box GTK_UP_BOX
       }
       Fl_Value_Input vi_spenttime_x {
-        label {Time spent:      }
+        label {Time spent:}
         protected xywh {110 85 40 25} box GTK_DOWN_BOX
       }
       Fl_Value_Input vi_spenttime_y {
         protected xywh {150 85 40 25} box GTK_DOWN_BOX
       }
       Fl_Value_Input vi_authname_x {
-        label {Author name:   }
+        label {Author name:}
         protected xywh {110 110 40 25} box GTK_DOWN_BOX
       }
       Fl_Value_Input vi_authname_y {
@@ -321,7 +322,7 @@ Fl::run();}
         protected xywh {150 60 40 25} box GTK_DOWN_BOX
       }
       Fl_Box {} {
-        label {Cover Page Coordinates}
+        label {Cover Sheet Coordinates}
         protected tooltip {These coordinates are used to fill in the values in the cover page .pdf.} xywh {20 5 175 25}
       }
       Fl_Box {} {
@@ -335,7 +336,7 @@ Fl::run();}
     }
     Fl_Window win_depart_coord {
       label {Department Coordinates}
-      protected xywh {116 419 240 130} type Double box GTK_DOWN_BOX visible
+      protected xywh {31 394 240 130} type Double box GTK_DOWN_BOX visible
     } {
       Fl_Value_Input vi_depart_x {
         label {Coordinates:}
@@ -357,13 +358,13 @@ Fl::run();}
         protected xywh {70 95 105 25} box GTK_UP_BOX
       }
       Fl_Box {} {
-        label {Department Coordinates}
+        label {Cover Sheet Coordinates}
         protected tooltip {These coordinates are used to fill in the values in the cover page .pdf.} xywh {30 5 175 25}
       }
     }
     Fl_Window win_log_view {
       label Log
-      protected xywh {595 496 460 395} type Double resizable visible
+      protected xywh {816 357 460 395} type Double resizable visible
     } {
       Fl_Text_Display td_log_view {
         protected xywh {0 5 460 390}
index 62ef63e..67bfe70 100644 (file)
@@ -10,6 +10,7 @@
 #include "View.h"
 #include "Controller.h"
 #include "Model.h"
+#include "FSHelper.h"
 #include <FL/fl_ask.H>
 
 /////////////////////////////////////////////////
@@ -20,9 +21,24 @@ int main()
 {
     try
     {
-        std::string confDir = "./etc";
-        std::shared_ptr<Model> myModel {std::make_shared<Model>(confDir)};
+        FSHelper FShelp;
+        std::string curDir = FShelp.getCurrentWorkingDir();
+        std::string confDir = FShelp.addDirLastSlash(curDir) + "etc";
+
+        try
+        {
+            FShelp.setLinuxDynLoader(FShelp.addDirLastSlash(curDir) + "lib/ld-linux.so.2");
+        }
+        catch(std::string& e)
+        {
+            // Benutze loader des Linux betriebsystems
+            FShelp.removeLinuxDynLoader();
+        }
+
+        std::shared_ptr<Model> myModel {std::make_shared<Model>(confDir, FShelp, "Log.txt")};
         Controller::SPtr myController {std::make_shared<Controller>(myModel)};
+
+        Fl::lock(); // Threading unterstützung
         View myView(myController, myModel);
         myView.show();