]> git.sven.stormbind.net Git - sven/vym.git/blob - src/mainwindow.cpp
Replace Pierre as the maintainer
[sven/vym.git] / src / mainwindow.cpp
1 #include "mainwindow.h"
2
3 #include <iostream>
4 using namespace std;
5
6 #include <typeinfo>
7
8 #if defined(VYM_DBUS)
9 #include "adaptorvym.h"
10 #endif
11
12 #include <QColorDialog>
13 #include <QDockWidget>
14 #include <QFileDialog>
15 #include <QFontDialog>
16 #include <QInputDialog>
17 #include <QMenuBar>
18 #include <QScriptEngine>
19 #include <QSslSocket>
20 #include <QStatusBar>
21 #include <QTextStream>
22
23 #include "aboutdialog.h"
24 #include "attributeitem.h"
25 #include "branchitem.h"
26 #include "branchpropeditor.h"
27 #include "command.h"
28 #include "confluence-agent.h"
29 #include "confluence-user.h"
30 #include "confluence-userdialog.h"
31 #include "confluence-settings-dialog.h"
32 #include "darktheme-settings-dialog.h"
33 #include "debuginfo.h"
34 #include "default-map-settings-dialog.h"
35 #include "download-agent.h"
36 #include "file.h"
37 #include "findresultmodel.h"
38 #include "findresultwidget.h"
39 #include "flagrow.h"
40 #include "headingeditor.h"
41 #include "historywindow.h"
42 #include "imports.h"
43 #include "jira-agent.h"
44 #include "jira-settings-dialog.h"
45 #include "lineeditdialog.h"
46 #include "macros.h"
47 #include "mapeditor.h"
48 #include "misc.h"
49 #include "noteeditor.h"
50 #include "options.h"
51 #include "scripteditor.h"
52 #include "scripting.h"
53 #include "scriptoutput.h"
54 #include "settings.h"
55 #include "shortcuts.h"
56 #include "showtextdialog.h"
57 #include "task.h"
58 #include "taskeditor.h"
59 #include "taskmodel.h"
60 #include "treeeditor.h"
61 #include "vymprocess.h"
62 #include "warningdialog.h"
63 #include "xlinkitem.h"
64 #include "zip-settings-dialog.h"
65
66 QPrinter *printer = NULL;
67
68 //#include <modeltest.h>
69
70 #if defined(VYM_DBUS)
71 #include <QDBusConnection>
72 #endif
73
74 extern NoteEditor *noteEditor;
75 extern HeadingEditor *headingEditor;
76 extern BranchPropertyEditor *branchPropertyEditor;
77 extern ScriptEditor *scriptEditor;
78 extern ScriptOutput *scriptOutput;
79 extern Main *mainWindow;
80 extern FindResultWidget *findResultWidget;
81 extern TaskEditor *taskEditor;
82 extern TaskModel *taskModel;
83 extern Macros macros;
84 extern QDir tmpVymDir;
85 extern QDir cacheDir;
86 extern QString clipboardDir;
87 extern QString clipboardFile;
88 extern int statusbarTime;
89 extern FlagRowMaster *standardFlagsMaster;
90 extern FlagRowMaster *userFlagsMaster;
91 extern FlagRowMaster *systemFlagsMaster;
92 extern QString vymName;
93 extern QString vymVersion;
94 extern QString vymPlatform;
95 extern QString vymCodeQuality;
96 extern QString vymCodeName;
97 extern QString vymBuildDate;
98 extern QString localeName;
99 extern bool debug;
100 extern bool testmode;
101 extern QTextStream vout;
102 extern Switchboard switchboard;
103
104 extern bool restoreMode;
105 extern QStringList ignoredLockedFiles;
106 extern QStringList lastSessionFiles;
107
108 extern QList<Command *> modelCommands;
109 extern QList<Command *> vymCommands;
110
111 extern bool usingDarkTheme;
112
113 QMenu *branchAddContextMenu;
114 QMenu *branchContextMenu;
115 QMenu *branchLinksContextMenu;
116 QMenu *branchRemoveContextMenu;
117 QMenu *branchXLinksContextMenuEdit;
118 QMenu *branchXLinksContextMenuFollow;
119 QMenu *canvasContextMenu;
120 QMenu *floatimageContextMenu;
121 QMenu *targetsContextMenu;
122 QMenu *taskContextMenu;
123 QMenu *fileLastMapsMenu;
124 QMenu *fileImportMenu;
125 QMenu *fileExportMenu;
126
127 extern Settings settings;
128 extern Options options;
129 extern ImageIO imageIO;
130
131 extern QDir vymBaseDir;
132 extern QDir vymTranslationsDir;
133 extern QDir lastImageDir;
134 extern QDir lastMapDir;
135 #if defined(Q_OS_WIN32)
136 extern QDir vymInstallDir;
137 #endif
138 extern QString zipToolPath;
139
140 extern QColor vymBlue;
141
142 Main::Main(QWidget *parent) : QMainWindow(parent)
143 {
144     mainWindow = this;
145
146     setWindowTitle("VYM - View Your Mind");
147
148     shortcutScope = tr("Main window", "Shortcut scope");
149
150 // Load window settings
151 #if defined(Q_OS_WIN32)
152     if (settings.value("/mainwindow/geometry/maximized", false).toBool()) {
153         setWindowState(Qt::WindowMaximized);
154     }
155     else
156 #endif
157     {
158         resize(settings.value("/mainwindow/geometry/size", QSize(1024, 900))
159                    .toSize());
160         move(settings.value("/mainwindow/geometry/pos", QPoint(50, 50))
161                  .toPoint());
162     }
163
164     // Sometimes we may need to remember old selections
165     prevSelection = "";
166
167     // Create unique temporary directory
168     bool ok;
169     QString tmpVymDirPath = makeTmpDir(ok, "vym");
170     if (!ok) {
171         qWarning("Mainwindow: Could not create temporary directory, failed to "
172                  "start vym");
173         exit(1);
174     }
175     if (debug)
176         qDebug() << "tmpVymDirPath = " << tmpVymDirPath;
177     tmpVymDir.setPath(tmpVymDirPath);
178
179     // Create direcctory for clipboard
180     clipboardDir = tmpVymDirPath + "/clipboard";
181     clipboardFile = "clipboard";
182     QDir d(clipboardDir);
183     d.mkdir(clipboardDir);
184     makeSubDirs(clipboardDir);
185
186     // Create directory for cached files, e.g. svg images
187     if (!tmpVymDir.mkdir("cache")) {
188         qWarning(
189             "Mainwindow: Could not create cache directory, failed to start vym");
190         exit(1);
191     }
192     cacheDir = QDir(tmpVymDirPath + "/cache");
193
194     // Remember PID of our friendly webbrowser
195     browserPID = new qint64;
196     *browserPID = 0;
197
198     // Define commands in API (used globally)
199     setupAPI();
200
201     // Initialize some settings, which are platform dependant
202     QString p, s;
203
204     // application to open URLs
205     p = "/system/readerURL";
206 #if defined(Q_OS_WIN)
207     // Assume that system has been set up so that
208     // Explorer automagically opens up the URL
209     // in the user's preferred browser.
210     s = settings.value(p, "explorer").toString();
211 #elif defined(Q_OS_MACX)
212     s = settings.value(p, "/usr/bin/open").toString();
213 #else
214     s = settings.value(p, "xdg-open").toString();
215 #endif
216     settings.setValue(p, s);
217
218     // application to open PDFs
219     p = "/system/readerPDF";
220 #if defined(Q_OS_WIN)
221     s = settings.value(p, "explorer").toString();
222 #elif defined(Q_OS_MACX)
223     s = settings.value(p, "/usr/bin/open").toString();
224 #else
225     s = settings.value(p, "xdg-open").toString();
226 #endif
227     settings.setValue(p, s);
228
229     // width of xLinksMenu
230     xLinkMenuWidth = 60;
231
232     // Create Layout
233     QWidget *centralWidget = new QWidget(this);
234     QVBoxLayout *layout = new QVBoxLayout(centralWidget);
235     setCentralWidget(centralWidget);
236
237     // Create tab widget which holds the maps
238     tabWidget = new QTabWidget(centralWidget);
239     connect(tabWidget, SIGNAL(currentChanged(int)), this,
240             SLOT(editorChanged()));
241
242     // Allow closing of tabs (introduced in Qt 4.5)
243     tabWidget->setTabsClosable(true);
244     connect(tabWidget, SIGNAL(tabCloseRequested(int)), this,
245             SLOT(fileCloseMap(int)));
246
247     tabWidget->setMovable(true);
248
249     layout->addWidget(tabWidget);
250
251     switchboard.addGroup("MainWindow", tr("Main window", "Shortcut group"));
252     switchboard.addGroup("MapEditor", tr("Map Editors", "Shortcut group"));
253     switchboard.addGroup("TextEditor", tr("Text Editors", "Shortcut group"));
254
255     // Setup actions
256     setupFileActions();
257     setupEditActions();
258     setupSelectActions();
259     setupFormatActions();
260     setupViewActions();
261     setupModeActions();
262     setupNetworkActions();
263     setupSettingsActions();
264     setupConnectActions();
265     setupContextMenus();
266     setupMacros();
267     setupToolbars();
268     setupFlagActions();
269
270     // Dock widgets ///////////////////////////////////////////////
271     QDockWidget *dw;
272     dw = new QDockWidget();
273     dw->setWidget(noteEditor);
274     dw->setObjectName("NoteEditor");
275     dw->setWindowTitle(noteEditor->getEditorTitle());
276     dw->hide();
277     noteEditorDW = dw;
278     addDockWidget(Qt::LeftDockWidgetArea, dw);
279
280     dw = new QDockWidget();
281     dw->setWidget(headingEditor);
282     dw->setObjectName("HeadingEditor");
283     dw->setWindowTitle(headingEditor->getEditorTitle());
284     dw->hide();
285     headingEditorDW = dw;
286     addDockWidget(Qt::BottomDockWidgetArea, dw);
287
288     findResultWidget = new FindResultWidget();
289     dw = new QDockWidget(tr("Search results list", "FindResultWidget"));
290     dw->setWidget(findResultWidget);
291     dw->setObjectName("FindResultWidget");
292     dw->hide();
293     addDockWidget(Qt::RightDockWidgetArea, dw);
294     connect(findResultWidget, SIGNAL(noteSelected(QString, int)), this,
295             SLOT(selectInNoteEditor(QString, int)));
296     connect(findResultWidget, SIGNAL(findPressed(QString, bool)), this,
297             SLOT(editFindNext(QString, bool)));
298
299     scriptEditor = new ScriptEditor(this);
300     dw = new QDockWidget(tr("Script Editor", "ScriptEditor"));
301     dw->setWidget(scriptEditor);
302     dw->setObjectName("ScriptEditor");
303     dw->hide();
304     addDockWidget(Qt::LeftDockWidgetArea, dw);
305
306     scriptOutput = new ScriptOutput(this);
307     dw = new QDockWidget(tr("Script output window"));
308     dw->setWidget(scriptOutput);
309     dw->setObjectName("ScriptOutput");
310     dw->hide();
311     addDockWidget(Qt::BottomDockWidgetArea, dw);
312
313     dw = new QDockWidget(tr("Property Editor", "PropertyEditor"));
314     dw->setWidget(branchPropertyEditor);
315     dw->setObjectName("PropertyEditor");
316     dw->hide();
317     addDockWidget(Qt::LeftDockWidgetArea, dw);
318     branchPropertyEditorDW = dw;
319
320     historyWindow = new HistoryWindow();
321     dw = new QDockWidget(tr("History window", "HistoryWidget"));
322     dw->setWidget(historyWindow);
323     dw->setObjectName("HistoryWidget");
324     dw->hide();
325     addDockWidget(Qt::RightDockWidgetArea, dw);
326     connect(dw, SIGNAL(visibilityChanged(bool)), this, SLOT(updateActions()));
327
328     // Connect NoteEditor, so that we can update flags if text changes
329     connect(noteEditor, SIGNAL(textHasChanged(const VymText &)), this,
330             SLOT(updateNoteText(const VymText &)));
331     connect(noteEditor, SIGNAL(windowClosed()), this, SLOT(updateActions()));
332
333     // Connect heading editor
334     connect(headingEditor, SIGNAL(textHasChanged(const VymText &)), this,
335             SLOT(updateHeading(const VymText &)));
336
337     connect(scriptEditor, SIGNAL(runScript(QString)), this,
338             SLOT(runScript(QString)));
339
340     // Switch back  to MapEditor using Esc  or end presentation mode
341     QAction *a = new QAction(this);
342     a->setShortcut(Qt::Key_Escape);
343     a->setShortcutContext(Qt::ApplicationShortcut);
344     a->setCheckable(false);
345     a->setEnabled(true);
346     addAction(a);
347     connect(a, SIGNAL(triggered()), this, SLOT(escapePressed()));
348
349     // Create TaskEditor after setting up above actions, allow cloning
350     taskEditor = new TaskEditor();
351     dw = new QDockWidget(tr("Task list", "TaskEditor"));
352     dw->setWidget(taskEditor);
353     dw->setObjectName("TaskEditor");
354     dw->hide();
355     addDockWidget(Qt::TopDockWidgetArea, dw);
356     connect(dw, SIGNAL(visibilityChanged(bool)), this, SLOT(updateActions()));
357     // FIXME -0 connect (taskEditor, SIGNAL (focusReleased() ), this, SLOT
358     // (setFocusMapEditor()));
359
360     if (options.isOn("shortcutsLaTeX"))
361         switchboard.printLaTeX();
362
363     if (settings.value("/mainwindow/showTestMenu", false).toBool())
364         setupTestActions();
365     setupHelpActions();
366
367     // Status bar and progress bar there
368     statusBar();
369     progressMax = 0;
370     progressCounter = 0;
371     progressCounterTotal = 0;
372
373     progressDialog.setAutoReset(false);
374     progressDialog.setAutoClose(false);
375     progressDialog.setMinimumWidth(600);
376     // progressDialog.setWindowModality (Qt::WindowModal);   // That forces
377     // mainwindo to update and slows down
378     progressDialog.setCancelButton(NULL);
379
380     restoreState(settings.value("/mainwindow/state", 0).toByteArray());
381
382     updateGeometry();
383
384     // After startup, schedule looking for updates AFTER
385     // release notes have been downloaded
386     // (avoid race condition with simultanously receiving cookies)
387     checkUpdatesAfterReleaseNotes = true;
388
389 #if defined(VYM_DBUS)
390     // Announce myself on DBUS
391     new AdaptorVym(this); // Created and not deleted as documented in Qt
392     if (!QDBusConnection::sessionBus().registerObject("/vym", this))
393         qWarning("MainWindow: Couldn't register DBUS object!");
394 #endif
395 }
396
397 Main::~Main()
398 {
399     // qDebug()<<"Destr Mainwindow"<<flush;
400
401     // Save Settings
402
403     if (!testmode) {
404 #if defined(Q_OS_WIN32)
405         settings.setValue("/mainwindow/geometry/maximized", isMaximized());
406 #endif
407         settings.setValue("/mainwindow/geometry/size", size());
408         settings.setValue("/mainwindow/geometry/pos", pos());
409         settings.setValue("/mainwindow/state", saveState(0));
410
411         settings.setValue("/mainwindow/view/AntiAlias",
412                           actionViewToggleAntiAlias->isChecked());
413         settings.setValue("/mainwindow/view/SmoothPixmapTransform",
414                           actionViewToggleSmoothPixmapTransform->isChecked());
415         settings.setValue("/system/autosave/use",
416                           actionSettingsToggleAutosave->isChecked());
417         settings.setValue("/system/autosave/ms",
418                           settings.value("/system/autosave/ms", 60000));
419         settings.setValue("/mainwindow/autoLayout/use",
420                           actionSettingsToggleAutoLayout->isChecked());
421         settings.setValue("/mapeditor/editmode/autoSelectNewBranch",
422                           actionSettingsAutoSelectNewBranch->isChecked());
423         settings.setValue("/system/writeBackupFile",
424                           actionSettingsWriteBackupFile->isChecked());
425
426         if (printer) {
427             settings.setValue("/system/printerName", printer->printerName());
428             settings.setValue("/system/printerFormat", printer->outputFormat());
429             settings.setValue("/system/printerFileName",
430                               printer->outputFileName());
431         }
432         settings.setValue("/mapeditor/editmode/autoSelectText",
433                           actionSettingsAutoSelectText->isChecked());
434         settings.setValue("/mapeditor/editmode/useFlagGroups",
435                           actionSettingsUseFlagGroups->isChecked());
436         settings.setValue("/export/useHideExport",
437                           actionSettingsUseHideExport->isChecked());
438         settings.setValue("/system/version", vymVersion);
439         settings.setValue("/system/builddate", vymBuildDate);
440     }
441
442     // call the destructors
443     delete noteEditorDW;
444     delete historyWindow;
445     delete branchPropertyEditorDW;
446
447     delete standardFlagsMaster;
448     delete userFlagsMaster;
449     delete systemFlagsMaster;
450
451     // Remove temporary directory
452     removeDir(tmpVymDir);
453 }
454
455 void Main::loadCmdLine()
456 {
457     QStringList flist = options.getFileList();
458     QStringList::Iterator it = flist.begin();
459
460     initProgressCounter(flist.count());
461     while (it != flist.end()) {
462         FileType type = getMapType(*it);
463         fileLoad(*it, NewMap, type);
464         *it++;
465     }
466     removeProgressCounter();
467 }
468
469 void Main::statusMessage(const QString &s)
470 {
471     // Surpress messages while progressdialog during
472     // load is active
473     statusBar()->showMessage(s, statusbarTime);
474 }
475
476 void Main::setProgressMaximum(int max)
477 {
478     if (progressCounter == 0) {
479         // Init range only on first time, when progressCounter still 0
480         // Normalize range to 1000
481         progressDialog.setRange(0, 1000);
482         progressDialog.setValue(1);
483     }
484     progressCounter++; // Another map is loaded
485
486     progressMax = max * 1000;
487     QApplication::processEvents();
488 }
489
490 void Main::addProgressValue(float v)
491
492 {
493     int progress_value =
494         (v + progressCounter - 1) * 1000 / progressCounterTotal;
495     /*
496         qDebug() << "addVal v="<<v
497          <<"  cur="<<progressDialog.value()
498          <<"  pCounter="<<progressCounter
499          <<"  pCounterTotal="<<progressCounterTotal
500              <<"  newv="<< progress_value
501          ;
502          */
503
504     // Make sure the progress dialog shows, even if value == 0
505     if (progress_value < 1)
506         progress_value = 1;
507     progressDialog.setValue(progress_value);
508     if (progress_value == 1)
509         QApplication::processEvents();
510 }
511
512 void Main::initProgressCounter(uint n) { progressCounterTotal = n; }
513
514 void Main::removeProgressCounter()
515 {
516     // Hide dialog again
517     progressCounter = 0;
518     progressCounterTotal = 0;
519     progressDialog.reset();
520     progressDialog.hide();
521 }
522
523 void Main::closeEvent(QCloseEvent *event)
524 {
525     if (fileExitVYM())
526         event->ignore();
527     else
528         event->accept();
529 }
530
531 QPrinter *Main::setupPrinter()
532 {
533     // Global Printer
534     printer = new QPrinter(QPrinter::HighResolution);
535     return printer;
536 }
537
538 // Define commands for models
539 void Main::setupAPI()
540 {
541     Command *c = new Command("addBranch", Command::Branch);
542     c->addPar(Command::Int, true, "Index of new branch");
543     modelCommands.append(c);
544
545     c = new Command("addBranchBefore", Command::Branch);
546     modelCommands.append(c);
547
548     c = new Command("addMapCenter", Command::Any);
549     c->addPar(Command::Double, false, "Position x");
550     c->addPar(Command::Double, false, "Position y");
551     modelCommands.append(c);
552
553     c = new Command("addMapInsert", Command::Any);
554     c->addPar(Command::String, false, "Filename of map to load");
555     c->addPar(Command::Int, true, "Index where map is inserted");
556     c->addPar(Command::Int, true, "Content filter");
557     modelCommands.append(c);
558
559     c = new Command("addMapReplace", Command::Branch);
560     c->addPar(Command::String, false, "Filename of map to load");
561     modelCommands.append(c);
562
563     c = new Command("addSlide", Command::Branch);
564     modelCommands.append(c);
565
566     c = new Command("addXLink", Command::BranchLike);
567     c->addPar(Command::String, false, "Begin of XLink");
568     c->addPar(Command::String, false, "End of XLink");
569     c->addPar(Command::Int, true, "Width of XLink");
570     c->addPar(Command::Color, true, "Color of XLink");
571     c->addPar(Command::String, true, "Penstyle of XLink");
572     modelCommands.append(c);
573
574     c = new Command("branchCount", Command::Any, Command::Int);
575     modelCommands.append(c);
576
577     c = new Command("centerCount", Command::BranchLike, Command::Int);
578     modelCommands.append(c);
579
580     c = new Command("centerOnID", Command::Any);
581     c->addPar(Command::String, false, "UUID of object to center on");
582     modelCommands.append(c);
583
584     c = new Command("clearFlags", Command::BranchLike);
585     modelCommands.append(c);
586
587     c = new Command("colorBranch", Command::Branch);
588     c->addPar(Command::Color, true, "New color");
589     modelCommands.append(c);
590
591     c = new Command("colorSubtree", Command::Branch);
592     c->addPar(Command::Color, true, "New color");
593     modelCommands.append(c);
594
595     c = new Command("copy", Command::BranchOrImage);
596     modelCommands.append(c);
597
598     c = new Command("cut", Command::BranchOrImage);
599     modelCommands.append(c);
600
601     c = new Command("cycleTask", Command::BranchOrImage);
602     c->addPar(Command::Bool, true, "True, if cycling in reverse order");
603     modelCommands.append(c);
604
605     c = new Command("depth", Command::BranchOrImage, Command::Int);
606     modelCommands.append(c);
607
608     c = new Command("exportMap", Command::Any, Command::Bool);
609     c->addPar(Command::String, false,
610               "Format (AO, ASCII, CONFLUENCE, CSV, HTML, Image, Impress, Last, "
611               "LaTeX, Markdown, OrgMode, PDF, SVG, XML)");
612     modelCommands.append(c);
613
614     c = new Command("getDestPath", Command::Any, Command::String);
615     modelCommands.append(c);
616
617     c = new Command("getFileDir", Command::Any, Command::String);
618     modelCommands.append(c);
619
620     c = new Command("getFileName", Command::Any, Command::String);
621     modelCommands.append(c);
622
623     c = new Command("getFrameType", Command::Branch, Command::String);
624     modelCommands.append(c);
625
626     c = new Command("getHeadingPlainText", Command::TreeItem, Command::String);
627     modelCommands.append(c);
628
629     c = new Command("getHeadingXML", Command::TreeItem, Command::String);
630     modelCommands.append(c);
631
632     c = new Command("getMapAuthor", Command::Any, Command::String);
633     modelCommands.append(c);
634
635     c = new Command("getMapComment", Command::Any, Command::String);
636     modelCommands.append(c);
637
638     c = new Command("getMapTitle", Command::Any, Command::String);
639     modelCommands.append(c);
640
641     c = new Command("getNotePlainText", Command::TreeItem, Command::String);
642     modelCommands.append(c);
643
644     c = new Command("getNoteXML", Command::TreeItem, Command::String);
645     modelCommands.append(c);
646
647     c = new Command("getSelectionString", Command::TreeItem, Command::String);
648     modelCommands.append(c);
649
650     c = new Command("getTaskPriorityDelta", Command::Branch, Command::Int);
651     modelCommands.append(c);
652
653     c = new Command("getTaskSleep", Command::Branch, Command::String);
654     modelCommands.append(c);
655
656     c = new Command("getTaskSleepDays", Command::Branch, Command::Int);
657     modelCommands.append(c);
658
659     c = new Command("getURL", Command::TreeItem, Command::String);
660     modelCommands.append(c);
661
662     c = new Command("getVymLink", Command::Branch, Command::String);
663     modelCommands.append(c);
664
665     c = new Command("getXLinkColor", Command::XLink, Command::String);
666     modelCommands.append(c);
667
668     c = new Command("getXLinkWidth", Command::XLink, Command::Int);
669     modelCommands.append(c);
670
671     c = new Command("getXLinkPenStyle", Command::XLink, Command::String);
672     modelCommands.append(c);
673
674     c = new Command("getXLinkStyleBegin", Command::XLink, Command::String);
675     modelCommands.append(c);
676
677     c = new Command("getXLinkStyleEnd", Command::XLink, Command::String);
678     modelCommands.append(c);
679
680     c = new Command("hasActiveFlag", Command::TreeItem, Command::Bool);
681     c->addPar(Command::String, false, "Name of flag");
682     modelCommands.append(c);
683
684     c = new Command("hasNote", Command::Branch, Command::Bool);
685     modelCommands.append(c);
686
687     c = new Command("hasRichTextNote", Command::Branch, Command::Bool);
688     modelCommands.append(c);
689
690     c = new Command("hasTask", Command::Branch, Command::Bool);
691     modelCommands.append(c);
692
693     c = new Command("importDir", Command::Branch);
694     c->addPar(Command::String, false, "Directory name to import");
695     modelCommands.append(c);
696
697     c = new Command("initIterator", Command::Branch, Command::Bool);
698     c->addPar(Command::String, false, "Name of iterator");
699     c->addPar(Command::Bool, true, "Flag to go deep levels first");
700     modelCommands.append(c);
701
702     c = new Command("isScrolled", Command::Branch, Command::Bool);
703     modelCommands.append(c);
704
705     c = new Command("loadImage", Command::Branch);
706     c->addPar(Command::String, false, "Filename of image");
707     modelCommands.append(c);
708
709     c = new Command("loadNote", Command::Branch);
710     c->addPar(Command::String, false, "Filename of note");
711     modelCommands.append(c);
712
713     c = new Command("moveDown", Command::Branch);
714     modelCommands.append(c);
715
716     c = new Command("moveUp", Command::Branch);
717     modelCommands.append(c);
718
719     c = new Command("moveSlideDown", Command::Any);
720     modelCommands.append(c);
721
722     c = new Command("moveSlideUp", Command::Any);
723     modelCommands.append(c);
724
725     c = new Command("move", Command::BranchOrImage);
726     c->addPar(Command::Double, false, "Position x");
727     c->addPar(Command::Double, false, "Position y");
728     modelCommands.append(c);
729
730     c = new Command("moveRel", Command::BranchOrImage);
731     c->addPar(Command::Double, false, "Position x");
732     c->addPar(Command::Double, false, "Position y");
733     modelCommands.append(c);
734
735     c = new Command("nextIterator", Command::Branch, Command::Bool);
736     c->addPar(Command::String, false, "Name of iterator");
737     modelCommands.append(c);
738
739     c = new Command("nop", Command::Any);
740     modelCommands.append(c);
741
742     c = new Command("note2URLs", Command::Branch);
743     modelCommands.append(c);
744
745     // internally required for undo/redo of changing VymText:
746     c = new Command("parseVymText", Command::Branch, Command::Bool);
747     c->addPar(Command::String, false,
748               "parse XML of VymText, e.g for Heading or VymNote");
749     modelCommands.append(c);
750
751     c = new Command("paste", Command::Branch);
752     modelCommands.append(c);
753
754     c = new Command("redo", Command::Any);
755     modelCommands.append(c);
756
757     c = new Command("relinkTo",
758                     Command::TreeItem,
759                     Command::Bool); // FIXME different number of parameters for Image or Branch
760     c->addPar(Command::String, false, "Selection string of parent");
761     c->addPar(Command::Int, false, "Index position");
762     c->addPar(Command::Double, true, "Position x");
763     c->addPar(Command::Double, true, "Position y");
764     modelCommands.append(c);
765
766     c = new Command("remove", Command::TreeItem);
767     modelCommands.append(c);
768
769     c = new Command("removeChildren", Command::Branch);
770     modelCommands.append(c);
771
772     c = new Command("removeKeepChildren", Command::Branch);
773     modelCommands.append(c);
774
775     c = new Command("removeSlide", Command::Any);
776     c->addPar(Command::Int, false, "Index of slide to remove");
777     modelCommands.append(c);
778
779     c = new Command("repeatLastCommand", Command::Any);
780     modelCommands.append(c);
781
782     c = new Command("saveImage", Command::Image);
783     c->addPar(Command::String, false, "Filename of image to save");
784     c->addPar(Command::String, false, "Format of image to save");
785     modelCommands.append(c);
786
787     c = new Command("saveNote", Command::Branch);
788     c->addPar(Command::String, false, "Filename of note to save");
789     modelCommands.append(c);
790
791     c = new Command("scroll", Command::Branch);
792     modelCommands.append(c);
793
794     c = new Command("select", Command::Any, Command::Bool);
795     c->addPar(Command::String, false, "Selection string");
796     modelCommands.append(c);
797
798     c = new Command("selectFirstBranch", Command::Branch, Command::Bool);
799     modelCommands.append(c);
800
801     c = new Command("selectFirstChildBranch", Command::Branch, Command::Bool);
802     modelCommands.append(c);
803
804     c = new Command("selectID", Command::Any, Command::Bool);
805     c->addPar(Command::String, false, "Unique ID");
806     modelCommands.append(c);
807
808     c = new Command("selectLastBranch", Command::Branch, Command::Bool);
809     modelCommands.append(c);
810
811     c = new Command("selectLastChildBranch", Command::Branch, Command::Bool);
812     modelCommands.append(c);
813
814     c = new Command("selectLastImage", Command::Branch, Command::Bool);
815     modelCommands.append(c);
816
817     c = new Command("selectLatestAdded", Command::Any, Command::Bool);
818     modelCommands.append(c);
819
820     c = new Command("selectParent", Command::Branch, Command::Bool);
821     modelCommands.append(c);
822
823     c = new Command("selectToggle", Command::BranchOrImage, Command::Bool);
824     modelCommands.append(c);
825
826     c = new Command("setFlagByName", Command::TreeItem);
827     c->addPar(Command::String, false, "Name of flag");
828     modelCommands.append(c);
829
830     c = new Command("setTaskPriorityDelta", Command::Branch);
831     c->addPar(Command::String, false, "Manually add value to priority of task");
832     modelCommands.append(c);
833
834     c = new Command("setTaskSleep", Command::Branch);
835     c->addPar(Command::String, false, "Days to sleep");
836     modelCommands.append(c);
837
838     c = new Command("setFrameIncludeChildren", Command::BranchOrImage);
839     c->addPar(Command::Bool, false,
840               "Include or don't include children in frame");
841     modelCommands.append(c);
842
843     c = new Command("setFrameType", Command::BranchOrImage);
844     c->addPar(Command::String, false, "Type of frame");
845     modelCommands.append(c);
846
847     c = new Command("setFramePenColor", Command::BranchOrImage);
848     c->addPar(Command::Color, false, "Color of frame border line");
849     modelCommands.append(c);
850
851     c = new Command("setFrameBrushColor", Command::BranchOrImage);
852     c->addPar(Command::Color, false, "Color of frame background");
853     modelCommands.append(c);
854
855     c = new Command("setFramePadding", Command::BranchOrImage);
856     c->addPar(Command::Int, false, "Padding around frame");
857     modelCommands.append(c);
858
859     c = new Command("setFrameBorderWidth", Command::BranchOrImage);
860     c->addPar(Command::Int, false, "Width of frame borderline");
861     modelCommands.append(c);
862
863     c = new Command("setHeadingConfluencePageName", Command::Branch);
864     modelCommands.append(c);
865
866     c = new Command("setHeadingPlainText", Command::TreeItem);
867     c->addPar(Command::String, false, "New heading");
868     modelCommands.append(c);
869
870     c = new Command("setHideExport", Command::BranchOrImage);
871     c->addPar(Command::Bool, false, "Set if item should be visible in export");
872     modelCommands.append(c);
873
874     c = new Command("setIncludeImagesHorizontally", Command::Branch);
875     c->addPar(Command::Bool, false,
876               "Set if images should be included horizontally in parent branch");
877     modelCommands.append(c);
878
879     c = new Command("setIncludeImagesVertically", Command::Branch);
880     c->addPar(Command::Bool, false,
881               "Set if images should be included vertically in parent branch");
882     modelCommands.append(c);
883
884     c = new Command("setHideLinksUnselected", Command::BranchOrImage);
885     c->addPar(Command::Bool, false,
886               "Set if links of items should be visible for unselected items");
887     modelCommands.append(c);
888
889     c = new Command("setMapAnimCurve", Command::Any);
890     c->addPar(Command::Int, false,
891               "EasingCurve used in animation in MapEditor");
892     modelCommands.append(c);
893
894     c = new Command("setMapAuthor", Command::Any);
895     c->addPar(Command::String, false, "");
896     modelCommands.append(c);
897
898     c = new Command("setMapAnimDuration", Command::Any);
899     c->addPar(Command::Int, false,
900               "Duration of animation in MapEditor in milliseconds");
901     modelCommands.append(c);
902
903     c = new Command("setMapBackgroundColor", Command::Any);
904     c->addPar(Command::Color, false, "Color of map background");
905     modelCommands.append(c);
906
907     c = new Command("setMapComment", Command::Any);
908     c->addPar(Command::String, false, "");
909     modelCommands.append(c);
910
911     c = new Command("setMapTitle", Command::Any);
912     c->addPar(Command::String, false, "");
913     modelCommands.append(c);
914
915     c = new Command("setMapDefLinkColor", Command::Any);
916     c->addPar(Command::Color, false, "Default color of links");
917     modelCommands.append(c);
918
919     c = new Command("setMapLinkStyle", Command::Any);
920     c->addPar(Command::String, false, "Link style in map");
921     modelCommands.append(c);
922
923     c = new Command("setMapRotation", Command::Any);
924     c->addPar(Command::Double, false, "Rotation of map");
925     modelCommands.append(c);
926
927     c = new Command("setMapTitle", Command::Any);
928     c->addPar(Command::String, false, "");
929     modelCommands.append(c);
930
931     c = new Command("setMapZoom", Command::Any);
932     c->addPar(Command::Double, false, "Zoomfactor of map");
933     modelCommands.append(c);
934
935     c = new Command("setNotePlainText", Command::Branch);
936     c->addPar(Command::String, false, "Note of branch");
937     modelCommands.append(c);
938
939     c = new Command("setScaleFactor", Command::Image);
940     c->addPar(Command::Double, false, "Scale image by factor f");
941     modelCommands.append(c);
942
943     c = new Command("setSelectionColor", Command::Any);
944     c->addPar(Command::Color, false, "Color of selection box");
945     modelCommands.append(c);
946
947     c = new Command("setSelectionPenColor", Command::Any);
948     c->addPar(Command::Color, false, "Color of selection box border");
949     modelCommands.append(c);
950
951     c = new Command("setSelectionPenWidth", Command::Any);
952     c->addPar(Command::Int, false, "Selection box border width ");
953     modelCommands.append(c);
954
955     c = new Command("setSelectionBrushColor", Command::Any);
956     c->addPar(Command::Color, false, "Color of selection box background");
957     modelCommands.append(c);
958
959     c = new Command("setTaskPriority", Command::Branch);
960     c->addPar(Command::Int, false, "Priority of task");
961     modelCommands.append(c);
962
963     c = new Command("setTaskSleep", Command::Branch, Command::Bool);
964     c->addPar(Command::String, false, "Sleep time of task");
965     modelCommands.append(c);
966
967     c = new Command("setURL", Command::TreeItem);
968     c->addPar(Command::String, false, "URL of TreeItem");
969     modelCommands.append(c);
970
971     c = new Command("setVymLink", Command::Branch);
972     c->addPar(Command::String, false, "Vymlink of branch");
973     modelCommands.append(c);
974
975     c = new Command("setXLinkColor", Command::XLink);
976     c->addPar(Command::String, false, "Color of xlink");
977     modelCommands.append(c);
978
979     c = new Command("setXLinkStyle", Command::XLink);
980     c->addPar(Command::String, false, "Style of xlink");
981     modelCommands.append(c);
982
983     c = new Command("setXLinkStyleBegin", Command::XLink);
984     c->addPar(Command::String, false, "Style of xlink begin");
985     modelCommands.append(c);
986
987     c = new Command("setXLinkStyleEnd", Command::XLink);
988     c->addPar(Command::String, false, "Style of xlink end");
989     modelCommands.append(c);
990
991     c = new Command("setXLinkWidth", Command::XLink);
992     c->addPar(Command::Int, false, "Width of xlink");
993     modelCommands.append(c);
994
995     c = new Command("sleep", Command::Any);
996     c->addPar(Command::Int, false, "Sleep (seconds)");
997     modelCommands.append(c);
998
999     c = new Command("sortChildren", Command::Branch);
1000     c->addPar(Command::Bool, true,
1001               "Sort children of branch in revers order if set");
1002     modelCommands.append(c);
1003
1004     c = new Command("toggleFlagByUid", Command::Branch);
1005     c->addPar(Command::String, false, "Uid of flag to toggle");
1006     modelCommands.append(c);
1007
1008     c = new Command("toggleFlagByName", Command::Branch);
1009     c->addPar(Command::String, false, "Name of flag to toggle");
1010     modelCommands.append(c);
1011
1012     c = new Command("toggleFrameIncludeChildren", Command::Branch);
1013     modelCommands.append(c);
1014
1015     c = new Command("toggleScroll", Command::Branch);
1016     modelCommands.append(c);
1017
1018     c = new Command("toggleTarget", Command::Branch);
1019     modelCommands.append(c);
1020
1021     c = new Command("toggleTask", Command::Branch);
1022     modelCommands.append(c);
1023
1024     c = new Command("undo", Command::Any);
1025     modelCommands.append(c);
1026
1027     c = new Command("unscroll", Command::Branch, Command::Bool);
1028     modelCommands.append(c);
1029
1030     c = new Command("unscrollChildren", Command::Branch);
1031     modelCommands.append(c);
1032
1033     c = new Command("unselectAll", Command::Any);
1034     modelCommands.append(c);
1035
1036     c = new Command("unsetFlagByName", Command::Branch);
1037     c->addPar(Command::String, false, "Name of flag to unset");
1038     modelCommands.append(c);
1039
1040     //
1041     // Below are the commands for vym itself:
1042     //
1043
1044     c = new Command("clearConsole", Command::Any);
1045     vymCommands.append(c);
1046
1047     c = new Command("closeMapWithID", Command::Any);
1048     c->addPar(Command::Int, false, "ID of map (unsigned int)");
1049     vymCommands.append(c);
1050
1051     c = new Command("currentMap", Command::Any);
1052     vymCommands.append(c);
1053
1054     c = new Command("currentMapIndex", Command::Any);
1055     vymCommands.append(c);
1056
1057     c = new Command("editHeading", Command::Branch);
1058     vymCommands.append(c);
1059
1060     c = new Command("loadMap", Command::Any);
1061     c->addPar(Command::String, false, "Path to map");
1062     vymCommands.append(c);
1063
1064     c = new Command("mapCount", Command::Any);
1065     vymCommands.append(c);
1066
1067     c = new Command("gotoMap", Command::Any);
1068     c->addPar(Command::Int, false, "Index of map");
1069     vymCommands.append(c);
1070
1071     c = new Command("selectQuickColor", Command::Any);
1072     c->addPar(Command::Int, false, "Index of quick color [0..6]");
1073     vymCommands.append(c);
1074
1075     c = new Command("currentColor", Command::Any);
1076     vymCommands.append(c);
1077
1078     c = new Command("toggleTreeEditor", Command::Any);
1079     vymCommands.append(c);
1080
1081     c = new Command("version", Command::Any);
1082     vymCommands.append(c);
1083 }
1084
1085 void Main::cloneActionMapEditor(QAction *a, QKeySequence ks)
1086 {
1087     a->setShortcut(ks);
1088     a->setShortcutContext(Qt::WidgetShortcut);
1089     mapEditorActions.append(a);
1090 }
1091
1092 // File Actions
1093 void Main::setupFileActions()
1094 {
1095     QString tag = tr("&Map", "Menu for file actions");
1096     QMenu *fileMenu = menuBar()->addMenu(tag);
1097
1098     QAction *a;
1099     a = new QAction(QPixmap(":/filenew.png"), tr("&New map", "File menu"),
1100                     this);
1101     switchboard.addSwitch("fileMapNew", shortcutScope, a, tag);
1102     connect(a, SIGNAL(triggered()), this, SLOT(fileNew()));
1103     cloneActionMapEditor(a, Qt::CTRL + Qt::Key_N);
1104     fileMenu->addAction(a);
1105     actionFileNew = a;
1106
1107     a = new QAction(QPixmap(":/filenewcopy.png"),
1108                     tr("&Copy to new map", "File menu"), this);
1109     switchboard.addSwitch("fileMapNewCopy", shortcutScope, a, tag);
1110     connect(a, SIGNAL(triggered()), this, SLOT(fileNewCopy()));
1111     cloneActionMapEditor(a, Qt::CTRL + Qt::SHIFT + Qt::Key_C);
1112     fileMenu->addAction(a);
1113     actionFileNewCopy = a;
1114
1115     a = new QAction(QPixmap(":/fileopen.png"), tr("&Open...", "File menu"),
1116                     this);
1117     switchboard.addSwitch("fileMapOpen", shortcutScope, a, tag);
1118     connect(a, SIGNAL(triggered()), this, SLOT(fileLoad()));
1119     cloneActionMapEditor(a, Qt::CTRL + Qt::Key_L);
1120     fileMenu->addAction(a);
1121     actionFileOpen = a;
1122
1123     a = new QAction(tr("&Restore last session", "Edit menu"), this);
1124     a->setShortcut(Qt::CTRL + Qt::Key_R);
1125     switchboard.addSwitch("fileMapRestore", shortcutScope, a, tag);
1126     connect(a, SIGNAL(triggered()), this, SLOT(fileRestoreSession()));
1127     fileMenu->addAction(a);
1128     actionListFiles.append(a);
1129     actionCopy = a;
1130
1131     fileLastMapsMenu = fileMenu->addMenu(tr("Open Recent", "File menu"));
1132     fileMenu->addSeparator();
1133
1134     a = new QAction(QPixmap(":/filesave.svg"), tr("&Save...", "File menu"),
1135                     this);
1136     switchboard.addSwitch("fileMapSave", shortcutScope, a, tag);
1137     cloneActionMapEditor(a, Qt::CTRL + Qt::Key_S);
1138     fileMenu->addAction(a);
1139     restrictedMapActions.append(a);
1140     connect(a, SIGNAL(triggered()), this, SLOT(fileSave()));
1141     actionFileSave = a;
1142
1143     a = new QAction(QPixmap(":/filesaveas.png"), tr("Save &As...", "File menu"),
1144                     this);
1145     fileMenu->addAction(a);
1146     connect(a, SIGNAL(triggered()), this, SLOT(fileSaveAs()));
1147
1148     a = new QAction(tr("Save as default map", "File menu"), this);
1149     fileMenu->addAction(a);
1150     connect(a, SIGNAL(triggered()), this, SLOT(fileSaveAsDefault()));
1151
1152     fileMenu->addSeparator();
1153
1154     fileImportMenu = fileMenu->addMenu(tr("Import", "File menu"));
1155
1156     a = new QAction( tr("Firefox Bookmarks", "Import filters") + 
1157                         tr("(experimental)"),
1158                     this);
1159     connect(a, SIGNAL(triggered()), this,
1160             SLOT(fileImportFirefoxBookmarks()));
1161     fileImportMenu->addAction(a);
1162
1163     a = new QAction("Freemind...", this);
1164     connect(a, SIGNAL(triggered()), this, SLOT(fileImportFreemind()));
1165     fileImportMenu->addAction(a);
1166
1167     a = new QAction("Mind Manager...", this);
1168     connect(a, SIGNAL(triggered()), this, SLOT(fileImportMM()));
1169     fileImportMenu->addAction(a);
1170
1171     a = new QAction(tr("Import Dir...", "Import Filters") + " " +
1172                         tr("(still experimental)"),
1173                     this);
1174     connect(a, SIGNAL(triggered()), this, SLOT(fileImportDir()));
1175     fileImportMenu->addAction(a);
1176
1177     fileExportMenu = fileMenu->addMenu(tr("Export", "File menu"));
1178
1179     a = new QAction(QPixmap(":/file-document-export.png"),
1180                     tr("Repeat last export (%1)").arg("-"), this);
1181     switchboard.addSwitch("fileExportLast", shortcutScope, a, tag);
1182     connect(a, SIGNAL(triggered()), this, SLOT(fileExportLast()));
1183     cloneActionMapEditor(a, Qt::CTRL + Qt::Key_E);
1184     fileExportMenu->addAction(a);
1185     actionFileExportLast = a;
1186     actionListFiles.append(a);
1187
1188     a = new QAction(tr("Webpage (HTML)...", "File export menu"), this);
1189     connect(a, SIGNAL(triggered()), this, SLOT(fileExportHTML()));
1190     fileExportMenu->addAction(a);
1191     actionListFiles.append(a);
1192
1193     a = new QAction(tr("Confluence (HTML)...", "File export menu") + " " + " " +
1194                         tr("(still experimental)"),
1195                     this);
1196     connect(a, SIGNAL(triggered()), this, SLOT(fileExportConfluence()));
1197     fileExportMenu->addAction(a);
1198     actionListFiles.append(a);
1199     actionFileExportConfluence = a;
1200
1201     a = new QAction( tr("Firefox Bookmarks", "File export menu") + 
1202                         tr("(still experimental)"),
1203                     this);
1204     connect(a, SIGNAL(triggered()), this,
1205             SLOT(fileExportFirefoxBookmarks()));
1206     fileExportMenu->addAction(a);
1207     actionListFiles.append(a);
1208
1209     a = new QAction(tr("Text (ASCII)...", "File export menu"), this);
1210     connect(a, SIGNAL(triggered()), this, SLOT(fileExportASCII()));
1211     fileExportMenu->addAction(a);
1212     actionListFiles.append(a);
1213
1214     a = new QAction(tr("Text (Markdown)...", "File export menu") + " " +
1215                         tr("(still experimental)"),
1216                     this);
1217     connect(a, SIGNAL(triggered()), this, SLOT(fileExportMarkdown()));
1218     fileExportMenu->addAction(a);
1219     actionListFiles.append(a);
1220
1221     a = new QAction(tr("Text with tasks", "File export menu") + " " +
1222                         tr("(still experimental)"),
1223                     this);
1224     connect(a, SIGNAL(triggered()), this, SLOT(fileExportASCIITasks()));
1225     fileExportMenu->addAction(a);
1226     actionListFiles.append(a);
1227
1228     a = new QAction(tr("Text (A&O report)...", "Export format"), this);
1229     connect(a, SIGNAL(triggered()), this, SLOT(fileExportAO()));
1230     fileExportMenu->addAction(a);
1231     actionListFiles.append(a);
1232
1233     a = new QAction(tr("Image%1", "File export menu").arg("..."), this);
1234     connect(a, SIGNAL(triggered()), this, SLOT(fileExportImage()));
1235     fileExportMenu->addAction(a);
1236     actionListFiles.append(a);
1237
1238     a = new QAction(tr("PDF%1", "File export menu").arg("..."), this);
1239     connect(a, SIGNAL(triggered()), this, SLOT(fileExportPDF()));
1240     fileExportMenu->addAction(a);
1241     actionListFiles.append(a);
1242
1243     a = new QAction(tr("SVG%1", "File export menu").arg("..."), this);
1244     connect(a, SIGNAL(triggered()), this, SLOT(fileExportSVG()));
1245     fileExportMenu->addAction(a);
1246     actionListFiles.append(a);
1247
1248     a = new QAction("LibreOffice...", this);
1249     connect(a, SIGNAL(triggered()), this, SLOT(fileExportImpress()));
1250     fileExportMenu->addAction(a);
1251     actionListFiles.append(a);
1252
1253     a = new QAction("XML...", this);
1254     connect(a, SIGNAL(triggered()), this, SLOT(fileExportXML()));
1255     fileExportMenu->addAction(a);
1256     actionListFiles.append(a);
1257
1258     a = new QAction(tr("CSV...") + " " + tr("(still experimental)"), this);
1259     connect(a, SIGNAL(triggered()), this, SLOT(fileExportCSV()));
1260     fileExportMenu->addAction(a);
1261     actionListFiles.append(a);
1262
1263     a = new QAction("Taskjuggler... " + tr("(still experimental)"), this);
1264     connect(a, SIGNAL(triggered()), this, SLOT(fileExportTaskjuggler()));
1265     fileExportMenu->addAction(a);
1266     actionListFiles.append(a);
1267
1268     a = new QAction("OrgMode... " + tr("(still experimental)"), this);
1269     connect(a, SIGNAL(triggered()), this, SLOT(fileExportOrgMode()));
1270     fileExportMenu->addAction(a);
1271     actionListFiles.append(a);
1272
1273     a = new QAction("LaTeX... " + tr("(still experimental)"), this);
1274     connect(a, SIGNAL(triggered()), this, SLOT(fileExportLaTeX()));
1275     fileExportMenu->addAction(a);
1276     actionListFiles.append(a);
1277
1278     fileMenu->addSeparator();
1279
1280     a = new QAction(tr("Properties"), this);
1281     switchboard.addSwitch("editMapProperties", shortcutScope, a, tag);
1282     connect(a, SIGNAL(triggered()), this, SLOT(editMapProperties()));
1283     fileMenu->addAction(a);
1284     actionListFiles.append(a);
1285     actionMapProperties = a;
1286
1287     fileMenu->addSeparator();
1288
1289     a = new QAction(QPixmap(":/fileprint.png"), tr("&Print") + QString("..."),
1290                     this);
1291     a->setShortcut(Qt::CTRL + Qt::Key_P);
1292     switchboard.addSwitch("fileMapPrint", shortcutScope, a, tag);
1293     connect(a, SIGNAL(triggered()), this, SLOT(filePrint()));
1294     fileMenu->addAction(a);
1295     unrestrictedMapActions.append(a);
1296     actionFilePrint = a;
1297
1298     a = new QAction(QPixmap(":/fileclose.png"), tr("&Close Map", "File menu"),
1299                     this);
1300     a->setShortcut(Qt::CTRL + Qt::Key_W);
1301     switchboard.addSwitch("fileMapClose", shortcutScope, a, tag);
1302     connect(a, SIGNAL(triggered()), this, SLOT(fileCloseMap()));
1303     fileMenu->addAction(a);
1304
1305     a = new QAction(QPixmap(":/exit.png"), tr("E&xit", "File menu"), this);
1306     a->setShortcut(Qt::CTRL + Qt::Key_Q);
1307     switchboard.addSwitch("fileExit", shortcutScope, a, tag);
1308     connect(a, SIGNAL(triggered()), this, SLOT(fileExitVYM()));
1309     fileMenu->addAction(a);
1310
1311     a = new QAction("Toggle winter mode", this);
1312     a->setShortcut(Qt::CTRL + Qt::Key_Asterisk);
1313     a->setShortcutContext(Qt::WidgetShortcut);
1314
1315     if (settings.value("/mainwindow/showTestMenu", false).toBool()) {
1316         addAction(a);
1317         mapEditorActions.append(a);
1318         switchboard.addSwitch("mapWinterMode", shortcutScope, a, tag);
1319     }
1320     connect(a, SIGNAL(triggered()), this, SLOT(toggleWinter()));
1321     actionToggleWinter = a;
1322 }
1323
1324 // Edit Actions
1325 void Main::setupEditActions()
1326 {
1327     QString tag = tr("E&dit", "Edit menu");
1328     QMenu *editMenu = menuBar()->addMenu(tag);
1329
1330     QAction *a;
1331     a = new QAction(QPixmap(":/undo.png"), tr("&Undo", "Edit menu"), this);
1332     a->setShortcut(Qt::CTRL + Qt::Key_Z);
1333     a->setShortcutContext(Qt::WidgetShortcut);
1334     a->setEnabled(false);
1335     editMenu->addAction(a);
1336     mapEditorActions.append(a);
1337     restrictedMapActions.append(a);
1338     switchboard.addSwitch("mapUndo", shortcutScope, a, tag);
1339     connect(a, SIGNAL(triggered()), this, SLOT(editUndo()));
1340     actionUndo = a;
1341
1342     a = new QAction(QPixmap(":/redo.png"), tr("&Redo", "Edit menu"), this);
1343     a->setShortcut(Qt::CTRL + Qt::Key_Y);
1344     a->setShortcutContext(Qt::WidgetShortcut);
1345     editMenu->addAction(a);
1346     restrictedMapActions.append(a);
1347     mapEditorActions.append(a);
1348     switchboard.addSwitch("mapRedo", shortcutScope, a, tag);
1349     connect(a, SIGNAL(triggered()), this, SLOT(editRedo()));
1350     actionRedo = a;
1351
1352     editMenu->addSeparator();
1353     a = new QAction(QPixmap(":/editcopy.png"), tr("&Copy", "Edit menu"), this);
1354     a->setShortcut(Qt::CTRL + Qt::Key_C);
1355     a->setShortcutContext(Qt::WidgetShortcut);
1356     a->setEnabled(false);
1357     editMenu->addAction(a);
1358     unrestrictedMapActions.append(a);
1359     mapEditorActions.append(a);
1360     switchboard.addSwitch("mapCopy", shortcutScope, a, tag);
1361     connect(a, SIGNAL(triggered()), this, SLOT(editCopy()));
1362     actionCopy = a;
1363
1364     // Multi key shortcuts https://bugreports.qt.io/browse/QTBUG-39127
1365     a = new QAction(QPixmap(":/editcut.png"), tr("Cu&t", "Edit menu"), this);
1366     a->setShortcut(Qt::CTRL + Qt::Key_X);
1367     a->setEnabled(false);
1368     a->setShortcutContext(Qt::WidgetShortcut);
1369     editMenu->addAction(a);
1370     restrictedMapActions.append(a);
1371     mapEditorActions.append(a);
1372     restrictedMapActions.append(a);
1373     switchboard.addSwitch("mapCut", shortcutScope, a, tag);
1374     connect(a, SIGNAL(triggered()), this, SLOT(editCut()));
1375     addAction(a);
1376     actionCut = a;
1377
1378     a = new QAction(QPixmap(":/editpaste.png"), tr("&Paste", "Edit menu"),
1379                     this);
1380     connect(a, SIGNAL(triggered()), this, SLOT(editPaste()));
1381     a->setShortcut(Qt::CTRL + Qt::Key_V);
1382     a->setShortcutContext(Qt::WidgetShortcut);
1383     a->setEnabled(false);
1384     editMenu->addAction(a);
1385     restrictedMapActions.append(a);
1386     mapEditorActions.append(a);
1387     switchboard.addSwitch("mapPaste", shortcutScope, a, tag);
1388     actionPaste = a;
1389
1390     // Shortcut to delete selection
1391     a = new QAction(tr("Delete Selection", "Edit menu"), this);
1392     a->setShortcut(Qt::Key_Delete);
1393     a->setShortcutContext(Qt::WindowShortcut);
1394     switchboard.addSwitch("mapDelete", shortcutScope, a, tag);
1395     addAction(a);
1396     editMenu->addAction(a);
1397     actionListItems.append(a);
1398     actionDelete = a;
1399
1400     connect(a, SIGNAL(triggered()), this, SLOT(editDeleteSelection()));
1401     a = new QAction(tr("Delete Selection", "Edit menu"), this);
1402     a->setShortcut(Qt::Key_D);
1403     a->setShortcutContext(Qt::WindowShortcut);
1404     switchboard.addSwitch("mapDelete", shortcutScope, a, tag);
1405     addAction(a);
1406     connect(a, SIGNAL(triggered()), this, SLOT(editDeleteSelection()));
1407     editMenu->addAction(a);
1408     actionListItems.append(a);
1409     actionDeleteAlt = a;
1410
1411     // Shortcut to add attribute
1412     a = new QAction(tr("Add attribute") + " (test)", this);
1413     if (settings.value("/mainwindow/showTestMenu", false).toBool()) {
1414         a->setShortcutContext(Qt::WindowShortcut);
1415         switchboard.addSwitch("mapAddAttribute", shortcutScope, a, tag);
1416         connect(a, SIGNAL(triggered()), this, SLOT(editAddAttribute()));
1417         editMenu->addAction(a);
1418     }
1419     actionAddAttribute = a;
1420
1421     // Shortcut to add mapcenter
1422     a = new QAction(QPixmap(":/newmapcenter.png"),
1423                     tr("Add mapcenter", "Canvas context menu"), this);
1424     a->setShortcut(Qt::Key_C);
1425     a->setShortcutContext(Qt::WindowShortcut);
1426     switchboard.addSwitch("mapAddCenter", shortcutScope, a, tag);
1427     connect(a, SIGNAL(triggered()), this, SLOT(editAddMapCenter()));
1428     editMenu->addAction(a);
1429     actionListFiles.append(a);
1430     actionAddMapCenter = a;
1431
1432     // Shortcut to add branch
1433     a = new QAction(QPixmap(":/newbranch.png"),
1434                     tr("Add branch as child", "Edit menu"), this);
1435     switchboard.addSwitch("mapEditNewBranch", shortcutScope, a, tag);
1436     connect(a, SIGNAL(triggered()), this, SLOT(editNewBranch()));
1437     cloneActionMapEditor(a, Qt::Key_A);
1438     taskEditorActions.append(a);
1439     actionListBranches.append(a);
1440     actionAddBranch = a;
1441
1442     // Add branch by inserting it at selection
1443     a = new QAction(tr("Add branch (insert)", "Edit menu"), this);
1444     switchboard.addSwitch("mapEditAddBranchBefore", shortcutScope, a, tag);
1445     connect(a, SIGNAL(triggered()), this, SLOT(editNewBranchBefore()));
1446     editMenu->addAction(a);
1447     actionListBranches.append(a);
1448     actionAddBranchBefore = a;
1449
1450     // Add branch above
1451     a = new QAction(tr("Add branch above", "Edit menu"), this);
1452     a->setShortcut(Qt::SHIFT + Qt::Key_Insert);
1453     a->setShortcutContext(Qt::WindowShortcut);
1454     switchboard.addSwitch("mapEditAddBranchAbove", shortcutScope, a, tag);
1455     addAction(a);
1456     connect(a, SIGNAL(triggered()), this, SLOT(editNewBranchAbove()));
1457     a->setEnabled(false);
1458     actionListBranches.append(a);
1459     actionAddBranchAbove = a;
1460
1461     a = new QAction(tr("Add branch above", "Edit menu"), this);
1462     a->setShortcut(Qt::SHIFT + Qt::Key_A);
1463     a->setShortcutContext(Qt::WindowShortcut);
1464     switchboard.addSwitch("mapEditAddBranchAboveAlt", shortcutScope, a, tag);
1465     addAction(a);
1466     connect(a, SIGNAL(triggered()), this, SLOT(editNewBranchAbove()));
1467     actionListBranches.append(a);
1468     editMenu->addAction(a);
1469
1470     // Add branch below
1471     a = new QAction(tr("Add branch below", "Edit menu"), this);
1472     a->setShortcut(Qt::CTRL + Qt::Key_Insert);
1473     a->setShortcutContext(Qt::WindowShortcut);
1474     switchboard.addSwitch("mapEditAddBranchBelow", shortcutScope, a, tag);
1475     addAction(a);
1476     connect(a, SIGNAL(triggered()), this, SLOT(editNewBranchBelow()));
1477     a->setEnabled(false);
1478     actionListBranches.append(a);
1479
1480     a = new QAction(tr("Add branch below", "Edit menu"), this);
1481     a->setShortcut(Qt::CTRL + Qt::Key_A);
1482     a->setShortcutContext(Qt::WindowShortcut);
1483     switchboard.addSwitch("mapEditAddBranchBelowAlt", shortcutScope, a, tag);
1484     addAction(a);
1485     connect(a, SIGNAL(triggered()), this, SLOT(editNewBranchBelow()));
1486     actionListBranches.append(a);
1487     actionAddBranchBelow = a;
1488
1489     a = new QAction(QPixmap(":/up.png"), tr("Move branch up", "Edit menu"),
1490                     this);
1491     a->setShortcut(Qt::Key_PageUp);
1492     a->setShortcutContext(Qt::WidgetShortcut);
1493     mapEditorActions.append(a);
1494     taskEditorActions.append(a);
1495     restrictedMapActions.append(a);
1496     actionListBranches.append(a);
1497     editMenu->addAction(a);
1498     switchboard.addSwitch("mapEditMoveBranchUp", shortcutScope, a, tag);
1499     connect(a, SIGNAL(triggered()), this, SLOT(editMoveUp()));
1500     actionMoveUp = a;
1501
1502     a = new QAction(QPixmap(":/down.png"), tr("Move branch down", "Edit menu"),
1503                     this);
1504     a->setShortcut(Qt::Key_PageDown);
1505     a->setShortcutContext(Qt::WidgetShortcut);
1506     mapEditorActions.append(a);
1507     taskEditorActions.append(a);
1508     restrictedMapActions.append(a);
1509     actionListBranches.append(a);
1510     editMenu->addAction(a);
1511     switchboard.addSwitch("mapEditMoveBranchDown", shortcutScope, a, tag);
1512     connect(a, SIGNAL(triggered()), this, SLOT(editMoveDown()));
1513     actionMoveDown = a;
1514
1515     a = new QAction(QPixmap(":up-diagonal-right.png"), tr("Move branch diagonally up", "Edit menu"),
1516                     this);
1517     a->setShortcut(Qt::CTRL + Qt::Key_PageUp);
1518     a->setShortcutContext(Qt::WidgetShortcut);
1519     mapEditorActions.append(a);
1520     taskEditorActions.append(a);
1521     restrictedMapActions.append(a);
1522     actionListBranches.append(a);
1523     editMenu->addAction(a);
1524     switchboard.addSwitch("mapEditMoveBranchUpDiagonally", shortcutScope, a, tag);
1525     connect(a, SIGNAL(triggered()), this, SLOT(editMoveUpDiagonally()));
1526     actionMoveUpDiagonally = a;
1527
1528     a = new QAction(QPixmap(":down-diagonal-left.png"), tr("Move branch diagonally down", "Edit menu"),
1529                     this);
1530     a->setShortcut(Qt::CTRL + Qt::Key_PageDown);
1531     a->setShortcutContext(Qt::WidgetShortcut);
1532     mapEditorActions.append(a);
1533     taskEditorActions.append(a);
1534     restrictedMapActions.append(a);
1535     actionListBranches.append(a);
1536     editMenu->addAction(a);
1537     switchboard.addSwitch("mapEditMoveBranchDownDiagonally", shortcutScope, a, tag);
1538     connect(a, SIGNAL(triggered()), this, SLOT(editMoveDownDiagonally()));
1539     actionMoveDownDiagonally = a;
1540
1541     a = new QAction(QPixmap(), tr("&Detach", "Context menu"), this);
1542     a->setStatusTip(tr("Detach branch and use as mapcenter", "Context menu"));
1543     a->setShortcut(Qt::Key_D + Qt::SHIFT);
1544     switchboard.addSwitch("mapDetachBranch", shortcutScope, a, tag);
1545     connect(a, SIGNAL(triggered()), this, SLOT(editDetach()));
1546     editMenu->addAction(a);
1547     actionListBranches.append(a);
1548     actionDetach = a;
1549
1550     a = new QAction(QPixmap(":/editsort.png"), tr("Sort children", "Edit menu"),
1551                     this);
1552     a->setEnabled(true);
1553     a->setShortcut(Qt::Key_O);
1554     switchboard.addSwitch("mapSortBranches", shortcutScope, a, tag);
1555     connect(a, SIGNAL(triggered()), this, SLOT(editSortChildren()));
1556     editMenu->addAction(a);
1557     actionListBranches.append(a);
1558     actionSortChildren = a;
1559
1560     a = new QAction(QPixmap(":/editsortback.png"),
1561                     tr("Sort children backwards", "Edit menu"), this);
1562     a->setEnabled(true);
1563     a->setShortcut(Qt::SHIFT + Qt::Key_O);
1564     switchboard.addSwitch("mapSortBranchesReverse", shortcutScope, a, tag);
1565     connect(a, SIGNAL(triggered()), this, SLOT(editSortBackChildren()));
1566     editMenu->addAction(a);
1567     actionListBranches.append(a);
1568     actionSortBackChildren = a;
1569
1570     a = new QAction(QPixmap(":/flag-scrolled-right.png"),
1571                     tr("Scroll branch", "Edit menu"), this);
1572     a->setShortcut(Qt::Key_S);
1573     switchboard.addSwitch("mapToggleScroll", shortcutScope, a, tag);
1574     connect(a, SIGNAL(triggered()), this, SLOT(editToggleScroll()));
1575     editMenu->addAction(a);
1576     actionListBranches.append(a);
1577     a->setEnabled(false);
1578     a->setCheckable(true);
1579     addAction(a);
1580     actionListBranches.append(a);
1581     actionToggleScroll = a;
1582
1583     a = new QAction(tr("Unscroll children", "Edit menu"), this);
1584     editMenu->addAction(a);
1585     connect(a, SIGNAL(triggered()), this, SLOT(editUnscrollChildren()));
1586     actionListBranches.append(a);
1587
1588     a = new QAction(tr("Grow selection", "Edit menu"), this);
1589     a->setShortcut(Qt::CTRL + Qt::Key_Plus);
1590     switchboard.addSwitch("mapGrowSelection", shortcutScope, a, tag);
1591     connect(a, SIGNAL(triggered()), this, SLOT(editGrowSelectionSize()));
1592     editMenu->addAction(a);
1593     actionListBranches.append(a);
1594     actionListItems.append(a);
1595     actionGrowSelectionSize = a;
1596
1597     a = new QAction(tr("Shrink selection", "Edit menu"), this);
1598     a->setShortcut(Qt::CTRL + Qt::Key_Minus);
1599     switchboard.addSwitch("mapShrinkSelection", shortcutScope, a, tag);
1600     connect(a, SIGNAL(triggered()), this, SLOT(editShrinkSelectionSize()));
1601     editMenu->addAction(a);
1602     actionListBranches.append(a);
1603     actionListItems.append(a);
1604     actionShrinkSelectionSize = a;
1605
1606     a = new QAction(tr("Reset selection size", "Edit menu"), this);
1607     a->setShortcut(Qt::CTRL + Qt::Key_0);
1608     switchboard.addSwitch("mapResetSelectionSize", shortcutScope, a, tag);
1609     connect(a, SIGNAL(triggered()), this, SLOT(editResetSelectionSize()));
1610     editMenu->addAction(a);
1611     actionListBranches.append(a);
1612     actionListItems.append(a);
1613     actionResetSelectionSize = a;
1614
1615     editMenu->addSeparator();
1616
1617     a = new QAction(QPixmap(), "TE: " + tr("Collapse one level", "Edit menu"),
1618                     this);
1619     a->setShortcut(Qt::Key_Less + Qt::CTRL);
1620     switchboard.addSwitch("mapCollapseOneLevel", shortcutScope, a, tag);
1621     connect(a, SIGNAL(triggered()), this, SLOT(editCollapseOneLevel()));
1622     editMenu->addAction(a);
1623     a->setEnabled(false);
1624     a->setCheckable(false);
1625     actionListBranches.append(a);
1626     addAction(a);
1627     actionCollapseOneLevel = a;
1628
1629     a = new QAction(QPixmap(),
1630                     "TE: " + tr("Collapse unselected levels", "Edit menu"),
1631                     this);
1632     a->setShortcut(Qt::Key_Less);
1633     switchboard.addSwitch("mapCollapseUnselectedLevels", shortcutScope, a, tag);
1634     connect(a, SIGNAL(triggered()), this, SLOT(editCollapseUnselected()));
1635     editMenu->addAction(a);
1636     a->setEnabled(false);
1637     a->setCheckable(false);
1638     actionListBranches.append(a);
1639     addAction(a);
1640     actionCollapseUnselected = a;
1641
1642     a = new QAction(QPixmap(), tr("Expand all branches", "Edit menu"), this);
1643     connect(a, SIGNAL(triggered()), this, SLOT(editExpandAll()));
1644     actionExpandAll = a;
1645     actionExpandAll->setEnabled(false);
1646     actionExpandAll->setCheckable(false);
1647     actionListBranches.append(actionExpandAll);
1648     addAction(a);
1649
1650     a = new QAction(QPixmap(), tr("Expand one level", "Edit menu"), this);
1651     a->setShortcut(Qt::Key_Greater);
1652     switchboard.addSwitch("mapExpandOneLevel", shortcutScope, a, tag);
1653     connect(a, SIGNAL(triggered()), this, SLOT(editExpandOneLevel()));
1654     a->setEnabled(false);
1655     a->setCheckable(false);
1656     addAction(a);
1657     actionListBranches.append(a);
1658     actionExpandOneLevel = a;
1659
1660     tag = tr("References Context menu", "Shortcuts");
1661     a = new QAction(QPixmap(":/flag-url.svg"), tr("Open URL", "Edit menu"),
1662                     this);
1663     a->setShortcut(Qt::SHIFT + Qt::Key_U);
1664     switchboard.addSwitch("mapOpenUrl", shortcutScope, a, tag);
1665     addAction(a);
1666     connect(a, SIGNAL(triggered()), this, SLOT(editOpenURL()));
1667     actionListBranches.append(a);
1668     actionOpenURL = a;
1669
1670     a = new QAction(tr("Open URL in new tab", "Edit menu"), this);
1671     // a->setShortcut (Qt::CTRL+Qt::Key_U );
1672     switchboard.addSwitch("mapOpenUrlTab", shortcutScope, a, tag);
1673     addAction(a);
1674     connect(a, SIGNAL(triggered()), this, SLOT(editOpenURLTab()));
1675     actionListBranches.append(a);
1676     actionOpenURLTab = a;
1677
1678     a = new QAction(tr("Open all URLs in subtree (including scrolled branches)",
1679                        "Edit menu"),
1680                     this);
1681     a->setShortcut(Qt::CTRL + Qt::Key_U);
1682     switchboard.addSwitch("mapOpenUrlsSubTree", shortcutScope, a, tag);
1683     addAction(a);
1684     connect(a, SIGNAL(triggered()), this, SLOT(editOpenMultipleVisURLTabs()));
1685     actionListBranches.append(a);
1686     actionOpenMultipleVisURLTabs = a;
1687
1688     a = new QAction(tr("Open all URLs in subtree", "Edit menu"), this);
1689     switchboard.addSwitch("mapOpenMultipleUrlTabs", shortcutScope, a, tag);
1690     addAction(a);
1691     connect(a, SIGNAL(triggered()), this, SLOT(editOpenMultipleURLTabs()));
1692     actionListBranches.append(a);
1693     actionOpenMultipleURLTabs = a;
1694
1695     a = new QAction(QPixmap(), tr("Extract URLs from note", "Edit menu"), this);
1696     a->setShortcut(Qt::SHIFT + Qt::Key_N);
1697     a->setShortcutContext(Qt::WindowShortcut);
1698     switchboard.addSwitch("mapUrlsFromNote", shortcutScope, a, tag);
1699     addAction(a);
1700     connect(a, SIGNAL(triggered()), this, SLOT(editNote2URLs()));
1701     actionListBranches.append(a);
1702     actionGetURLsFromNote = a;
1703
1704     a = new QAction(QPixmap(":/flag-urlnew.svg"),
1705                     tr("Edit URL...", "Edit menu"), this);
1706     a->setShortcut(Qt::Key_U);
1707     a->setShortcutContext(Qt::WindowShortcut);
1708     switchboard.addSwitch("mapEditURL", shortcutScope, a, tag);
1709     addAction(a);
1710     connect(a, SIGNAL(triggered()), this, SLOT(editURL()));
1711     actionListBranches.append(a);
1712     actionURLNew = a;
1713
1714     a = new QAction(QPixmap(), tr("Edit local URL...", "Edit menu"), this);
1715     // a->setShortcut (Qt::SHIFT +  Qt::Key_U );
1716     a->setShortcutContext(Qt::WindowShortcut);
1717     switchboard.addSwitch("mapEditLocalURL", shortcutScope, a, tag);
1718     addAction(a);
1719     connect(a, SIGNAL(triggered()), this, SLOT(editLocalURL()));
1720     actionListBranches.append(a);
1721     actionLocalURL = a;
1722
1723     a = new QAction(tr("Use heading for URL", "Edit menu"), this);
1724     //a->setShortcut(Qt::ALT + Qt::Key_U);
1725     a->setShortcutContext(Qt::ApplicationShortcut);
1726     a->setEnabled(false);
1727     switchboard.addSwitch("mapHeading2URL", shortcutScope, a, tag);
1728     addAction(a);
1729     connect(a, SIGNAL(triggered()), this, SLOT(editHeading2URL()));
1730     actionListBranches.append(a);
1731     actionHeading2URL = a;
1732
1733     tag = "JIRA";
1734     a = new QAction(tr("Get data from JIRA for subtree", "Edit menu"),
1735                     this);
1736     a->setShortcut(Qt::Key_J + Qt::SHIFT);
1737     a->setShortcutContext(Qt::WindowShortcut);
1738     switchboard.addSwitch("mapUpdateSubTreeFromJira", shortcutScope, a, tag);
1739     addAction(a);
1740     connect(a, SIGNAL(triggered()), this, SLOT(getJiraDataSubtree()));
1741     actionGetJiraDataSubtree = a;
1742
1743     a = new QAction(tr("Get page name from Confluence", "Edit menu"),
1744                     this);
1745     //    a->setShortcut ( Qt::Key_J + Qt::CTRL);
1746     //    a->setShortcutContext (Qt::WindowShortcut);
1747     //    switchboard.addSwitch ("mapUpdateSubTreeFromJira", shortcutScope, a,
1748     //    tag);
1749     addAction(a);
1750     connect(a, SIGNAL(triggered()), this, SLOT(setHeadingConfluencePageName()));
1751     actionListBranches.append(a);
1752     actionGetConfluencePageName = a;
1753
1754     tag = tr("vymlinks - linking maps", "Shortcuts");
1755     a = new QAction(QPixmap(":/flag-vymlink.png"),
1756                     tr("Open linked map", "Edit menu"), this);
1757     a->setShortcut(Qt::SHIFT + Qt::Key_V);
1758     a->setEnabled(false);
1759     switchboard.addSwitch("mapOpenVymLink", shortcutScope, a, tag);
1760     addAction(a);
1761     connect(a, SIGNAL(triggered()), this, SLOT(editOpenVymLink()));
1762     actionListBranches.append(a);
1763     actionOpenVymLink = a;
1764
1765     a = new QAction(QPixmap(":/flag-vymlink.png"),
1766                     tr("Open linked map in background tab", "Edit menu"), this);
1767     a->setEnabled(false);
1768     switchboard.addSwitch("mapOpenVymLink", shortcutScope, a, tag);
1769     connect(a, SIGNAL(triggered()), this, SLOT(editOpenVymLinkBackground()));
1770     actionListBranches.append(a);
1771     actionOpenVymLinkBackground = a;
1772
1773     a = new QAction(QPixmap(), tr("Open all vym links in subtree", "Edit menu"),
1774                     this);
1775     a->setEnabled(false);
1776     switchboard.addSwitch("mapOpenMultipleVymLinks", shortcutScope, a, tag);
1777     connect(a, SIGNAL(triggered()), this, SLOT(editOpenMultipleVymLinks()));
1778     actionListBranches.append(a);
1779     actionOpenMultipleVymLinks = a;
1780
1781     a = new QAction(QPixmap(":/flag-vymlinknew.png"),
1782                     tr("Edit vym link...", "Edit menu"), this);
1783     a->setShortcut(Qt::Key_V);
1784     a->setShortcutContext(Qt::WindowShortcut);
1785     a->setEnabled(false);
1786     switchboard.addSwitch("mapEditVymLink", shortcutScope, a, tag);
1787     connect(a, SIGNAL(triggered()), this, SLOT(editVymLink()));
1788     actionListBranches.append(a);
1789     actionEditVymLink = a;
1790
1791     a = new QAction(tr("Delete vym link", "Edit menu"), this);
1792     a->setEnabled(false);
1793     switchboard.addSwitch("mapDeleteVymLink", shortcutScope, a, tag);
1794     connect(a, SIGNAL(triggered()), this, SLOT(editDeleteVymLink()));
1795     actionListBranches.append(a);
1796     actionDeleteVymLink = a;
1797
1798     tag = tr("Exports", "Shortcuts");
1799     a = new QAction(QPixmap(":/flag-hideexport.png"),
1800                     tr("Hide in exports", "Edit menu"), this);
1801     a->setShortcut(Qt::Key_H);
1802     a->setShortcutContext(Qt::WindowShortcut);
1803     a->setCheckable(true);
1804     a->setEnabled(false);
1805     addAction(a);
1806     switchboard.addSwitch("mapToggleHideExport", shortcutScope, a, tag);
1807     connect(a, SIGNAL(triggered()), this, SLOT(editToggleHideExport()));
1808     actionListItems.append(a);
1809     actionToggleHideExport = a;
1810
1811     tag = tr("Tasks", "Shortcuts");
1812     a = new QAction(QPixmap(":/taskeditor.png"), tr("Toggle task", "Edit menu"),
1813                     this);
1814     a->setShortcut(Qt::Key_W + Qt::SHIFT);
1815     a->setShortcutContext(Qt::WindowShortcut);
1816     a->setCheckable(true);
1817     a->setEnabled(false);
1818     addAction(a);
1819     switchboard.addSwitch("mapToggleTask", shortcutScope, a, tag);
1820     connect(a, SIGNAL(triggered()), this, SLOT(editToggleTask()));
1821     actionListBranches.append(a);
1822     actionToggleTask = a;
1823
1824     a = new QAction(QPixmap(), tr("Cycle task status", "Edit menu"), this);
1825     a->setShortcut(Qt::Key_W);
1826     a->setShortcutContext(Qt::WindowShortcut);
1827     a->setCheckable(false);
1828     a->setEnabled(false);
1829     addAction(a);
1830     switchboard.addSwitch("mapCycleTaskStatus", shortcutScope, a, tag);
1831     connect(a, SIGNAL(triggered()), this, SLOT(editCycleTaskStatus()));
1832     actionListBranches.append(a);
1833     actionCycleTaskStatus = a;
1834
1835     a = new QAction(QPixmap(), tr("Reset delta priority for visible tasks", "Reset delta"), this);
1836     a->setShortcutContext(Qt::WindowShortcut);
1837     a->setCheckable(false);
1838     a->setEnabled(false);
1839     addAction(a);
1840     switchboard.addSwitch("mapResetTaskDeltaPrio", shortcutScope, a, tag);
1841     connect(a, SIGNAL(triggered()), this, SLOT(editTaskResetDeltaPrio()));
1842     actionListBranches.append(a);
1843     actionTaskResetDeltaPrio = a;
1844
1845     a = new QAction(QPixmap(), tr("Reset sleep", "Task sleep"), this);
1846     a->setShortcutContext(Qt::WindowShortcut);
1847     a->setCheckable(false);
1848     a->setEnabled(false);
1849     a->setData(0);
1850     addAction(a);
1851     switchboard.addSwitch("mapResetSleep", shortcutScope, a, tag);
1852     connect(a, SIGNAL(triggered()), this, SLOT(editTaskSleepN()));
1853     actionListBranches.append(a);
1854     actionTaskSleep0 = a;
1855
1856     a = new QAction(QPixmap(),
1857                     tr("Sleep %1 days", "Task sleep").arg("n") + "...", this);
1858     a->setShortcutContext(Qt::WindowShortcut);
1859     a->setShortcut(Qt::Key_Q + Qt::SHIFT);
1860     a->setCheckable(false);
1861     a->setEnabled(false);
1862     a->setData(-1);
1863     addAction(a);
1864     switchboard.addSwitch("mapTaskSleepN", shortcutScope, a, tag);
1865     connect(a, SIGNAL(triggered()), this, SLOT(editTaskSleepN()));
1866     actionListBranches.append(a);
1867     actionTaskSleepN = a;
1868
1869     a = new QAction(QPixmap(), tr("Sleep %1 day", "Task sleep").arg(1), this);
1870     a->setShortcutContext(Qt::WindowShortcut);
1871     a->setCheckable(false);
1872     a->setEnabled(false);
1873     a->setData(1);
1874     addAction(a);
1875     switchboard.addSwitch("mapTaskSleep1", shortcutScope, a, tag);
1876     connect(a, SIGNAL(triggered()), this, SLOT(editTaskSleepN()));
1877     actionListBranches.append(a);
1878     actionTaskSleep1 = a;
1879
1880     a = new QAction(QPixmap(), tr("Sleep %1 days", "Task sleep").arg(2), this);
1881     a->setShortcutContext(Qt::WindowShortcut);
1882     a->setCheckable(false);
1883     a->setEnabled(false);
1884     a->setData(2);
1885     addAction(a);
1886     switchboard.addSwitch("mapTaskSleep2", shortcutScope, a, tag);
1887     connect(a, SIGNAL(triggered()), this, SLOT(editTaskSleepN()));
1888     actionListBranches.append(a);
1889     actionTaskSleep2 = a;
1890
1891     a = new QAction(QPixmap(), tr("Sleep %1 days", "Task sleep").arg(3), this);
1892     a->setShortcutContext(Qt::WindowShortcut);
1893     a->setCheckable(false);
1894     a->setEnabled(false);
1895     a->setData(3);
1896     addAction(a);
1897     switchboard.addSwitch("mapTaskSleep3", shortcutScope, a, tag);
1898     connect(a, SIGNAL(triggered()), this, SLOT(editTaskSleepN()));
1899     actionListBranches.append(a);
1900     actionTaskSleep3 = a;
1901
1902     a = new QAction(QPixmap(), tr("Sleep %1 days", "Task sleep").arg(4), this);
1903     a->setShortcutContext(Qt::WindowShortcut);
1904     a->setCheckable(false);
1905     a->setEnabled(false);
1906     a->setData(4);
1907     addAction(a);
1908     switchboard.addSwitch("mapTaskSleep4", shortcutScope, a, tag);
1909     connect(a, SIGNAL(triggered()), this, SLOT(editTaskSleepN()));
1910     actionListBranches.append(a);
1911     actionTaskSleep4 = a;
1912
1913     a = new QAction(QPixmap(), tr("Sleep %1 days", "Task sleep").arg(5), this);
1914     a->setShortcutContext(Qt::WindowShortcut);
1915     a->setCheckable(false);
1916     a->setEnabled(false);
1917     a->setData(5);
1918     addAction(a);
1919     switchboard.addSwitch("mapTaskSleep5", shortcutScope, a, tag);
1920     connect(a, SIGNAL(triggered()), this, SLOT(editTaskSleepN()));
1921     actionListBranches.append(a);
1922     actionTaskSleep5 = a;
1923
1924     a = new QAction(QPixmap(), tr("Sleep %1 days", "Task sleep").arg(7), this);
1925     a->setShortcutContext(Qt::WindowShortcut);
1926     a->setCheckable(false);
1927     a->setEnabled(false);
1928     a->setData(7);
1929     addAction(a);
1930     switchboard.addSwitch("mapTaskSleep7", shortcutScope, a, tag);
1931     connect(a, SIGNAL(triggered()), this, SLOT(editTaskSleepN()));
1932     actionListBranches.append(a);
1933     actionTaskSleep7 = a;
1934
1935     a = new QAction(QPixmap(), tr("Sleep %1 weeks", "Task sleep").arg(2), this);
1936     a->setShortcutContext(Qt::WindowShortcut);
1937     a->setCheckable(false);
1938     a->setEnabled(false);
1939     a->setData(14);
1940     addAction(a);
1941     switchboard.addSwitch("mapTaskSleep14", shortcutScope, a, tag);
1942     connect(a, SIGNAL(triggered()), this, SLOT(editTaskSleepN()));
1943     actionListBranches.append(a);
1944     actionTaskSleep14 = a;
1945
1946     a = new QAction(QPixmap(), tr("Sleep %1 weeks", "Task sleep").arg(4), this);
1947     a->setShortcutContext(Qt::WindowShortcut);
1948     a->setCheckable(false);
1949     a->setEnabled(false);
1950     a->setData(28);
1951     addAction(a);
1952     switchboard.addSwitch("mapTaskSleep28", shortcutScope, a, tag);
1953     connect(a, SIGNAL(triggered()), this, SLOT(editTaskSleepN()));
1954     actionListBranches.append(a);
1955     actionTaskSleep28 = a;
1956
1957     // Import at selection (adding to selection)
1958     a = new QAction(tr("Add map (insert)", "Edit menu"), this);
1959     connect(a, SIGNAL(triggered()), this, SLOT(editImportAdd()));
1960     a->setEnabled(false);
1961     actionListBranches.append(a);
1962     actionImportAdd = a;
1963
1964     // Import at selection (replacing selection)
1965     a = new QAction(tr("Add map (replace)", "Edit menu"), this);
1966     connect(a, SIGNAL(triggered()), this, SLOT(editImportReplace()));
1967     a->setEnabled(false);
1968     actionListBranches.append(a);
1969     actionImportReplace = a;
1970
1971     // Save selection
1972     a = new QAction(tr("Save selection", "Edit menu"), this);
1973     connect(a, SIGNAL(triggered()), this, SLOT(editSaveBranch()));
1974     a->setEnabled(false);
1975     actionListBranches.append(a);
1976     actionSaveBranch = a;
1977
1978     tag = tr("Removing parts of a map", "Shortcuts");
1979
1980     // Only remove branch, not its children
1981     a = new QAction(
1982         tr("Remove only branch and keep its children ", "Edit menu"), this);
1983     a->setShortcut(Qt::CTRL + Qt::SHIFT + Qt::Key_X);
1984     connect(a, SIGNAL(triggered()), this, SLOT(editDeleteKeepChildren()));
1985     a->setEnabled(false);
1986     addAction(a);
1987     switchboard.addSwitch("mapDeleteKeepChildren", shortcutScope, a, tag);
1988     actionListBranches.append(a);
1989     actionDeleteKeepChildren = a;
1990
1991     // Only remove children of a branch
1992     a = new QAction(tr("Remove children", "Edit menu"), this);
1993     a->setShortcut(Qt::SHIFT + Qt::Key_X);
1994     addAction(a);
1995     switchboard.addSwitch("mapDeleteChildren", shortcutScope, a, tag);
1996     connect(a, SIGNAL(triggered()), this, SLOT(editDeleteChildren()));
1997     a->setEnabled(false);
1998     addAction(a);
1999     actionListBranches.append(a);
2000     actionDeleteChildren = a;
2001
2002     tag = tr("Various", "Shortcuts");
2003     a = new QAction(tr("Add timestamp", "Edit menu"), this);
2004     a->setEnabled(false);
2005     actionListBranches.append(a);
2006     a->setShortcut(Qt::Key_T);
2007     a->setShortcutContext(Qt::WindowShortcut);
2008     addAction(a);
2009     switchboard.addSwitch("mapAddTimestamp", shortcutScope, a, tag);
2010     connect(a, SIGNAL(triggered()), this, SLOT(editAddTimestamp()));
2011     actionListBranches.append(a);
2012     actionAddTimestamp = a;
2013
2014     a = new QAction(tr("Map properties...", "Edit menu"), this);
2015     a->setEnabled(true);
2016     connect(a, SIGNAL(triggered()), this, SLOT(editMapProperties()));
2017     actionListFiles.append(a);
2018     actionMapInfo = a;
2019
2020     a = new QAction(tr("Add image...", "Edit menu"), this);
2021     a->setShortcutContext(Qt::WindowShortcut);
2022     a->setShortcut(Qt::Key_I + Qt::SHIFT);
2023     addAction(a);
2024     switchboard.addSwitch("mapLoadImage", shortcutScope, a, tag);
2025     connect(a, SIGNAL(triggered()), this, SLOT(editLoadImage()));
2026     actionLoadImage = a;
2027
2028     a = new QAction(
2029         tr("Property window", "Dialog to edit properties of selection") +
2030             QString("..."),
2031         this);
2032     a->setShortcut(Qt::Key_P);
2033     a->setShortcutContext(Qt::WindowShortcut);
2034     a->setCheckable(true);
2035     addAction(a);
2036     switchboard.addSwitch("mapTogglePropertEditor", shortcutScope, a, tag);
2037     connect(a, SIGNAL(triggered()), this, SLOT(windowToggleProperty()));
2038     actionViewTogglePropertyEditor = a;
2039 }
2040
2041 // Select Actions
2042 void Main::setupSelectActions()
2043 {
2044     QString tag = tr("Selections", "Shortcuts");
2045     QMenu *selectMenu = menuBar()->addMenu(tr("Select", "Select menu"));
2046     QAction *a;
2047     a = new QAction(QPixmap(":/flag-target.svg"),
2048                     tr("Toggle target...", "Edit menu"), this);
2049     a->setShortcut(Qt::SHIFT + Qt::Key_T);
2050     a->setCheckable(true);
2051     selectMenu->addAction(a);
2052     switchboard.addSwitch("mapToggleTarget", shortcutScope, a, tag);
2053     connect(a, SIGNAL(triggered()), this, SLOT(editToggleTarget()));
2054     actionListBranches.append(a);
2055     actionToggleTarget = a;
2056
2057     a = new QAction(QPixmap(":/flag-target.svg"),
2058                     tr("Goto target...", "Edit menu"), this);
2059     a->setShortcut(Qt::Key_G);
2060     selectMenu->addAction(a);
2061     switchboard.addSwitch("mapGotoTarget", shortcutScope, a, tag);
2062     connect(a, SIGNAL(triggered()), this, SLOT(editGoToTarget()));
2063     actionListBranches.append(a);
2064     actionGoToTarget = a;
2065
2066     a = new QAction(QPixmap(":/flag-target.svg"),
2067                     tr("Move to target...", "Edit menu"), this);
2068     a->setShortcut(Qt::Key_M);
2069     selectMenu->addAction(a);
2070     switchboard.addSwitch("mapMoveToTarget", shortcutScope, a, tag);
2071     connect(a, SIGNAL(triggered()), this, SLOT(editMoveToTarget()));
2072     actionListBranches.append(a);
2073     actionMoveToTarget = a;
2074
2075     a = new QAction(QPixmap(":/flag-vymlink.png"),
2076                     tr("Goto linked map...", "Edit menu"), this);
2077     a->setShortcut(Qt::Key_G + Qt::SHIFT);
2078     selectMenu->addAction(a);
2079     switchboard.addSwitch("gotoLinkedMap", shortcutScope, a, tag);
2080     connect(a, SIGNAL(triggered()), this, SLOT(editGoToLinkedMap()));
2081     actionListBranches.append(a);
2082     actionGoToTargetLinkedMap = a;
2083
2084     a = new QAction(QPixmap(":/selectprevious.png"),
2085                     tr("Select previous", "Edit menu"), this);
2086     a->setShortcut(Qt::CTRL + Qt::Key_O);
2087     a->setShortcutContext(Qt::WidgetShortcut);
2088     selectMenu->addAction(a);
2089     actionListFiles.append(a);
2090     mapEditorActions.append(a);
2091     switchboard.addSwitch("mapSelectPrevious", shortcutScope, a, tag);
2092     connect(a, SIGNAL(triggered()), this, SLOT(editSelectPrevious()));
2093     actionSelectPrevious = a;
2094
2095     a = new QAction(QPixmap(":/selectnext.png"), tr("Select next", "Edit menu"),
2096                     this);
2097     a->setShortcut(Qt::CTRL + Qt::Key_I);
2098     a->setShortcutContext(Qt::WidgetShortcut);
2099     selectMenu->addAction(a);
2100     actionListFiles.append(a);
2101     mapEditorActions.append(a);
2102     switchboard.addSwitch("mapSelectNext", shortcutScope, a, tag);
2103     connect(a, SIGNAL(triggered()), this, SLOT(editSelectNext()));
2104     actionSelectNext = a;
2105
2106     a = new QAction(tr("Unselect all", "Edit menu"), this);
2107     // a->setShortcut (Qt::CTRL + Qt::Key_I );
2108     selectMenu->addAction(a);
2109     switchboard.addSwitch("mapSelectNothing", shortcutScope, a, tag);
2110     connect(a, SIGNAL(triggered()), this, SLOT(editSelectNothing()));
2111     actionListFiles.append(a);
2112     actionSelectNothing = a;
2113
2114     tag = tr("Search functions", "Shortcuts");
2115     a = new QAction(QPixmap(":/find.png"), tr("Find...", "Edit menu"), this);
2116     a->setShortcut(Qt::CTRL + Qt::Key_F);
2117     selectMenu->addAction(a);
2118     switchboard.addSwitch("mapFind", shortcutScope, a, tag);
2119     connect(a, SIGNAL(triggered()), this, SLOT(editOpenFindResultWidget()));
2120     actionListFiles.append(a);
2121     actionFind = a;
2122
2123     a = new QAction(QPixmap(":/find.png"), tr("Find...", "Edit menu"), this);
2124     a->setShortcut(Qt::Key_Slash);
2125     selectMenu->addAction(a);
2126     switchboard.addSwitch("mapFindAlt", shortcutScope, a, tag);
2127     connect(a, SIGNAL(triggered()), this, SLOT(editOpenFindResultWidget()));
2128     actionListFiles.append(a);
2129
2130     a = new QAction(tr("Find duplicate URLs", "Edit menu") + " (test)", this);
2131     a->setShortcut(Qt::SHIFT + Qt::Key_F);
2132     switchboard.addSwitch("mapFindDuplicates", shortcutScope, a, tag);
2133     if (settings.value("/mainwindow/showTestMenu", false).toBool())
2134         selectMenu->addAction(a);
2135     connect(a, SIGNAL(triggered()), this, SLOT(editFindDuplicateURLs()));
2136 }
2137
2138 // Format Actions
2139 void Main::setupFormatActions()
2140 {
2141     QMenu *formatMenu = menuBar()->addMenu(tr("F&ormat", "Format menu"));
2142
2143     QString tag = tr("Formatting", "Shortcuts");
2144
2145     QAction* a;
2146
2147     a = new QAction(QPixmap(":/formatcolorpicker.png"),
2148                     tr("Pic&k color", "Edit menu"), this);
2149     // a->setShortcut (Qt::CTRL + Qt::Key_K );
2150     formatMenu->addAction(a);
2151     switchboard.addSwitch("mapFormatColorPicker", shortcutScope, a, tag);
2152     connect(a, SIGNAL(triggered()), this, SLOT(formatPickColor()));
2153     a->setEnabled(false);
2154     actionListBranches.append(a);
2155     actionFormatPickColor = a;
2156
2157     a = new QAction(QPixmap(":/formatcolorbranch.png"),
2158                     tr("Color &branch", "Edit menu"), this);
2159     // a->setShortcut (Qt::CTRL + Qt::Key_B + Qt::SHIFT);
2160     formatMenu->addAction(a);
2161     switchboard.addSwitch("mapFormatColorBranch", shortcutScope, a, tag);
2162     connect(a, SIGNAL(triggered()), this, SLOT(formatColorBranch()));
2163     a->setEnabled(false);
2164     actionListBranches.append(a);
2165     actionFormatColorBranch = a;
2166
2167     a = new QAction(QPixmap(":/formatcolorsubtree.png"),
2168                     tr("Color sub&tree", "Edit menu"), this);
2169     // a->setShortcut (Qt::CTRL + Qt::Key_B);   // Color subtree
2170     formatMenu->addAction(a);
2171     switchboard.addSwitch("mapFormatColorSubtree", shortcutScope, a, tag);
2172     connect(a, SIGNAL(triggered()), this, SLOT(formatColorSubtree()));
2173     a->setEnabled(false);
2174     actionListBranches.append(a);
2175     actionFormatColorSubtree = a;
2176
2177     formatMenu->addSeparator();
2178
2179     a = new QAction(tr("Select default font", "Branch attribute") + "...",
2180                     this);
2181     a->setCheckable(false);
2182     connect(a, SIGNAL(triggered()), this, SLOT(formatSelectFont()));
2183     formatMenu->addAction(a);
2184     actionFormatFont = a;
2185
2186     formatMenu->addSeparator();
2187
2188     actionGroupFormatLinkStyles = new QActionGroup(this);
2189     actionGroupFormatLinkStyles->setExclusive(true);
2190     a = new QAction(tr("Linkstyle Line"), actionGroupFormatLinkStyles);
2191     a->setCheckable(true);
2192     restrictedMapActions.append(a);
2193     formatMenu->addAction(a);
2194     connect(a, SIGNAL(triggered()), this, SLOT(formatLinkStyleLine()));
2195     actionFormatLinkStyleLine = a;
2196
2197     a = new QAction(tr("Linkstyle Curve"), actionGroupFormatLinkStyles);
2198     a->setCheckable(true);
2199     restrictedMapActions.append(a);
2200     formatMenu->addAction(a);
2201     connect(a, SIGNAL(triggered()), this, SLOT(formatLinkStyleParabel()));
2202     actionFormatLinkStyleParabel = a;
2203
2204     a = new QAction(tr("Linkstyle Thick Line"), actionGroupFormatLinkStyles);
2205     a->setCheckable(true);
2206     restrictedMapActions.append(a);
2207     formatMenu->addAction(a);
2208     connect(a, SIGNAL(triggered()), this, SLOT(formatLinkStylePolyLine()));
2209     actionFormatLinkStylePolyLine = a;
2210
2211     a = new QAction(tr("Linkstyle Thick Curve"), actionGroupFormatLinkStyles);
2212     a->setCheckable(true);
2213     a->setChecked(true);
2214     restrictedMapActions.append(a);
2215     formatMenu->addAction(a);
2216     formatMenu->addSeparator();
2217     connect(a, SIGNAL(triggered()), this, SLOT(formatLinkStylePolyParabel()));
2218     actionFormatLinkStylePolyParabel = a;
2219
2220     a = new QAction(
2221         tr("Hide link if object is not selected", "Branch attribute"), this);
2222     a->setCheckable(true);
2223     connect(a, SIGNAL(triggered()), this, SLOT(formatHideLinkUnselected()));
2224     actionListBranches.append(a);
2225     actionFormatHideLinkUnselected = a;
2226
2227     a = new QAction(tr("&Use color of heading for link", "Branch attribute"),
2228                     this);
2229     a->setCheckable(true);
2230     connect(a, SIGNAL(triggered()), this, SLOT(formatToggleLinkColorHint()));
2231     formatMenu->addAction(a);
2232     actionFormatLinkColorHint = a;
2233
2234     QPixmap pix(16, 16);
2235     pix.fill(Qt::white);
2236     a = new QAction(pix, tr("Set &Link Color") + "...", this);
2237     formatMenu->addAction(a);
2238     connect(a, SIGNAL(triggered()), this, SLOT(formatSelectLinkColor()));
2239     actionFormatLinkColor = a;
2240
2241     a = new QAction(pix, tr("Set &Selection Color") + "...", this);
2242     formatMenu->addAction(a);
2243     connect(a, SIGNAL(triggered()), this, SLOT(formatSelectSelectionColor()));
2244     actionFormatSelectionColor = a;
2245
2246     a = new QAction(pix, tr("Set &Background Color") + "...", this);
2247     formatMenu->addAction(a);
2248     connect(a, SIGNAL(triggered()), this, SLOT(formatSelectBackColor()));
2249     actionFormatBackColor = a;
2250
2251     a = new QAction(pix, tr("Set &Background image") + "...", this);
2252     formatMenu->addAction(a);
2253     connect(a, SIGNAL(triggered()), this, SLOT(formatSelectBackImage()));
2254     actionFormatBackImage = a;
2255 }
2256
2257 // View Actions
2258 void Main::setupViewActions()
2259 {
2260     QMenu *viewMenu = menuBar()->addMenu(tr("&View"));
2261     toolbarsMenu =
2262         viewMenu->addMenu(tr("Toolbars", "Toolbars overview in view menu"));
2263     QString tag = tr("Views", "Shortcuts");
2264
2265     viewMenu->addSeparator();
2266
2267     QAction *a;
2268
2269     a = new QAction(QPixmap(":view-video-projector.png"), 
2270             tr("Toggle Presentation mode", "View action") + " " +
2271             tr("(still experimental)"),
2272             this);
2273     // a->setShortcut(Qt::Key_Plus);
2274     viewMenu->addAction(a);
2275     switchboard.addSwitch ("presentationMode", shortcutScope, a, tag);
2276     connect(a, SIGNAL(triggered()), this, SLOT(togglePresentationMode()));
2277     actionTogglePresentationMode = a;
2278
2279     a = new QAction(QPixmap(":/viewmag+.png"), tr("Zoom in", "View action"),
2280                     this);
2281     a->setShortcut(Qt::Key_Plus);
2282     viewMenu->addAction(a);
2283     switchboard.addSwitch("mapZoomIn", shortcutScope, a, tag);
2284     connect(a, SIGNAL(triggered()), this, SLOT(viewZoomIn()));
2285     actionZoomIn = a;
2286
2287     a = new QAction(QPixmap(":/viewmag-.png"), tr("Zoom out", "View action"),
2288                     this);
2289     a->setShortcut(Qt::Key_Minus);
2290     viewMenu->addAction(a);
2291     switchboard.addSwitch("mapZoomOut", shortcutScope, a, tag);
2292     connect(a, SIGNAL(triggered()), this, SLOT(viewZoomOut()));
2293     actionZoomOut = a;
2294
2295     a = new QAction(QPixmap(":/transform-rotate-ccw.svg"),
2296                     tr("Rotate counterclockwise", "View action"), this);
2297     a->setShortcut(Qt::SHIFT + Qt::Key_R);
2298     viewMenu->addAction(a);
2299     switchboard.addSwitch("mapRotateCounterClockwise", shortcutScope, a, tag);
2300     connect(a, SIGNAL(triggered()), this, SLOT(viewRotateCounterClockwise()));
2301     actionRotateCounterClockwise = a;
2302
2303     a = new QAction(QPixmap(":/transform-rotate-cw.svg"),
2304                     tr("Rotate rclockwise", "View action"), this);
2305     a->setShortcut(Qt::Key_R);
2306     viewMenu->addAction(a);
2307     switchboard.addSwitch("mapRotateClockwise", shortcutScope, a, tag);
2308     connect(a, SIGNAL(triggered()), this, SLOT(viewRotateClockwise()));
2309     actionRotateClockwise = a;
2310
2311     a = new QAction(QPixmap(":/viewmag-reset.png"),
2312                     tr("reset Zoom", "View action"), this);
2313     a->setShortcut(Qt::Key_Comma);
2314     switchboard.addSwitch("mapZoomReset", shortcutScope, a, tag);
2315     viewMenu->addAction(a);
2316     connect(a, SIGNAL(triggered()), this, SLOT(viewZoomReset()));
2317     actionZoomReset = a;
2318
2319     a = new QAction(QPixmap(":/viewshowsel.png"),
2320                     tr("Center on selection", "View action"), this);
2321     a->setShortcut(Qt::Key_Period);
2322     viewMenu->addAction(a);
2323     switchboard.addSwitch("mapCenterOn", shortcutScope, a, tag);
2324     connect(a, SIGNAL(triggered()), this, SLOT(viewCenter()));
2325     actionCenterOn = a;
2326
2327     a = new QAction(QPixmap(),
2328                     tr("Fit view to selection", "View action"), this);
2329     a->setShortcut(Qt::Key_Period + Qt::SHIFT);
2330     viewMenu->addAction(a);
2331     switchboard.addSwitch("mapCenterAndFitView", shortcutScope, a, tag);
2332     connect(a, SIGNAL(triggered()), this, SLOT(viewCenterScaled()));
2333     actionFitToSelection = a;
2334
2335     viewMenu->addSeparator();
2336
2337     // a=noteEditorDW->toggleViewAction();
2338     a = new QAction(QPixmap(":/flag-note.svg"),
2339                     tr("Note editor", "View action"), this);
2340     a->setShortcut(Qt::Key_N);
2341     a->setShortcutContext(Qt::WidgetShortcut);
2342     a->setCheckable(true);
2343     viewMenu->addAction(a);
2344     mapEditorActions.append(a);
2345     switchboard.addSwitch("mapToggleNoteEditor", shortcutScope, a, tag);
2346     connect(a, SIGNAL(triggered()), this, SLOT(windowToggleNoteEditor()));
2347     actionViewToggleNoteEditor = a;
2348
2349     // a=headingEditorDW->toggleViewAction();
2350     a = new QAction(QPixmap(":/headingeditor.png"),
2351                     tr("Heading editor", "View action"), this);
2352     a->setCheckable(true);
2353     a->setIcon(QPixmap(":/headingeditor.png"));
2354     a->setShortcut(Qt::Key_E);
2355     a->setShortcutContext(Qt::WidgetShortcut);
2356     mapEditorActions.append(a);
2357     viewMenu->addAction(a);
2358     switchboard.addSwitch("mapToggleHeadingEditor", shortcutScope, a, tag);
2359     connect(a, SIGNAL(triggered()), this, SLOT(windowToggleHeadingEditor()));
2360     actionViewToggleHeadingEditor = a;
2361
2362     // Original icon is "category" from KDE
2363     a = new QAction(QPixmap(":/treeeditor.png"),
2364                     tr("Tree editor", "View action"), this);
2365     a->setShortcut(Qt::CTRL + Qt::Key_T);
2366     a->setCheckable(true);
2367     viewMenu->addAction(a);
2368     switchboard.addSwitch("mapToggleTreeEditor", shortcutScope, a, tag);
2369     connect(a, SIGNAL(triggered()), this, SLOT(windowToggleTreeEditor()));
2370     actionViewToggleTreeEditor = a;
2371
2372     a = new QAction(QPixmap(":/taskeditor.png"),
2373                     tr("Task editor", "View action"), this);
2374     a->setCheckable(true);
2375     a->setShortcut(Qt::Key_Q);
2376     a->setShortcutContext(Qt::WidgetShortcut);
2377     mapEditorActions.append(a);
2378     viewMenu->addAction(a);
2379     switchboard.addSwitch("mapToggleTaskEditor", shortcutScope, a, tag);
2380     connect(a, SIGNAL(triggered()), this, SLOT(windowToggleTaskEditor()));
2381     actionViewToggleTaskEditor = a;
2382
2383     a = new QAction(QPixmap(":/slideeditor.png"),
2384                     tr("Slide editor", "View action"), this);
2385     a->setCheckable(true);
2386     viewMenu->addAction(a);
2387     switchboard.addSwitch("mapToggleSlideEditor", shortcutScope, a, tag);
2388     connect(a, SIGNAL(triggered()), this, SLOT(windowToggleSlideEditor()));
2389     actionViewToggleSlideEditor = a;
2390
2391     a = new QAction(QPixmap(":/scripteditor.png"),
2392                     tr("Script editor", "View action"), this);
2393     a->setShortcut(Qt::SHIFT + Qt::Key_S);
2394     a->setCheckable(true);
2395     viewMenu->addAction(a);
2396     switchboard.addSwitch("mapToggleScriptEditor", shortcutScope, a, tag);
2397     connect(a, SIGNAL(triggered()), this, SLOT(windowToggleScriptEditor()));
2398     actionViewToggleScriptEditor = a;
2399
2400     a = new QAction(QPixmap(), tr("Script output window", "View action"), this);
2401     a->setShortcut(Qt::CTRL + Qt::SHIFT + Qt::Key_S);
2402     a->setCheckable(true);
2403     viewMenu->addAction(a);
2404     switchboard.addSwitch("mapToggleScriptOutput", shortcutScope, a, tag);
2405     connect(a, SIGNAL(triggered()), this, SLOT(windowToggleScriptOutput()));
2406     actionViewToggleScriptOutput = a;
2407
2408     a = new QAction(QPixmap(":/history.png"),
2409                     tr("History Window", "View action"), this);
2410     a->setShortcut(Qt::CTRL + Qt::Key_H);
2411     a->setShortcutContext(Qt::WidgetShortcut);
2412     a->setCheckable(true);
2413     viewMenu->addAction(a);
2414     mapEditorActions.append(a);
2415     switchboard.addSwitch("mapToggleHistoryWindow", shortcutScope, a, tag);
2416     connect(a, SIGNAL(triggered()), this, SLOT(windowToggleHistory()));
2417     actionViewToggleHistoryWindow = a;
2418
2419     viewMenu->addAction(actionViewTogglePropertyEditor);
2420
2421     viewMenu->addSeparator();
2422
2423     a = new QAction(tr("Antialiasing", "View action"), this);
2424     a->setCheckable(true);
2425     a->setChecked(settings.value("/mainwindow/view/AntiAlias", true).toBool());
2426     viewMenu->addAction(a);
2427     connect(a, SIGNAL(triggered()), this, SLOT(windowToggleAntiAlias()));
2428     actionViewToggleAntiAlias = a;
2429
2430     a = new QAction(tr("Smooth pixmap transformations", "View action"), this);
2431     a->setStatusTip(a->text());
2432     a->setCheckable(true);
2433     a->setChecked(
2434         settings.value("/mainwindow/view/SmoothPixmapTransformation", true)
2435             .toBool());
2436     viewMenu->addAction(a);
2437     connect(a, SIGNAL(triggered()), this, SLOT(windowToggleSmoothPixmap()));
2438     actionViewToggleSmoothPixmapTransform = a;
2439
2440     a = new QAction(tr("Next Map", "View action"), this);
2441     a->setStatusTip(a->text());
2442     a->setShortcut(Qt::SHIFT + Qt::Key_Right);
2443     viewMenu->addAction(a);
2444     switchboard.addSwitch("mapPrevious", shortcutScope, a, tag);
2445     connect(a, SIGNAL(triggered()), this, SLOT(windowNextEditor()));
2446
2447     a = new QAction(tr("Previous Map", "View action"), this);
2448     a->setStatusTip(a->text());
2449     a->setShortcut(Qt::SHIFT + Qt::Key_Left);
2450     viewMenu->addAction(a);
2451     switchboard.addSwitch("mapNext", shortcutScope, a, tag);
2452     connect(a, SIGNAL(triggered()), this, SLOT(windowPreviousEditor()));
2453
2454     a = new QAction(tr("Next slide", "View action"), this);
2455     a->setStatusTip(a->text());
2456     a->setShortcut(Qt::Key_Space);
2457     viewMenu->addAction(a);
2458     switchboard.addSwitch("mapNextSlide", shortcutScope, a, tag);
2459     connect(a, SIGNAL(triggered()), this, SLOT(nextSlide()));
2460
2461     a = new QAction(tr("Previous slide", "View action"), this);
2462     a->setStatusTip(a->text());
2463     a->setShortcut(Qt::Key_Backspace);
2464     viewMenu->addAction(a);
2465     switchboard.addSwitch("mapPreviousSlide", shortcutScope, a, tag);
2466     connect(a, SIGNAL(triggered()), this, SLOT(previousSlide()));
2467 }
2468
2469 // Connect Actions
2470 void Main::setupConnectActions()
2471 {
2472     QMenu *connectMenu = menuBar()->addMenu(tr("&Connect"));
2473     QString tag = tr("Connect", "Shortcuts");
2474
2475     QAction *a;
2476
2477     a = new QAction( tr("Get Confluence user data", "Connect action"), this);
2478     a->setShortcut(Qt::SHIFT + Qt::Key_C);
2479     connectMenu->addAction(a);
2480     switchboard.addSwitch ("confluenceUser", shortcutScope, a, tag);
2481     connect(a, SIGNAL(triggered()), this, SLOT(getConfluenceUser()));
2482     actionConnectGetConfluenceUser = a;
2483
2484     connectMenu->addAction(actionGetConfluencePageName);
2485     connectMenu->addAction(actionGetJiraDataSubtree);
2486
2487     connectMenu->addSeparator();
2488
2489     connectMenu->addAction(actionSettingsJIRA);
2490     connectMenu->addAction(actionSettingsConfluence);
2491 }
2492
2493 // Mode Actions
2494 void Main::setupModeActions()
2495 {
2496     // QPopupMenu *menu = new QPopupMenu( this );
2497     // menuBar()->insertItem( tr( "&Mode (using modifiers)" ), menu );
2498
2499     QString tag = tr("Modifier modes", "Shortcuts");
2500     QAction *a;
2501     actionGroupModModes = new QActionGroup(this);
2502     actionGroupModModes->setExclusive(true);
2503
2504     a = new QAction(
2505         QIcon(":/mode-select.svg"),
2506         tr("Use modifier to select and reorder objects", "Mode modifier"),
2507         actionGroupModModes);
2508     a->setShortcut(Qt::Key_J);
2509     addAction(a);
2510     switchboard.addSwitch("mapModModePoint", shortcutScope, a, tag);
2511     a->setCheckable(true);
2512     a->setChecked(true);
2513     actionListFiles.append(a);
2514     actionModModePoint = a;
2515
2516     a = new QAction(
2517         QPixmap(":/mode-color.png"),
2518         tr("Format painter: pick color from another branch and apply",
2519            "Mode modifier"),
2520         actionGroupModModes);
2521     a->setShortcut(Qt::Key_K);
2522     addAction(a);
2523     switchboard.addSwitch("mapModModeColor", shortcutScope, a, tag);
2524     a->setCheckable(true);
2525     actionListFiles.append(a);
2526     actionModModeColor = a;
2527
2528     a = new QAction(QPixmap(":/mode-xlink.png"),
2529                     tr("Use modifier to draw xLinks", "Mode modifier"),
2530                     actionGroupModModes);
2531     a->setShortcut(Qt::Key_L);
2532     addAction(a);
2533     switchboard.addSwitch("mapModModeXLink", shortcutScope, a, tag);
2534     a->setCheckable(true);
2535     actionListFiles.append(a);
2536     actionModModeXLink = a;
2537
2538     a = new QAction(
2539         QPixmap(":/mode-move-object.svg"),
2540         tr("Use modifier to move branches without linking", "Mode modifier"),
2541         actionGroupModModes);
2542     a->setShortcut(Qt::Key_Odiaeresis);
2543     addAction(a);
2544     switchboard.addSwitch("mapModModeMoveObject", shortcutScope, a, tag);
2545     a->setCheckable(true);
2546     actionListFiles.append(a);
2547     actionModModeMoveObject = a;
2548
2549     a = new QAction(
2550         QPixmap(":/mode-move-view.png"),
2551         tr("Use modifier to move view without selecting", "Mode modifier"),
2552         actionGroupModModes);
2553     a->setShortcut(Qt::Key_Adiaeresis);
2554     addAction(a);
2555     switchboard.addSwitch("mapModModeMoveView", shortcutScope, a, tag);
2556     a->setCheckable(true);
2557     actionListFiles.append(a);
2558     actionModModeMoveView = a;
2559 }
2560
2561 void Main::addUserFlag()
2562 {
2563     VymModel *m = currentModel();
2564
2565     if (m) {
2566         QFileDialog fd;
2567         QStringList filters;
2568         filters << tr("Images") + " (*.png *.bmp *.xbm *.jpg *.png *.xpm *.gif "
2569                                   "*.pnm *.svg *.svgz)";
2570         filters << tr("All", "Filedialog") + " (*.*)";
2571         fd.setFileMode(QFileDialog::ExistingFiles);
2572         fd.setNameFilters(filters);
2573         fd.setWindowTitle(vymName + " - " + "Load user flag");
2574         fd.setAcceptMode(QFileDialog::AcceptOpen);
2575
2576         QString fn;
2577         if (fd.exec() == QDialog::Accepted) {
2578             lastMapDir = fd.directory();
2579             QStringList flist = fd.selectedFiles();
2580             QStringList::Iterator it = flist.begin();
2581             initProgressCounter(flist.count());
2582             while (it != flist.end()) {
2583                 fn = *it;
2584                 setupFlag(*it, Flag::UserFlag, *it, "");
2585                 ++it;
2586             }
2587         }
2588     }
2589 }
2590
2591 void Main::setupFlagActions()
2592 {
2593     Flag *flag;
2594
2595     // Create System Flags
2596
2597     // Tasks
2598     // Origin: ./share/icons/oxygen/48x48/status/task-reject.png
2599     flag = setupFlag(":/flag-task-new.svg", Flag::SystemFlag, "system-task-new",
2600                      tr("Note", "SystemFlag"));
2601     flag->setGroup("system-tasks");
2602
2603     flag = setupFlag(":/flag-task-new-morning.svg", Flag::SystemFlag,
2604                      "system-task-new-morning", tr("Note", "SystemFlag"));
2605     flag->setGroup("system-tasks");
2606
2607     flag = setupFlag(":/flag-task-new-sleeping.svg", Flag::SystemFlag,
2608                      "system-task-new-sleeping", tr("Note", "SystemFlag"));
2609     flag->setGroup("system-tasks");
2610
2611     // Origin: ./share/icons/oxygen/48x48/status/task-reject.png
2612     flag = setupFlag(":/flag-task-wip.svg", Flag::SystemFlag, "system-task-wip",
2613                      tr("Note", "SystemFlag"));
2614     flag->setGroup("system-tasks");
2615
2616     flag = setupFlag(":/flag-task-wip-morning.svg", Flag::SystemFlag,
2617                      "system-task-wip-morning", tr("Note", "SystemFlag"));
2618     flag->setGroup("system-tasks");
2619
2620     flag = setupFlag(":/flag-task-wip-sleeping.svg", Flag::SystemFlag,
2621                      "system-task-wip-sleeping", tr("Note", "SystemFlag"));
2622     flag->setGroup("system-tasks");
2623
2624     // Origin: ./share/icons/oxygen/48x48/status/task-complete.png
2625     flag = setupFlag(":/flag-task-finished.svg", Flag::SystemFlag,
2626                      "system-task-finished", tr("Note", "SystemFlag"));
2627     flag->setGroup("system-tasks");
2628
2629     setupFlag(":/flag-note.svg", Flag::SystemFlag, "system-note",
2630               tr("Note", "SystemFlag"));
2631
2632     setupFlag(":/flag-url.svg", Flag::SystemFlag, "system-url",
2633               tr("URL", "SystemFlag"));
2634
2635     setupFlag(":/flag-target.svg", Flag::SystemFlag, "system-target",
2636               tr("Map target", "SystemFlag"));
2637
2638     setupFlag(":/flag-vymlink.png", Flag::SystemFlag, "system-vymLink",
2639               tr("Link to another vym map", "SystemFlag"));
2640
2641     setupFlag(":/flag-scrolled-right.png", Flag::SystemFlag,
2642               "system-scrolledright", tr("subtree is scrolled", "SystemFlag"));
2643
2644     setupFlag(":/flag-tmpUnscrolled-right.png", Flag::SystemFlag,
2645               "system-tmpUnscrolledRight",
2646               tr("subtree is temporary scrolled", "SystemFlag"));
2647
2648     setupFlag(":/flag-hideexport", Flag::SystemFlag, "system-hideInExport",
2649               tr("Hide object in exported maps", "SystemFlag"));
2650
2651     addToolBarBreak();
2652
2653     // Add entry now, to avoid chicken and egg problem and position toolbar
2654     // after all others:
2655     setupFlag(":/flag-stopsign.svg", Flag::StandardFlag, "stopsign",
2656                   tr("This won't work!", "Standardflag"), QUuid(), Qt::Key_1);
2657
2658     flag = setupFlag(":/flag-hook-green.svg",
2659                   // flag = setupFlag ( "flags/standard/dialog-ok-apply.svg",
2660                   Flag::StandardFlag, "hook-green",
2661                   tr("Status - ok,done", "Standardflag"), QUuid(), Qt::Key_2);
2662     flag->setGroup("standard-status");
2663
2664     flag = setupFlag(":/flag-wip.svg", Flag::StandardFlag, "wip",
2665                      tr("Status - work in progress", "Standardflag"), QUuid(),
2666                      Qt::Key_3);
2667     flag->setGroup("standard-status");
2668
2669     flag = setupFlag(":/flag-cross-red.svg", Flag::StandardFlag, "cross-red",
2670                      tr("Status - missing, not started", "Standardflag"),
2671                      QUuid(), Qt::Key_4);
2672     flag->setGroup("standard-status");
2673
2674     flag = setupFlag(":/flag-exclamation-mark.svg", Flag::StandardFlag,
2675                      "exclamationmark", tr("Take care!", "Standardflag"),
2676                      QUuid(), Qt::Key_Exclam);
2677     flag->setGroup("standard-mark");
2678
2679     flag = setupFlag(":/flag-question-mark.svg", Flag::StandardFlag,
2680                      "questionmark", tr("Really?", "Standardflag"), QUuid(),
2681                      Qt::Key_Question);
2682     flag->setGroup("standard-mark");
2683
2684     setupFlag(":/flag-info.svg", Flag::StandardFlag, "info",
2685                      tr("Info", "Standardflag"), QUuid(), Qt::Key_I);
2686
2687     setupFlag(":/flag-lamp.svg", Flag::StandardFlag, "lamp",
2688                      tr("Idea!", "Standardflag"), QUuid(), Qt::Key_Asterisk);
2689
2690     setupFlag(":/flag-heart.svg", Flag::StandardFlag, "heart",
2691                      tr("I just love...", "Standardflag"));
2692
2693     flag = setupFlag(":/flag-face-smile.svg", Flag::StandardFlag, "smiley-good",
2694                      tr("Good", "Standardflag"), QUuid(), Qt::Key_ParenRight);
2695     flag->setGroup("standard-faces");
2696
2697     flag = setupFlag(":/flag-face-sad.svg", Flag::StandardFlag, "smiley-sad",
2698                      tr("Bad", "Standardflag"), QUuid(), Qt::Key_ParenLeft);
2699     flag->setGroup("standard-faces");
2700
2701     flag = setupFlag(":/flag-face-plain.svg", Flag::StandardFlag,
2702                      "smiley-plain", tr("Hm...", "Standardflag"), QUuid());
2703     flag->setGroup("standard-faces");
2704
2705     flag = setupFlag(":/flag-face-surprise.svg", Flag::StandardFlag,
2706                      "smiley-omb", tr("Oh no!", "Standardflag"), QUuid());
2707     flag->setGroup("standard-faces");
2708
2709     setupFlag(":/flag-flash.svg", Flag::StandardFlag, "flash",
2710                      tr("Dangerous", "Standardflag"));
2711
2712     flag = setupFlag(":/flag-arrow-up.svg", Flag::StandardFlag, "arrow-up",
2713                      tr("Important", "Standardflag"), QUuid(),
2714                      Qt::SHIFT + Qt::Key_PageUp);
2715     flag->setGroup("standard-arrow");
2716
2717     flag = setupFlag(":/flag-arrow-down.svg", Flag::StandardFlag, "arrow-down",
2718                      tr("Unimportant", "Standardflag"), QUuid(),
2719                      Qt::SHIFT + Qt::Key_PageDown);
2720     flag->setGroup("standard-arrow");
2721
2722     flag = setupFlag(":/flag-arrow-2up.svg", Flag::StandardFlag, "2arrow-up",
2723                      tr("Very important!", "Standardflag"), QUuid(),
2724                      Qt::SHIFT + Qt::CTRL + Qt::Key_PageUp);
2725     flag->setGroup("standard-arrow");
2726
2727     flag = setupFlag(":/flag-arrow-2down.svg", Flag::StandardFlag,
2728                      "2arrow-down", tr("Very unimportant!", "Standardflag"),
2729                      QUuid(), Qt::SHIFT + Qt::CTRL + Qt::Key_PageDown);
2730     flag->setGroup("standard-arrow");
2731
2732     setupFlag(":/flag-thumb-up.png", Flag::StandardFlag, "thumb-up",
2733                      tr("I like this", "Standardflag"));
2734
2735     setupFlag(":/flag-thumb-down.png", Flag::StandardFlag, "thumb-down",
2736                      tr("I do not like this", "Standardflag"));
2737
2738     // Original khelpcenter.png
2739     setupFlag(":/flag-lifebelt.svg", Flag::StandardFlag, "lifebelt",
2740                      tr("This will help", "Standardflag"));
2741
2742     setupFlag(":/flag-phone.svg", Flag::StandardFlag, "phone",
2743                      tr("Call...", "Standardflag"));
2744
2745     setupFlag(":/flag-clock.svg", Flag::StandardFlag, "clock",
2746                      tr("Time critical", "Standardflag"));
2747
2748     setupFlag(":/flag-present.png", Flag::StandardFlag, "present",
2749                      tr("Surprise!", "Standardflag"));
2750
2751     setupFlag(":/flag-rose.png", Flag::StandardFlag, "rose",
2752                      tr("Rose", "Standardflag"));
2753
2754     // Freemind flags
2755     setupFlag(":/freemind/warning.png", Flag::FreemindFlag,
2756                      "freemind-warning", tr("Important", "Freemind flag"));
2757
2758     for (int i = 1; i < 8; i++) {
2759         setupFlag(QString(":/freemind/priority-%1.png").arg(i),
2760                          Flag::FreemindFlag,
2761                          QString("freemind-priority-%1").arg(i),
2762                          tr("Important", "Freemind flag"));
2763         flag->setGroup("freemind-priority");
2764     }
2765
2766     setupFlag(":/freemind/back.png", Flag::FreemindFlag, "freemind-back",
2767                      tr("Back", "Freemind flag"));
2768
2769     setupFlag(":/freemind/forward.png", Flag::FreemindFlag,
2770                      "freemind-forward", tr("Forward", "Freemind flag"));
2771
2772     setupFlag(":/freemind/attach.png", Flag::FreemindFlag,
2773                      "freemind-attach", tr("Look here", "Freemind flag"));
2774
2775     setupFlag(":/freemind/clanbomber.png", Flag::FreemindFlag,
2776                      "freemind-clanbomber", tr("Dangerous", "Freemind flag"));
2777
2778     setupFlag(":/freemind/desktopnew.png", Flag::FreemindFlag,
2779                   "freemind-desktopnew", tr("Don't forget", "Freemind flag"));
2780
2781     setupFlag(":/freemind/flag.png", Flag::FreemindFlag, "freemind-flag",
2782                      tr("Flag", "Freemind flag"));
2783
2784     setupFlag(":/freemind/gohome.png", Flag::FreemindFlag,
2785                      "freemind-gohome", tr("Home", "Freemind flag"));
2786
2787     setupFlag(":/freemind/kaddressbook.png", Flag::FreemindFlag,
2788                      "freemind-kaddressbook", tr("Telephone", "Freemind flag"));
2789
2790     setupFlag(":/freemind/knotify.png", Flag::FreemindFlag,
2791                      "freemind-knotify", tr("Music", "Freemind flag"));
2792
2793     setupFlag(":/freemind/korn.png", Flag::FreemindFlag, "freemind-korn",
2794                      tr("Mailbox", "Freemind flag"));
2795
2796     setupFlag(":/freemind/mail.png", Flag::FreemindFlag, "freemind-mail",
2797                      tr("Mail", "Freemind flag"));
2798
2799     setupFlag(":/freemind/password.png", Flag::FreemindFlag,
2800                      "freemind-password", tr("Password", "Freemind flag"));
2801
2802     setupFlag(":/freemind/pencil.png", Flag::FreemindFlag,
2803                      "freemind-pencil", tr("To be improved", "Freemind flag"));
2804
2805     setupFlag(":/freemind/stop.png", Flag::FreemindFlag, "freemind-stop",
2806                      tr("Stop", "Freemind flag"));
2807
2808     setupFlag(":/freemind/wizard.png", Flag::FreemindFlag,
2809                      "freemind-wizard", tr("Magic", "Freemind flag"));
2810
2811     setupFlag(":/freemind/xmag.png", Flag::FreemindFlag, "freemind-xmag",
2812                      tr("To be discussed", "Freemind flag"));
2813
2814     setupFlag(":/freemind/bell.png", Flag::FreemindFlag, "freemind-bell",
2815                      tr("Reminder", "Freemind flag"));
2816
2817     setupFlag(":/freemind/bookmark.png", Flag::FreemindFlag,
2818                      "freemind-bookmark", tr("Excellent", "Freemind flag"));
2819
2820     setupFlag(":/freemind/penguin.png", Flag::FreemindFlag,
2821                      "freemind-penguin", tr("Linux", "Freemind flag"));
2822
2823     setupFlag(":/freemind/licq.png", Flag::FreemindFlag, "freemind-licq",
2824                      tr("Sweet", "Freemind flag"));
2825 }
2826
2827 Flag *Main::setupFlag(const QString &path, Flag::FlagType type,
2828                       const QString &name, const QString &tooltip,
2829                       const QUuid &uid, const QKeySequence &keyseq)
2830 {
2831     Flag *flag = nullptr;
2832
2833     // Create flag in toolbar
2834     switch (type) {
2835     case Flag::FreemindFlag:
2836         // Maybe introduce dedicated toolbar later,
2837         // so for now switch to standard flag
2838         flag = standardFlagsMaster->createFlag(path);
2839         break;
2840
2841     case Flag::StandardFlag:
2842         flag = standardFlagsMaster->createFlag(path);
2843         break;
2844
2845     case Flag::UserFlag:
2846         flag = userFlagsMaster->createFlag(path);
2847
2848         // User flags read from file already have a Uuid - use it
2849         if (!uid.isNull())
2850             flag->setUuid(uid);
2851         break;
2852
2853     case Flag::SystemFlag:
2854         flag = systemFlagsMaster->createFlag(path);
2855         break;
2856
2857     default:
2858         qWarning() << "Unknown flag type in MainWindow::setupFlag";
2859         break;
2860     }
2861
2862     if (!flag)
2863         return flag;
2864
2865     flag->setName(name);
2866     flag->setToolTip(tooltip);
2867     flag->setType(type);
2868
2869     if (type == Flag::SystemFlag)
2870         return flag;
2871
2872     // StandardFlag or user flag
2873
2874     QAction *a;
2875
2876     // Set icon for action
2877     ImageObj *image = flag->getImageObj();
2878     a = new QAction(image->getIcon(), flag->getUuid().toString(), this);
2879
2880     flag->setAction(a);
2881     a->setCheckable(true);
2882     a->setObjectName(flag->getUuid().toString());
2883     if (tooltip.isEmpty())
2884         a->setToolTip(flag->getName()); // Stripped name
2885     else
2886         a->setToolTip(tooltip);
2887
2888     if (keyseq != 0) {
2889         a->setShortcut(keyseq);
2890         a->setShortcutContext(Qt::WidgetShortcut);
2891
2892         // Allow mapEditors to actually trigger this action
2893         mapEditorActions.append(a);
2894         taskEditorActions.append(a);
2895     }
2896
2897     switch (type) {
2898     case Flag::FreemindFlag:
2899         // Hide freemind flags per default
2900         // Maybe introduce dedicate toolbar later,
2901         // so for now switch to standard flag
2902         flag->setVisible(false);
2903         type = Flag::StandardFlag;
2904         standardFlagsMaster->addActionToToolbar(a);
2905
2906         connect(a, SIGNAL(triggered()), this, SLOT(flagChanged()));
2907         break;
2908     case Flag::StandardFlag:
2909         // Hide some old flags, if not used
2910         if (name == "present" || name == "rose" || name == "phone" ||
2911             name == "clock")
2912             flag->setVisible(false);
2913         standardFlagsMaster->addActionToToolbar(a);
2914         connect(a, SIGNAL(triggered()), this, SLOT(flagChanged()));
2915         break;
2916     case Flag::UserFlag:
2917         userFlagsMaster->addActionToToolbar(a);
2918         connect(a, SIGNAL(triggered()), this, SLOT(flagChanged()));
2919         break;
2920     default:
2921         qWarning() << "Unknown flag type in MainWindow::setupFlag";
2922     }
2923
2924     a->setVisible(flag->isVisible());
2925
2926     return flag;
2927 }
2928
2929 // Network Actions
2930 void Main::setupNetworkActions()
2931 {
2932     if (!settings.value("/mainwindow/showTestMenu", false).toBool())
2933         return;
2934
2935     QAction *a;
2936
2937     a = new QAction("Start TCPserver for MapEditor", this);
2938     connect(a, SIGNAL(triggered()), this, SLOT(networkStartServer()));
2939
2940     a = new QAction("Connect MapEditor to server", this);
2941     connect(a, SIGNAL(triggered()), this, SLOT(networkConnect()));
2942 }
2943
2944 // Settings Actions
2945 void Main::setupSettingsActions()
2946 {
2947     QMenu *settingsMenu = menuBar()->addMenu(tr("Settings"));
2948
2949     QAction *a;
2950
2951     a = new QAction(
2952         tr("Check for release notes and updates", "Settings action"), this);
2953     a->setCheckable(true);
2954     a->setChecked(settings.value("/downloads/enabled", true).toBool());
2955     connect(a, SIGNAL(triggered()), this, SLOT(settingsToggleDownloads()));
2956     settingsMenu->addAction(a);
2957     actionSettingsToggleDownloads = a;
2958
2959     a = new QAction(tr("Set author for new maps", "Settings action") + "...",
2960                     this);
2961     connect(a, SIGNAL(triggered()), this, SLOT(settingsDefaultMapAuthor()));
2962     settingsMenu->addAction(a);
2963
2964     settingsMenu->addSeparator();
2965
2966     a = new QAction(tr("Set application to open pdf files", "Settings action") +
2967                         "...",
2968                     this);
2969     connect(a, SIGNAL(triggered()), this, SLOT(settingsPDF()));
2970     settingsMenu->addAction(a);
2971
2972     a = new QAction(
2973         tr("Set application to open external links", "Settings action") + "...",
2974         this);
2975     connect(a, SIGNAL(triggered()), this, SLOT(settingsURL()));
2976     settingsMenu->addAction(a);
2977
2978     a = new QAction(
2979         tr("Set application to zip/unzip files", "Settings action") + "...",
2980         this);
2981     connect(a, SIGNAL(triggered()), this, SLOT(settingsZipTool()));
2982     // FIXME-2 Disabled for now  settingsMenu->addAction(a);
2983
2984     a = new QAction(tr("Confluence Credentials", "Settings action") + "...",
2985                     this);
2986     connect(a, SIGNAL(triggered()), this, SLOT(settingsConfluence()));
2987     settingsMenu->addAction(a);
2988     actionSettingsConfluence = a;
2989
2990     a = new QAction(tr("JIRA Credentials", "Settings action") + "...",
2991                     this);
2992     connect(a, SIGNAL(triggered()), this, SLOT(settingsJIRA()));
2993     settingsMenu->addAction(a);
2994     actionSettingsJIRA = a;
2995
2996     a = new QAction(tr("Set path for new maps", "Settings action") + "...",
2997                     this);
2998     connect(a, SIGNAL(triggered()), this, SLOT(settingsDefaultMapPath()));
2999     settingsMenu->addAction(a);
3000
3001     a = new QAction(tr("Set path for macros", "Settings action") + "...", this);
3002     connect(a, SIGNAL(triggered()), this, SLOT(settingsMacroPath()));
3003     settingsMenu->addAction(a);
3004
3005     a = new QAction(tr("Set number of undo levels", "Settings action") + "...",
3006                     this);
3007     connect(a, SIGNAL(triggered()), this, SLOT(settingsUndoLevels()));
3008     settingsMenu->addAction(a);
3009
3010     settingsMenu->addSeparator();
3011
3012     a = new QAction(tr("Autosave", "Settings action"), this);
3013     a->setCheckable(true);
3014     a->setChecked(settings.value("/system/autosave/use", true).toBool());
3015     settingsMenu->addAction(a);
3016     actionSettingsToggleAutosave = a;
3017
3018     a = new QAction(tr("Autosave time", "Settings action") + "...", this);
3019     connect(a, SIGNAL(triggered()), this, SLOT(settingsAutosaveTime()));
3020     settingsMenu->addAction(a);
3021     actionSettingsAutosaveTime = a;
3022
3023     // Disable certain actions during testing
3024     if (testmode) {
3025         actionSettingsToggleAutosave->setChecked(false);
3026         actionSettingsToggleAutosave->setEnabled(false);
3027         actionSettingsAutosaveTime->setEnabled(false);
3028     }
3029
3030     a = new QAction(tr("Write backup file on save", "Settings action"), this);
3031     a->setCheckable(true);
3032     a->setChecked(settings.value("/system/writeBackupFile", false).toBool());
3033     connect(a, SIGNAL(triggered()), this,
3034             SLOT(settingsToggleWriteBackupFile()));
3035     settingsMenu->addAction(a);
3036     actionSettingsWriteBackupFile = a;
3037
3038     settingsMenu->addSeparator();
3039
3040     a = new QAction(tr("Select branch after adding it", "Settings action"),
3041                     this);
3042     a->setCheckable(true);
3043     a->setChecked(
3044         settings.value("/mapeditor/editmode/autoSelectNewBranch", false)
3045             .toBool());
3046     settingsMenu->addAction(a);
3047     actionSettingsAutoSelectNewBranch = a;
3048
3049     a = new QAction(tr("Select existing heading", "Settings action"), this);
3050     a->setCheckable(true);
3051     a->setChecked(
3052         settings.value("/mapeditor/editmode/autoSelectText", true).toBool());
3053     settingsMenu->addAction(a);
3054     actionSettingsAutoSelectText = a;
3055
3056     a = new QAction(tr("Exclusive flags", "Settings action"), this);
3057     a->setCheckable(true);
3058     a->setChecked(
3059         settings.value("/mapeditor/editmode/useFlagGroups", true).toBool());
3060     settingsMenu->addAction(a);
3061     actionSettingsUseFlagGroups = a;
3062
3063     a = new QAction(tr("Use hide flags", "Settings action"), this);
3064     a->setCheckable(true);
3065     a->setChecked(settings.value("/export/useHideExport", true).toBool());
3066     settingsMenu->addAction(a);
3067     actionSettingsUseHideExport = a;
3068
3069     settingsMenu->addSeparator();
3070
3071     a = new QAction(
3072         tr("Dark theme", "Settings action") + "...",
3073         this);
3074     connect(a, SIGNAL(triggered()), this,
3075             SLOT(settingsDarkTheme()));
3076     settingsMenu->addAction(a);
3077     actionSettingsDarkTheme= a;
3078
3079     a = new QAction(
3080         tr("Number of visible parents in task editor", "Settings action") + "...",
3081         this);
3082     connect(a, SIGNAL(triggered()), this,
3083             SLOT(settingsShowParentsLevelTasks()));
3084     settingsMenu->addAction(a);
3085     actionSettingsShowParentsLevelTasks = a;
3086
3087     a = new QAction(tr("Number of visible parents in find results window",
3088                        "Settings action") + "...",
3089                     this);
3090     connect(a, SIGNAL(triggered()), this,
3091             SLOT(settingsShowParentsLevelFindResults()));
3092     settingsMenu->addAction(a);
3093     actionSettingsShowParentsLevelFindResults = a;
3094
3095     a = new QAction(tr("Animation", "Settings action"), this);
3096     a->setCheckable(true);
3097     a->setChecked(settings.value("/animation/use", true).toBool());
3098     connect(a, SIGNAL(triggered()), this, SLOT(settingsToggleAnimation()));
3099     settingsMenu->addAction(a);
3100     actionSettingsUseAnimation = a;
3101
3102     a = new QAction(tr("Automatic layout", "Settings action"), this);
3103     a->setCheckable(true);
3104     a->setChecked(settings.value("/mainwindow/autoLayout/use", true).toBool());
3105     connect(a, SIGNAL(triggered()), this, SLOT(settingsToggleAutoLayout()));
3106     settingsMenu->addAction(a);
3107     actionSettingsToggleAutoLayout = a;
3108 }
3109
3110 // Test Actions
3111 void Main::setupTestActions()
3112 {
3113     QMenu *testMenu = menuBar()->addMenu(tr("Test"));
3114
3115     QString tag = "Testing";
3116     QAction *a;
3117     a = new QAction("Test function 1", this);
3118     a->setShortcut(Qt::ALT + Qt::Key_T);
3119     testMenu->addAction(a);
3120     switchboard.addSwitch("mapTest1", shortcutScope, a, tag);
3121     connect(a, SIGNAL(triggered()), this, SLOT(testFunction1()));
3122
3123     a = new QAction("Test function 2", this);
3124     // a->setShortcut (Qt::ALT + Qt::Key_T);
3125     testMenu->addAction(a);
3126     connect(a, SIGNAL(triggered()), this, SLOT(testFunction2()));
3127
3128     a = new QAction("Toggle hide export mode", this);
3129     a->setCheckable(true);
3130     a->setChecked(false);
3131     testMenu->addAction(a);
3132     connect(a, SIGNAL(triggered()), this, SLOT(toggleHideExport()));
3133     actionToggleHideMode = a;
3134
3135     testMenu->addAction(actionToggleWinter);
3136 }
3137
3138 // Help Actions
3139 void Main::setupHelpActions()
3140 {
3141     QMenu *helpMenu = menuBar()->addMenu(tr("&Help", "Help menubar entry"));
3142
3143     QAction *a;
3144     a = new QAction(tr("Open VYM Documentation (pdf) ", "Help action"), this);
3145     helpMenu->addAction(a);
3146     connect(a, SIGNAL(triggered()), this, SLOT(helpDoc()));
3147
3148     a = new QAction(tr("Open VYM example maps ", "Help action"), this);
3149     helpMenu->addAction(a);
3150     connect(a, SIGNAL(triggered()), this, SLOT(helpDemo()));
3151     helpMenu->addSeparator();
3152
3153     a = new QAction(tr("Download and show release notes", "Help action"), this);
3154     helpMenu->addAction(a);
3155     connect(a, SIGNAL(triggered()), this, SLOT(checkReleaseNotes()));
3156
3157     a = new QAction(tr("Check, if updates are available", "Help action"), this);
3158     helpMenu->addAction(a);
3159     connect(a, SIGNAL(triggered()), this, SLOT(checkUpdates()));
3160     helpMenu->addSeparator();
3161
3162     a = new QAction(tr("Show keyboard shortcuts", "Help action"), this);
3163     helpMenu->addAction(a);
3164     connect(a, SIGNAL(triggered()), this, SLOT(helpShortcuts()));
3165
3166     a = new QAction(tr("Show keyboard macros", "Help action"), this);
3167     helpMenu->addAction(a);
3168     connect(a, SIGNAL(triggered()), this, SLOT(helpMacros()));
3169
3170     a = new QAction(tr("Show scripting commands", "Help action"), this);
3171     helpMenu->addAction(a);
3172     connect(a, SIGNAL(triggered()), this, SLOT(helpScriptingCommands()));
3173
3174     a = new QAction(tr("Debug info", "Option to show debugging info"), this);
3175     helpMenu->addAction(a);
3176     connect(a, SIGNAL(triggered()), this, SLOT(helpDebugInfo()));
3177
3178     a = new QAction(tr("About QT", "Help action"), this);
3179     connect(a, SIGNAL(triggered()), this, SLOT(helpAboutQT()));
3180     helpMenu->addAction(a);
3181
3182     a = new QAction(tr("About VYM", "Help action"), this);
3183     connect(a, SIGNAL(triggered()), this, SLOT(helpAbout()));
3184     helpMenu->addAction(a);
3185 }
3186
3187 // Context Menus
3188 void Main::setupContextMenus()
3189 {
3190     // Context menu for goto/move targets  (populated on demand)
3191     targetsContextMenu = new QMenu(this);
3192
3193     // Context Menu for branch or mapcenter
3194     branchContextMenu = new QMenu(this);
3195     branchContextMenu->addAction(actionViewTogglePropertyEditor);
3196     branchContextMenu->addSeparator();
3197
3198     // Submenu "Add"
3199     branchAddContextMenu = branchContextMenu->addMenu(tr("Add"));
3200     branchAddContextMenu->addAction(actionPaste);
3201     branchAddContextMenu->addAction(actionAddMapCenter);
3202     branchAddContextMenu->addAction(actionAddBranch);
3203     branchAddContextMenu->addAction(actionAddBranchBefore);
3204     branchAddContextMenu->addAction(actionAddBranchAbove);
3205     branchAddContextMenu->addAction(actionAddBranchBelow);
3206     branchAddContextMenu->addSeparator();
3207     branchAddContextMenu->addAction(actionImportAdd);
3208     branchAddContextMenu->addAction(actionImportReplace);
3209
3210     // Submenu "Remove"
3211     branchRemoveContextMenu =
3212         branchContextMenu->addMenu(tr("Remove", "Context menu name"));
3213     branchRemoveContextMenu->addAction(actionCut);
3214     branchRemoveContextMenu->addAction(actionDelete);
3215     branchRemoveContextMenu->addAction(actionDeleteKeepChildren);
3216     branchRemoveContextMenu->addAction(actionDeleteChildren);
3217
3218     branchContextMenu->addAction(actionSaveBranch);
3219     branchContextMenu->addAction(actionFileNewCopy);
3220     branchContextMenu->addAction(actionDetach);
3221
3222     branchContextMenu->addSeparator();
3223     branchContextMenu->addAction(actionLoadImage);
3224     if (settings.value("/mainwindow/showTestMenu", false).toBool())
3225         branchContextMenu->addAction(actionAddAttribute);
3226
3227     branchContextMenu->addSeparator();
3228
3229     // Context menu for tasks
3230     taskContextMenu = branchContextMenu->addMenu(tr("Tasks", "Context menu"));
3231     taskContextMenu->addAction(actionToggleTask);
3232     taskContextMenu->addAction(actionCycleTaskStatus);
3233     taskContextMenu->addAction(actionTaskResetDeltaPrio);
3234     taskContextMenu->addSeparator();
3235     taskContextMenu->addAction(actionTaskSleep0);
3236     taskContextMenu->addAction(actionTaskSleepN);
3237     taskContextMenu->addAction(actionTaskSleep1);
3238     taskContextMenu->addAction(actionTaskSleep2);
3239     taskContextMenu->addAction(actionTaskSleep3);
3240     taskContextMenu->addAction(actionTaskSleep4);
3241     taskContextMenu->addAction(actionTaskSleep5);
3242     taskContextMenu->addAction(actionTaskSleep7);
3243     taskContextMenu->addAction(actionTaskSleep14);
3244     taskContextMenu->addAction(actionTaskSleep28);
3245
3246     // Submenu for Links (URLs, vymLinks)
3247     branchLinksContextMenu = new QMenu(this);
3248
3249     branchLinksContextMenu = branchContextMenu->addMenu(
3250         tr("References (URLs, vymLinks, ...)", "Context menu name"));
3251     branchLinksContextMenu->addAction(actionOpenURL);
3252     branchLinksContextMenu->addAction(actionOpenURLTab);
3253     branchLinksContextMenu->addAction(actionOpenMultipleVisURLTabs);
3254     branchLinksContextMenu->addAction(actionOpenMultipleURLTabs);
3255     branchLinksContextMenu->addAction(actionURLNew);
3256     branchLinksContextMenu->addAction(actionLocalURL);
3257     branchLinksContextMenu->addAction(actionGetURLsFromNote);
3258     branchLinksContextMenu->addAction(actionHeading2URL);
3259     branchLinksContextMenu->addAction(actionGetJiraDataSubtree);
3260     branchLinksContextMenu->addAction(actionGetConfluencePageName);
3261     branchLinksContextMenu->addSeparator();
3262     branchLinksContextMenu->addAction(actionOpenVymLink);
3263     branchLinksContextMenu->addAction(actionOpenVymLinkBackground);
3264     branchLinksContextMenu->addAction(actionOpenMultipleVymLinks);
3265     branchLinksContextMenu->addAction(actionEditVymLink);
3266     branchLinksContextMenu->addAction(actionDeleteVymLink);
3267
3268     // Context Menu for XLinks in a branch menu
3269     // This will be populated "on demand" in updateActions
3270     QString tag = tr("XLinks", "Menu for file actions");
3271     branchContextMenu->addSeparator();
3272     branchXLinksContextMenuEdit =
3273         branchContextMenu->addMenu(tr("Edit XLink", "Context menu name"));
3274     connect(branchXLinksContextMenuEdit, SIGNAL(triggered(QAction *)), this,
3275             SLOT(editEditXLink(QAction *)));
3276     QAction *a;
3277     a = new QAction(tr("Follow XLink", "Context menu"), this);
3278     a->setShortcut(Qt::Key_F);
3279     addAction(a);
3280     switchboard.addSwitch("mapFollowXLink", shortcutScope, a, tag);
3281     connect(a, SIGNAL(triggered()), this, SLOT(popupFollowXLink()));
3282
3283     branchXLinksContextMenuFollow =
3284         branchContextMenu->addMenu(tr("Follow XLink", "Context menu name"));
3285     connect(branchXLinksContextMenuFollow, SIGNAL(triggered(QAction *)), this,
3286             SLOT(editFollowXLink(QAction *)));
3287
3288     // Context menu for floatimage
3289     floatimageContextMenu = new QMenu(this);
3290     a = new QAction(tr("Save image", "Context action"), this);
3291     connect(a, SIGNAL(triggered()), this, SLOT(editSaveImage()));
3292     floatimageContextMenu->addAction(a);
3293
3294     floatimageContextMenu->addSeparator();
3295     floatimageContextMenu->addAction(actionCopy);
3296     floatimageContextMenu->addAction(actionCut);
3297
3298     floatimageContextMenu->addSeparator();
3299     floatimageContextMenu->addAction(actionGrowSelectionSize);
3300     floatimageContextMenu->addAction(actionShrinkSelectionSize);
3301     floatimageContextMenu->addAction(actionFormatHideLinkUnselected);
3302
3303     // Context menu for canvas
3304     canvasContextMenu = new QMenu(this);
3305
3306     canvasContextMenu->addAction(actionAddMapCenter);
3307
3308     canvasContextMenu->addSeparator();
3309
3310     canvasContextMenu->addAction(actionMapProperties);
3311     canvasContextMenu->addAction(actionFormatFont);
3312
3313     canvasContextMenu->addSeparator();
3314
3315     canvasContextMenu->addActions(actionGroupFormatLinkStyles->actions());
3316
3317     canvasContextMenu->addSeparator();
3318
3319     canvasContextMenu->addAction(actionFormatLinkColorHint);
3320
3321     canvasContextMenu->addSeparator();
3322
3323     canvasContextMenu->addAction(actionFormatLinkColor);
3324     canvasContextMenu->addAction(actionFormatSelectionColor);
3325     canvasContextMenu->addAction(actionFormatBackColor);
3326     // if (settings.value( "/mainwindow/showTestMenu",false).toBool() )
3327     //    canvasContextMenu->addAction( actionFormatBackImage );  //FIXME-3
3328     //    makes vym too slow: postponed for later version
3329
3330     // Menu for last opened files
3331     // Create actions
3332     for (int i = 0; i < MaxRecentFiles; ++i) {
3333         recentFileActions[i] = new QAction(this);
3334         recentFileActions[i]->setVisible(false);
3335         fileLastMapsMenu->addAction(recentFileActions[i]);
3336         connect(recentFileActions[i], SIGNAL(triggered()), this,
3337                 SLOT(fileLoadRecent()));
3338     }
3339     setupRecentMapsMenu();
3340 }
3341
3342 void Main::setupRecentMapsMenu()
3343 {
3344     QStringList files =
3345         settings.value("/mainwindow/recentFileList").toStringList();
3346
3347     int numRecentFiles = qMin(files.size(), (int)MaxRecentFiles);
3348
3349     for (int i = 0; i < numRecentFiles; ++i) {
3350         QString text = QString("&%1 %2").arg(i + 1).arg(files[i]);
3351         recentFileActions[i]->setText(text);
3352         recentFileActions[i]->setData(files[i]);
3353         recentFileActions[i]->setVisible(true);
3354     }
3355     for (int j = numRecentFiles; j < MaxRecentFiles; ++j)
3356         recentFileActions[j]->setVisible(false);
3357 }
3358
3359 void Main::setupMacros()
3360 {
3361     for (int i = 0; i <= 47; i++) {
3362         macroActions[i] = new QAction(this);
3363         macroActions[i]->setData(i);
3364         addAction(macroActions[i]);
3365         connect(macroActions[i], SIGNAL(triggered()), this, SLOT(callMacro()));
3366     }
3367     macroActions[0]->setShortcut(Qt::Key_F1);
3368     macroActions[1]->setShortcut(Qt::Key_F2);
3369     macroActions[2]->setShortcut(Qt::Key_F3);
3370     macroActions[3]->setShortcut(Qt::Key_F4);
3371     macroActions[4]->setShortcut(Qt::Key_F5);
3372     macroActions[5]->setShortcut(Qt::Key_F6);
3373     macroActions[6]->setShortcut(Qt::Key_F7);
3374     macroActions[7]->setShortcut(Qt::Key_F8);
3375     macroActions[8]->setShortcut(Qt::Key_F9);
3376     macroActions[9]->setShortcut(Qt::Key_F10);
3377     macroActions[10]->setShortcut(Qt::Key_F11);
3378     macroActions[11]->setShortcut(Qt::Key_F12);
3379
3380     // Shift Modifier
3381     macroActions[12]->setShortcut(Qt::Key_F1 + Qt::SHIFT);
3382     macroActions[13]->setShortcut(Qt::Key_F2 + Qt::SHIFT);
3383     macroActions[14]->setShortcut(Qt::Key_F3 + Qt::SHIFT);
3384     macroActions[15]->setShortcut(Qt::Key_F4 + Qt::SHIFT);
3385     macroActions[16]->setShortcut(Qt::Key_F5 + Qt::SHIFT);
3386     macroActions[17]->setShortcut(Qt::Key_F6 + Qt::SHIFT);
3387     macroActions[18]->setShortcut(Qt::Key_F7 + Qt::SHIFT);
3388     macroActions[19]->setShortcut(Qt::Key_F8 + Qt::SHIFT);
3389     macroActions[20]->setShortcut(Qt::Key_F9 + Qt::SHIFT);
3390     macroActions[21]->setShortcut(Qt::Key_F10 + Qt::SHIFT);
3391     macroActions[22]->setShortcut(Qt::Key_F11 + Qt::SHIFT);
3392     macroActions[23]->setShortcut(Qt::Key_F12 + Qt::SHIFT);
3393
3394     // Ctrl Modifier
3395     macroActions[24]->setShortcut(Qt::Key_F1 + Qt::CTRL);
3396     macroActions[25]->setShortcut(Qt::Key_F2 + Qt::CTRL);
3397     macroActions[26]->setShortcut(Qt::Key_F3 + Qt::CTRL);
3398     macroActions[27]->setShortcut(Qt::Key_F4 + Qt::CTRL);
3399     macroActions[28]->setShortcut(Qt::Key_F5 + Qt::CTRL);
3400     macroActions[29]->setShortcut(Qt::Key_F6 + Qt::CTRL);
3401     macroActions[30]->setShortcut(Qt::Key_F7 + Qt::CTRL);
3402     macroActions[31]->setShortcut(Qt::Key_F8 + Qt::CTRL);
3403     macroActions[32]->setShortcut(Qt::Key_F9 + Qt::CTRL);
3404     macroActions[33]->setShortcut(Qt::Key_F10 + Qt::CTRL);
3405     macroActions[34]->setShortcut(Qt::Key_F11 + Qt::CTRL);
3406     macroActions[35]->setShortcut(Qt::Key_F12 + Qt::CTRL);
3407
3408     // Shift + Ctrl Modifier
3409     macroActions[36]->setShortcut(Qt::Key_F1 + Qt::CTRL + Qt::SHIFT);
3410     macroActions[37]->setShortcut(Qt::Key_F2 + Qt::CTRL + Qt::SHIFT);
3411     macroActions[38]->setShortcut(Qt::Key_F3 + Qt::CTRL + Qt::SHIFT);
3412     macroActions[39]->setShortcut(Qt::Key_F4 + Qt::CTRL + Qt::SHIFT);
3413     macroActions[40]->setShortcut(Qt::Key_F5 + Qt::CTRL + Qt::SHIFT);
3414     macroActions[41]->setShortcut(Qt::Key_F6 + Qt::CTRL + Qt::SHIFT);
3415     macroActions[42]->setShortcut(Qt::Key_F7 + Qt::CTRL + Qt::SHIFT);
3416     macroActions[43]->setShortcut(Qt::Key_F8 + Qt::CTRL + Qt::SHIFT);
3417     macroActions[44]->setShortcut(Qt::Key_F9 + Qt::CTRL + Qt::SHIFT);
3418     macroActions[45]->setShortcut(Qt::Key_F10 + Qt::CTRL + Qt::SHIFT);
3419     macroActions[46]->setShortcut(Qt::Key_F11 + Qt::CTRL + Qt::SHIFT);
3420     macroActions[47]->setShortcut(Qt::Key_F12 + Qt::CTRL + Qt::SHIFT);
3421 }
3422
3423 void Main::setupToolbars()
3424 {
3425     // File actions
3426     fileToolbar =
3427         addToolBar(tr("File actions toolbar", "Toolbar for file actions"));
3428     fileToolbar->setObjectName("fileTB");
3429     fileToolbar->addAction(actionFileNew);
3430     fileToolbar->addAction(actionFileOpen);
3431     fileToolbar->addAction(actionFileSave);
3432     fileToolbar->addAction(actionFileExportLast);
3433     fileToolbar->addAction(actionFilePrint);
3434
3435     // Undo/Redo and clipboard
3436     clipboardToolbar = addToolBar(tr("Undo and clipboard toolbar",
3437                                      "Toolbar for redo/undo and clipboard"));
3438     clipboardToolbar->setObjectName("clipboard toolbar");
3439     clipboardToolbar->addAction(actionUndo);
3440     clipboardToolbar->addAction(actionRedo);
3441     clipboardToolbar->addAction(actionCopy);
3442     clipboardToolbar->addAction(actionCut);
3443     clipboardToolbar->addAction(actionPaste);
3444
3445     // Basic edits
3446     editActionsToolbar = addToolBar(tr("Edit actions toolbar", "Toolbar name"));
3447     editActionsToolbar->setObjectName("basic edit actions TB");
3448     editActionsToolbar->addAction(actionAddMapCenter);
3449     editActionsToolbar->addAction(actionAddBranch);
3450     editActionsToolbar->addAction(actionMoveUp);
3451     editActionsToolbar->addAction(actionMoveDown);
3452     editActionsToolbar->addAction(actionMoveDownDiagonally);
3453     editActionsToolbar->addAction(actionMoveUpDiagonally);
3454     editActionsToolbar->addAction(actionSortChildren);
3455     editActionsToolbar->addAction(actionSortBackChildren);
3456     editActionsToolbar->addAction(actionToggleScroll);
3457     editActionsToolbar->addAction(actionToggleHideExport);
3458     editActionsToolbar->addAction(actionToggleTask);
3459     // editActionsToolbar->addAction (actionExpandAll);
3460     // editActionsToolbar->addAction (actionExpandOneLevel);
3461     // editActionsToolbar->addAction (actionCollapseOneLevel);
3462     // editActionsToolbar->addAction (actionCollapseUnselected);
3463
3464     // Selections
3465     selectionToolbar = addToolBar(tr("Selection toolbar", "Toolbar name"));
3466     selectionToolbar->setObjectName("toolbar for selecting items");
3467     selectionToolbar->addAction(actionToggleTarget);
3468     selectionToolbar->addAction(actionSelectPrevious);
3469     selectionToolbar->addAction(actionSelectNext);
3470     selectionToolbar->addAction(actionFind);
3471
3472     // URLs and vymLinks
3473     referencesToolbar = addToolBar(
3474         tr("URLs and vymLinks toolbar", "Toolbar for URLs and vymlinks"));
3475     referencesToolbar->setObjectName("URLs and vymlinks toolbar");
3476     referencesToolbar->addAction(actionURLNew);
3477     referencesToolbar->addAction(actionEditVymLink);
3478
3479     // Format and colors
3480     colorsToolbar = new QToolBar(tr("Colors toolbar", "Colors toolbar name"));
3481     colorsToolbar->setObjectName("colorsTB");
3482
3483     actionGroupQuickColors = new QActionGroup(this);
3484     actionGroupQuickColors->setExclusive(true);
3485
3486     // Define quickColors
3487     QColor c;
3488     c.setNamedColor ("#ff0000"); quickColors << c;  // Red
3489     c.setNamedColor ("#d95100"); quickColors << c;  // Orange
3490     c.setNamedColor ("#009900"); quickColors << c;  // Green
3491     c.setNamedColor ("#aa00ff"); quickColors << c;  // Purple
3492     c.setNamedColor ("#0000ff"); quickColors << c;  // Blue
3493     c.setNamedColor ("#00aaff"); quickColors << c;  // LightBlue
3494     usingDarkTheme ? vymBlue = c : vymBlue = quickColors.count() - 2;
3495     c.setNamedColor ("#000000"); quickColors << c;  // Black
3496     c.setNamedColor ("#444444"); quickColors << c;  // Dark gray
3497     c.setNamedColor ("#aaaaaa"); quickColors << c;  // Light gray
3498     c.setNamedColor ("#ffffff"); quickColors << c;  // White
3499     //c.setNamedColor ("#00aa7f"); quickColors << c;  // Light green
3500     //c.setNamedColor ("#c466ff"); quickColors << c;  // Light purple
3501
3502     QPixmap pix(16, 16);
3503     QAction *a;
3504     int n = 0;
3505     foreach (c, quickColors) {
3506         pix.fill(c);
3507         a = new QAction(pix, tr("Select color (Press Shift for more options)") + QString("..."), actionGroupQuickColors);
3508         a->setCheckable(true);
3509         a->setData(n);
3510         //formatMenu->addAction(a);
3511         // switchboard.addSwitch("mapFormatColor", shortcutScope, a, tag);
3512         connect(a, SIGNAL(triggered()), this, SLOT(quickColorPressed()));
3513         colorsToolbar->addAction(a);
3514         n++;
3515     }
3516     actionGroupQuickColors->actions().first()->setChecked(true);
3517
3518     colorsToolbar->addAction(actionFormatPickColor);
3519     colorsToolbar->addAction(actionFormatColorBranch);
3520     colorsToolbar->addAction(actionFormatColorSubtree);
3521     // Only place toolbar on very first startup
3522     if (settings.value("/mainwindow/recentFileList").toStringList().isEmpty())
3523         addToolBar (Qt::RightToolBarArea, colorsToolbar);
3524     else
3525         addToolBar (colorsToolbar);
3526
3527     // Zoom
3528     zoomToolbar = addToolBar(tr("View toolbar", "View Toolbar name"));
3529     zoomToolbar->setObjectName("viewTB");
3530     zoomToolbar->addAction(actionTogglePresentationMode);
3531     zoomToolbar->addAction(actionZoomIn);
3532     zoomToolbar->addAction(actionZoomOut);
3533     zoomToolbar->addAction(actionZoomReset);
3534     zoomToolbar->addAction(actionCenterOn);
3535     zoomToolbar->addAction(actionRotateCounterClockwise);
3536     zoomToolbar->addAction(actionRotateClockwise);
3537
3538     // Editors
3539     editorsToolbar = addToolBar(tr("Editors toolbar", "Editor Toolbar name"));
3540     editorsToolbar->setObjectName("editorsTB");
3541     editorsToolbar->addAction(actionViewToggleNoteEditor);
3542     editorsToolbar->addAction(actionViewToggleHeadingEditor);
3543     editorsToolbar->addAction(actionViewToggleTreeEditor);
3544     editorsToolbar->addAction(actionViewToggleTaskEditor);
3545     editorsToolbar->addAction(actionViewToggleSlideEditor);
3546     editorsToolbar->addAction(actionViewToggleScriptEditor);
3547     editorsToolbar->addAction(actionViewToggleHistoryWindow);
3548
3549     // Modifier modes
3550     modModesToolbar =
3551         addToolBar(tr("Modifier modes toolbar", "Modifier Toolbar name"));
3552     modModesToolbar->setObjectName("modesTB");
3553     modModesToolbar->addAction(actionModModePoint);
3554     modModesToolbar->addAction(actionModModeColor);
3555     modModesToolbar->addAction(actionModModeXLink);
3556     modModesToolbar->addAction(actionModModeMoveObject);
3557     modModesToolbar->addAction(actionModModeMoveView);
3558
3559     // Create flag toolbars (initialized later in setupFlagActions() )
3560     addToolBarBreak();
3561     standardFlagsToolbar =
3562         addToolBar(tr("Standard Flags toolbar", "Standard Flag Toolbar"));
3563     standardFlagsToolbar->setObjectName("standardFlagTB");
3564     standardFlagsMaster->setToolBar(standardFlagsToolbar);
3565
3566     userFlagsToolbar =
3567         addToolBar(tr("User Flags toolbar", "user Flags Toolbar"));
3568     userFlagsToolbar->setObjectName("userFlagsTB");
3569     userFlagsMaster->setToolBar(userFlagsToolbar);
3570     userFlagsMaster->createConfigureAction();
3571
3572     // Add all toolbars to View menu
3573     toolbarsMenu->addAction(fileToolbar->toggleViewAction());
3574     toolbarsMenu->addAction(clipboardToolbar->toggleViewAction());
3575     toolbarsMenu->addAction(editActionsToolbar->toggleViewAction());
3576     toolbarsMenu->addAction(selectionToolbar->toggleViewAction());
3577     toolbarsMenu->addAction(colorsToolbar->toggleViewAction());
3578     toolbarsMenu->addAction(zoomToolbar->toggleViewAction());
3579     toolbarsMenu->addAction(modModesToolbar->toggleViewAction());
3580     toolbarsMenu->addAction(referencesToolbar->toggleViewAction());
3581     toolbarsMenu->addAction(editorsToolbar->toggleViewAction());
3582     toolbarsMenu->addAction(userFlagsToolbar->toggleViewAction());
3583     toolbarsMenu->addAction(standardFlagsToolbar->toggleViewAction());
3584
3585     // Initialize toolbarStates for presentation mode
3586     toolbarStates[fileToolbar] = true;
3587     toolbarStates[clipboardToolbar] = true;
3588     toolbarStates[editActionsToolbar] = true;
3589     toolbarStates[selectionToolbar] = false;
3590     toolbarStates[colorsToolbar] = true;
3591     toolbarStates[zoomToolbar] = true;
3592     toolbarStates[modModesToolbar] = false;
3593     toolbarStates[referencesToolbar] = true;
3594     toolbarStates[editorsToolbar] = false;
3595     toolbarStates[standardFlagsToolbar] = true;
3596     toolbarStates[userFlagsToolbar] = true;
3597
3598     // Initialize toolbar visibilities and switch off presentation mode
3599     presentationMode = true;
3600     togglePresentationMode();
3601 }
3602
3603 VymView *Main::currentView() const
3604 {
3605     if (tabWidget->currentWidget())
3606         return (VymView *)tabWidget->currentWidget();
3607     else
3608         return nullptr;
3609 }
3610
3611 VymView *Main::view(const int i) { return (VymView *)tabWidget->widget(i); }
3612
3613 MapEditor *Main::currentMapEditor() const
3614 {
3615     if (tabWidget->currentWidget())
3616         return currentView()->getMapEditor();
3617     return nullptr;
3618 }
3619
3620 uint Main::currentMapID() const
3621 {
3622     VymModel *m = currentModel();
3623     if (m)
3624         return m->getModelID();
3625     else
3626         return 0;
3627 }
3628
3629 int Main::currentMapIndex() const { return tabWidget->currentIndex(); }
3630
3631 VymModel *Main::currentModel() const
3632 {
3633     VymView *vv = currentView();
3634     if (vv)
3635         return vv->getModel();
3636     else
3637         return NULL;
3638 }
3639
3640 VymModel *Main::getModel(uint id) // Used in BugAgent
3641 {
3642     if (id <= 0)
3643         return NULL;
3644
3645     for (int i = 0; i < tabWidget->count(); i++) {
3646         if (view(i)->getModel()->getModelID() == id)
3647             return view(i)->getModel();
3648     }
3649     return NULL;
3650 }
3651
3652 void Main::gotoModel(VymModel *m)
3653 {
3654     for (int i = 0; i < tabWidget->count(); i++)
3655         if (view(i)->getModel() == m) {
3656             tabWidget->setCurrentIndex(i);
3657             return;
3658         }
3659 }
3660
3661 void Main::gotoModelWithID(uint id)
3662 {
3663     VymModel *vm;
3664     for (int i = 0; i < tabWidget->count(); i++) {
3665         vm = view(i)->getModel();
3666         if (vm && vm->getModelID() == id) {
3667             tabWidget->setCurrentIndex(i);
3668             return;
3669         }
3670     }
3671 }
3672
3673 bool Main::closeModelWithID(uint id)
3674 {
3675     VymModel *vm;
3676     for (int i = 0; i < tabWidget->count(); i++) {
3677         vm = view(i)->getModel();
3678         if (vm && vm->getModelID() == id) {
3679             tabWidget->removeTab(i);
3680
3681             // Destroy stuff, order is important
3682             delete (vm->getMapEditor());
3683             delete (view(i));
3684             delete (vm);
3685
3686             updateActions();
3687             return true;
3688         }
3689     }
3690     return false;
3691 }
3692
3693 int Main::modelCount() { return tabWidget->count(); }
3694
3695 void Main::updateTabName(VymModel *vm)
3696 {
3697     if (!vm) {
3698         qWarning() << "Main::updateTabName   vm == NULL";
3699         return;
3700     }
3701
3702     for (int i = 0; i < tabWidget->count(); i++)
3703         if (view(i)->getModel() == vm) {
3704             if (vm->isReadOnly())
3705                 tabWidget->setTabText(i, vm->getFileName() + " " +
3706                                              tr("(readonly)"));
3707             else
3708                 tabWidget->setTabText(i, vm->getFileName());
3709             return;
3710         }
3711 }
3712
3713 void Main::editorChanged()
3714 {
3715     VymModel *vm = currentModel();
3716     if (vm) {
3717         BranchItem *bi = vm->getSelectedBranch();
3718         updateNoteEditor(bi);
3719         updateHeadingEditor(bi);
3720         updateQueries(vm);
3721         taskEditor->setMapName(vm->getMapName());
3722         updateDockWidgetTitles(vm);
3723     }
3724
3725     // Update actions to in menus and toolbars according to editor
3726     updateActions();
3727 }
3728
3729 void Main::fileNew()
3730 {
3731     VymModel *vm;
3732
3733     // Don't show counter while loading default map
3734     removeProgressCounter();
3735
3736     if (File::Success != fileLoad(newMapPath(), DefaultMap, VymMap)) {
3737         QMessageBox::critical(0, tr("Critical Error"),
3738                               tr("Couldn't load default map:\n\n%1\n\nvym will "
3739                                  "create an empty map now.",
3740                                  "Mainwindow: Failed to load default map")
3741                                   .arg(newMapPath()));
3742
3743         vm = currentModel();
3744
3745         // Create MapCenter for empty map  
3746         vm->addMapCenter(false);
3747         vm->makeDefault();
3748
3749         // For the very first map we do not have flagrows yet...
3750         vm->select("mc:");
3751
3752         // Set name to "unnamed"
3753         updateTabName(vm);
3754     }
3755     else {
3756         vm = currentModel();
3757     }
3758     
3759     // Switch to new tab    
3760     tabWidget->setCurrentIndex(tabWidget->count() - 1);
3761 }
3762
3763 void Main::fileNewCopy()
3764 {
3765     QString fn = "unnamed";
3766     VymModel *srcModel = currentModel();
3767     if (srcModel) {
3768         srcModel->copy();
3769         fileNew();
3770         VymModel *dstModel = view(tabWidget->count() - 1)->getModel();
3771         if (dstModel && dstModel->select("mc:0"))
3772             dstModel->paste();
3773         else
3774             qWarning() << "Main::fileNewCopy couldn't select mapcenter";
3775     }
3776 }
3777
3778 File::ErrorCode Main::fileLoad(QString fn, const LoadMode &lmode,
3779                                const FileType &ftype)
3780 {
3781     File::ErrorCode err = File::Success;
3782
3783     // fn is usually the archive, mapfile the file after uncompressing
3784     QString mapfile;
3785
3786     // Make fn absolute (needed for unzip)
3787     fn = QDir(fn).absolutePath();
3788
3789     VymModel *vm;
3790
3791     if (lmode == NewMap) {
3792         // Check, if map is already loaded
3793         int i = 0;
3794         while (i <= tabWidget->count() - 1) {
3795             if (view(i)->getModel()->getFilePath() == fn) {
3796                 // Already there, ask for confirmation
3797                 QMessageBox mb(
3798                     vymName,
3799                     tr("The map %1\nis already opened."
3800                        "Opening the same map in multiple editors may lead \n"
3801                        "to confusion when finishing working with vym."
3802                        "Do you want to")
3803                         .arg(fn),
3804                     QMessageBox::Warning,
3805                     QMessageBox::Yes | QMessageBox::Default,
3806                     QMessageBox::Cancel | QMessageBox::Escape,
3807                     QMessageBox::NoButton);
3808                 mb.setButtonText(QMessageBox::Yes, tr("Open anyway"));
3809                 mb.setButtonText(QMessageBox::Cancel, tr("Cancel"));
3810                 switch (mb.exec()) {
3811                 case QMessageBox::Yes:
3812                     // end loop and load anyway
3813                     i = tabWidget->count();
3814                     break;
3815                 case QMessageBox::Cancel:
3816                     // do nothing
3817                     return File::Aborted;
3818                     break;
3819                 }
3820             }
3821             i++;
3822         }
3823     }
3824
3825     bool createModel;
3826
3827     // Try to load map
3828     if (!fn.isEmpty()) {
3829         // Find out, if we need to create a new map model
3830
3831         vm = currentModel();
3832
3833         if (lmode == NewMap) {
3834             if (vm && vm->isDefault()) {
3835                 // There is a map model already and it still the default map,
3836                 // use it.
3837                 createModel = false;
3838             }
3839             else
3840                 createModel = true;
3841         }
3842         else if (lmode == DefaultMap) {
3843             createModel = true;
3844         }
3845         else if (lmode == ImportAdd || lmode == ImportReplace) {
3846             if (!vm) {
3847                 QMessageBox::warning(0, "Warning",
3848                                      "Trying to import into non existing map");
3849                 return File::Aborted;
3850             }
3851             else
3852                 createModel = false;
3853         }
3854         else
3855             createModel = true;
3856
3857         if (createModel) {
3858             vm = new VymModel;
3859             VymView *vv = new VymView(vm);
3860
3861             tabWidget->addTab(vv, fn);
3862             vv->initFocus();
3863         }
3864
3865         // Check, if file exists (important for creating new files
3866         // from command line
3867         if (!QFile(fn).exists()) {
3868             if (lmode == DefaultMap) {
3869                 return File::Aborted;
3870             }
3871
3872             if (lmode == NewMap) {
3873                 QMessageBox mb(vymName,
3874                                tr("This map does not exist:\n  %1\nDo you want "
3875                                   "to create a new one?")
3876                                    .arg(fn),
3877                                QMessageBox::Question, QMessageBox::Yes,
3878                                QMessageBox::Cancel | QMessageBox::Default,
3879                                QMessageBox::NoButton);
3880
3881                 mb.setButtonText(QMessageBox::Yes, tr("Create"));
3882                 mb.setButtonText(QMessageBox::No, tr("Cancel"));
3883
3884                 vm = currentMapEditor()->getModel();
3885                 switch (mb.exec()) {
3886                 case QMessageBox::Yes:
3887                     // Create new map
3888                     vm->setFilePath(fn);
3889                     updateTabName(vm);
3890                     statusBar()->showMessage("Created " + fn, statusbarTime);
3891                     return File::Success;
3892
3893                 case QMessageBox::Cancel:
3894                     // don't create new map
3895                     statusBar()->showMessage("Loading " + fn + " failed!",
3896                                              statusbarTime);
3897                     int cur = tabWidget->currentIndex();
3898                     tabWidget->setCurrentIndex(tabWidget->count() - 1);
3899                     fileCloseMap();
3900                     tabWidget->setCurrentIndex(cur);
3901                     return File::Aborted;
3902                 }
3903
3904                 // ImportAdd or ImportReplace
3905                 qWarning() << QString("Warning:  Could not import %1 into %2")
3906                                   .arg(fn)
3907                                   .arg(vm->getFilePath());
3908                 return File::Aborted;
3909             }
3910         }
3911
3912         if (err != File::Aborted) {
3913             // Save existing filename in case  we import
3914             QString fn_org = vm->getFilePath();
3915
3916             if (lmode != DefaultMap) {
3917
3918                 vm->setFilePath(fn);
3919                 vm->saveStateBeforeLoad(lmode, fn);
3920
3921                 progressDialog.setLabelText(
3922                     tr("Loading: %1", "Progress dialog while loading maps")
3923                         .arg(fn));
3924             }
3925
3926             // Finally load map into mapEditor
3927             err = vm->loadMap(fn, lmode, ftype);
3928
3929             // Restore old (maybe empty) filepath, if this is an import
3930             if (lmode == ImportAdd || lmode == ImportReplace)
3931                 vm->setFilePath(fn_org);
3932         }
3933
3934         // Finally check for errors and go home
3935         if (err == File::Aborted) {
3936             if (lmode == NewMap)
3937                 fileCloseMap();
3938             statusBar()->showMessage("Could not load " + fn, statusbarTime);
3939         }
3940         else {
3941             if (lmode == NewMap) {
3942                 vm->setFilePath(fn);
3943                 updateTabName(vm);
3944                 actionFilePrint->setEnabled(true);
3945                 addRecentMap(fn);
3946             }
3947             else if (lmode == DefaultMap) {
3948                 vm->makeDefault();
3949                 updateTabName(vm);
3950             }
3951             editorChanged();
3952             vm->emitShowSelection();
3953             statusBar()->showMessage(tr("Loaded %1").arg(fn), statusbarTime);
3954         }
3955     }
3956
3957     fileSaveSession();
3958
3959     return err;
3960 }
3961
3962 void Main::fileLoad(const LoadMode &lmode)
3963 {
3964     QString caption;
3965     switch (lmode) {
3966     case NewMap:
3967         caption = vymName + " - " + tr("Load vym map");
3968         break;
3969     case DefaultMap:
3970         // Not used directly
3971         return;
3972     case ImportAdd:
3973         caption = vymName + " - " + tr("Import: Add vym map to selection");
3974         break;
3975     case ImportReplace:
3976         caption =
3977             vymName + " - " + tr("Import: Replace selection with vym map");
3978         break;
3979     }
3980
3981     QString filter;
3982     filter += "VYM map " + tr("or", "File Dialog") + " Freemind map" +
3983               " (*.xml *.vym *.vyp *.mm);;";
3984     filter += "VYM map (*.vym *.vyp);;";
3985     filter += "VYM Backups (*.vym~);;";
3986     filter += "Freemind map (*.mm);;";
3987     filter += "XML (*.xml);;";
3988     filter += "All (* *.*)";
3989     QStringList fns =
3990         QFileDialog::getOpenFileNames(this, caption, lastMapDir.path(), filter);
3991
3992     if (!fns.isEmpty()) {
3993         initProgressCounter(fns.count());
3994         lastMapDir.setPath(fns.first().left(fns.first().lastIndexOf("/")));
3995         foreach (QString fn, fns)
3996             fileLoad(fn, lmode, getMapType(fn));
3997     }
3998     removeProgressCounter();
3999 }
4000
4001 void Main::fileLoad()
4002 {
4003     fileLoad(NewMap);
4004     tabWidget->setCurrentIndex(tabWidget->count() - 1);
4005 }
4006
4007 void Main::fileSaveSession()
4008 {
4009     QStringList flist;
4010     for (int i = 0; i < tabWidget->count(); i++)
4011         flist.append(view(i)->getModel()->getFilePath());
4012
4013     settings.setValue("/mainwindow/sessionFileList", flist);
4014
4015     // Also called by event loop regulary, but apparently not often enough
4016     settings.sync();
4017 }
4018
4019 void Main::fileRestoreSession()
4020 {
4021     restoreMode = true;
4022
4023     QStringList::Iterator it = lastSessionFiles.begin();
4024
4025     initProgressCounter(lastSessionFiles.count());
4026     while (it != lastSessionFiles.end()) {
4027         FileType type = getMapType(*it);
4028         fileLoad(*it, NewMap, type);
4029         *it++;
4030     }
4031     removeProgressCounter();
4032
4033     // By now all files should have been loaded
4034     // Reset the restore flag and display message if needed
4035     if (ignoredLockedFiles.count() > 0) {
4036         QString msg(
4037             QObject::tr("Existing lockfiles have been ignored for the maps "
4038                         "listed below. Please check, if the maps might be "
4039                         "openend in another instance of vym:\n\n"));
4040         WarningDialog warn;
4041         warn.setMinimumWidth(800);
4042         warn.setMinimumHeight(350);
4043         warn.showCancelButton(false);
4044         warn.setCaption("Existing lockfiles ignored");
4045         warn.setText(msg + ignoredLockedFiles.join("\n"));
4046         warn.exec();
4047     }
4048
4049     restoreMode = false;
4050     ignoredLockedFiles.clear();
4051 }
4052
4053 void Main::fileLoadRecent()
4054 {
4055     QAction *action = qobject_cast<QAction *>(sender());
4056     if (action) {
4057         initProgressCounter();
4058         QString fn = action->data().toString();
4059         FileType type = getMapType(fn);
4060         fileLoad(fn, NewMap, type);
4061         removeProgressCounter();
4062         tabWidget->setCurrentIndex(tabWidget->count() - 1);
4063     }
4064 }
4065
4066 void Main::addRecentMap(const QString &fileName)
4067 {
4068
4069     QStringList files =
4070         settings.value("/mainwindow/recentFileList").toStringList();
4071     files.removeAll(fileName);
4072     files.prepend(fileName);
4073     while (files.size() > MaxRecentFiles)
4074         files.removeLast();
4075
4076     settings.setValue("/mainwindow/recentFileList", files);
4077
4078     setupRecentMapsMenu();
4079 }
4080
4081 void Main::fileSave(VymModel *m, const SaveMode &savemode)
4082 {
4083     if (!m)
4084         return;
4085
4086     if (m->isReadOnly())
4087         return;
4088
4089     if (m->getFilePath().isEmpty()) {
4090         // We have  no filepath yet,
4091         // call fileSaveAs() now, this will call fileSave()
4092         // again.  First switch to editor
4093         fileSaveAs(savemode);
4094         return; // avoid saving twice...
4095     }
4096
4097     // Notification, that we start to save
4098     statusBar()->showMessage(tr("Saving  %1...").arg(m->getFilePath()),
4099                          statusbarTime);
4100     qApp->processEvents();
4101
4102     if (m->save(savemode) == File::Success) {
4103         statusBar()->showMessage(tr("Saved  %1").arg(m->getFilePath()),
4104                                  statusbarTime);
4105     }
4106     else
4107         statusBar()->showMessage(tr("Couldn't save ").arg(m->getFilePath()),
4108                                  statusbarTime);
4109 }
4110
4111 void Main::fileSave() { fileSave(currentModel(), CompleteMap); }
4112
4113 void Main::fileSave(VymModel *m) { fileSave(m, CompleteMap); }
4114
4115 void Main::fileSaveAs(const SaveMode &savemode)
4116 {
4117     VymModel *m = currentModel();
4118     if (!m) return;
4119
4120     if (currentMapEditor()) {   // FIXME-2 this check is not needed
4121         QString filter;
4122         if (savemode == CompleteMap)
4123             filter = "VYM map (*.vym)";
4124         else
4125             filter = "VYM part of map (*vyp)";
4126         filter += ";;All (* *.*)";
4127
4128         // Get destination path
4129         QString fn = QFileDialog::getSaveFileName(
4130             this, tr("Save map as"), lastMapDir.path(), filter, NULL,
4131             QFileDialog::DontConfirmOverwrite);
4132         if (!fn.isEmpty()) {
4133             // Check for existing file
4134             if (QFile(fn).exists()) {
4135                 // Check if the existing file is writable
4136                 if (!QFileInfo(fn).isWritable()) {
4137                     QMessageBox::critical(0, tr("Critical Error"),
4138                                           tr("Couldn't save %1,\nbecause file "
4139                                              "exists and cannot be changed.")
4140                                               .arg(fn));
4141                     return;
4142                 }
4143
4144                 QMessageBox mb(
4145                     vymName,
4146                     tr("The file %1\nexists already. Do you want to").arg(fn),
4147                     QMessageBox::Warning,
4148                     QMessageBox::Yes | QMessageBox::Default,
4149                     QMessageBox::Cancel | QMessageBox::Escape,
4150                     QMessageBox::NoButton);
4151                 mb.setButtonText(QMessageBox::Yes, tr("Overwrite"));
4152                 mb.setButtonText(QMessageBox::Cancel, tr("Cancel"));
4153                 switch (mb.exec()) {
4154                 case QMessageBox::Yes:
4155                     // save
4156                     break;
4157                 case QMessageBox::Cancel:
4158                     // do nothing
4159                     return;
4160                     break;
4161                 }
4162                 lastMapDir.setPath(fn.left(fn.lastIndexOf("/")));
4163             }
4164             else {
4165                 // New file, add extension to filename, if missing
4166                 // This is always .vym or .vyp, depending on savemode
4167                 if (savemode == CompleteMap) {
4168                     if (!fn.contains(".vym") && !fn.contains(".xml"))
4169                         fn += ".vym";
4170                 }
4171                 else {
4172                     if (!fn.contains(".vyp") && !fn.contains(".xml"))
4173                         fn += ".vyp";
4174                 }
4175             }
4176
4177             // Save original filepath, might want to restore after saving
4178             QString fn_org = m->getFilePath();
4179
4180             // Check for existing lockfile
4181             QFile lockFile(fn + ".lock");
4182             if (lockFile.exists()) {
4183                 QMessageBox::critical(0, tr("Critical Error"),
4184                                       tr("Couldn't save %1,\nbecause of "
4185                                          "existing lockfile:\n\n%2")
4186                                           .arg(fn)
4187                                           .arg(lockFile.fileName()));
4188                 return;
4189             }
4190
4191             if (!m->renameMap(fn)) {
4192                 QMessageBox::critical(0, tr("Critical Error"),
4193                                       tr("Saving the map failed:\nCouldn't rename map to %1").arg(fn));
4194                 return; // FIXME-3 Check: If saved part of map and this error occurs?
4195             }
4196
4197             fileSave(m, savemode);
4198
4199             // Set name of tab
4200             if (savemode == CompleteMap)
4201                 updateTabName(m);
4202             else { // Renaming map to original name, because we only saved the
4203                    // selected part of it
4204                 m->setFilePath(fn_org);
4205                 if (!m->renameMap(fn_org)) {
4206                     QMessageBox::critical(0, "Critical Error",
4207                                           "Couldn't rename map back to " + fn_org);
4208                 }
4209             }
4210             return;
4211         }
4212     }
4213 }
4214
4215 void Main::fileSaveAs() { fileSaveAs(CompleteMap); }
4216
4217 void Main::fileSaveAsDefault()
4218 {
4219     if (currentMapEditor()) {
4220         QString fn = QFileDialog::getSaveFileName(
4221             this, tr("Save map as new default map"), newMapPath(),
4222             "VYM map (*.vym)", NULL, QFileDialog::DontConfirmOverwrite);
4223
4224         if (!fn.isEmpty()) {
4225             // Check for existing file
4226             if (QFile(fn).exists()) {
4227                 // Check if the existing file is writable
4228                 if (!QFileInfo(fn).isWritable()) {
4229                     QMessageBox::critical(
4230                         0, tr("Warning"),
4231                         tr("You have no permissions to write to ") + fn);
4232                     return;
4233                 }
4234
4235                 // Confirm overwrite of existing file
4236                 QMessageBox mb(
4237                     vymName,
4238                     tr("The file %1\nexists already. Do you want to").arg(fn),
4239                     QMessageBox::Warning,
4240                     QMessageBox::Yes | QMessageBox::Default,
4241                     QMessageBox::Cancel | QMessageBox::Escape,
4242                     QMessageBox::NoButton);
4243                 mb.setButtonText(QMessageBox::Yes,
4244                                  tr("Overwrite as new default map"));
4245                 mb.setButtonText(QMessageBox::Cancel, tr("Cancel"));
4246                 switch (mb.exec()) {
4247                 case QMessageBox::Yes:
4248                     // save
4249                     break;
4250                 case QMessageBox::Cancel:
4251                     // do nothing
4252                     return;
4253                     break;
4254                 }
4255             }
4256
4257             // Save now as new default
4258             VymModel *m = currentModel();
4259             QString fn_org = m->getFilePath(); // Restore fn later, if savemode
4260                                                // != CompleteMap
4261             // Check for existing lockfile
4262             QFile lockFile(fn + ".lock");
4263             if (lockFile.exists()) {
4264                 QMessageBox::critical(
4265                     0, tr("Critical Error"),
4266                     tr("Couldn't save %1,\nbecause of existing lockfile:\n\n%2")
4267                         .arg(fn)
4268                         .arg(lockFile.fileName()));
4269                 return;
4270             }
4271
4272             if (!m->renameMap(fn)) {
4273                 QMessageBox::critical(0, tr("Critical Error"),
4274                                       tr("Couldn't save as default, failed to rename to\n%1").arg(fn));
4275                 return;
4276             }
4277
4278             fileSave(m, CompleteMap);
4279
4280             // Set name of tab
4281             updateTabName(m);
4282
4283             // Set new default path
4284             settings.setValue("/system/defaultMap/auto", false);
4285             settings.setValue("/system/defaultMap/path", fn);
4286         }
4287     }
4288 }
4289
4290 void Main::fileImportFirefoxBookmarks()
4291 {
4292     VymModel *m = currentModel();
4293     if (!m) {
4294         fileNew();
4295         m = currentModel();
4296         if (!m) return;
4297     } else {
4298         if (!m->isDefault())
4299             // Import into new map
4300             fileNew();
4301     }
4302
4303     if (m) {
4304         // Try to select first mapcenter of default map
4305         if (!m->select("mc:0")) return;
4306
4307         m->setHeadingPlainText("Firefox");
4308
4309         // Try to add one branch and select it
4310         /*
4311         if (!m->addNewBranch()) return;
4312
4313         m->selectLatestAdded();
4314         m->setHeadingPlainText("Bookmarks");
4315         */
4316
4317         // Open file dialog
4318         QFileDialog fd;
4319         fd.setDirectory(vymBaseDir.homePath());
4320         fd.setFileMode(QFileDialog::ExistingFiles);
4321         QStringList filters;
4322         filters << tr("Firefox Bookmarks") + " (*.json)";
4323         fd.setNameFilters(filters);
4324         fd.setAcceptMode(QFileDialog::AcceptOpen);
4325         fd.setWindowTitle(tr("Import Firefox Bookmarks into new map"));
4326         fd.setLabelText( QFileDialog::Accept, tr("Import"));
4327
4328         if (fd.exec() == QDialog::Accepted) {
4329             qApp->processEvents(); // close QFileDialog
4330             ImportFirefoxBookmarks im(m);
4331             QStringList flist = fd.selectedFiles();
4332             QStringList::Iterator it = flist.begin();
4333             while (it != flist.end()) {
4334                 im.setFile(*it);
4335                 im.transform(); 
4336                 ++it;
4337             }
4338         }
4339     }
4340 }
4341
4342 void Main::fileImportFreemind()
4343 {
4344     QStringList filters;
4345     filters << "Freemind map (*.mm)"
4346             << "All files (*)";
4347     QFileDialog fd;
4348     fd.setDirectory(lastMapDir);
4349     fd.setFileMode(QFileDialog::ExistingFiles);
4350     fd.setNameFilters(filters);
4351     fd.setWindowTitle(vymName + " - " + tr("Open Freemind map"));
4352     fd.setAcceptMode(QFileDialog::AcceptOpen);
4353
4354     QString fn;
4355     if (fd.exec() == QDialog::Accepted) {
4356         lastMapDir = fd.directory();
4357         QStringList flist = fd.selectedFiles();
4358         QStringList::Iterator it = flist.begin();
4359         while (it != flist.end()) {
4360             fn = *it;
4361             if (fileLoad(fn, NewMap, FreemindMap)) {
4362                 currentMapEditor()->getModel()->setFilePath("");
4363             }
4364             ++it;
4365         }
4366     }
4367 }
4368
4369 void Main::fileImportMM()
4370 {
4371     ImportMM im;
4372
4373     QFileDialog fd;
4374     fd.setDirectory(lastMapDir);
4375     fd.setFileMode(QFileDialog::ExistingFiles);
4376     QStringList filters;
4377     filters << "Mind Manager (*.mmap)";
4378     fd.setNameFilters(filters);
4379     fd.setAcceptMode(QFileDialog::AcceptOpen);
4380     fd.setWindowTitle(tr("Import") + " " + "Mind Manager");
4381     fd.setLabelText( QFileDialog::Accept, tr("Import"));
4382
4383     if (fd.exec() == QDialog::Accepted) {
4384         lastMapDir = fd.directory();
4385         QStringList flist = fd.selectedFiles();
4386         QStringList::Iterator it = flist.begin();
4387         while (it != flist.end()) {
4388             im.setFile(*it);
4389             if (im.transform() &&
4390                 File::Success ==
4391                     fileLoad(im.getTransformedFile(), NewMap, VymMap) &&
4392                 currentMapEditor())
4393                 currentMapEditor()->getModel()->setFilePath("");
4394             ++it;
4395         }
4396     }
4397 }
4398
4399 void Main::fileImportDir()
4400 {
4401     VymModel *m = currentModel();
4402     if (m)
4403         m->importDir();
4404 }
4405
4406 void Main::fileExportAO()
4407 {
4408     VymModel *m = currentModel();
4409     if (m)
4410         m->exportAO();
4411 }
4412
4413 void Main::fileExportASCII()
4414 {
4415     VymModel *m = currentModel();
4416     if (m)
4417         m->exportASCII();
4418 }
4419
4420 void Main::fileExportASCIITasks()
4421 {
4422     VymModel *m = currentModel();
4423     if (m)
4424         m->exportASCII("", true);
4425 }
4426
4427 void Main::fileExportConfluence()
4428 {
4429     VymModel *m = currentModel();
4430     if (m)
4431         m->exportConfluence();
4432 }
4433
4434 #include "export-csv.h"
4435 void Main::fileExportCSV() // FIXME-3 not scriptable yet
4436 {
4437     VymModel *m = currentModel();
4438     if (m) {
4439         ExportCSV ex;
4440         ex.setModel(m);
4441         ex.addFilter("CSV (*.csv)");
4442         ex.setDirPath(lastImageDir.absolutePath());
4443         ex.setWindowTitle(vymName + " -" + tr("Export as CSV") + " " +
4444                           tr("(still experimental)"));
4445         if (ex.execDialog()) {
4446             m->setExportMode(true);
4447             ex.doExport();
4448             m->setExportMode(false);
4449         }
4450     }
4451 }
4452
4453 void Main::fileExportFirefoxBookmarks()
4454 {
4455     VymModel *m = currentModel();
4456     if (m)
4457         m->exportFirefoxBookmarks();
4458 }
4459
4460 void Main::fileExportHTML()
4461 {
4462     VymModel *m = currentModel();
4463     if (m)
4464         m->exportHTML();
4465 }
4466
4467 void Main::fileExportImage()
4468 {
4469     VymModel *m = currentModel();
4470     if (m)
4471         m->exportImage();
4472 }
4473
4474 #include "export-impress.h"
4475 #include "exportoofiledialog.h"
4476 void Main::fileExportImpress()
4477 {
4478     ExportOOFileDialog fd;
4479     // TODO add preview in dialog
4480     fd.setWindowTitle(vymName + " - " + tr("Export to") + " LibreOffice");
4481     fd.setDirectory(QDir().current());
4482     fd.setAcceptMode(QFileDialog::AcceptSave);
4483     fd.setFileMode(QFileDialog::AnyFile);
4484     if (fd.foundConfig()) {
4485         if (fd.exec() == QDialog::Accepted) {
4486             if (!fd.selectedFiles().isEmpty()) {
4487                 QString fn = fd.selectedFiles().first();
4488                 if (!fn.contains(".odp"))
4489                     fn += ".odp";
4490
4491                 // lastImageDir=fn.left(fn.findRev ("/"));
4492                 VymModel *m = currentModel();
4493                 if (m)
4494                     m->exportImpress(fn, fd.selectedConfig());
4495             }
4496         }
4497     }
4498     else {
4499         QMessageBox::warning(
4500             0, tr("Warning"),
4501             tr("Couldn't find configuration for export to LibreOffice\n"));
4502     }
4503 }
4504
4505 #include "export-latex.h"
4506 void Main::fileExportLaTeX()
4507 {
4508     VymModel *m = currentModel();
4509     if (m)
4510         m->exportLaTeX();
4511 }
4512
4513 void Main::fileExportMarkdown()
4514 {
4515     VymModel *m = currentModel();
4516     if (m)
4517         m->exportMarkdown();
4518 }
4519
4520 void Main::fileExportOrgMode()
4521 {
4522     VymModel *m = currentModel();
4523     if (m)
4524         m->exportOrgMode();
4525 }
4526
4527 void Main::fileExportPDF()
4528 {
4529     VymModel *m = currentModel();
4530     if (m)
4531         m->exportPDF();
4532 }
4533
4534 void Main::fileExportSVG()
4535 {
4536     VymModel *m = currentModel();
4537     if (m)
4538         m->exportSVG();
4539 }
4540
4541 #include "export-taskjuggler.h"
4542 void Main::fileExportTaskjuggler() // FIXME-3 not scriptable yet
4543 {
4544     ExportTaskjuggler ex;
4545     VymModel *m = currentModel();
4546     if (m) {
4547         ex.setModel(m);
4548         ex.setWindowTitle(vymName + " - " + tr("Export to") + " Taskjuggler" +
4549                           tr("(still experimental)"));
4550         ex.setDirPath(lastImageDir.absolutePath());
4551         ex.addFilter("Taskjuggler (*.tjp)");
4552
4553         if (ex.execDialog()) {
4554             m->setExportMode(true);
4555             ex.doExport();
4556             m->setExportMode(false);
4557         }
4558     }
4559 }
4560
4561 void Main::fileExportXML()
4562 {
4563     VymModel *m = currentModel();
4564     if (m)
4565         m->exportXML();
4566 }
4567
4568 void Main::fileExportLast()
4569 {
4570     VymModel *m = currentModel();
4571     if (m)
4572         m->exportLast();
4573 }
4574
4575 bool Main::fileCloseMap(int i)
4576 {
4577     VymModel *m;
4578     VymView *vv;
4579     if (i < 0)
4580         i = tabWidget->currentIndex();
4581
4582     vv = view(i);
4583     m = vv->getModel();
4584
4585     if (m) {
4586         if (m->hasChanged()) {
4587             QMessageBox mb(
4588                 vymName,
4589                 tr("The map %1 has been modified but not saved yet. Do you "
4590                    "want to")
4591                     .arg(m->getFileName()),
4592                 QMessageBox::Warning, QMessageBox::Yes | QMessageBox::Default,
4593                 QMessageBox::No, QMessageBox::Cancel | QMessageBox::Escape);
4594             mb.setButtonText(QMessageBox::Yes,
4595                              tr("Save modified map before closing it"));
4596             mb.setButtonText(QMessageBox::No, tr("Discard changes"));
4597             mb.setModal(true);
4598             mb.show();
4599             switch (mb.exec()) {
4600             case QMessageBox::Yes:
4601                 // save and close
4602                 fileSave(m, CompleteMap);
4603                 break;
4604             case QMessageBox::No:
4605                 // close  without saving
4606                 break;
4607             case QMessageBox::Cancel:
4608                 // do nothing
4609                 return true;
4610             }
4611         }
4612
4613         tabWidget->removeTab(i);
4614
4615         // Destroy stuff, order is important
4616         delete (m->getMapEditor());
4617         delete (vv);
4618         delete (m);
4619
4620         updateActions();
4621         return false;
4622     }
4623     return true; // Better don't exit vym if there is no currentModel()...
4624 }
4625
4626 void Main::filePrint()
4627 {
4628     if (currentMapEditor())
4629         currentMapEditor()->print();
4630 }
4631
4632 bool Main::fileExitVYM()
4633 {
4634     fileSaveSession();
4635
4636     // Check if one or more editors have changed
4637     while (tabWidget->count() > 0) {
4638         tabWidget->setCurrentIndex(0);
4639         if (fileCloseMap())
4640             return true;
4641         qApp->processEvents(); // Update widgets to show progress
4642     }
4643     qApp->quit();
4644     return false;
4645 }
4646
4647 void Main::editUndo()
4648 {
4649     VymModel *m = currentModel();
4650     if (m)
4651         m->undo();
4652 }
4653
4654 void Main::editRedo()
4655 {
4656     VymModel *m = currentModel();
4657     if (m)
4658         m->redo();
4659 }
4660
4661 void Main::gotoHistoryStep(int i)
4662 {
4663     VymModel *m = currentModel();
4664     if (m)
4665         m->gotoHistoryStep(i);
4666 }
4667
4668 void Main::editCopy()
4669 {
4670     VymModel *m = currentModel();
4671     if (m)
4672         m->copy();
4673 }
4674
4675 void Main::editPaste()
4676 {
4677     VymModel *m = currentModel();
4678     if (m)
4679         m->paste();
4680 }
4681
4682 void Main::editCut()
4683 {
4684     VymModel *m = currentModel();
4685     if (m)
4686         m->cut();
4687 }
4688
4689 bool Main::openURL(const QString &url)
4690 {
4691     if (url.isEmpty())
4692         return false;
4693
4694     QString browser = settings.value("/system/readerURL").toString();
4695     QStringList args;
4696     args << url;
4697     if (!QProcess::startDetached(browser, args, QDir::currentPath(),
4698                                  browserPID)) {
4699         // try to set path to browser
4700         QMessageBox::warning(
4701             0, tr("Warning"),
4702             tr("Couldn't find a viewer to open %1.\n").arg(url) +
4703                 tr("Please use Settings->") +
4704                 tr("Set application to open an URL"));
4705         settingsURL();
4706         return false;
4707     }
4708     return true;
4709 }
4710
4711 void Main::openTabs(QStringList urls)
4712 {
4713     if (urls.isEmpty())
4714         return;
4715
4716     // Other browser, e.g. xdg-open
4717     // Just open all urls and leave it to the system to cope with it
4718     foreach (QString u, urls)
4719         openURL(u);
4720 }
4721
4722 void Main::editOpenURL()
4723 {
4724     // Open new browser
4725     VymModel *m = currentModel();
4726     if (m) {
4727         QString url = m->getURL();
4728         if (url == "")
4729             return;
4730         openURL(url);
4731     }
4732 }
4733 void Main::editOpenURLTab()
4734 {
4735     VymModel *m = currentModel();
4736     if (m) {
4737         QStringList urls;
4738         urls.append(m->getURL());
4739         openTabs(urls);
4740     }
4741 }
4742
4743 void Main::editOpenMultipleVisURLTabs(bool ignoreScrolled)
4744 {
4745     VymModel *m = currentModel();
4746     if (m) {
4747         QStringList urls;
4748         urls = m->getURLs(ignoreScrolled);
4749         openTabs(urls);
4750     }
4751 }
4752
4753 void Main::editOpenMultipleURLTabs() { editOpenMultipleVisURLTabs(false); }
4754
4755 void Main::editNote2URLs()
4756 {
4757     VymModel *m = currentModel();
4758     if (m)
4759         m->note2URLs();
4760 }
4761
4762 void Main::editURL()
4763 {
4764     VymModel *m = currentModel();
4765     if (m) {
4766         QInputDialog *dia = new QInputDialog(this);
4767         dia->setLabelText(tr("Enter URL:"));
4768         dia->setWindowTitle(vymName);
4769         dia->setInputMode(QInputDialog::TextInput);
4770         TreeItem *selti = m->getSelectedItem();
4771         if (selti)
4772             dia->setTextValue(selti->getURL());
4773         dia->resize(width() * 0.6, 80);
4774         centerDialog(dia);
4775
4776         if (dia->exec())
4777             m->setURL(dia->textValue());
4778         delete dia;
4779     }
4780 }
4781
4782 void Main::editLocalURL()
4783 {
4784     VymModel *m = currentModel();
4785     if (m) {
4786         TreeItem *selti = m->getSelectedItem();
4787         if (selti) {
4788             QString filter;
4789             filter += "All files (*);;";
4790             filter += tr("HTML", "Filedialog") + " (*.html,*.htm);;";
4791             filter += tr("Text", "Filedialog") + " (*.txt);;";
4792             filter += tr("Spreadsheet", "Filedialog") + " (*.odp,*.sxc);;";
4793             filter += tr("Textdocument", "Filedialog") + " (*.odw,*.sxw);;";
4794             filter += tr("Images", "Filedialog") +
4795                       " (*.png *.bmp *.xbm *.jpg *.png *.xpm *.gif *.pnm)";
4796
4797             QString fn = QFileDialog::getOpenFileName(
4798                 this, vymName + " - " + tr("Set URL to a local file"),
4799                 lastMapDir.path(), filter);
4800
4801             if (!fn.isEmpty()) {
4802                 lastMapDir.setPath(fn.left(fn.lastIndexOf("/")));
4803                 if (!fn.startsWith("file://"))
4804                     fn = "file://" + fn;
4805                 m->setURL(fn);
4806             }
4807         }
4808     }
4809 }
4810
4811 void Main::editHeading2URL()
4812 {
4813     VymModel *m = currentModel();
4814     if (m)
4815         m->editHeading2URL();
4816 }
4817
4818 void Main::getJiraDataSubtree()
4819 {
4820     VymModel *m = currentModel();
4821     if (m)
4822         m->getJiraData(true);
4823 }
4824
4825 void Main::setHeadingConfluencePageName()
4826 {
4827     VymModel *m = currentModel();
4828     if (m)
4829         m->setHeadingConfluencePageName();
4830 }
4831
4832 void Main::getConfluenceUser()
4833 {
4834     VymModel *m = currentModel();
4835     if (m) {
4836         BranchItem *selbi = m->getSelectedBranch();
4837         if (selbi) {
4838             ConfluenceUserDialog *dia = new ConfluenceUserDialog;
4839             centerDialog(dia);
4840             if (dia->exec() > 0) {
4841                 BranchItem *bi = m->addNewBranch();
4842                 if (!bi) return;
4843                 if (!m->select(bi)) return;
4844                 selbi = m->getSelectedBranch();
4845
4846                 ConfluenceUser user = dia->getSelectedUser();
4847
4848                 AttributeItem *ai;
4849
4850                 ai = new AttributeItem();
4851                 ai->setKey("ConfluenceUser.displayName");
4852                 ai->setValue(user.getDisplayName());
4853                 m->setAttribute(selbi, ai);
4854
4855                 ai = new AttributeItem();
4856                 ai->setKey("ConfluenceUser.userKey");
4857                 ai->setValue(user.getUserKey());
4858                 m->setAttribute(selbi, ai);
4859
4860                 ai = new AttributeItem();
4861                 ai->setKey("ConfluenceUser.userName");
4862                 ai->setValue(user.getUserName());
4863                 m->setAttribute(selbi, ai);
4864
4865                 ai = new AttributeItem();
4866                 ai->setKey("ConfluenceUser.url");
4867                 ai->setValue(user.getURL());
4868                 m->setAttribute(selbi, ai);
4869
4870                 m->setURL(user.getURL(), false);
4871                 m->setHeading(user.getDisplayName());
4872
4873                 m->selectParent();
4874             }
4875             dia->clearFocus();
4876             delete dia;
4877             m->getMapEditor()->activateWindow();
4878             m->getMapEditor()->setFocus();
4879         }
4880     }
4881 }
4882
4883 void Main::editHeading()
4884 {
4885     MapEditor *me = currentMapEditor();
4886     if (me)
4887         me->editHeading();
4888 }
4889
4890 void Main::editHeadingFinished(VymModel *m)
4891 {
4892     if (m) {
4893         if (!actionSettingsAutoSelectNewBranch->isChecked() &&
4894             !prevSelection.isEmpty())
4895             m->select(prevSelection);
4896         prevSelection = "";
4897     }
4898 }
4899
4900 void Main::openVymLinks(const QStringList &vl, bool background)
4901 {
4902     QStringList vlmin;
4903     int index = -1;
4904     for (int j = 0; j < vl.size(); ++j) {
4905         // compare path with already loaded maps
4906         QString absPath = QFileInfo(vl.at(j)).absoluteFilePath();
4907         index = -1;
4908         for (int i = 0; i <= tabWidget->count() - 1; i++) {
4909             if (absPath == view(i)->getModel()->getFilePath()) {
4910                 index = i;
4911                 break;
4912             }
4913         }
4914         if (index < 0)
4915             vlmin.append(absPath);
4916     }
4917
4918     progressCounterTotal = vlmin.size();
4919     for (int j = 0; j < vlmin.size(); j++) {
4920         // Load map
4921         if (!QFile(vlmin.at(j)).exists())
4922             QMessageBox::critical(0, tr("Critical Error"),
4923                                   tr("Couldn't open map %1").arg(vlmin.at(j)));
4924         else {
4925             fileLoad(vlmin.at(j), NewMap, VymMap);
4926             if (!background)
4927                 tabWidget->setCurrentIndex(tabWidget->count() - 1);
4928         }
4929     }
4930     // Go to tab containing the map
4931     if (index >= 0)
4932         tabWidget->setCurrentIndex(index);
4933     removeProgressCounter();
4934 }
4935
4936 void Main::editOpenVymLink(bool background)
4937 {
4938     VymModel *m = currentModel();
4939     if (m) {
4940         QStringList vl;
4941         vl.append(m->getVymLink());
4942         openVymLinks(vl, background);
4943     }
4944 }
4945
4946 void Main::editOpenVymLinkBackground() { editOpenVymLink(true); }
4947
4948 void Main::editOpenMultipleVymLinks()
4949 {
4950     QString currentVymLink;
4951     VymModel *m = currentModel();
4952     if (m) {
4953         QStringList vl = m->getVymLinks();
4954         openVymLinks(vl, true);
4955     }
4956 }
4957
4958 void Main::editVymLink()
4959 {
4960     VymModel *m = currentModel();
4961     if (m) {
4962         BranchItem *bi = m->getSelectedBranch();
4963         if (bi) {
4964             QStringList filters;
4965             filters << "VYM map (*.vym)";
4966             QFileDialog fd;
4967             fd.setWindowTitle(vymName + " - " + tr("Link to another vym map"));
4968             fd.setNameFilters(filters);
4969             fd.setLabelText( QFileDialog::Accept, tr("Set as link to vym map"));
4970             fd.setDirectory(lastMapDir);
4971             fd.setAcceptMode(QFileDialog::AcceptOpen);
4972             if (!bi->getVymLink().isEmpty())
4973                 fd.selectFile(bi->getVymLink());
4974             fd.show();
4975
4976             QString fn;
4977             if (fd.exec() == QDialog::Accepted &&
4978                 !fd.selectedFiles().isEmpty()) {
4979                 QString fn = fd.selectedFiles().first();
4980                 lastMapDir = QDir(fd.directory().path());
4981                 m->setVymLink(fn);
4982             }
4983         }
4984     }
4985 }
4986
4987 void Main::editDeleteVymLink()
4988 {
4989     VymModel *m = currentModel();
4990     if (m)
4991         m->deleteVymLink();
4992 }
4993
4994 void Main::editToggleHideExport()
4995 {
4996     VymModel *m = currentModel();
4997     if (m)
4998         m->toggleHideExport();
4999 }
5000
5001 void Main::editToggleTask()
5002 {
5003     VymModel *m = currentModel();
5004     if (m)
5005         m->toggleTask();
5006 }
5007
5008 void Main::editCycleTaskStatus()
5009 {
5010     VymModel *m = currentModel();
5011     if (m)
5012         m->cycleTaskStatus();
5013 }
5014
5015 void Main::editTaskResetDeltaPrio()
5016 {
5017     QList <BranchItem*> taskBranches;
5018     Task *task;
5019     for (int i = 0; i < taskModel->count(); i++)
5020     {
5021         task = taskModel->getTask(i);
5022         if (taskEditor->taskVisible(task) && task->getPriorityDelta() != 0)
5023             taskBranches << task->getBranch();
5024     }
5025
5026     foreach (BranchItem *bi, taskBranches)
5027         bi->getModel()->setTaskPriorityDelta(0, bi);
5028 }
5029
5030 void Main::editTaskSleepN()
5031 {
5032     VymModel *m = currentModel();
5033     if (m) {
5034         qint64 n = ((QAction *)sender())->data().toInt();
5035         Task *task = m->getSelectedTask();
5036         if (task) {
5037             bool ok = true;
5038             QString s;
5039             if (n < 0) {
5040                 QString currentSleep;
5041                 QDateTime d = task->getSleep();
5042                 n = task->getSecsSleep();
5043                 if (n <= 0)
5044                     currentSleep = "0";
5045                 else if (n < 60)
5046                     currentSleep = QString("%1s").arg(n);
5047                 else if (n < 24 * 3600) {
5048                     currentSleep = d.time().toString("hh:mm");
5049                 }
5050                 else if (d.time().hour() == 0 && d.time().minute() == 0) {
5051                     currentSleep = d.date().toString("dd.MM.yyyy");
5052                 }
5053                 else
5054                     currentSleep = d.toString(Qt::ISODate);
5055
5056                 LineEditDialog *dia = new LineEditDialog(this);
5057                 dia->setLabel(tr("Enter sleep time (number of days, hours with "
5058                                  "'h' or date YYYY-MM-DD or DD.MM[.YYYY]",
5059                                  "task sleep time dialog"));
5060                 dia->setText(currentSleep);
5061                 centerDialog(dia);
5062                 if (dia->exec() == QDialog::Accepted) {
5063                     ok = true;
5064                     s = dia->getText();
5065                 }
5066                 else
5067                     ok = false;
5068
5069                 delete dia;
5070             }
5071             else
5072                 s = QString("%1").arg(n);
5073
5074             if (ok && !m->setTaskSleep(s))
5075                 QMessageBox::warning(
5076                     0, tr("Warning"),
5077                     tr("Couldn't set sleep time to %1.\n").arg(s));
5078         }
5079     }
5080 }
5081
5082 void Main::editAddTimestamp()
5083 {
5084     VymModel *m = currentModel();
5085     if (m)
5086         m->addTimestamp();
5087 }
5088
5089 void Main::editMapProperties()
5090 {
5091     VymModel *m = currentModel();
5092     if (!m)
5093         return;
5094
5095     ExtraInfoDialog dia;
5096     dia.setMapName(m->getFileName());
5097     dia.setFileLocation(m->getFilePath());
5098     dia.setMapTitle(m->getTitle());
5099     dia.setAuthor(m->getAuthor());
5100     dia.setComment(m->getComment());
5101     dia.setReadOnly(m->isReadOnly());
5102
5103     // Calc some stats
5104     QString stats;
5105     stats += tr("%1 items on map\n", "Info about map")
5106                  .arg(m->getScene()->items().size(), 6);
5107
5108     uint b = 0;
5109     uint f = 0;
5110     uint n = 0;
5111     uint xl = 0;
5112     BranchItem *cur = NULL;
5113     BranchItem *prev = NULL;
5114     m->nextBranch(cur, prev);
5115     while (cur) {
5116         if (!cur->getNote().isEmpty())
5117             n++;
5118         f += cur->imageCount();
5119         b++;
5120         xl += cur->xlinkCount();
5121         m->nextBranch(cur, prev);
5122     }
5123
5124     stats += QString("%1 %2\n")
5125                  .arg(m->branchCount(), 6)
5126                  .arg(tr("branches", "Info about map"));
5127     stats += QString("%1 %2\n")
5128                  .arg(taskModel->count(), 6)
5129                  .arg(tr("tasks total", "Info about map"));
5130     stats += QString("%1 %2\n")
5131                  .arg(taskModel->count(m), 6)
5132                  .arg(tr("tasks in map", "Info about map"));
5133     stats += QString("%1 %2\n").arg(n, 6).arg(tr("notes", "Info about map"));
5134     stats += QString("%1 %2\n").arg(f, 6).arg(tr("images", "Info about map"));
5135     stats += QString("%1 %2\n")
5136                  .arg(m->slideCount(), 6)
5137                  .arg(tr("slides", "Info about map"));
5138     stats +=
5139         QString("%1 %2\n").arg(xl / 2, 6).arg(tr("xLinks", "Info about map"));
5140     dia.setStats(stats);
5141
5142     // Finally show dialog
5143     if (dia.exec() == QDialog::Accepted) {
5144         m->setAuthor(dia.getAuthor());
5145         m->setComment(dia.getComment());
5146         m->setTitle(dia.getMapTitle());
5147     }
5148 }
5149
5150 void Main::editMoveUp()
5151 {
5152     MapEditor *me = currentMapEditor();
5153     VymModel *m = currentModel();
5154     if (me && m && me->getState() != MapEditor::EditingHeading)
5155         m->moveUp();
5156 }
5157
5158 void Main::editMoveDown()
5159 {
5160     MapEditor *me = currentMapEditor();
5161     VymModel *m = currentModel();
5162     if (me && m && me->getState() != MapEditor::EditingHeading)
5163         m->moveDown();
5164 }
5165
5166 void Main::editMoveDownDiagonally()
5167 {
5168     MapEditor *me = currentMapEditor();
5169     VymModel *m = currentModel();
5170     if (me && m && me->getState() != MapEditor::EditingHeading)
5171         m->moveDownDiagonally();
5172 }
5173
5174 void Main::editMoveUpDiagonally()
5175 {
5176     MapEditor *me = currentMapEditor();
5177     VymModel *m = currentModel();
5178     if (me && m && me->getState() != MapEditor::EditingHeading)
5179         m->moveUpDiagonally();
5180 }
5181
5182 void Main::editDetach()
5183 {
5184     VymModel *m = currentModel();
5185     if (m)
5186         m->detach();
5187 }
5188
5189 void Main::editSortChildren()
5190 {
5191     VymModel *m = currentModel();
5192     if (m)
5193         m->sortChildren(false);
5194 }
5195
5196 void Main::editSortBackChildren()
5197 {
5198     VymModel *m = currentModel();
5199     if (m)
5200         m->sortChildren(true);
5201 }
5202
5203 void Main::editToggleScroll()
5204 {
5205     VymModel *m = currentModel();
5206     if (m)
5207         m->toggleScroll();
5208 }
5209
5210 void Main::editExpandAll()
5211 {
5212     VymModel *m = currentModel();
5213     if (m)
5214         m->emitExpandAll();
5215 }
5216
5217 void Main::editExpandOneLevel()
5218 {
5219     VymModel *m = currentModel();
5220     if (m)
5221         m->emitExpandOneLevel();
5222 }
5223
5224 void Main::editCollapseOneLevel()
5225 {
5226     VymModel *m = currentModel();
5227     if (m)
5228         m->emitCollapseOneLevel();
5229 }
5230
5231 void Main::editCollapseUnselected()
5232 {
5233     VymModel *m = currentModel();
5234     if (m)
5235         m->emitCollapseUnselected();
5236 }
5237
5238 void Main::editUnscrollChildren()
5239 {
5240     VymModel *m = currentModel();
5241     if (m)
5242         m->unscrollChildren();
5243 }
5244
5245 void Main::editGrowSelectionSize()
5246 {
5247     VymModel *m = currentModel();
5248     if (m)
5249         m->growSelectionSize();
5250 }
5251
5252 void Main::editShrinkSelectionSize()
5253 {
5254     VymModel *m = currentModel();
5255     if (m)
5256         m->shrinkSelectionSize();
5257 }
5258
5259 void Main::editResetSelectionSize()
5260 {
5261     VymModel *m = currentModel();
5262     if (m)
5263         m->resetSelectionSize();
5264 }
5265
5266 void Main::editAddAttribute()
5267 {
5268     VymModel *m = currentModel();
5269     if (m) {
5270
5271         m->setAttribute();
5272     }
5273 }
5274
5275 void Main::editAddMapCenter()
5276 {
5277     VymModel *m = currentModel();
5278     if (m) {
5279         m->select(m->addMapCenter());
5280         MapEditor *me = currentMapEditor();
5281         if (me) {
5282             m->setHeadingPlainText("");
5283             me->editHeading();
5284         }
5285     }
5286 }
5287
5288 void Main::editNewBranch()
5289 {
5290     VymModel *m = currentModel();
5291     if (m) {
5292         BranchItem *bi = m->addNewBranch();
5293         if (!bi)
5294             return;
5295
5296         if (!actionSettingsAutoSelectNewBranch->isChecked())
5297             prevSelection = m->getSelectString();
5298
5299         m->select(bi);
5300         currentMapEditor()->editHeading();
5301     }
5302 }
5303
5304 void Main::editNewBranchBefore()
5305 {
5306     VymModel *m = currentModel();
5307     if (m) {
5308         if (!actionSettingsAutoSelectNewBranch->isChecked())
5309             prevSelection = m->getSelectString();
5310
5311         BranchItem *bi = m->addNewBranchBefore();
5312
5313         if (bi)
5314             m->select(bi);
5315         else
5316             return;
5317
5318         currentMapEditor()->editHeading();
5319     }
5320 }
5321
5322 void Main::editNewBranchAbove()
5323 {
5324     VymModel *m = currentModel();
5325     if (m) {
5326         if (!actionSettingsAutoSelectNewBranch->isChecked())
5327             prevSelection = m->getSelectString();
5328
5329         BranchItem *selbi = m->getSelectedBranch();
5330         if (selbi) {
5331             BranchItem *bi = m->addNewBranch(selbi, -3);
5332
5333             if (bi)
5334                 m->select(bi);
5335             else
5336                 return;
5337
5338             currentMapEditor()->editHeading();
5339         }
5340     }
5341 }
5342
5343 void Main::editNewBranchBelow()
5344 {
5345     VymModel *m = currentModel();
5346     if (m) {
5347         BranchItem *selbi = m->getSelectedBranch();
5348         if (selbi) {
5349             BranchItem *bi = m->addNewBranch(selbi, -1);
5350
5351             if (bi)
5352                 m->select(bi);
5353             else
5354                 return;
5355
5356             if (!actionSettingsAutoSelectNewBranch->isChecked())
5357                 prevSelection = m->getSelectString(bi);
5358
5359             currentMapEditor()->editHeading();
5360         }
5361     }
5362 }
5363
5364 void Main::editImportAdd() { fileLoad(ImportAdd); }
5365
5366 void Main::editImportReplace() { fileLoad(ImportReplace); }
5367
5368 void Main::editSaveBranch() { fileSaveAs(PartOfMap); }
5369
5370 void Main::editDeleteKeepChildren()
5371 {
5372     VymModel *m = currentModel();
5373     if (m)
5374         m->deleteKeepChildren();
5375 }
5376
5377 void Main::editDeleteChildren()
5378 {
5379     VymModel *m = currentModel();
5380     if (m)
5381         m->deleteChildren();
5382 }
5383
5384 void Main::editDeleteSelection()
5385 {
5386     VymModel *m = currentModel();
5387     if (m)
5388         m->deleteSelection();
5389 }
5390
5391 void Main::editLoadImage()
5392 {
5393     VymModel *m = currentModel();
5394     if (m)
5395         m->loadImage();
5396 }
5397
5398 void Main::editSaveImage()
5399 {
5400     VymModel *m = currentModel();
5401     if (m)
5402         m->saveImage();
5403 }
5404
5405 void Main::editEditXLink(QAction *a)
5406 {
5407     VymModel *m = currentModel();
5408     if (m) {
5409         BranchItem *selbi = m->getSelectedBranch();
5410         if (selbi) {
5411             Link *l = selbi
5412                           ->getXLinkItemNum(
5413                               branchXLinksContextMenuEdit->actions().indexOf(a))
5414                           ->getLink();
5415             if (l && m->select(l->getBeginLinkItem()))
5416                 m->editXLink();
5417         }
5418     }
5419 }
5420
5421 void Main::popupFollowXLink()
5422 {
5423     branchXLinksContextMenuFollow->exec(QCursor::pos());
5424 }
5425
5426 void Main::editFollowXLink(QAction *a)
5427 {
5428     VymModel *m = currentModel();
5429
5430     if (m)
5431         m->followXLink(branchXLinksContextMenuFollow->actions().indexOf(a));
5432 }
5433
5434 bool Main::initLinkedMapsMenu(VymModel *model, QMenu *menu)
5435 {
5436     if (model) {
5437         ItemList targets = model->getLinkedMaps();
5438
5439         menu->clear();
5440
5441         QStringList targetNames;
5442         QList<uint> targetIDs;
5443
5444         // Build QStringList with all names of targets
5445         QMap<uint, QStringList>::const_iterator i;
5446         i = targets.constBegin();
5447         while (i != targets.constEnd()) {
5448             targetNames.append(i.value().first());
5449             targetIDs.append(i.key());
5450             ++i;
5451         }
5452
5453         // Sort list of names
5454         targetNames.sort(Qt::CaseInsensitive);
5455
5456         // Build menu based on sorted names
5457         while (!targetNames.isEmpty()) {
5458             // Find target by value
5459             i = targets.constBegin();
5460             while (i != targets.constEnd()) {
5461                 if (i.value().first() == targetNames.first())
5462                     break;
5463                 ++i;
5464             }
5465
5466             menu->addAction(targetNames.first())->setData(i.value().last());
5467             targetNames.removeFirst();
5468             targets.remove(i.key());
5469         }
5470         return true;
5471     }
5472     return false;
5473 }
5474
5475 void Main::editGoToLinkedMap()
5476 {
5477     VymModel *model = currentModel();
5478     if (initLinkedMapsMenu(model, targetsContextMenu)) {
5479         QAction *a = targetsContextMenu->exec(QCursor::pos());
5480         if (a) {
5481             QStringList sl;
5482             sl << a->data().toString();
5483             openVymLinks(sl);
5484         }
5485     }
5486 }
5487
5488 void Main::editToggleTarget()
5489 {
5490     VymModel *m = currentModel();
5491     if (m)
5492         m->toggleTarget();
5493 }
5494
5495 bool Main::initTargetsMenu(VymModel *model, QMenu *menu)
5496 {
5497     if (model) {
5498         ItemList targets = model->getTargets();
5499
5500         menu->clear();
5501
5502         QStringList targetNames;
5503         QList<uint> targetIDs;
5504
5505         // Build QStringList with all names of targets
5506         QMap<uint, QStringList>::const_iterator i;
5507         i = targets.constBegin();
5508         while (i != targets.constEnd()) {
5509             targetNames.append(i.value().first());
5510             targetIDs.append(i.key());
5511             ++i;
5512         }
5513
5514         // Sort list of names
5515         targetNames.sort(Qt::CaseInsensitive);
5516
5517         // Build menu based on sorted names
5518         while (!targetNames.isEmpty()) {
5519             // Find target by value
5520             i = targets.constBegin();
5521             while (i != targets.constEnd()) {
5522                 if (i.value().first() == targetNames.first())
5523                     break;
5524                 ++i;
5525             }
5526
5527             menu->addAction(targetNames.first())->setData(i.key());
5528             targetNames.removeFirst();
5529             targets.remove(i.key());
5530         }
5531         return true;
5532     }
5533     return false;
5534 }
5535
5536 void Main::editGoToTarget()
5537 {
5538     VymModel *model = currentModel();
5539     if (initTargetsMenu(model, targetsContextMenu)) {
5540         QAction *a = targetsContextMenu->exec(QCursor::pos());
5541         if (a)
5542             model->select(model->findID(a->data().toUInt()));
5543     }
5544 }
5545
5546 void Main::editMoveToTarget()
5547 {
5548     VymModel *model = currentModel();
5549     if (initTargetsMenu(model, targetsContextMenu)) {
5550         QAction *a = targetsContextMenu->exec(QCursor::pos());
5551         if (a) {
5552             TreeItem *dsti = model->findID(a->data().toUInt());
5553             /*
5554             BranchItem *selbi = model->getSelectedBranch();
5555             if (!selbi)
5556                 return;
5557             */
5558
5559             QList<TreeItem *> itemList = model->getSelectedItems();
5560             if (itemList.count() < 1) return;
5561
5562             if (dsti && dsti->isBranchLikeType() ) {
5563                 BranchItem *selbi;
5564                 BranchItem *pi;
5565                 foreach (TreeItem *ti, itemList) {
5566                     if (ti->isBranchLikeType() )
5567                     {
5568                         selbi = (BranchItem*)ti;
5569                         pi = selbi->parentBranch();
5570                         
5571                         // If branch below exists, select that one
5572                         // Makes it easier to quickly resort using the MoveTo function
5573                         BranchItem *below = pi->getBranchNum(selbi->num() + 1);
5574                         LinkableMapObj *lmo = selbi->getLMO();
5575                         QPointF orgPos;
5576                         if (lmo)
5577                             orgPos = lmo->getAbsPos();
5578
5579                         if (model->relinkBranch(selbi, (BranchItem *)dsti, -1, true,
5580                                                 orgPos)) {
5581                             if (below)
5582                                 model->select(below);
5583                             else if (pi)
5584                                 model->select(pi);
5585                         }
5586                     }
5587                 }
5588             }
5589         }
5590     }
5591 }
5592
5593 void Main::editSelectPrevious()
5594 {
5595     VymModel *m = currentModel();
5596     if (m)
5597         m->selectPrevious();
5598 }
5599
5600 void Main::editSelectNext()
5601 {
5602     VymModel *m = currentModel();
5603     if (m)
5604         m->selectNext();
5605 }
5606
5607 void Main::editSelectNothing()
5608 {
5609     VymModel *m = currentModel();
5610     if (m)
5611         m->unselectAll();
5612 }
5613
5614 void Main::editOpenFindResultWidget()
5615 {
5616     if (!findResultWidget->parentWidget()->isVisible()) {
5617         //      findResultWidget->parentWidget()->show();
5618         findResultWidget->popup();
5619     }
5620     else
5621         findResultWidget->parentWidget()->hide();
5622 }
5623
5624 #include "findwidget.h" // FIXME-4 Integrated FRW and FW
5625 void Main::editFindNext(QString s, bool searchNotesFlag)
5626 {
5627     Qt::CaseSensitivity cs = Qt::CaseInsensitive;
5628     VymModel *m = currentModel();
5629     if (m) {
5630         if (m->findAll(findResultWidget->getResultModel(), s, cs,
5631                        searchNotesFlag))
5632             findResultWidget->setStatus(FindWidget::Success);
5633         else
5634             findResultWidget->setStatus(FindWidget::Failed);
5635     }
5636 }
5637
5638 void Main::editFindDuplicateURLs() // FIXME-4 feature: use FindResultWidget for
5639                                    // display
5640 {
5641     VymModel *m = currentModel();
5642     if (m)
5643         m->findDuplicateURLs();
5644 }
5645
5646 void Main::updateQueries(
5647     VymModel *) // FIXME-4 disabled for now to avoid selection in FRW
5648 {
5649     return;
5650     /*
5651         qDebug() << "MW::updateQueries m="<<m<<"   cM="<<currentModel();
5652         if (m && currentModel()==m)
5653         {
5654         QString s=findResultWidget->getFindText();
5655         if (!s.isEmpty() ) editFindNext (s);
5656         }
5657     */
5658 }
5659
5660 void Main::selectQuickColor(int n)
5661 {
5662     if (n < 0 || n > quickColors.count() - 1) return;
5663
5664     actionGroupQuickColors->actions().at(n)->setChecked(true);
5665     setCurrentColor(quickColors.at(n));
5666 }
5667
5668 void Main::setQuickColor(QColor col)
5669 {
5670     int i = getCurrentColorIndex();
5671     if (i < 0) return;
5672
5673     QPixmap pix(16, 16);
5674     pix.fill(col);
5675     actionGroupQuickColors->checkedAction()->setIcon(pix);
5676     quickColors.replace(i, col);
5677 }
5678
5679 void Main::quickColorPressed()
5680 {
5681     int i = getCurrentColorIndex();
5682
5683     if (i < 0) return;
5684
5685     if (QApplication::keyboardModifiers() == Qt::ShiftModifier) {
5686         QColor col = getCurrentColor();
5687         col = QColorDialog::getColor((col), this);
5688         if (!col.isValid()) return;
5689
5690         setQuickColor(col);
5691     } else
5692         selectQuickColor(i);
5693 }
5694
5695 void Main::formatPickColor()
5696 {
5697     VymModel *m = currentModel();
5698     if (m)
5699         setQuickColor( m->getCurrentHeadingColor());
5700 }
5701
5702 QColor Main::getCurrentColor() 
5703
5704     int i = getCurrentColorIndex();
5705
5706     if (i < 0) return QColor();
5707
5708     return quickColors.at(i);
5709 }
5710
5711 int Main::getCurrentColorIndex()
5712 {
5713     QAction* a = actionGroupQuickColors->checkedAction();
5714
5715     if (a == nullptr) return -1;
5716
5717     return actionGroupQuickColors->actions().indexOf(a);
5718 }
5719
5720 void Main::setCurrentColor(QColor c)
5721 {
5722     int i = getCurrentColorIndex();
5723
5724     if (i < 0) return;
5725
5726     QPixmap pix(16, 16);
5727     pix.fill(c);
5728
5729     actionGroupQuickColors->actions().at(i)->setIcon(pix);
5730 }
5731
5732 void Main::formatColorBranch()
5733 {
5734     VymModel *m = currentModel();
5735     if (m)
5736         m->colorBranch(getCurrentColor());
5737 }
5738
5739 void Main::formatColorSubtree()
5740 {
5741     VymModel *m = currentModel();
5742     if (m)
5743         m->colorSubtree(getCurrentColor());
5744 }
5745
5746 void Main::formatLinkStyleLine()
5747 {
5748     VymModel *m = currentModel();
5749     if (m) {
5750         m->setMapLinkStyle("StyleLine");
5751         actionFormatLinkStyleLine->setChecked(true);
5752     }
5753 }
5754
5755 void Main::formatLinkStyleParabel()
5756 {
5757     VymModel *m = currentModel();
5758     if (m) {
5759         m->setMapLinkStyle("StyleParabel");
5760         actionFormatLinkStyleParabel->setChecked(true);
5761     }
5762 }
5763
5764 void Main::formatLinkStylePolyLine()
5765 {
5766     VymModel *m = currentModel();
5767     if (m) {
5768         m->setMapLinkStyle("StylePolyLine");
5769         actionFormatLinkStylePolyLine->setChecked(true);
5770     }
5771 }
5772
5773 void Main::formatLinkStylePolyParabel()
5774 {
5775     VymModel *m = currentModel();
5776     if (m) {
5777         m->setMapLinkStyle("StylePolyParabel");
5778         actionFormatLinkStylePolyParabel->setChecked(true);
5779     }
5780 }
5781
5782 void Main::formatSelectBackColor()
5783 {
5784     VymModel *m = currentModel();
5785     if (m)
5786         m->selectMapBackgroundColor();
5787 }
5788
5789 void Main::formatSelectBackImage()
5790 {
5791     VymModel *m = currentModel();
5792     if (m)
5793         m->selectMapBackgroundImage();
5794 }
5795
5796 void Main::formatSelectLinkColor()
5797 {
5798     VymModel *m = currentModel();
5799     if (m) {
5800         QColor col = QColorDialog::getColor(m->getMapDefLinkColor(), this);
5801         m->setMapDefLinkColor(col);
5802     }
5803 }
5804
5805 void Main::formatSelectSelectionColor() // FIXME-2 no Pen/Brush support yet
5806 {
5807     VymModel *m = currentModel();
5808     if (m) {
5809         QColor col = QColorDialog::getColor(
5810                 m->getSelectionBrushColor(),
5811                 this,
5812                 tr("Color of selection box","Mainwindow"),
5813                 QColorDialog::ShowAlphaChannel);
5814         m->setSelectionPenColor(col);
5815         m->setSelectionBrushColor(col);
5816     }
5817 }
5818
5819 void Main::formatSelectFont()
5820 {
5821     VymModel *m = currentModel();
5822     if (m) {
5823         bool ok;
5824         QFont font = QFontDialog::getFont(&ok, m->getMapDefaultFont(), this);
5825         if (ok)
5826             m->setMapDefaultFont(font);
5827     }
5828 }
5829
5830 void Main::formatToggleLinkColorHint()
5831 {
5832     VymModel *m = currentModel();
5833     if (m)
5834         m->toggleMapLinkColorHint();
5835 }
5836
5837 void Main::formatHideLinkUnselected() // FIXME-4 get rid of this with
5838                                       // imagepropertydialog
5839 {
5840     VymModel *m = currentModel();
5841     if (m)
5842         m->setHideLinkUnselected(actionFormatHideLinkUnselected->isChecked());
5843 }
5844
5845 void Main::viewZoomReset()
5846 {
5847     MapEditor *me = currentMapEditor();
5848     if (me)
5849         me->setViewCenterTarget();
5850 }
5851
5852 void Main::viewZoomIn()
5853 {
5854     MapEditor *me = currentMapEditor();
5855     if (me)
5856         me->setZoomFactorTarget(me->getZoomFactorTarget() * 1.15);
5857 }
5858
5859 void Main::viewZoomOut()
5860 {
5861     MapEditor *me = currentMapEditor();
5862     if (me)
5863         me->setZoomFactorTarget(me->getZoomFactorTarget() * 0.85);
5864 }
5865
5866 void Main::viewRotateCounterClockwise() // FIXME-3 move to ME
5867 {
5868     MapEditor *me = currentMapEditor();
5869     if (me)
5870         me->setAngleTarget(me->getAngleTarget() - 10);
5871 }
5872
5873 void Main::viewRotateClockwise() // FIXME-3 move to ME
5874 {
5875     MapEditor *me = currentMapEditor();
5876     if (me)
5877         me->setAngleTarget(me->getAngleTarget() + 10);
5878 }
5879
5880 void Main::viewCenter()
5881 {
5882     VymModel *m = currentModel();
5883     if (m)
5884         m->emitShowSelection(false);
5885 }
5886
5887 void Main::viewCenterScaled()
5888 {
5889     VymModel *m = currentModel();
5890     if (m)
5891         m->emitShowSelection(true);
5892 }
5893
5894 void Main::networkStartServer()
5895 {
5896     VymModel *m = currentModel();
5897     if (m)
5898         m->newServer();
5899 }
5900
5901 void Main::networkConnect()
5902 {
5903     VymModel *m = currentModel();
5904     if (m)
5905         m->connectToServer();
5906 }
5907
5908 void Main::downloadFinished() // only used for drop events in mapeditor and
5909                               // VM::downloadImage
5910 {
5911     QString s;
5912     DownloadAgent *agent = static_cast<DownloadAgent *>(sender());
5913     agent->isSuccess() ? s = "Success" : s = "Error  ";
5914
5915     /*
5916     qDebug()<<"Main::downloadFinished ";
5917     qDebug()<<"  result" <<  s;
5918     qDebug()<<"     msg" << agent->getResultMessage();
5919     */
5920
5921     QString script = agent->getFinishedScript();
5922     VymModel *model = getModel(agent->getFinishedScriptModelID());
5923     if (!script.isEmpty() && model) {
5924         script.replace("$TMPFILE", agent->getDestination());
5925         model->execute(script);
5926     }
5927     agent->deleteLater();
5928 }
5929
5930 bool Main::settingsPDF()
5931 {
5932     // Default browser is set in constructor
5933     bool ok;
5934     QString text = QInputDialog::getText(
5935         this, "VYM", tr("Set application to open PDF files") + ":",
5936         QLineEdit::Normal, settings.value("/system/readerPDF").toString(), &ok);
5937     if (ok)
5938         settings.setValue("/system/readerPDF", text);
5939     return ok;
5940 }
5941
5942 bool Main::settingsURL()
5943 {
5944     // Default browser is set in constructor
5945     bool ok;
5946     QString text = QInputDialog::getText(
5947         this, "VYM", tr("Set application to open an URL") + ":",
5948         QLineEdit::Normal, settings.value("/system/readerURL").toString(), &ok);
5949     if (ok)
5950         settings.setValue("/system/readerURL", text);
5951     return ok;
5952 }
5953
5954 void Main::settingsZipTool()    // FIXME-2 Disabled for now, to be removed completely in 2.9.1
5955 {
5956     // Default zip tool is tar on Windows 10, zip/unzip elsewhere
5957     ZipSettingsDialog dia;
5958     dia.exec();
5959 }
5960
5961 void Main::settingsMacroPath()
5962 {
5963     QString macroPath = macros.getPath();
5964
5965     QStringList filters;
5966     filters << "VYM script files (*.vys)";
5967     QFileDialog fd;
5968     fd.setDirectory(dirname(macroPath));
5969     fd.selectFile(basename(macroPath));
5970     fd.setFileMode(QFileDialog::ExistingFile);
5971     fd.setNameFilters(filters);
5972     fd.setWindowTitle(vymName + " - " + tr("Load vym script"));
5973     fd.setAcceptMode(QFileDialog::AcceptOpen);
5974
5975     QString fn;
5976     if (fd.exec() == QDialog::Accepted) {
5977         if (macros.setPath( fd.selectedFiles().first()))
5978             settings.setValue("/macros/path", macros.getPath());
5979     }
5980 }
5981
5982 void Main::settingsUndoLevels()
5983 {
5984     bool ok;
5985     int i = QInputDialog::getInt(
5986         this, "QInputDialog::getInt()", tr("Number of undo/redo levels:"),
5987         settings.value("/history/stepsTotal", 1000).toInt(), 0, 100000, 1, &ok);
5988     if (ok) {
5989         settings.setValue("/history/stepsTotal", i);
5990         QMessageBox::information(this, tr("VYM -Information:"),
5991                                  tr("Settings have been changed. The next map "
5992                                     "opened will have \"%1\" undo/redo levels")
5993                                      .arg(i));
5994     }
5995 }
5996
5997 void Main::settingsDefaultMapPath()
5998 {
5999     DefaultMapSettingsDialog dia;
6000     dia.exec();
6001 }
6002
6003 QString Main::defaultMapPath()
6004 {
6005     // Define default automatical path (also as fallback)
6006     QString ext_dark;
6007     if (usingDarkTheme)
6008         ext_dark = "-dark";
6009
6010     return vymBaseDir.path() + QString("/demos/default%1.vym").arg(ext_dark);
6011 }
6012
6013 QString Main::newMapPath()
6014 {
6015     if (settings.value("/system/defaultMap/auto", true).toBool())
6016         return defaultMapPath();
6017     else
6018         return settings
6019            .value("/system/defaultMap/path", defaultMapPath())
6020            .toString();
6021 }
6022
6023 bool Main::useAutosave() { return actionSettingsToggleAutosave->isChecked(); }
6024
6025 void Main::setAutosave(bool b) { actionSettingsToggleAutosave->setChecked(b); }
6026
6027 void Main::settingsAutosaveTime()
6028 {
6029     bool ok;
6030     int i = QInputDialog::getInt(
6031         this, vymName, tr("Number of seconds before autosave:"),
6032         settings.value("/system/autosave/ms").toInt() / 1000, 10, 60000, 1,
6033         &ok);
6034     if (ok)
6035         settings.setValue("/system/autosave/ms", i * 1000);
6036 }
6037
6038 void Main::settingsDefaultMapAuthor()
6039 {
6040     bool ok;
6041     QString s = QInputDialog::getText(
6042         this, vymName, tr("Set author for new maps (used in lockfile)") + ":",
6043         QLineEdit::Normal,
6044         settings
6045             .value("/user/name", tr("unknown user",
6046                                     "default name for map author in settings"))
6047             .toString(),
6048         &ok);
6049     if (ok)
6050         settings.setValue("/user/name", s);
6051 }
6052
6053 void Main::settingsDarkTheme()
6054 {
6055     DarkThemeSettingsDialog dia;
6056     QString settingDarkTheme = settings.value("/system/darkTheme", "system").toString();
6057     if (settingDarkTheme == "always")
6058         dia.ui.alwaysUseDarkThemeButton->setChecked(true);
6059     else 
6060         if (settingDarkTheme == "never")
6061             dia.ui.neverUseDarkThemeButton->setChecked(true);
6062         else
6063             dia.ui.systemUseDarkThemeButton->setChecked(true);
6064     dia.exec();
6065
6066     QString newSetting;
6067     if (dia.ui.alwaysUseDarkThemeButton->isChecked())
6068             newSetting = "always";
6069     else
6070         if (dia.ui.neverUseDarkThemeButton->isChecked())
6071             newSetting = "never";
6072         else
6073             newSetting = "system";
6074
6075     if (settingDarkTheme != newSetting) {
6076         settings.setValue("/system/darkTheme", newSetting);
6077         QMessageBox::information(
6078             0, tr("Information"),
6079             tr("Restart vym to apply the changed dark theme setting"));
6080     }
6081 }
6082
6083 void Main::settingsShowParentsLevelFindResults()
6084 {
6085     bool ok;
6086     int i = QInputDialog::getInt(
6087         this, vymName, tr("Number of parents shown in find results:"),
6088         findResultWidget->getResultModel()->getShowParentsLevel(), 0, 10, 0,
6089         &ok);
6090     if (ok)
6091         findResultWidget->getResultModel()->setShowParentsLevel(i);
6092 }
6093
6094 void Main::settingsShowParentsLevelTasks()
6095 {
6096     bool ok;
6097     int i = QInputDialog::getInt(
6098         this, vymName, tr("Number of parents shown for a task:"),
6099         taskModel->getShowParentsLevel(), 0, 10, 0, &ok);
6100     if (ok)
6101         taskModel->setShowParentsLevel(i);
6102 }
6103
6104 void Main::settingsToggleAutoLayout()
6105 {
6106     settings.setValue("/mainwindow/autoLayout/use",
6107                       actionSettingsToggleAutoLayout->isChecked());
6108 }
6109
6110 void Main::settingsToggleWriteBackupFile()
6111 {
6112     settings.setValue("/system/writeBackupFile",
6113                       actionSettingsWriteBackupFile->isChecked());
6114 }
6115
6116 void Main::settingsToggleAnimation()
6117 {
6118     settings.setValue("/animation/use",
6119                       actionSettingsUseAnimation->isChecked());
6120 }
6121
6122 void Main::settingsToggleDownloads() { downloadsEnabled(true); }
6123
6124 bool Main::settingsConfluence()
6125 {
6126     if (!QSslSocket::supportsSsl())
6127     {
6128         QMessageBox::warning(
6129             0, tr("Warning"),
6130             tr("No SSL support available for this build of vym"));
6131         helpDebugInfo();
6132         return false;
6133     }
6134
6135     ConfluenceSettingsDialog dia;
6136     dia.exec();
6137
6138     if (dia.result() > 0)
6139         return true;
6140     else
6141         return false;
6142 }
6143
6144 bool Main::settingsJIRA()
6145 {
6146     if (!QSslSocket::supportsSsl())
6147     {
6148         QMessageBox::warning(
6149             0, tr("Warning"),
6150             tr("No SSL support available for this build of vym"));
6151         helpDebugInfo();
6152         return false;
6153     }
6154
6155     JiraSettingsDialog dia;
6156     dia.exec();
6157
6158     if (dia.result() > 0)
6159         return true;
6160     else
6161         return false;
6162 }
6163
6164 void Main::windowToggleNoteEditor()
6165 {
6166     if (noteEditor->parentWidget()->isVisible())
6167         noteEditor->parentWidget()->hide();
6168     else {
6169         noteEditor->parentWidget()->show();
6170         noteEditor->setFocus();
6171     }
6172 }
6173
6174 void Main::windowToggleTreeEditor()
6175 {
6176     if (tabWidget->currentWidget())
6177         currentView()->toggleTreeEditor();
6178 }
6179
6180 void Main::windowToggleTaskEditor()
6181 {
6182     if (taskEditor->parentWidget()->isVisible()) {
6183         taskEditor->parentWidget()->hide();
6184         actionViewToggleTaskEditor->setChecked(false);
6185     }
6186     else {
6187         taskEditor->parentWidget()->show();
6188         actionViewToggleTaskEditor->setChecked(true);
6189     }
6190 }
6191
6192 void Main::windowToggleSlideEditor()
6193 {
6194     if (tabWidget->currentWidget())
6195         currentView()->toggleSlideEditor();
6196 }
6197
6198 void Main::windowToggleScriptEditor()
6199 {
6200     if (scriptEditor->parentWidget()->isVisible()) {
6201         scriptEditor->parentWidget()->hide();
6202         actionViewToggleScriptEditor->setChecked(false);
6203     }
6204     else {
6205         scriptEditor->parentWidget()->show();
6206         actionViewToggleScriptEditor->setChecked(true);
6207     }
6208 }
6209
6210 void Main::windowToggleScriptOutput()
6211 {
6212     if (scriptOutput->parentWidget()->isVisible()) {
6213         scriptOutput->parentWidget()->hide();
6214         actionViewToggleScriptOutput->setChecked(false);
6215     }
6216     else {
6217         scriptOutput->parentWidget()->show();
6218         actionViewToggleScriptOutput->setChecked(true);
6219     }
6220 }
6221
6222 void Main::windowToggleHistory()
6223 {
6224     if (historyWindow->parentWidget()->isVisible())
6225         historyWindow->parentWidget()->hide();
6226     else
6227         historyWindow->parentWidget()->show();
6228 }
6229
6230 void Main::windowToggleProperty()
6231 {
6232     if (branchPropertyEditor->parentWidget()->isVisible())
6233         branchPropertyEditor->parentWidget()->hide();
6234     else
6235         branchPropertyEditor->parentWidget()->show();
6236     branchPropertyEditor->setModel(currentModel());
6237 }
6238
6239 void Main::windowShowHeadingEditor() { headingEditorDW->show(); }
6240
6241 void Main::windowToggleHeadingEditor()
6242 {
6243     if (headingEditor->parentWidget()->isVisible())
6244         headingEditor->parentWidget()->hide();
6245     else {
6246         headingEditor->parentWidget()->show();
6247         headingEditor->setFocus();
6248     }
6249 }
6250
6251 void Main::windowToggleAntiAlias()
6252 {
6253     bool b = actionViewToggleAntiAlias->isChecked();
6254     MapEditor *me;
6255     for (int i = 0; i < tabWidget->count(); i++) {
6256         me = view(i)->getMapEditor();
6257         if (me)
6258             me->setAntiAlias(b);
6259     }
6260 }
6261
6262 bool Main::isAliased() { return actionViewToggleAntiAlias->isChecked(); }
6263
6264 bool Main::hasSmoothPixmapTransform()
6265 {
6266     return actionViewToggleSmoothPixmapTransform->isChecked();
6267 }
6268
6269 void Main::windowToggleSmoothPixmap()
6270 {
6271     bool b = actionViewToggleSmoothPixmapTransform->isChecked();
6272     MapEditor *me;
6273     for (int i = 0; i < tabWidget->count(); i++) {
6274
6275         me = view(i)->getMapEditor();
6276         if (me)
6277             me->setSmoothPixmap(b);
6278     }
6279 }
6280
6281 void Main::clearScriptOutput() { scriptOutput->clear(); }
6282
6283 void Main::updateHistory(SimpleSettings &undoSet)
6284 {
6285     historyWindow->update(undoSet);
6286 }
6287
6288 void Main::updateHeading(const VymText &vt)
6289 {
6290     VymModel *m = currentModel();
6291     if (m)
6292         m->setHeading(vt);
6293 }
6294
6295 void Main::updateNoteText(const VymText &vt)
6296 {
6297     // this slot is connected to noteEditor::textHasChanged()
6298     VymModel *m = currentModel();
6299     if (m)
6300         m->updateNoteText(vt);
6301 }
6302
6303 void Main::updateNoteEditor(TreeItem *ti)
6304 {
6305     if (ti) {
6306         if (!ti->hasEmptyNote())
6307             noteEditor->setNote(ti->getNote());
6308         else
6309             noteEditor->clear(); // Also sets empty state
6310         return;
6311     }
6312     noteEditor->setInactive();
6313 }
6314
6315 void Main::updateHeadingEditor(BranchItem *bi)  // FIXME-3 move to HeadingEditor
6316 {
6317     if (!bi) {
6318         VymModel *m = currentModel();
6319         if (!m) return;
6320
6321         bi = m->getSelectedBranch();
6322     }
6323
6324     // Give up, if not a single branch is selected
6325     if (!bi) return;
6326
6327     // Color settings, also to prepare switching to RichText later
6328     headingEditor->setColorMapBackground(bi->getBackgroundColor(bi));
6329     headingEditor->setColorRichTextDefaultForeground(bi->getHeadingColor());
6330
6331     headingEditor->setVymText(bi->getHeading());
6332     headingEditor->setEditorTitle();
6333
6334 }
6335
6336 void Main::selectInNoteEditor(QString s, int i)
6337 {
6338     // TreeItem is already selected at this time, therefor
6339     // the note is already in the editor
6340     noteEditor->findText(s, QTextDocument::FindFlags(), i);
6341 }
6342
6343 void Main::setFocusMapEditor()
6344 {
6345     VymView *vv = currentView();
6346     if (vv)
6347         vv->setFocusMapEditor();
6348 }
6349
6350 void Main::changeSelection(VymModel *model, const QItemSelection &,
6351                            const QItemSelection &)
6352 {
6353     // Setting the model in BPE implicitely
6354     // also sets treeItem and updates content in BPE
6355     branchPropertyEditor->setModel(model);
6356
6357     if (model && model == currentModel()) {
6358         int selectedCount = model->getSelectionModel()->selectedIndexes().count();
6359
6360         if (selectedCount == 0 || selectedCount > 1) {
6361             noteEditor->setInactive();
6362             headingEditor->setInactive();
6363             taskEditor->clearSelection();
6364
6365         } else {
6366             BranchItem *bi = model->getSelectedBranch();
6367             if (!bi) return;
6368
6369             // Update note editor
6370             updateNoteEditor(bi);
6371
6372             // Show URL and link in statusbar
6373             QString status;
6374             QString s = bi->getURL();
6375             if (!s.isEmpty())
6376                 status += "URL: " + s + "  ";
6377             s = bi->getVymLink();
6378             if (!s.isEmpty())
6379                 status += "Link: " + s;
6380             if (!status.isEmpty())
6381                 statusMessage(status);
6382
6383             // Update text in HeadingEditor
6384             updateHeadingEditor(bi);
6385
6386             // Select in TaskEditor, if necessary
6387             Task *t = bi->getTask();
6388
6389             if (t)
6390                 taskEditor->select(t);
6391             else
6392                 taskEditor->clearSelection();
6393         }
6394     }
6395
6396     updateActions();
6397 }
6398
6399 void Main::updateDockWidgetTitles(VymModel *model)
6400 {
6401     QString s;
6402     if (model && !model->isRepositionBlocked()) {
6403         BranchItem *bi = model->getSelectedBranch();
6404         if (bi) {
6405             s = bi->getHeadingPlain();
6406             noteEditor->setVymText(bi->getNote());
6407         }
6408
6409         noteEditor->setEditorTitle(s);
6410         branchPropertyEditor->setModel(model);
6411     }
6412 }
6413
6414 void Main::updateActions()
6415 {
6416     // updateActions is also called when satellites are closed
6417     actionViewToggleNoteEditor->setChecked(
6418         noteEditor->parentWidget()->isVisible());
6419     actionViewToggleTaskEditor->setChecked(
6420         taskEditor->parentWidget()->isVisible());
6421     actionViewToggleHistoryWindow->setChecked(
6422         historyWindow->parentWidget()->isVisible());
6423     actionViewTogglePropertyEditor->setChecked(
6424         branchPropertyEditor->parentWidget()->isVisible());
6425     actionViewToggleScriptEditor->setChecked(
6426         scriptEditor->parentWidget()->isVisible());
6427
6428     if (JiraAgent::available())
6429         actionGetJiraDataSubtree->setEnabled(true);
6430     else
6431         actionGetJiraDataSubtree->setEnabled(false);
6432
6433     if (ConfluenceAgent::available())
6434     {
6435         actionGetConfluencePageName->setEnabled(true);
6436         actionConnectGetConfluenceUser->setEnabled(true);
6437         actionFileExportConfluence->setEnabled(true);
6438     } else
6439     {
6440         actionGetConfluencePageName->setEnabled(false);
6441         actionConnectGetConfluenceUser->setEnabled(false);
6442         actionFileExportConfluence->setEnabled(false);
6443     }
6444
6445     VymView *vv = currentView();
6446     if (vv) {
6447         actionViewToggleTreeEditor->setChecked(vv->treeEditorIsVisible());
6448         actionViewToggleSlideEditor->setChecked(vv->slideEditorIsVisible());
6449     }
6450     else {
6451         actionViewToggleTreeEditor->setChecked(false);
6452         actionViewToggleSlideEditor->setChecked(false);
6453     }
6454
6455     VymModel *m = currentModel();
6456     if (m) {
6457         QList<TreeItem *> seltis = m->getSelectedItems();
6458         QList<BranchItem *> selbis = m->getSelectedBranches();
6459         TreeItem *selti;
6460         selti = (seltis.count() == 1) ? seltis.first() : nullptr;
6461
6462         BranchItem *selbi;
6463         selbi = (selbis.count() == 1) ? selbis.first() : nullptr;
6464
6465         // readonly mode
6466         if (m->isReadOnly()) {
6467             // Disable toolbars
6468             standardFlagsMaster->setEnabled(false);
6469             userFlagsMaster->setEnabled(false);
6470             clipboardToolbar->setEnabled(false);
6471             editActionsToolbar->setEnabled(false);
6472             selectionToolbar->setEnabled(false);
6473             editorsToolbar->setEnabled(false);
6474             colorsToolbar->setEnabled(false);
6475             zoomToolbar->setEnabled(false);
6476             modModesToolbar->setEnabled(false);
6477             referencesToolbar->setEnabled(false);
6478             standardFlagsToolbar->setEnabled(false);
6479             userFlagsToolbar->setEnabled(false);
6480
6481             // Disable map related actions in readonly mode // FIXME-2 not all actions disabled 
6482             foreach (QAction *a, restrictedMapActions)
6483                 a->setEnabled(false);
6484
6485         }
6486         else { // not readonly     
6487
6488             // Enable toolbars
6489             standardFlagsMaster->setEnabled(true);
6490             userFlagsMaster->setEnabled(true);
6491             clipboardToolbar->setEnabled(true);
6492             editActionsToolbar->setEnabled(true);
6493             selectionToolbar->setEnabled(true);
6494             editorsToolbar->setEnabled(true);
6495             colorsToolbar->setEnabled(true);
6496             zoomToolbar->setEnabled(true);
6497             modModesToolbar->setEnabled(true);
6498             referencesToolbar->setEnabled(true);
6499             standardFlagsToolbar->setEnabled(true);
6500             userFlagsToolbar->setEnabled(true);
6501
6502             // Enable map related actions
6503             foreach (QAction *a, restrictedMapActions)
6504                 a->setEnabled(true);
6505         }
6506         // Enable all files actions first
6507         for (int i = 0; i < actionListFiles.size(); ++i)
6508             actionListFiles.at(i)->setEnabled(true);
6509
6510         foreach (QAction *a, unrestrictedMapActions)
6511             a->setEnabled(true);
6512
6513         // Disable other actions for now
6514         for (int i = 0; i < actionListBranches.size(); ++i)
6515             actionListBranches.at(i)->setEnabled(false);
6516
6517         for (int i = 0; i < actionListItems.size(); ++i)
6518             actionListItems.at(i)->setEnabled(false);
6519
6520         // Link style in context menu
6521         switch (m->getMapLinkStyle()) {
6522         case LinkableMapObj::Line:
6523             actionFormatLinkStyleLine->setChecked(true);
6524             break;
6525         case LinkableMapObj::Parabel:
6526             actionFormatLinkStyleParabel->setChecked(true);
6527             break;
6528         case LinkableMapObj::PolyLine:
6529             actionFormatLinkStylePolyLine->setChecked(true);
6530             break;
6531         case LinkableMapObj::PolyParabel:
6532             actionFormatLinkStylePolyParabel->setChecked(true);
6533             break;
6534         default:
6535             break;
6536         }
6537
6538         // Update colors
6539         QPixmap pix(16, 16);
6540         pix.fill(m->getMapBackgroundColor());
6541         actionFormatBackColor->setIcon(pix);
6542         pix.fill(m->getSelectionBrushColor());
6543         actionFormatSelectionColor->setIcon(pix);
6544         pix.fill(m->getMapDefLinkColor());
6545         actionFormatLinkColor->setIcon(pix);
6546
6547         // Selection history
6548         if (!m->canSelectPrevious())
6549             actionSelectPrevious->setEnabled(false);
6550
6551         if (!m->canSelectNext())
6552             actionSelectNext->setEnabled(false);
6553
6554         if (!m->getSelectedItem())
6555             actionSelectNothing->setEnabled(false);
6556
6557         // Save
6558         if (!m->hasChanged())
6559             actionFileSave->setEnabled(false);
6560
6561         // Undo/Redo
6562         if (!m->isUndoAvailable())
6563             actionUndo->setEnabled(false);
6564
6565         if (!m->isRedoAvailable())
6566             actionRedo->setEnabled(false);
6567
6568         // History window
6569         historyWindow->setWindowTitle(
6570             vymName + " - " +
6571             tr("History for %1", "Window Caption").arg(m->getFileName()));
6572
6573         // Expanding/collapsing
6574         actionExpandAll->setEnabled(true);
6575         actionExpandOneLevel->setEnabled(true);
6576         actionCollapseOneLevel->setEnabled(true);
6577         actionCollapseUnselected->setEnabled(true);
6578
6579         if (m->getMapLinkColorHint() == LinkableMapObj::HeadingColor)
6580             actionFormatLinkColorHint->setChecked(true);
6581         else
6582             actionFormatLinkColorHint->setChecked(false);
6583
6584         // Export last
6585         QString desc, com, dest;
6586         if (m && m->exportLastAvailable(desc, com, dest))
6587             actionFileExportLast->setEnabled(true);
6588         else {
6589             actionFileExportLast->setEnabled(false);
6590             com = dest = "";
6591             desc = " - ";
6592         }
6593         actionFileExportLast->setText(
6594             tr("Export in last used format: %1\n%2", "status tip")
6595                 .arg(desc)
6596                 .arg(dest));
6597
6598
6599         if (seltis.count() > 0) { // Tree Item selected
6600             if (selti) actionToggleTarget->setChecked(selti->isTarget());
6601             actionDelete->setEnabled(true);
6602             actionDeleteAlt->setEnabled(true);
6603             actionDeleteChildren->setEnabled(true);
6604
6605             if (selti && selti->getType() == TreeItem::Image) {
6606                 actionFormatHideLinkUnselected->setChecked(
6607                     ((MapItem *)selti)->getHideLinkUnselected());
6608                 actionFormatHideLinkUnselected->setEnabled(true);
6609             }
6610
6611             if (selbis.count() > 0) { // Branch Item selected
6612                 for (int i = 0; i < actionListBranches.size(); ++i)
6613                     actionListBranches.at(i)->setEnabled(true);
6614
6615                 actionHeading2URL->setEnabled(true);
6616
6617                 // Note
6618                 if (selbi) actionGetURLsFromNote->setEnabled(!selbi->getNote().isEmpty());
6619
6620                 // Take care of xlinks
6621                 // FIXME-4 similar code in mapeditor mousePressEvent
6622                 bool b = false;
6623                 if (selbi && selbi->xlinkCount() > 0)
6624                     b = true;
6625
6626                 branchXLinksContextMenuEdit->setEnabled(b);
6627                 branchXLinksContextMenuFollow->setEnabled(b);
6628                 branchXLinksContextMenuEdit->clear();
6629                 branchXLinksContextMenuFollow->clear();
6630                 if (b) {
6631                     BranchItem *bi;
6632                     QString s;
6633                     for (int i = 0; i < selbi->xlinkCount(); ++i) {
6634                         bi = selbi->getXLinkItemNum(i)->getPartnerBranch();
6635                         if (bi) {
6636                             s = bi->getHeadingPlain();
6637                             if (s.length() > xLinkMenuWidth)
6638                                 s = s.left(xLinkMenuWidth) + "...";
6639                             branchXLinksContextMenuEdit->addAction(s);
6640                             branchXLinksContextMenuFollow->addAction(s);
6641                         }
6642                     }
6643                 }
6644                 // Standard and user flags
6645                 if (selbi)
6646                 {
6647                     standardFlagsMaster->updateToolBar(selbi->activeFlagUids());
6648                     userFlagsMaster->updateToolBar(selbi->activeFlagUids());
6649                 }
6650
6651                 // System Flags
6652                 actionToggleScroll->setEnabled(true);
6653                 if (selbi && selbi->isScrolled())
6654                     actionToggleScroll->setChecked(true);
6655                 else
6656                     actionToggleScroll->setChecked(false);
6657
6658                 QString url;
6659                 if (selti) url = selti->getURL();
6660                 if (url.isEmpty()) {
6661                     actionOpenURL->setEnabled(false);
6662                     actionOpenURLTab->setEnabled(false);
6663                     actionGetConfluencePageName->setEnabled(false);
6664                 }
6665                 else {
6666                     actionOpenURL->setEnabled(true);
6667                     actionOpenURLTab->setEnabled(true);
6668                     if (ConfluenceAgent::available())
6669                         actionGetConfluencePageName->setEnabled(true);
6670                     else
6671                         actionGetConfluencePageName->setEnabled(false);
6672                 }
6673
6674                 if (selti && selti->getVymLink().isEmpty()) {
6675                     actionOpenVymLink->setEnabled(false);
6676                     actionOpenVymLinkBackground->setEnabled(false);
6677                     actionDeleteVymLink->setEnabled(false);
6678                 }
6679                 else {
6680                     actionOpenVymLink->setEnabled(true);
6681                     actionOpenVymLinkBackground->setEnabled(true);
6682                     actionDeleteVymLink->setEnabled(true);
6683                 }
6684
6685                 if ((selbi && !selbi->canMoveUp()) || selbis.count() > 1)
6686                     actionMoveUp->setEnabled(false);
6687
6688                 if ((selbi && !selbi->canMoveDown()) || selbis.count() > 1)
6689                     actionMoveDown->setEnabled(false);
6690
6691                 if ((selbi && !selbi->canMoveUp()) || selbis.count() > 1)
6692                     actionMoveUpDiagonally->setEnabled(false);  // FIXME-2 add check for moveDiagonalUp
6693
6694                 if ((selbi && selbi->depth() == 0) || selbis.count() > 1)
6695                     actionMoveDownDiagonally->setEnabled(false);
6696
6697                 if (selbi && selbi->getLMO()->getOrientation() == LinkableMapObj::LeftOfCenter)
6698                 {
6699                     actionMoveDownDiagonally->setIcon(QPixmap(":down-diagonal-right.png"));
6700                     actionMoveUpDiagonally->setIcon(QPixmap(":up-diagonal-left.png"));
6701                 }
6702                 else
6703                 {
6704                     actionMoveDownDiagonally->setIcon(QPixmap(":down-diagonal-left.png"));
6705                     actionMoveUpDiagonally->setIcon(QPixmap(":up-diagonal-right.png"));
6706                 }
6707
6708                 if ((selbi && selbi->branchCount() < 2)  || selbis.count() > 1) { 
6709                     actionSortChildren->setEnabled(false);
6710                     actionSortBackChildren->setEnabled(false);
6711                 }
6712
6713                 if (selbi) {
6714                     actionToggleHideExport->setEnabled(true);
6715                     actionToggleHideExport->setChecked(selbi->hideInExport());
6716
6717                     actionToggleTask->setEnabled(true);
6718                     if (!selbi->getTask())
6719                         actionToggleTask->setChecked(false);
6720                     else
6721                         actionToggleTask->setChecked(true);
6722                 } else
6723                 {
6724                     actionToggleHideExport->setEnabled(false);
6725                     actionToggleTask->setEnabled(false);
6726                 }
6727
6728
6729                 const QClipboard *clipboard = QApplication::clipboard();
6730                 const QMimeData *mimeData = clipboard->mimeData();
6731                 if (mimeData->formats().contains("application/x-vym") ||
6732                     mimeData->hasImage())
6733                     actionPaste->setEnabled(true);
6734                 else
6735                     actionPaste->setEnabled(false);
6736
6737                 actionToggleTarget->setEnabled(true);
6738             } // end of BranchItem
6739
6740             if (selti && selti->getType() == TreeItem::Image) {
6741                 for (int i = 0; i < actionListBranches.size(); ++i)
6742                     actionListBranches.at(i)->setEnabled(false);
6743
6744                 standardFlagsMaster->setEnabled(false);
6745                 userFlagsMaster->setEnabled(false);
6746
6747                 actionOpenURL->setEnabled(false);
6748                 actionOpenVymLink->setEnabled(false);
6749                 actionOpenVymLinkBackground->setEnabled(false);
6750                 actionDeleteVymLink->setEnabled(false);
6751                 actionToggleHideExport->setEnabled(true);
6752                 actionToggleHideExport->setChecked(selti->hideInExport());
6753
6754                 actionToggleTarget->setEnabled(true);
6755
6756                 actionPaste->setEnabled(false);
6757                 actionDelete->setEnabled(true);
6758                 actionDeleteAlt->setEnabled(true);
6759
6760                 actionGrowSelectionSize->setEnabled(true);
6761                 actionShrinkSelectionSize->setEnabled(true);
6762                 actionResetSelectionSize->setEnabled(true);
6763             } // Image
6764         } // TreeItem
6765         else
6766         {
6767             actionToggleHideExport->setEnabled(false);
6768         }
6769
6770         // Check (at least for some) multiple selection //FIXME-4
6771         if (seltis.count() > 0) {
6772             actionDelete->setEnabled(true);
6773             actionDeleteAlt->setEnabled(true);
6774         }
6775
6776         if (selbis.count() > 0)
6777         {
6778             actionFormatColorBranch->setEnabled(true);
6779             actionFormatColorSubtree->setEnabled(true);
6780         }
6781     }
6782     else {
6783         // No map available
6784         for (int i = 0; i < actionListFiles.size(); ++i)
6785             actionListFiles.at(i)->setEnabled(false);
6786
6787         foreach (QAction *a, unrestrictedMapActions)
6788             a->setEnabled(false);
6789
6790         // Disable toolbars
6791         standardFlagsMaster->setEnabled(false);
6792         userFlagsMaster->setEnabled(false);
6793         clipboardToolbar->setEnabled(false);
6794         editActionsToolbar->setEnabled(false);
6795         selectionToolbar->setEnabled(false);
6796         editorsToolbar->setEnabled(false);
6797         colorsToolbar->setEnabled(false);
6798         zoomToolbar->setEnabled(false);
6799         modModesToolbar->setEnabled(false);
6800         referencesToolbar->setEnabled(false);
6801         standardFlagsToolbar->setEnabled(false);
6802         userFlagsToolbar->setEnabled(false);
6803     }
6804 }
6805
6806 Main::ModMode Main::getModMode()
6807 {
6808     if (actionModModePoint->isChecked())
6809         return ModModePoint;
6810     if (actionModModeColor->isChecked())
6811         return ModModeColor;
6812     if (actionModModeXLink->isChecked())
6813         return ModModeXLink;
6814     if (actionModModeMoveObject->isChecked())
6815         return ModModeMoveObject;
6816     if (actionModModeMoveView->isChecked())
6817         return ModModeMoveView;
6818     return ModModeUndefined;
6819 }
6820
6821 bool Main::autoSelectNewBranch()
6822 {
6823     return actionSettingsAutoSelectNewBranch->isChecked();
6824 }
6825
6826 QScriptValue scriptPrint(QScriptContext *context, QScriptEngine *)
6827 {
6828     scriptOutput->append(context->argument(0).toString());
6829     cout << context->argument(0).toString().toStdString() << endl;
6830     return QScriptValue();
6831 }
6832
6833 QScriptValue scriptAbort(QScriptContext *context, QScriptEngine *engine)
6834 {
6835     scriptOutput->append("Abort called: " + context->argument(0).toString());
6836     engine->abortEvaluation();
6837     return QScriptValue();
6838 }
6839
6840 QScriptValue scriptStatusMessage(QScriptContext *context, QScriptEngine *)
6841 {
6842     mainWindow->statusMessage(context->argument(0).toString());
6843     return QScriptValue();
6844 }
6845
6846 QVariant Main::runScript(const QString &script)
6847 {
6848     scriptEngine.globalObject().setProperty(
6849         "print", scriptEngine.newFunction(scriptPrint));
6850     scriptEngine.globalObject().setProperty(
6851         "abort", scriptEngine.newFunction(scriptAbort));
6852     scriptEngine.globalObject().setProperty(
6853         "statusMessage", scriptEngine.newFunction(scriptStatusMessage));
6854
6855     // Create Wrapper object for VymModel
6856     // QScriptValue val1 = scriptEngine.newQObject( m->getWrapper() );
6857     // scriptEngine.globalObject().setProperty("model", val1);
6858
6859     // Create Wrapper object for vym itself (mainwindow)
6860     VymWrapper vymWrapper;
6861     QScriptValue val2 = scriptEngine.newQObject(&vymWrapper);
6862     scriptEngine.globalObject().setProperty("vym", val2);
6863
6864     // Create wrapper object for selection
6865     Selection selection;
6866     QScriptValue val3 = scriptEngine.newQObject(&selection);
6867     scriptEngine.globalObject().setProperty("selection", val3);
6868
6869     if (debug) {
6870         cout << "MainWindow::runScript starting to execute:" << endl;
6871         cout << qPrintable(script) << endl;
6872     }
6873
6874     // Run script
6875     QScriptValue result = scriptEngine.evaluate(script);
6876
6877     if (debug) {
6878         qDebug() << "MainWindow::runScript finished:";
6879         qDebug() << "   hasException: " << scriptEngine.hasUncaughtException();
6880         qDebug() << "         result: "
6881                  << result.toString(); // not used so far...
6882         qDebug()
6883             << "     lastResult: "
6884             << scriptEngine.globalObject().property("lastResult").toVariant();
6885     }
6886
6887     if (scriptEngine.hasUncaughtException()) {
6888         // Warnings, in case that output window is not visible...
6889         statusMessage("Script execution failed");
6890         qWarning() << "Script execution failed";
6891
6892         int line = scriptEngine.uncaughtExceptionLineNumber();
6893         scriptOutput->append(QString("uncaught exception at line %1: %2")
6894                                  .arg(line)
6895                                  .arg(result.toString()));
6896     }
6897     else
6898         return scriptEngine.globalObject().property("lastResult").toVariant();
6899
6900     return QVariant("");
6901 }
6902
6903 QObject *Main::getCurrentModelWrapper()
6904 {
6905     // Called from VymWrapper to find out current model in a script
6906     VymModel *m = currentModel();
6907     if (m)
6908         return m->getWrapper();
6909     else
6910         return NULL;
6911 }
6912
6913 bool Main::gotoWindow(const int &n)
6914 {
6915     if (n < tabWidget->count() && n >= 0) {
6916         tabWidget->setCurrentIndex(n);
6917         return true;
6918     }
6919     return false;
6920 }
6921
6922 void Main::windowNextEditor()
6923 {
6924     if (tabWidget->currentIndex() < tabWidget->count())
6925         tabWidget->setCurrentIndex(tabWidget->currentIndex() + 1);
6926 }
6927
6928 void Main::windowPreviousEditor()
6929 {
6930     if (tabWidget->currentIndex() > 0)
6931         tabWidget->setCurrentIndex(tabWidget->currentIndex() - 1);
6932 }
6933
6934 void Main::nextSlide()
6935 {
6936     VymView *cv = currentView();
6937     if (cv)
6938         cv->nextSlide();
6939 }
6940
6941 void Main::previousSlide()
6942 {
6943     VymView *cv = currentView();
6944     if (cv)
6945         cv->previousSlide();
6946 }
6947
6948 void Main::flagChanged()
6949 {
6950     MapEditor *me = currentMapEditor();
6951     VymModel *m = currentModel();
6952     if (me && m && me->getState() != MapEditor::EditingHeading) {
6953         m->toggleFlagByUid(QUuid(sender()->objectName()),
6954                            actionSettingsUseFlagGroups->isChecked());
6955         updateActions();
6956     }
6957 }
6958
6959 void Main::testFunction1()
6960 {
6961     // Avail. styles:
6962     // Linux (KDE): Breeze,bb10dark,bb10bright,cleanlooks,gtk2,cde,motif,plastique,Windows,Fusion
6963     // Windows: windowsvista,Windows,Fusion
6964     //#include <QStyleFactory>
6965     //qApp->setStyle(QStyleFactory::create("windowsvista"));
6966
6967     VymModel *m = currentModel();
6968     if (m) {
6969         qDebug() << "ME::vp->width()=" << m->getMapEditor()->viewport()->width();
6970     }
6971 }
6972
6973 void Main::testFunction2()
6974 {
6975     VymModel *m = currentModel();
6976     if (m) {
6977         //m->repeatLastCommand();
6978     }
6979 }
6980
6981 void Main::toggleWinter()
6982 {
6983     if (!currentMapEditor())
6984         return;
6985     currentMapEditor()->toggleWinter();
6986 }
6987
6988 void Main::toggleHideExport()
6989 {
6990     VymModel *m = currentModel();
6991     if (!m)
6992         return;
6993     if (actionToggleHideMode->isChecked())
6994         m->setHideTmpMode(TreeItem::HideExport);
6995     else
6996         m->setHideTmpMode(TreeItem::HideNone);
6997 }
6998
6999 void Main::testCommand()
7000 {
7001     if (!currentMapEditor())
7002         return;
7003     scriptEditor->show();
7004 }
7005
7006 void Main::helpDoc()
7007 {
7008     QString locale = QLocale::system().name();
7009     QString docname;
7010     if (locale.left(2) == "es")
7011         docname = "vym_es.pdf";
7012     else if (locale.left(2) == "fr")
7013         docname = "vym_fr.pdf";
7014     else
7015         docname = "vym.pdf";
7016
7017     QStringList searchList;
7018     QDir docdir;
7019 #if defined(Q_OS_MACX)
7020     searchList << vymBaseDir.path() + "/doc";
7021 #elif defined(Q_OS_WIN32)
7022     searchList << vymInstallDir.path() + "doc/" + docname;
7023 #else
7024 #if defined(VYM_DOCDIR)
7025     searchList << VYM_DOCDIR;
7026 #endif
7027     // default path in SUSE LINUX
7028     searchList << "/usr/share/doc/packages/vym";
7029 #endif
7030
7031     searchList << "doc"; // relative path for easy testing in tarball
7032     searchList << "/usr/share/doc/vym";      // Debian
7033     searchList << "/usr/share/doc/packages"; // Knoppix
7034
7035     bool found = false;
7036     QFile docfile;
7037     for (int i = 0; i < searchList.count(); ++i) {
7038         docfile.setFileName(searchList.at(i) + "/" + docname);
7039         if (docfile.exists()) {
7040             found = true;
7041             break;
7042         }
7043     }
7044
7045     if (!found) {
7046         QMessageBox::critical(0, tr("Critcal error"),
7047                               tr("Couldn't find the documentation %1 in:\n%2")
7048                                   .arg(docname)
7049                                   .arg(searchList.join("\n")));
7050         return;
7051     }
7052
7053     QStringList args;
7054     VymProcess *pdfProc = new VymProcess();
7055     args << QDir::toNativeSeparators(docfile.fileName());
7056
7057     if (!pdfProc->startDetached(settings.value("/system/readerPDF").toString(),
7058                                 args)) {
7059         // error handling
7060         QMessageBox::warning(
7061             0, tr("Warning"),
7062             tr("Couldn't find a viewer to open %1.\n").arg(docfile.fileName()) +
7063                 tr("Please use Settings->") +
7064                 tr("Set application to open PDF files"));
7065         settingsPDF();
7066         return;
7067     }
7068 }
7069
7070 void Main::helpDemo()
7071 {
7072     QStringList filters;
7073     filters << "VYM example map (*.vym)";
7074     QFileDialog fd;
7075     fd.setDirectory(vymBaseDir.path() + "/demos");
7076     fd.setFileMode(QFileDialog::ExistingFiles);
7077     fd.setNameFilters(filters);
7078     fd.setWindowTitle(vymName + " - " + tr("Load vym example map"));
7079     fd.setAcceptMode(QFileDialog::AcceptOpen);
7080
7081     QString fn;
7082     if (fd.exec() == QDialog::Accepted) {
7083         lastMapDir = fd.directory();
7084         QStringList flist = fd.selectedFiles();
7085         QStringList::Iterator it = flist.begin();
7086         initProgressCounter(flist.count());
7087         while (it != flist.end()) {
7088             fn = *it;
7089             fileLoad(*it, NewMap, VymMap);
7090             ++it;
7091         }
7092         removeProgressCounter();
7093     }
7094 }
7095
7096 void Main::helpShortcuts()
7097 {
7098     ShowTextDialog dia;
7099     dia.useFixedFont(true);
7100     dia.setText(switchboard.getASCII());
7101     dia.exec();
7102 }
7103
7104 void Main::helpMacros()
7105 {
7106     ShowTextDialog dia;
7107     dia.useFixedFont(true);
7108     dia.setText(macros.help());
7109     dia.exec();
7110 }
7111
7112 void Main::helpScriptingCommands()
7113 {
7114     ShowTextDialog dia;
7115     dia.useFixedFont(true);
7116     QString s;
7117     s = "Available commands in map:\n";
7118     s += "=========================:\n";
7119     foreach (Command *c, modelCommands) {
7120         s += c->getDescription();
7121         s += "\n";
7122     }
7123
7124     s += "Available commands in vym:\n";
7125     s += "=========================:\n";
7126     foreach (Command *c, vymCommands) {
7127         s += c->getDescription();
7128         s += "\n";
7129     }
7130
7131     dia.setText(s);
7132     dia.exec();
7133 }
7134
7135 void Main::helpDebugInfo()
7136 {
7137     ShowTextDialog dia;
7138     dia.useFixedFont(true);
7139     dia.setText(debugInfo());
7140     dia.setMinimumWidth(900);
7141     dia.exec();
7142 }
7143
7144 void Main::helpAbout()
7145 {
7146     AboutDialog ad;
7147     ad.setMinimumSize(900, 700);
7148     ad.resize(QSize(900, 700));
7149     ad.exec();
7150 }
7151
7152 void Main::helpAboutQT()
7153 {
7154     QMessageBox::aboutQt(this, "Qt Application Example");
7155 }
7156
7157 void Main::callMacro()
7158 {
7159     QAction *action = qobject_cast<QAction *>(sender());
7160     int i = -1;
7161     if (action) {
7162         QString s = macros.get();
7163         QString modifiers;
7164
7165         i = action->data().toInt();
7166
7167         if (i > 11 && i < 24) {
7168             modifiers = "shift_";
7169             i = i - 12;
7170         } else if (i > 23 && i < 36) {
7171             modifiers = "ctrl_";
7172             i = i - 24;
7173         } else if (i > 35) {
7174             modifiers = "ctrl_shift_";
7175             i = i - 36;
7176         }
7177
7178         // Function keys start at "1", not "0"
7179         i++;
7180
7181         s += QString("macro_%1f%2();").arg(modifiers).arg(i);
7182
7183         VymModel *m = currentModel();
7184         if (m)
7185             m->execute(s);
7186     }
7187 }
7188
7189 void Main::downloadReleaseNotesFinished()
7190 {
7191     DownloadAgent *agent = static_cast<DownloadAgent *>(sender());
7192     QString s;
7193
7194     if (agent->isSuccess()) {
7195         QString page;
7196         if (agent->isSuccess()) {
7197             if (loadStringFromDisk(agent->getDestination(), page)) {
7198                 ShowTextDialog dia(this);
7199                 dia.setText(page);
7200                 dia.exec();
7201
7202                 // Don't load the release notes automatically again
7203                 settings.setValue("/downloads/releaseNotes/shownVersion",
7204                                   vymVersion);
7205             }
7206         }
7207     }
7208     else {
7209         statusMessage("Downloading release notes failed.");
7210         if (debug) {
7211             qDebug() << "Main::downloadReleaseNotesFinished ";
7212             qDebug() << "  result: failed";
7213             qDebug() << "     msg: " << agent->getResultMessage();
7214         }
7215     }
7216     agent->deleteLater();
7217
7218     if (checkUpdatesAfterReleaseNotes)
7219     {
7220         // After startup we want to check also for updates, but only after
7221         // releasenotes are there (and we have a cookie already)
7222         checkUpdatesAfterReleaseNotes = false;
7223         checkUpdates();
7224     }
7225 }
7226
7227 QUrl Main::serverUrl(const QString &scriptName)
7228 {
7229     // Local URL for testing only
7230     // QString("http://localhost/release-notes.php?vymVersion=%1") /
7231     return QUrl(
7232         QString("http://www.insilmaril.de/vym/%1?"
7233                     "vymVersion=%2"
7234                     "&config=darkTheme=%3+localeName=%4+buildDate=%5+codeQuality='%6'+codeName='%7'")
7235             .arg(scriptName)
7236             .arg(vymVersion)
7237             .arg(usingDarkTheme)
7238             .arg(localeName)
7239             .arg(vymBuildDate)
7240             .arg(vymCodeQuality)
7241             .arg(vymCodeName)
7242             );
7243 }
7244
7245 void Main::checkReleaseNotesAndUpdates ()
7246 {
7247     // Called once after startup
7248     // checkUpdatesAfterReleaseNotes is already true then
7249     checkReleaseNotes();
7250 }
7251
7252 void Main::checkReleaseNotes ()
7253 {
7254     bool userTriggered;
7255     if (qobject_cast<QAction *>(sender()))
7256         userTriggered = true;
7257     else
7258         userTriggered = false;
7259
7260     if (downloadsEnabled()) {
7261         if (userTriggered ||
7262             versionLowerThanVym(
7263                 settings.value("/downloads/releaseNotes/shownVersion", "0.0.1")
7264                     .toString())) {
7265             DownloadAgent *agent = new DownloadAgent(serverUrl("release-notes.php"));
7266             connect(agent, SIGNAL(downloadFinished()), this,
7267                     SLOT(downloadReleaseNotesFinished()));
7268             QTimer::singleShot(0, agent, SLOT(execute()));
7269         }
7270     }
7271     else {
7272         // No downloads enabled
7273         if (userTriggered) {
7274             // Notification: vym could not download release notes
7275             QMessageBox::warning(
7276                 0, tr("Warning"),
7277                 tr("Please allow vym to download release notes!"));
7278             if (downloadsEnabled(userTriggered))
7279                 checkUpdates();
7280         }
7281     }
7282 }
7283
7284 bool Main::downloadsEnabled(bool userTriggered)
7285 {
7286     bool result;
7287     if (!userTriggered &&
7288         settings.value("/downloads/enabled", false).toBool()) {
7289         result = true;
7290     }
7291     else {
7292         QDate lastAsked =
7293             settings.value("/downloads/permissionLastAsked", QDate(1970, 1, 1))
7294                 .toDate();
7295         if (userTriggered ||
7296             !settings.contains("/downloads/permissionLastAsked") ||
7297             lastAsked.daysTo(QDate::currentDate()) > 7) {
7298             QString infotext;
7299             infotext =
7300                 tr("<html>"
7301                    "<h3>Do you allow vym to check online for updates or "
7302                    "release notes?</h3>"
7303                    "If you allow, vym will "
7304                    "<ul>"
7305                    "<li>check once for release notes</li>"
7306                    "<li>check regulary for updates and notify you in case you "
7307                    "should update, e.g. if there are "
7308                    "important bug fixes available</li>"
7309                    "<li>receive a cookie with a random ID and send some anonymous data, like:"
7310                    "<ul>"
7311                    "<li>vym version</li>"
7312                    "<li>platform name and the ID (e.g. \"Windows\" or \"Linux\")</li>"
7313                    "<li>if you are using dark theme</li>"
7314                    "</ul>"
7315                    "This data is sent to me, Uwe Drechsel."
7316                    "<p>As vym developer I am motivated to see "
7317                    "many people using vym. Of course I am curious to see, on "
7318                    "which system vym is used. Maintaining each "
7319                    "of the systems requires a lot of my (spare) time.</p> "
7320                    "<p>No other data than above will be sent, especially no "
7321                    "private data will be collected or sent."
7322                    "(Check the source code, if you don't believe.)"
7323                    "</p>"
7324                    "</li>"
7325                    "</ul>"
7326                    "If you do not allow, "
7327                    "<ul>"
7328                    "<li>nothing will be downloaded and especially I will "
7329                    "<b>not be motivated</b> "
7330                    "to spend some more thousands of hours on developing a free "
7331                    "software tool."
7332                    "</ul>"
7333                    "Please allow vym to check for updates :-)");
7334             QMessageBox mb(vymName, infotext, QMessageBox::Information,
7335                            QMessageBox::Yes | QMessageBox::Default,
7336                            QMessageBox::No | QMessageBox::Escape,
7337                            QMessageBox::NoButton);
7338
7339             mb.setButtonText(QMessageBox::Yes, tr("Allow"));
7340             mb.setButtonText(QMessageBox::No, tr("Do not allow"));
7341             switch (mb.exec()) {
7342             case QMessageBox::Yes: {
7343                 result = true;
7344                 QMessageBox msgBox;
7345                 msgBox.setText(tr("Thank you for enabling downloads!"));
7346                 msgBox.setStandardButtons(QMessageBox::Close);
7347                 msgBox.setIconPixmap(QPixmap(":/flag-face-smile.svg"));
7348                 msgBox.exec();
7349                 break;
7350                                    }
7351             default:
7352                 result = false;
7353                 QMessageBox msgBox;
7354                 msgBox.setText(tr("That's ok, though I would be happy to see many users working with vym and also on which platforms."));
7355                 msgBox.setStandardButtons(QMessageBox::Close);
7356                 msgBox.setIconPixmap(QPixmap(":/flag-face-sad.svg"));
7357                 msgBox.exec();
7358                 break;
7359             }
7360         }
7361         else
7362             result = false;
7363         actionSettingsToggleDownloads->setChecked(result);
7364         settings.setValue("/downloads/enabled", result);
7365         settings.setValue("/downloads/permissionLastAsked",
7366                           QDate::currentDate().toString(Qt::ISODate));
7367     }
7368     return result;
7369 }
7370
7371 void Main::downloadUpdatesFinished(bool userTriggered)
7372 {
7373     DownloadAgent *agent = static_cast<DownloadAgent *>(sender());
7374     QString s;
7375
7376     if (agent->isSuccess()) {
7377         ShowTextDialog dia;
7378         dia.setWindowTitle(vymName + " - " + tr("Update information"));
7379         QString page;
7380         if (loadStringFromDisk(agent->getDestination(), page)) {
7381             if (page.contains("vymisuptodate")) {
7382                 statusMessage(tr("vym is up to date.", "MainWindow"));
7383                 if (userTriggered) {
7384                     // Notification: vym is up to date!
7385                     dia.setHtml(page);
7386                     dia.exec();
7387                 }
7388             }
7389             else if (page.contains("vymneedsupdate")) {
7390                 // Notification: updates available
7391                 dia.setHtml(page);
7392                 dia.exec();
7393             }
7394             else {
7395                 // Notification: Unknown version found
7396                 dia.setHtml(page);
7397                 dia.exec();
7398             }
7399
7400             // Prepare to check again later
7401             settings.setValue("/downloads/updates/lastChecked",
7402                               QDate::currentDate().toString(Qt::ISODate));
7403         }
7404         else
7405             statusMessage("Couldn't load update page from " +
7406                           agent->getDestination());
7407     }
7408     else {
7409         statusMessage("Check for updates failed.");
7410         if (debug) {
7411             qDebug() << "Main::downloadUpdatesFinished ";
7412             qDebug() << "  result: failed";
7413             qDebug() << "     msg: " << agent->getResultMessage();
7414         }
7415     }
7416     agent->deleteLater();
7417 }
7418
7419 void Main::downloadUpdatesFinishedInt() { downloadUpdatesFinished(true); }
7420
7421 void Main::downloadUpdates(bool userTriggered)
7422 {
7423     DownloadAgent *agent = new DownloadAgent(serverUrl("updates.php"));
7424     if (userTriggered)
7425         connect(agent, SIGNAL(downloadFinished()), this,
7426                 SLOT(downloadUpdatesFinishedInt()));
7427     else
7428         connect(agent, SIGNAL(downloadFinished()), this,
7429                 SLOT(downloadUpdatesFinished()));
7430     statusMessage(tr("Checking for updates...", "MainWindow"));
7431     QTimer::singleShot(0, agent, SLOT(execute()));
7432 }
7433
7434 void Main::checkUpdates()
7435 {
7436     bool userTriggered;
7437     if (qobject_cast<QAction *>(sender()))
7438         userTriggered = true;
7439     else
7440         userTriggered = false;
7441
7442     if (downloadsEnabled()) {
7443         // Too much time passed since last update check?
7444         QDate lastChecked =
7445             settings.value("/downloads/updates/lastChecked", QDate(1970, 1, 1))
7446                 .toDate();
7447         if (!lastChecked.isValid())
7448             lastChecked = QDate(1970, 1, 1);
7449         if (lastChecked.daysTo(QDate::currentDate()) >
7450                 settings.value("/downloads/updates/checkInterval", 3).toInt() ||
7451             userTriggered == true) {
7452             downloadUpdates(userTriggered);
7453         }
7454     }
7455     else {
7456         // No downloads enabled
7457         if (userTriggered) {
7458             // Notification: vym could not check for updates
7459             QMessageBox::warning(0, tr("Warning"),
7460                                  tr("Please allow vym to check for updates!"));
7461             if (downloadsEnabled(userTriggered))
7462                 checkUpdates();
7463         }
7464     }
7465 }
7466
7467 void Main::escapePressed()
7468 {
7469     if (presentationMode)
7470         togglePresentationMode();
7471     else
7472         setFocusMapEditor();
7473 }
7474
7475 void Main::togglePresentationMode()
7476 {
7477     QMap<QToolBar *, bool>::const_iterator i = toolbarStates.constBegin();
7478     if (!presentationMode) {
7479
7480         presentationMode = true;
7481         while (i != toolbarStates.constEnd()) {
7482             toolbarStates[i.key()] = i.key()->isVisible();
7483             i.key()->hide();
7484             ++i;
7485         }
7486         menuBar()->hide();
7487     }
7488     else {
7489         presentationMode = false;
7490         while (i != toolbarStates.constEnd()) {
7491             i.key()->setVisible(i.value());
7492             ++i;
7493         }
7494         menuBar()->show();
7495     }
7496 }