]> git.sven.stormbind.net Git - sven/vym.git/blob - main.cpp
e3fccfaa777f11b5b57006b3b2f2b9006b668e5c
[sven/vym.git] / main.cpp
1 #include <QApplication>
2 #include <QMessageBox>
3
4 #include <cstdlib>
5 #include <iostream>
6 using namespace std;
7
8 #include "command.h"
9 #include "findwidget.h"
10 #include "findresultwidget.h"
11 #include "flagrow.h"
12 #include "flagrowobj.h"
13 #include "headingeditor.h"
14 #include "macros.h"
15 #include "mainwindow.h"
16 #include "noteeditor.h"
17 #include "options.h"
18 #include "settings.h"
19 #include "scripteditor.h"
20 #include "shortcuts.h"
21 #include "taskeditor.h"
22 #include "taskmodel.h"
23 #include "version.h"
24
25 #if defined(VYM_DBUS)
26 #include <sys/types.h>          // To retrieve PID for use in DBUS
27 #endif
28
29 #if defined(Q_OS_WIN32)
30 #define WIN32_LEAN_AND_MEAN
31 #include <windows.h>
32 #define getpid GetCurrentProcessId
33 #else
34 #include <unistd.h>
35 #endif
36
37 #if defined(VYM_DBUS)
38 #include <QtDBus/QDBusConnection>
39 #include <QtDBus/QDBusError>
40 #endif
41
42 QString vymName;
43 QString vymVersion;
44 QString vymHome;
45 QString vymBuildDate;
46 QString vymCodeName;
47 QString vymInstanceName;
48 QString vymPlatform;
49 QString localeName;
50
51 QTextStream vout(stdout);        // vymout - Testing for now. Flush after writing...
52
53 bool bugzillaClientAvailable;   // openSUSE specific currently
54
55 TaskModel     *taskModel;
56 TaskEditor    *taskEditor;
57 ScriptEditor  *scriptEditor;
58 HeadingEditor *headingEditor;       
59 NoteEditor    *noteEditor;      // used in Constr. of LinkableMapObj
60 // initialized in mainwindow
61 Main *mainWindow;               // used in BranchObj::select()          
62 FindWidget *findWidget;
63 FindResultWidget *findResultWidget;
64
65 Macros macros;
66
67 uint itemLastID=0;              // Unique ID for all items in all models
68
69 QString tmpVymDir;              // All temp files go there, created in mainwindow
70 QString clipboardDir;           // Clipboard used in all mapEditors
71 QString clipboardFile;          // Clipboard used in all mapEditors
72 QDir vymBaseDir;                // Containing all styles, scripts, images, ...
73 QDir lastImageDir;
74 QDir lastMapDir;
75 QDir lastExportDir;
76 #if defined(Q_OS_WIN32)
77 QDir vymInstallDir;
78 #endif
79 QString iconPath;               // Pointing to icons used for toolbars
80 QString flagsPath;              // Pointing to flags
81 QString macroPath;              // Pointing to macros
82
83 bool clipboardEmpty;            
84 bool debug;             // global debugging flag
85 bool testmode;                  // Used to disable saving of autosave setting
86 FlagRow *systemFlagsMaster; 
87 FlagRow *standardFlagsMaster;   
88
89 Switchboard switchboard;
90
91 Settings settings ("InSilmaril","vym"); // Organization, Application name
92 QString zipToolPath;    // Platform dependant zip tool
93
94 QList <Command*> modelCommands;
95
96 Options options;
97 ImageIO imageIO;
98
99 int statusbarTime=10000;
100
101 int warningCount=0;
102 int criticalCount=0;
103 int fatalCount=0;
104
105 void msgHandler (QtMsgType type, const QMessageLogContext &context, const QString &msg)
106 {
107     QByteArray localMsg = msg.toLocal8Bit();
108     switch (type)
109     {
110     case QtDebugMsg:
111         fprintf(stderr, "%s (%s:%u, %s)\n", localMsg.constData(), context.file, context.line, context.function);
112         break;
113     case QtWarningMsg:
114         fprintf(stderr, "Warning: %s (%s:%u, %s)\n", localMsg.constData(), context.file, context.line, context.function);
115         warningCount++;
116         break;
117     case QtCriticalMsg:
118         fprintf(stderr, "Critical: %s (%s:%u, %s)\n", localMsg.constData(), context.file, context.line, context.function);
119         criticalCount++;
120         break;
121     case QtFatalMsg:
122         fprintf(stderr, "Fatal: %s (%s:%u, %s)\n", localMsg.constData(), context.file, context.line, context.function);
123         fatalCount++;
124     default:
125         fprintf(stderr, "Info: %s (%s:%u, %s)\n", localMsg.constData(), context.file, context.line, context.function);
126     }
127 }
128
129 int main(int argc, char* argv[])
130 {
131     QApplication app(argc,argv);
132
133     vymName=__VYM_NAME;
134     vymVersion=__VYM_VERSION;
135     vymBuildDate=__VYM_BUILD_DATE;
136     vymCodeName=__VYM_CODENAME;
137     vymHome=__VYM_HOME;
138
139     // Install our own handler for messages
140     qInstallMessageHandler(msgHandler);
141
142     // Testing for now
143     vout.setCodec("UTF-8");
144
145     // Reading and initializing options commandline options
146     options.add ("batch", Option::Switch, "b", "batch");
147     options.add ("commands", Option::Switch, "c", "commands");
148     options.add ("commandslatex", Option::Switch, "cl", "commandslatex");
149     options.add ("debug", Option::Switch, "d", "debug");
150     options.add ("help", Option::Switch, "h", "help");
151     options.add ("local", Option::Switch, "l", "local");
152     options.add ("locale", Option::String, "locale", "locale");
153     options.add ("name", Option::String, "n", "name");
154     options.add ("quit", Option::Switch, "q", "quit");
155     options.add ("run", Option::String, "r", "run");
156     options.add ("restore", Option::Switch, "R", "restore");
157     options.add ("shortcuts", Option::Switch, "s", "shortcuts");
158     options.add ("shortcutsLaTeX", Option::Switch, "sl", "shortcutsLaTeX");
159     options.add ("testmode", Option::Switch, "t", "testmode");
160     options.add ("version", Option::Switch, "v","version");
161     options.setHelpText (
162                 "VYM - View Your Mind\n"
163                 "--------------------\n\n"
164                 "Information about vym can be found in vym.pdf,\n"
165                 "which should be part of the vym package.\n"
166                 "It is also available at the project homepage:\n\n"
167                 "http://www.InSilmaril.de/vym\n\n"
168                 "Usage: vym [OPTION]... [FILE]... \n"
169                 "Open FILEs with vym\n\n"
170                 "-b           batch       batch mode: hide windows\n"
171                 "-c           commands    List all available commands\n"
172                 "-d           debug       Show debugging output\n"
173                 "-h           help        Show this help text\n"
174                 "-l           local       Run with ressources in current directory\n"
175                 "--locale     locale      Override system locale setting to select language\n"
176                 "-n  STRING   name        Set name of instance for DBus access\n"
177                 "-q           quit        Quit immediatly after start for benchmarking\n"
178                 "-r  FILE     run         Run script\n"
179                 "-R           restore     Restore last session\n"
180                 "-s           shortcuts   Show Keyboard shortcuts on start\n"
181                 "--sl         LaTeX       Show Keyboard shortcuts in LaTeX format on start\n"
182                 "-t           testmode    Test mode, e.g. no autosave and changing of its setting\n"
183                 "-v           version     Show vym version\n"
184                 );
185
186     if (options.parse())
187     {
188         cout << endl << qPrintable( options.getHelpText())<<endl;
189         return 1;
190     }
191
192     if (options.isOn ("version"))
193     {
194         cout << "VYM - View Your Mind (c) 2004-"<< QDate::currentDate().year()<<" Uwe Drechsel "  << endl
195              <<"   Version: "<<__VYM_VERSION <<endl
196             <<"Build date: "<<__VYM_BUILD_DATE << endl
197            <<"  "<<__VYM_CODENAME<<endl;
198
199         return 0;
200     }
201     
202     // Update some configurations, which were moved in 2.4.0
203     // This code should be removed later, e.g. in 2.6.0...
204     QStringList settingsChanged;
205     settingsChanged  << "readerURL"
206                      << "readerPDF"
207                      << "autosave/use"
208                      << "autosave/ms"
209                      << "writeBackupFile"
210                      << "printerName"
211                      << "printerFormat"
212                      << "printerFileName";
213     foreach (QString s, settingsChanged)
214     {
215         if (settings.contains("/mainwindow/" + s))
216         {
217             settings.setValue("/system/" + s, settings.value("/mainwindow/" + s));
218             settings.remove  ("/mainwindow/" + s);
219         }
220     }
221
222     if (settings.contains( "/mainwindow/readerURL") )
223         settings.setValue( "/system/readerURL", settings.value( "/mainwindow/readerURL"));
224
225     taskModel = new TaskModel();
226
227     debug=options.isOn ("debug");
228     //debug=true;
229     testmode=options.isOn ("testmode");
230
231     QString pidString=QString ("%1").arg(getpid());
232     if (debug) qDebug()<< "vym PID="<<pidString;
233
234 #if defined(VYM_DBUS)
235     // Register for DBUS
236     QDBusConnection dbusConnection=QDBusConnection::sessionBus();
237     if (!dbusConnection.registerService ("org.insilmaril.vym-"+pidString))
238     {
239         fprintf(stderr, "%s\n",
240                 qPrintable(QDBusConnection::sessionBus().lastError().message()));
241         exit(1);
242     }
243 #endif
244
245     if (options.isOn ("name"))
246         vymInstanceName=options.getArg ("name");
247     else
248         vymInstanceName=pidString;
249     
250     bool debugBuild=false;
251 #ifdef QT_DEBUG
252     qDebug()<<"QT_DEBUG is set";
253     debugBuild=true;
254 #endif
255
256     // Use /usr/share/vym or /usr/local/share/vym or . ?
257     // First try options
258     if (options.isOn ("local") || debugBuild)
259     {
260         vymBaseDir.setPath (vymBaseDir.currentPath());
261     } else
262         // then look for environment variable
263         if (getenv("VYMHOME")!=0)
264         {
265             vymBaseDir.setPath (getenv("VYMHOME"));
266         } else
267             // ok, let's find my way on my own
268         {
269 #if defined (Q_OS_MACX)
270             // Executable is in vym.app/Contents/MacOS, so go up first:
271             vymBaseDir = QCoreApplication::applicationDirPath();
272             vymBaseDir.cdUp();
273             vymBaseDir.cd("Resources");
274 #elif defined (Q_OS_WIN32)
275             QString basePath;
276
277             wchar_t wbuf[512];
278             if (GetModuleFileName(NULL, wbuf, 512))
279             {
280                 QString mfn(QString::fromWCharArray(wbuf));
281                 mfn.replace('\\', '/');
282                 int i=mfn.lastIndexOf('/');
283                 if (i<0)
284                 {
285                     QMessageBox::critical(0,
286                         "Error",
287                         "Couldn't setup vymBasePath");
288                     return 0;
289                 }
290                 if (mfn.right(mfn.length() -i -1) != "vym.exe")
291                 {
292                     QMessageBox::critical(0,
293                         "Error",
294                         "vym executable not known as vym.exe");
295                     return 0;
296                 }
297                 basePath=mfn.left(i);
298             }
299             if (basePath.isEmpty())
300                 basePath = vymBaseDir.currentPath();
301
302             vymInstallDir.setPath(basePath);
303             vymBaseDir.setPath(basePath);
304 #else
305             vymBaseDir.setPath ("/usr/share/vym");
306             if (!vymBaseDir.exists())
307             {
308                 vymBaseDir.setPath ("/usr/local/share/vym");
309                 if (!vymBaseDir.exists())
310                     vymBaseDir.setPath(vymBaseDir.currentPath() );
311             }
312 #endif
313         }
314
315     // Platform specific settings
316     vymPlatform = QSysInfo::prettyProductName();
317
318 #if defined(Q_OS_MACX)
319 #elif defined(Q_OS_WIN32)
320     zipToolPath = settings.value("/system/zipToolPath", "c:\\Program Files\\7-Zip\\7z.exe").toString();
321 #elif defined(Q_OS_LINUX)
322 #else
323 #endif
324     iconPath=vymBaseDir.path()+"/icons/";
325     flagsPath=vymBaseDir.path()+"/flags/";
326     macroPath=vymBaseDir.path() + "/macros/";
327
328     // Some directories
329     QDir useDir;
330     if (options.isOn ("local"))
331         useDir=QDir().current();
332     else
333         useDir=QDir().home();
334     lastImageDir=useDir;
335     lastMapDir=useDir;
336     lastExportDir=useDir;
337
338     if (options.isOn ("help"))
339     {
340         cout << qPrintable (options.getHelpText())<<endl;
341         return 0;
342     }
343
344     // Initialize translations
345     if (options.isOn ("locale"))
346     {
347         localeName = options.getArg ("locale");
348         if (debug) qDebug() << "Main:  using option for locale";
349     }
350     else
351     {
352 #if defined(Q_OS_LINUX)
353         if (debug) qDebug() << "Main:  (OS Linux)   using $LANG for locale";
354         localeName = QProcessEnvironment::systemEnvironment().value("LANG","en");
355 #else
356         if (debug) qDebug() << "Main:  (OS other)   using  QLocale::system().uiLanguages(  using for locale";
357         localeName = QLocale::system().uiLanguages().first();
358
359         if (localeName.contains("-"))
360         {
361             if (debug) qDebug() << "Main:  Replacing '-' with '_' in locale";
362             localeName.replace( "-", "_");
363         }
364 #endif
365     }
366     
367     if (debug) 
368     {
369         qDebug() << "Main:     localName: " << localeName;
370         qDebug() << "Main:  translations: " << localeName, vymBaseDir.path() + "/lang";
371         qDebug() << "Main:   uiLanguages: " << QLocale::system().uiLanguages();
372         qDebug() << "Main:          LANG: " << QProcessEnvironment::systemEnvironment().value("LANG","foobar");
373     }
374   
375     QTranslator vymTranslator;
376     if (!vymTranslator.load( QString("vym.%1").arg( localeName ), vymBaseDir.path() + "/lang") )
377         QMessageBox::warning( 0, QObject::tr( "Warning" ),
378                                QString("Couldn't load translations for locale \"%1\" in\n%2")
379                                .arg(localeName)
380                                .arg(vymBaseDir.path() + "/lang") );
381     app.installTranslator( &vymTranslator );
382
383     // Initializing the master rows of flags
384     systemFlagsMaster=new FlagRow;
385     systemFlagsMaster->setName ("systemFlagsMaster");
386     standardFlagsMaster=new FlagRow;
387     standardFlagsMaster->setName ("standardFlagsMaster");
388
389     // Initialize editors
390     noteEditor = new NoteEditor("noteeditor");
391     noteEditor->setWindowIcon (QPixmap (":/vym-editor.png"));
392     headingEditor = new HeadingEditor("headingeditor");
393
394     // Check if there is a BugzillaClient
395     QFileInfo fi(vymBaseDir.path()+"/scripts/BugzillaClient.pm");
396     //bugzillaClientAvailable=fi.exists();
397     bugzillaClientAvailable=true;   //FIXME-3 add real check again
398
399     // Initialize mainwindow
400 #if defined(Q_OS_WIN32)
401     Main m(0, Qt::Window | Qt::MSWindowsOwnDC);
402 #else
403     Main m;
404 #endif
405
406     // Check for zip tools (at least on windows...)
407 #if defined(Q_OS_WIN32)
408     QFile zipTool(zipToolPath);
409     if (!zipTool.exists() )
410     {
411         QMessageBox::critical( 0, QObject::tr( "Critical Error" ),
412                                QObject::tr("Couldn't find tool to unzip data. "
413                                            "Please download and install 7z and set "
414                                            "path in Settings menu:\n ") +
415                                            "http://www.7-zip.org/");
416          m.settingsZipTool();
417     }
418 #endif
419
420     m.setWindowIcon (QPixmap (":/vym.png"));
421     m.fileNew();
422
423     if (options.isOn ("commands"))
424     {
425         cout << "Available commands:\n";
426         cout << "==================:\n";
427         foreach (Command* c, modelCommands)
428             cout << c->getDescription().toStdString() << endl;
429         return 0;
430     }
431
432     if (options.isOn ("commandslatex"))
433     {
434         foreach (Command* c, modelCommands)
435             cout << c->getDescriptionLaTeX().toStdString() << endl;
436         return 0;
437     }
438
439     if (options.isOn ("batch"))
440         m.hide();
441     else
442     {
443         // Paint Mainwindow first time
444         qApp->processEvents();
445         m.show();
446     }
447
448     // Show release notes, if not already done
449     m.checkReleaseNotes();
450
451     // Check for updates
452     m.checkUpdates();
453
454     if (options.isOn("shortcuts")) switchboard.printASCII();    //FIXME-3 global switchboard and exit after listing
455
456     m.loadCmdLine();
457
458     // For whatever reason tableView is not sorted initially
459     taskEditor->sort();
460
461     // Restore last session
462     if (options.isOn ("restore"))
463         m.fileRestoreSession();
464
465     // Run script
466     if (options.isOn ("run"))
467     {
468         QString script;
469         QString fn=options.getArg ("run");
470         if ( !fn.isEmpty() )
471         {
472             QFile f( fn );
473             if ( !f.open( QFile::ReadOnly|QFile::Text ) )
474             {
475                 QString error (QObject::tr("Error"));
476                 QString msg (QObject::tr("Couldn't open \"%1\"\n%2.").arg(fn).arg(f.errorString()));
477                 if (options.isOn("batch"))
478                     qWarning ()<<error+": "+msg;
479                 else QMessageBox::warning(0, error,msg);
480                 return 0;
481             }
482
483             QTextStream in( &f );
484             script=in.readAll();
485             f.close();
486             m.executeEverywhere (script);
487             m.setScriptFile (fn);
488         }
489     }
490     
491     // For benchmarking we may want to quit instead of entering event loop
492     if (options.isOn ("quit")) return 0;
493
494     // Enable some last minute cleanup
495     QObject::connect( &app, SIGNAL(lastWindowClosed()), &app, SLOT(quit()) );
496
497     app.exec();
498
499     // Cleanup
500     delete noteEditor;
501
502     int s = warningCount + criticalCount + fatalCount;
503     if ( s > 0 ) 
504         qDebug() << "vym exiting with:\n" << 
505         warningCount << " warning messages\n" << 
506         criticalCount<<" critical messages\n" <<
507         fatalCount<<" fatal messages";
508     return s;
509 }