3 #include <q3filedialog.h>
12 #include "editxlinkdialog.h"
14 #include "extrainfodialog.h"
16 #include "linkablemapobj.h"
17 #include "mainwindow.h"
19 #include "texteditor.h"
20 #include "warningdialog.h"
24 extern TextEditor *textEditor;
25 extern int statusbarTime;
26 extern Main *mainWindow;
27 extern QString tmpVymDir;
28 extern QString clipboardDir;
29 extern QString clipboardFile;
30 extern bool clipboardEmpty;
32 extern FlagRowObj *standardFlagsDefault;
34 extern QMenu* branchContextMenu;
35 extern QMenu* branchAddContextMenu;
36 extern QMenu* branchRemoveContextMenu;
37 extern QMenu* branchLinksContextMenu;
38 extern QMenu* branchXLinksContextMenuEdit;
39 extern QMenu* branchXLinksContextMenuFollow;
40 extern QMenu* floatimageContextMenu;
41 extern QMenu* canvasContextMenu;
44 extern Settings settings;
45 extern ImageIO imageIO;
47 extern QString vymName;
48 extern QString vymVersion;
50 extern QString iconPath;
51 extern QDir vymBaseDir;
52 extern QDir lastImageDir;
53 extern QDir lastFileDir;
55 int MapEditor::mapNum=0; // make instance
57 ///////////////////////////////////////////////////////////////////////
58 ///////////////////////////////////////////////////////////////////////
59 MapEditor::MapEditor( QWidget* parent) :
62 //cout << "Constructor ME "<<this<<endl;
66 mapScene= new QGraphicsScene(parent);
67 //mapScene= new QGraphicsScene(QRectF(0,0,width(),height()), parent);
68 mapScene->setBackgroundBrush (QBrush(Qt::white, Qt::SolidPattern));
73 mapCenter = new MapCenterObj(mapScene);
74 mapCenter->setVisibility (true);
75 mapCenter->setMapEditor (this);
76 mapCenter->setHeading (tr("New Map","Heading of mapcenter in new map"));
77 //mapCenter->move(mapScene->width()/2-mapCenter->width()/2,mapScene->height()/2-mapCenter->height()/2);
82 defLinkColor=QColor (0,0,255);
83 defXLinkColor=QColor (180,180,180);
84 linkcolorhint=LinkableMapObj::DefaultColor;
85 linkstyle=LinkableMapObj::PolyParabel;
87 // Create bitmap cursors, platform dependant
88 HandOpenCursor=QCursor (QPixmap(iconPath+"cursorhandopen.png"),1,1);
89 PickColorCursor=QCursor ( QPixmap(iconPath+"cursorcolorpicker.png"), 5,27 );
90 CopyCursor=QCursor ( QPixmap(iconPath+"cursorcopy.png"), 1,1 );
91 XLinkCursor=QCursor ( QPixmap(iconPath+"cursorxlink.png"), 1,7 );
93 setFocusPolicy (Qt::StrongFocus);
102 xelection.setMapEditor (this);
103 xelection.unselect();
106 defXLinkColor=QColor (230,230,230);
114 fileName=tr("unnamed");
117 stepsTotal=settings.readNumEntry("/mapeditor/stepsTotal",100);
118 undoSet.setEntry ("/history/stepsTotal",QString::number(stepsTotal));
119 mainWindow->updateHistory (undoSet);
121 // Initialize find routine
128 blockReposition=false;
129 blockSaveState=false;
131 hidemode=BranchObj::HideNone;
133 // Create temporary files
140 setAcceptDrops (true);
142 mapCenter->reposition(); // for positioning heading
146 //timerId = startTimer(100);
149 autosaveTimer=new QTimer (this);
150 connect(autosaveTimer, SIGNAL(timeout()), this, SLOT(autosave()));
153 MapEditor::~MapEditor()
155 //cout <<"Destructor MapEditor\n";
156 autosaveTimer->stop();
159 MapCenterObj* MapEditor::getMapCenter()
164 QGraphicsScene * MapEditor::getScene()
169 MapEditor::State MapEditor::getState()
174 void MapEditor::setStateEditHeading(bool s)
178 if (state==Idle) state=EditHeading;
184 bool MapEditor::isRepositionBlocked()
186 return blockReposition;
189 void MapEditor::setSaveStateBlocked(bool b)
194 bool MapEditor::isSelectBlocked()
196 if (state==EditHeading)
202 QString MapEditor::getName (const LinkableMapObj *lmo)
205 if (!lmo) return QString("Error: NULL has no name!");
207 if ((typeid(*lmo) == typeid(BranchObj) ||
208 typeid(*lmo) == typeid(MapCenterObj)))
211 s=(((BranchObj*)lmo)->getHeading());
212 if (s=="") s="unnamed";
213 return QString("branch (%1)").arg(s);
214 //return QString("branch (<font color=\"#0000ff\">%1</font>)").arg(s);
216 if ((typeid(*lmo) == typeid(FloatImageObj) ))
217 return QString ("floatimage [%1]").arg(((FloatImageObj*)lmo)->getOriginalFilename());
218 //return QString ("floatimage [<font color=\"#0000ff\">%1</font>]").arg(((FloatImageObj*)lmo)->getOriginalFilename());
219 return QString("Unknown type has no name!");
222 void MapEditor::makeTmpDirs()
224 // Create unique temporary directories
225 tmpMapDir=QDir::convertSeparators (tmpVymDir+QString("/mapeditor-%1").arg(mapNum));
226 histPath=QDir::convertSeparators (tmpMapDir+"/history");
231 QString MapEditor::saveToDir(const QString &tmpdir, const QString &prefix, bool writeflags, const QPointF &offset, LinkableMapObj *saveSel)
233 // tmpdir temporary directory to which data will be written
234 // prefix mapname, which will be appended to images etc.
235 // writeflags Only write flags for "real" save of map, not undo
236 // offset offset of bbox of whole map in scene.
237 // Needed for XML export
243 case LinkableMapObj::Line:
246 case LinkableMapObj::Parabel:
249 case LinkableMapObj::PolyLine:
253 ls="StylePolyParabel";
257 QString s="<?xml version=\"1.0\" encoding=\"utf-8\"?><!DOCTYPE vymmap>\n";
259 if (linkcolorhint==LinkableMapObj::HeadingColor)
260 colhint=attribut("linkColorHint","HeadingColor");
262 QString mapAttr=attribut("version",vymVersion);
263 if (!saveSel || saveSel==mapCenter)
264 mapAttr+= attribut("author",mapCenter->getAuthor()) +
265 attribut("comment",mapCenter->getComment()) +
266 attribut("date",mapCenter->getDate()) +
267 attribut("backgroundColor", mapScene->backgroundBrush().color().name() ) +
268 attribut("selectionColor", xelection.getColor().name() ) +
269 attribut("linkStyle", ls ) +
270 attribut("linkColor", defLinkColor.name() ) +
271 attribut("defXLinkColor", defXLinkColor.name() ) +
272 attribut("defXLinkWidth", QString().setNum(defXLinkWidth,10) ) +
274 s+=beginElement("vymmap",mapAttr);
277 // Find the used flags while traversing the tree
278 standardFlagsDefault->resetUsedCounter();
280 // Reset the counters before saving
281 // TODO constr. of FIO creates lots of objects, better do this in some other way...
282 FloatImageObj (mapScene).resetSaveCounter();
284 // Build xml recursivly
285 if (!saveSel || typeid (*saveSel) == typeid (MapCenterObj))
286 // Save complete map, if saveSel not set
287 s+=mapCenter->saveToDir(tmpdir,prefix,writeflags,offset);
290 if ( typeid(*saveSel) == typeid(BranchObj) )
292 s+=((BranchObj*)(saveSel))->saveToDir(tmpdir,prefix,offset);
293 else if ( typeid(*saveSel) == typeid(FloatImageObj) )
295 s+=((FloatImageObj*)(saveSel))->saveToDir(tmpdir,prefix);
298 // Save local settings
299 s+=settings.getXMLData (destPath);
302 if (!xelection.isEmpty() && !saveSel )
303 s+=valueElement("select",xelection.getSelectString());
306 s+=endElement("vymmap");
309 standardFlagsDefault->saveToDir (tmpdir+"/flags/","",writeflags);
313 void MapEditor::saveState(const SaveMode &savemode, const QString &undoSelection, const QString &undoCom, const QString &redoSelection, const QString &redoCom, const QString &comment, LinkableMapObj *saveSel)
317 if (blockSaveState) return;
319 if (debug) cout << "ME::saveState() for "<<mapName.ascii()<<endl;
321 // Find out current undo directory
322 if (undosAvail<stepsTotal) undosAvail++;
324 if (curStep>stepsTotal) curStep=1;
326 QString backupXML="";
327 QString bakMapName=QDir::convertSeparators (QString("history-%1").arg(curStep));
328 QString bakMapDir=QDir::convertSeparators (tmpMapDir +"/"+bakMapName);
329 QString bakMapPath=QDir::convertSeparators(bakMapDir+"/map.xml");
331 // Create bakMapDir if not available
334 makeSubDirs (bakMapDir);
336 // Save depending on how much needs to be saved
338 backupXML=saveToDir (bakMapDir,mapName+"-",false, QPointF (),saveSel);
340 QString undoCommand="";
341 if (savemode==UndoCommand)
345 else if (savemode==PartOfMap )
348 undoCommand.replace ("PATH",bakMapPath);
351 if (!backupXML.isEmpty())
352 // Write XML Data to disk
353 saveStringToDisk (QString(bakMapPath),backupXML);
355 // We would have to save all actions in a tree, to keep track of
356 // possible redos after a action. Possible, but we are too lazy: forget about redos.
359 // Write the current state to disk
360 undoSet.setEntry ("/history/undosAvail",QString::number(undosAvail));
361 undoSet.setEntry ("/history/redosAvail",QString::number(redosAvail));
362 undoSet.setEntry ("/history/curStep",QString::number(curStep));
363 undoSet.setEntry (QString("/history/step-%1/undoCommand").arg(curStep),undoCommand);
364 undoSet.setEntry (QString("/history/step-%1/undoSelection").arg(curStep),undoSelection);
365 undoSet.setEntry (QString("/history/step-%1/redoCommand").arg(curStep),redoCom);
366 undoSet.setEntry (QString("/history/step-%1/redoSelection").arg(curStep),redoSelection);
367 undoSet.setEntry (QString("/history/step-%1/comment").arg(curStep),comment);
368 undoSet.setEntry (QString("/history/version"),vymVersion);
369 undoSet.writeSettings(histPath);
373 // TODO remove after testing
374 //cout << " into="<< histPath.toStdString()<<endl;
375 cout << " stepsTotal="<<stepsTotal<<
376 ", undosAvail="<<undosAvail<<
377 ", redosAvail="<<redosAvail<<
378 ", curStep="<<curStep<<endl;
379 cout << " ---------------------------"<<endl;
380 cout << " comment="<<comment.toStdString()<<endl;
381 cout << " undoCom="<<undoCommand.toStdString()<<endl;
382 cout << " undoSel="<<undoSelection.toStdString()<<endl;
383 cout << " redoCom="<<redoCom.toStdString()<<endl;
384 cout << " redoSel="<<redoSelection.toStdString()<<endl;
385 if (saveSel) cout << " saveSel="<<saveSel->getSelectString().ascii()<<endl;
386 cout << " ---------------------------"<<endl;
389 mainWindow->updateHistory (undoSet);
395 void MapEditor::saveStateChangingPart(LinkableMapObj *undoSel, LinkableMapObj* redoSel, const QString &rc, const QString &comment)
397 // save the selected part of the map, Undo will replace part of map
398 QString undoSelection="";
400 undoSelection=undoSel->getSelectString();
402 qWarning ("MapEditor::saveStateChangingPart no undoSel given!");
403 QString redoSelection="";
405 redoSelection=undoSel->getSelectString();
407 qWarning ("MapEditor::saveStateChangingPart no redoSel given!");
410 saveState (PartOfMap,
411 undoSelection, "addMapReplace (\"PATH\")",
417 void MapEditor::saveStateRemovingPart(LinkableMapObj *redoSel, const QString &comment)
421 qWarning ("MapEditor::saveStateRemovingPart no redoSel given!");
424 QString undoSelection=redoSel->getParObj()->getSelectString();
425 QString redoSelection=redoSel->getSelectString();
426 if (typeid(*redoSel) == typeid(BranchObj) )
428 // save the selected branch of the map, Undo will insert part of map
429 saveState (PartOfMap,
430 undoSelection, QString("addMapInsert (\"PATH\",%1)").arg(((BranchObj*)redoSel)->getNum()),
431 redoSelection, "delete ()",
438 void MapEditor::saveState(LinkableMapObj *undoSel, const QString &uc, LinkableMapObj *redoSel, const QString &rc, const QString &comment)
440 // "Normal" savestate: save commands, selections and comment
441 // so just save commands for undo and redo
442 // and use current selection
444 QString redoSelection="";
445 if (redoSel) redoSelection=redoSel->getSelectString();
446 QString undoSelection="";
447 if (undoSel) undoSelection=undoSel->getSelectString();
449 saveState (UndoCommand,
456 void MapEditor::saveState(const QString &undoSel, const QString &uc, const QString &redoSel, const QString &rc, const QString &comment)
458 // "Normal" savestate: save commands, selections and comment
459 // so just save commands for undo and redo
460 // and use current selection
461 saveState (UndoCommand,
469 void MapEditor::parseAtom(const QString &atom)
471 BranchObj *selb=xelection.getBranch();
476 // Split string s into command and parameters
477 parser.parseAtom (atom);
478 QString com=parser.getCommand();
481 if (com=="addBranch")
483 if (xelection.isEmpty())
485 parser.setError (Aborted,"Nothing selected");
488 parser.setError (Aborted,"Type of selection is not a branch");
493 if (parser.checkParamCount(pl))
495 if (parser.paramCount()==0)
496 addNewBranchInt (-2);
499 y=parser.parInt (ok,0);
500 if (ok ) addNewBranchInt (y);
504 } else if (com=="addBranchBefore")
506 if (xelection.isEmpty())
508 parser.setError (Aborted,"Nothing selected");
511 parser.setError (Aborted,"Type of selection is not a branch");
514 if (parser.paramCount()==0)
516 addNewBranchBefore ();
519 } else if (com==QString("addMapReplace"))
521 if (xelection.isEmpty())
523 parser.setError (Aborted,"Nothing selected");
526 parser.setError (Aborted,"Type of selection is not a branch");
527 } else if (parser.checkParamCount(1))
529 //s=parser.parString (ok,0); // selection
530 t=parser.parString (ok,0); // path to map
531 if (QDir::isRelativePath(t)) t=QDir::convertSeparators (tmpMapDir + "/"+t);
532 addMapReplaceInt(selb->getSelectString(),t);
534 } else if (com==QString("addMapInsert"))
536 if (xelection.isEmpty())
538 parser.setError (Aborted,"Nothing selected");
541 parser.setError (Aborted,"Type of selection is not a branch");
544 if (parser.checkParamCount(2))
546 t=parser.parString (ok,0); // path to map
547 y=parser.parInt(ok,1); // position
548 if (QDir::isRelativePath(t)) t=QDir::convertSeparators (tmpMapDir + "/"+t);
549 addMapInsertInt(t,y);
552 } else if (com=="clearFlags")
554 if (xelection.isEmpty() )
556 parser.setError (Aborted,"Nothing selected");
559 parser.setError (Aborted,"Type of selection is not a branch");
560 } else if (parser.checkParamCount(0))
562 selb->clearStandardFlags();
563 selb->updateFlagsToolbar();
565 } else if (com=="colorBranch")
567 if (xelection.isEmpty())
569 parser.setError (Aborted,"Nothing selected");
572 parser.setError (Aborted,"Type of selection is not a branch");
573 } else if (parser.checkParamCount(1))
575 QColor c=parser.parColor (ok,0);
576 if (ok) colorBranch (c);
578 } else if (com=="colorSubtree")
580 if (xelection.isEmpty())
582 parser.setError (Aborted,"Nothing selected");
585 parser.setError (Aborted,"Type of selection is not a branch");
586 } else if (parser.checkParamCount(1))
588 QColor c=parser.parColor (ok,0);
589 if (ok) colorSubtree (c);
591 } else if (com=="copy")
593 if (xelection.isEmpty())
595 parser.setError (Aborted,"Nothing selected");
598 parser.setError (Aborted,"Type of selection is not a branch");
599 } else if (parser.checkParamCount(0))
601 //FIXME missing action for copy
603 } else if (com=="cut")
605 if (xelection.isEmpty())
607 parser.setError (Aborted,"Nothing selected");
608 } else if ( xelection.type()!=Selection::Branch &&
609 xelection.type()!=Selection::MapCenter &&
610 xelection.type()!=Selection::FloatImage )
612 parser.setError (Aborted,"Type of selection is not a branch or floatimage");
613 } else if (parser.checkParamCount(0))
617 } else if (com=="delete")
619 if (xelection.isEmpty())
621 parser.setError (Aborted,"Nothing selected");
622 } else if (xelection.type() != Selection::Branch && xelection.type() != Selection::FloatImage )
624 parser.setError (Aborted,"Type of selection is wrong.");
625 } else if (parser.checkParamCount(0))
629 } else if (com=="deleteKeepChilds")
631 if (xelection.isEmpty())
633 parser.setError (Aborted,"Nothing selected");
636 parser.setError (Aborted,"Type of selection is not a branch");
637 } else if (parser.checkParamCount(0))
641 } else if (com=="deleteChilds")
643 if (xelection.isEmpty())
645 parser.setError (Aborted,"Nothing selected");
648 parser.setError (Aborted,"Type of selection is not a branch");
649 } else if (parser.checkParamCount(0))
653 } else if (com=="importDir")
655 if (xelection.isEmpty())
657 parser.setError (Aborted,"Nothing selected");
660 parser.setError (Aborted,"Type of selection is not a branch");
661 } else if (parser.checkParamCount(1))
663 s=parser.parString(ok,0);
664 if (ok) importDirInt(s);
666 } else if (com=="linkTo")
668 if (xelection.isEmpty())
670 parser.setError (Aborted,"Nothing selected");
673 if (parser.checkParamCount(4))
675 // 0 selectstring of parent
676 // 1 num in parent (for branches)
677 // 2,3 x,y of mainbranch or mapcenter
678 s=parser.parString(ok,0);
679 LinkableMapObj *dst=mapCenter->findObjBySelect (s);
682 if (typeid(*dst) == typeid(BranchObj) )
684 // Get number in parent
685 x=parser.parInt (ok,1);
687 selb->linkTo ((BranchObj*)(dst),x);
688 } else if (typeid(*dst) == typeid(MapCenterObj) )
690 selb->linkTo ((BranchObj*)(dst),-1);
691 // Get coordinates of mainbranch
692 x=parser.parInt (ok,2);
695 y=parser.parInt (ok,3);
696 if (ok) selb->move (x,y);
701 } else if ( xelection.type() == Selection::FloatImage)
703 if (parser.checkParamCount(1))
705 // 0 selectstring of parent
706 s=parser.parString(ok,0);
707 LinkableMapObj *dst=mapCenter->findObjBySelect (s);
710 if (typeid(*dst) == typeid(BranchObj) ||
711 typeid(*dst) == typeid(MapCenterObj))
712 linkTo (dst->getSelectString());
714 parser.setError (Aborted,"Destination is not a branch");
717 parser.setError (Aborted,"Type of selection is not a floatimage or branch");
718 } else if (com=="loadImage")
720 if (xelection.isEmpty())
722 parser.setError (Aborted,"Nothing selected");
725 parser.setError (Aborted,"Type of selection is not a branch");
726 } else if (parser.checkParamCount(1))
728 s=parser.parString(ok,0);
729 if (ok) loadFloatImageInt (s);
731 } else if (com=="moveBranchUp")
733 if (xelection.isEmpty() )
735 parser.setError (Aborted,"Nothing selected");
738 parser.setError (Aborted,"Type of selection is not a branch");
739 } else if (parser.checkParamCount(0))
743 } else if (com=="moveBranchDown")
745 if (xelection.isEmpty() )
747 parser.setError (Aborted,"Nothing selected");
750 parser.setError (Aborted,"Type of selection is not a branch");
751 } else if (parser.checkParamCount(0))
755 } else if (com=="move")
757 if (xelection.isEmpty() )
759 parser.setError (Aborted,"Nothing selected");
760 } else if ( xelection.type()!=Selection::Branch &&
761 xelection.type()!=Selection::MapCenter &&
762 xelection.type()!=Selection::FloatImage )
764 parser.setError (Aborted,"Type of selection is not a branch or floatimage");
765 } else if (parser.checkParamCount(2))
767 x=parser.parInt (ok,0);
770 y=parser.parInt (ok,1);
774 } else if (com=="moveRel")
776 if (xelection.isEmpty() )
778 parser.setError (Aborted,"Nothing selected");
779 } else if ( xelection.type()!=Selection::Selection::Branch &&
780 xelection.type()!=Selection::Selection::MapCenter &&
781 xelection.type()!=Selection::Selection::FloatImage )
783 parser.setError (Aborted,"Type of selection is not a branch or floatimage");
784 } else if (parser.checkParamCount(2))
786 x=parser.parInt (ok,0);
789 y=parser.parInt (ok,1);
790 if (ok) moveRel (x,y);
793 } else if (com=="nop")
795 } else if (com=="paste")
797 if (xelection.isEmpty() )
799 parser.setError (Aborted,"Nothing selected");
802 parser.setError (Aborted,"Type of selection is not a branch");
803 } else if (parser.checkParamCount(1))
805 x=parser.parInt (ok,0);
806 if (ok) pasteNoSave(x);
808 /////////////////////////////////////////////////////////////////////
809 } else if (com=="qa")
811 if (xelection.isEmpty() )
813 parser.setError (Aborted,"Nothing selected");
816 parser.setError (Aborted,"Type of selection is not a branch");
817 } else if (parser.checkParamCount(4))
820 c=parser.parString (ok,0);
823 parser.setError (Aborted,"No comment given");
826 s=parser.parString (ok,1);
829 parser.setError (Aborted,"First parameter is not a string");
832 t=parser.parString (ok,2);
835 parser.setError (Aborted,"Condition is not a string");
838 u=parser.parString (ok,3);
841 parser.setError (Aborted,"Third parameter is not a string");
846 parser.setError (Aborted,"Unknown type: "+s);
851 parser.setError (Aborted,"Unknown operator: "+t);
856 parser.setError (Aborted,"Type of selection is not a branch");
859 if (selb->getHeading() == u)
861 cout << "PASSED: " << c.ascii() << endl;
864 cout << "FAILED: " << c.ascii() << endl;
874 } else if (com=="saveImage")
876 FloatImageObj *fio=xelection.getFloatImage();
879 parser.setError (Aborted,"Type of selection is not an image");
880 } else if (parser.checkParamCount(2))
882 s=parser.parString(ok,0);
885 t=parser.parString(ok,1);
886 if (ok) saveFloatImageInt (fio,t,s);
889 } else if (com=="scroll")
891 if (xelection.isEmpty() )
893 parser.setError (Aborted,"Nothing selected");
896 parser.setError (Aborted,"Type of selection is not a branch");
897 } else if (parser.checkParamCount(0))
899 if (!scrollBranch (selb))
900 parser.setError (Aborted,"Could not scroll branch");
902 } else if (com=="select")
904 if (parser.checkParamCount(1))
906 s=parser.parString(ok,0);
909 } else if (com=="selectLastBranch")
911 if (xelection.isEmpty() )
913 parser.setError (Aborted,"Nothing selected");
916 parser.setError (Aborted,"Type of selection is not a branch");
917 } else if (parser.checkParamCount(0))
919 BranchObj *bo=selb->getLastBranch();
921 parser.setError (Aborted,"Could not select last branch");
925 } else if (com=="selectLastImage")
927 if (xelection.isEmpty() )
929 parser.setError (Aborted,"Nothing selected");
932 parser.setError (Aborted,"Type of selection is not a branch");
933 } else if (parser.checkParamCount(0))
935 FloatImageObj *fio=selb->getLastFloatImage();
937 parser.setError (Aborted,"Could not select last image");
941 } else if (com=="setFrameType")
943 if ( xelection.type()!=Selection::Branch && xelection.type()!= Selection::MapCenter && xelection.type()!=Selection::FloatImage)
945 parser.setError (Aborted,"Type of selection does not allow setting frame type");
947 else if (parser.checkParamCount(1))
949 s=parser.parString(ok,0);
950 if (ok) setFrameType (s);
952 } else if (com=="setFramePenColor")
954 if ( xelection.type()!=Selection::Branch && xelection.type()!= Selection::MapCenter && xelection.type()!=Selection::FloatImage)
956 parser.setError (Aborted,"Type of selection does not allow setting of pen color");
958 else if (parser.checkParamCount(1))
960 QColor c=parser.parColor(ok,0);
961 if (ok) setFramePenColor (c);
963 } else if (com=="setFrameBrushColor")
965 if ( xelection.type()!=Selection::Branch && xelection.type()!= Selection::MapCenter && xelection.type()!=Selection::FloatImage)
967 parser.setError (Aborted,"Type of selection does not allow setting brush color");
969 else if (parser.checkParamCount(1))
971 QColor c=parser.parColor(ok,0);
972 if (ok) setFrameBrushColor (c);
974 } else if (com=="setFramePadding")
976 if ( xelection.type()!=Selection::Branch && xelection.type()!= Selection::MapCenter && xelection.type()!=Selection::FloatImage)
978 parser.setError (Aborted,"Type of selection does not allow setting frame padding");
980 else if (parser.checkParamCount(1))
982 x=parser.parInt(ok,0);
983 if (ok) setFramePadding(x);
985 } else if (com=="setFrameBorderWidth")
987 if ( xelection.type()!=Selection::Branch && xelection.type()!= Selection::MapCenter && xelection.type()!=Selection::FloatImage)
989 parser.setError (Aborted,"Type of selection does not allow setting frame border width");
991 else if (parser.checkParamCount(1))
993 x=parser.parInt(ok,0);
994 if (ok) setFrameBorderWidth (x);
996 } else if (com=="setMapAuthor")
998 if (parser.checkParamCount(1))
1000 s=parser.parString(ok,0);
1001 if (ok) setMapAuthor (s);
1003 } else if (com=="setMapComment")
1005 if (parser.checkParamCount(1))
1007 s=parser.parString(ok,0);
1008 if (ok) setMapComment(s);
1010 } else if (com=="setMapBackgroundColor")
1012 if (xelection.isEmpty() )
1014 parser.setError (Aborted,"Nothing selected");
1015 } else if (! xelection.getBranch() )
1017 parser.setError (Aborted,"Type of selection is not a branch");
1018 } else if (parser.checkParamCount(1))
1020 QColor c=parser.parColor (ok,0);
1021 if (ok) setMapBackgroundColor (c);
1023 } else if (com=="setMapDefLinkColor")
1025 if (xelection.isEmpty() )
1027 parser.setError (Aborted,"Nothing selected");
1030 parser.setError (Aborted,"Type of selection is not a branch");
1031 } else if (parser.checkParamCount(1))
1033 QColor c=parser.parColor (ok,0);
1034 if (ok) setMapDefLinkColor (c);
1036 } else if (com=="setMapLinkStyle")
1038 if (parser.checkParamCount(1))
1040 s=parser.parString (ok,0);
1041 if (ok) setMapLinkStyle(s);
1043 } else if (com=="setHeading")
1045 if (xelection.isEmpty() )
1047 parser.setError (Aborted,"Nothing selected");
1050 parser.setError (Aborted,"Type of selection is not a branch");
1051 } else if (parser.checkParamCount(1))
1053 s=parser.parString (ok,0);
1057 } else if (com=="setHideExport")
1059 if (xelection.isEmpty() )
1061 parser.setError (Aborted,"Nothing selected");
1062 } else if (xelection.type()!=Selection::Branch && xelection.type() != Selection::MapCenter &&xelection.type()!=Selection::FloatImage)
1064 parser.setError (Aborted,"Type of selection is not a branch or floatimage");
1065 } else if (parser.checkParamCount(1))
1067 b=parser.parBool(ok,0);
1068 if (ok) setHideExport (b);
1070 } else if (com=="setIncludeImagesHorizontally")
1072 if (xelection.isEmpty() )
1074 parser.setError (Aborted,"Nothing selected");
1077 parser.setError (Aborted,"Type of selection is not a branch");
1078 } else if (parser.checkParamCount(1))
1080 b=parser.parBool(ok,0);
1081 if (ok) setIncludeImagesHor(b);
1083 } else if (com=="setIncludeImagesVertically")
1085 if (xelection.isEmpty() )
1087 parser.setError (Aborted,"Nothing selected");
1090 parser.setError (Aborted,"Type of selection is not a branch");
1091 } else if (parser.checkParamCount(1))
1093 b=parser.parBool(ok,0);
1094 if (ok) setIncludeImagesVer(b);
1096 } else if (com=="setHideLinkUnselected")
1098 if (xelection.isEmpty() )
1100 parser.setError (Aborted,"Nothing selected");
1101 } else if ( xelection.type()!=Selection::Branch && xelection.type()!= Selection::MapCenter && xelection.type()!=Selection::FloatImage)
1103 parser.setError (Aborted,"Type of selection does not allow hiding the link");
1104 } else if (parser.checkParamCount(1))
1106 b=parser.parBool(ok,0);
1107 if (ok) setHideLinkUnselected(b);
1109 } else if (com=="setSelectionColor")
1111 if (parser.checkParamCount(1))
1113 QColor c=parser.parColor (ok,0);
1114 if (ok) setSelectionColorInt (c);
1116 } else if (com=="setURL")
1118 if (xelection.isEmpty() )
1120 parser.setError (Aborted,"Nothing selected");
1123 parser.setError (Aborted,"Type of selection is not a branch");
1124 } else if (parser.checkParamCount(1))
1126 s=parser.parString (ok,0);
1129 } else if (com=="setVymLink")
1131 if (xelection.isEmpty() )
1133 parser.setError (Aborted,"Nothing selected");
1136 parser.setError (Aborted,"Type of selection is not a branch");
1137 } else if (parser.checkParamCount(1))
1139 s=parser.parString (ok,0);
1140 if (ok) setVymLinkInt(s);
1143 else if (com=="setFlag")
1145 if (xelection.isEmpty() )
1147 parser.setError (Aborted,"Nothing selected");
1150 parser.setError (Aborted,"Type of selection is not a branch");
1151 } else if (parser.checkParamCount(1))
1153 s=parser.parString(ok,0);
1156 selb->activateStandardFlag(s);
1157 selb->updateFlagsToolbar();
1160 } else if (com=="setFrameType")
1162 if (xelection.isEmpty() )
1164 parser.setError (Aborted,"Nothing selected");
1167 parser.setError (Aborted,"Type of selection is not a branch");
1168 } else if (parser.checkParamCount(1))
1170 s=parser.parString(ok,0);
1174 } else if (com=="toggleFlag")
1176 if (xelection.isEmpty() )
1178 parser.setError (Aborted,"Nothing selected");
1181 parser.setError (Aborted,"Type of selection is not a branch");
1182 } else if (parser.checkParamCount(1))
1184 s=parser.parString(ok,0);
1187 selb->toggleStandardFlag(s);
1188 selb->updateFlagsToolbar();
1191 } else if (com=="unscroll")
1193 if (xelection.isEmpty() )
1195 parser.setError (Aborted,"Nothing selected");
1198 parser.setError (Aborted,"Type of selection is not a branch");
1199 } else if (parser.checkParamCount(0))
1201 if (!unscrollBranch (selb))
1202 parser.setError (Aborted,"Could not unscroll branch");
1204 } else if (com=="unscrollChilds")
1206 if (xelection.isEmpty() )
1208 parser.setError (Aborted,"Nothing selected");
1211 parser.setError (Aborted,"Type of selection is not a branch");
1212 } else if (parser.checkParamCount(0))
1216 } else if (com=="unsetFlag")
1218 if (xelection.isEmpty() )
1220 parser.setError (Aborted,"Nothing selected");
1223 parser.setError (Aborted,"Type of selection is not a branch");
1224 } else if (parser.checkParamCount(1))
1226 s=parser.parString(ok,0);
1229 selb->deactivateStandardFlag(s);
1230 selb->updateFlagsToolbar();
1234 parser.setError (Aborted,"Unknown command");
1237 if (parser.errorLevel()==NoError)
1240 mapCenter->reposition();
1244 // TODO Error handling
1245 qWarning("MapEditor::parseAtom: Error!");
1246 qWarning(parser.errorMessage());
1250 void MapEditor::runScript (QString script)
1252 parser.setScript (script);
1254 while (parser.next() )
1255 parseAtom(parser.getAtom());
1258 bool MapEditor::isDefault()
1263 bool MapEditor::hasChanged()
1268 void MapEditor::setChanged()
1271 autosaveTimer->start(settings.value("/mapeditor/autosave/ms/",300000).toInt());
1279 void MapEditor::closeMap()
1281 // Unselect before disabling the toolbar actions
1282 if (!xelection.isEmpty() ) xelection.unselect();
1290 void MapEditor::setFilePath(QString fpath, QString destname)
1292 if (fpath.isEmpty() || fpath=="")
1299 filePath=fpath; // becomes absolute path
1300 fileName=fpath; // gets stripped of path
1301 destPath=destname; // needed for vymlinks
1303 // If fpath is not an absolute path, complete it
1304 filePath=QDir(fpath).absPath();
1305 fileDir=filePath.left (1+filePath.findRev ("/"));
1307 // Set short name, too. Search from behind:
1308 int i=fileName.findRev("/");
1309 if (i>=0) fileName=fileName.remove (0,i+1);
1311 // Forget the .vym (or .xml) for name of map
1312 mapName=fileName.left(fileName.findRev(".",-1,true) );
1316 void MapEditor::setFilePath(QString fpath)
1318 setFilePath (fpath,fpath);
1321 QString MapEditor::getFilePath()
1326 QString MapEditor::getFileName()
1331 QString MapEditor::getMapName()
1336 QString MapEditor::getDestPath()
1341 ErrorCode MapEditor::load (QString fname, LoadMode lmode)
1343 ErrorCode err=success;
1347 if (xelection.isEmpty() ) xelection.unselect();
1350 mapCenter->setMapEditor(this);
1351 // (map state is set later at end of load...)
1354 BranchObj *bo=xelection.getBranch();
1355 if (!bo) return aborted;
1356 if (lmode==ImportAdd)
1357 saveStateChangingPart(
1360 QString("addMapInsert (%1)").arg(fname),
1361 QString("Add map %1 to %2").arg(fname).arg(getName(bo)));
1363 saveStateChangingPart(
1366 QString("addMapReplace(%1)").arg(fname),
1367 QString("Add map %1 to %2").arg(fname).arg(getName(bo)));
1371 mapBuilderHandler handler;
1372 QFile file( fname );
1374 // I am paranoid: file should exist anyway
1375 // according to check in mainwindow.
1376 if (!file.exists() )
1378 QMessageBox::critical( 0, tr( "Critical Parse Error" ),
1379 tr("Couldn't open map " +fname)+".");
1383 bool blockSaveStateOrg=blockSaveState;
1384 blockReposition=true;
1385 blockSaveState=true;
1386 QXmlInputSource source( file);
1387 QXmlSimpleReader reader;
1388 reader.setContentHandler( &handler );
1389 reader.setErrorHandler( &handler );
1390 handler.setMapEditor( this );
1393 // We need to set the tmpDir in order to load files with rel. path
1394 QString tmpdir= fname.left(fname.findRev("/",-1));
1395 handler.setTmpDir (tmpdir);
1396 handler.setInputFile (file.name());
1397 handler.setLoadMode (lmode);
1398 bool ok = reader.parse( source );
1399 blockReposition=false;
1400 blockSaveState=blockSaveStateOrg;
1404 mapCenter->reposition();
1411 autosaveTimer->stop();
1415 QMessageBox::critical( 0, tr( "Critical Parse Error" ),
1416 tr( handler.errorProtocol() ) );
1418 // Still return "success": the map maybe at least
1419 // partially read by the parser
1426 int MapEditor::save (const SaveMode &savemode)
1430 // Create mapName and fileDir
1431 makeSubDirs (fileDir);
1435 fname=mapName+".xml";
1437 // use name given by user, even if he chooses .doc
1442 if (savemode==CompleteMap || xelection.isEmpty())
1443 saveFile=saveToDir (fileDir,mapName+"-",true,QPointF(),NULL);
1446 // TODO take care of multiselections
1447 if (xelection.type()==Selection::FloatImage)
1450 saveFile=saveToDir (fileDir,mapName+"-",true,QPointF(),xelection.getBranch());
1453 if (!saveStringToDisk(fileDir+fname,saveFile))
1460 autosaveTimer->stop();
1467 void MapEditor::setZipped (bool z)
1472 bool MapEditor::saveZipped ()
1477 void MapEditor::print()
1481 printer = new QPrinter;
1482 printer->setColorMode (QPrinter::Color);
1483 printer->setPrinterName (settings.value("/mainwindow/printerName",printer->printerName()).toString());
1484 printer->setOutputFormat((QPrinter::OutputFormat)settings.value("/mainwindow/printerFormat",printer->outputFormat()).toInt());
1485 printer->setOutputFileName(settings.value("/mainwindow/printerFileName",printer->outputFileName()).toString());
1488 QRectF totalBBox=mapCenter->getTotalBBox();
1490 // Try to set orientation automagically
1491 // Note: Interpretation of generated postscript is amibiguous, if
1492 // there are problems with landscape mode, see
1493 // http://sdb.suse.de/de/sdb/html/jsmeix_print-cups-landscape-81.html
1495 if (totalBBox.width()>totalBBox.height())
1496 // recommend landscape
1497 printer->setOrientation (QPrinter::Landscape);
1499 // recommend portrait
1500 printer->setOrientation (QPrinter::Portrait);
1502 if ( printer->setup(this) )
1503 // returns false, if printing is canceled
1505 QPainter pp(printer);
1507 pp.setRenderHint(QPainter::Antialiasing,true);
1509 // Don't print the visualisation of selection
1510 xelection.unselect();
1512 QRectF mapRect=totalBBox;
1513 QGraphicsRectItem *frame=NULL;
1517 // Print frame around map
1518 mapRect.setRect (totalBBox.x()-10, totalBBox.y()-10,
1519 totalBBox.width()+20, totalBBox.height()+20);
1520 frame=mapScene->addRect (mapRect, QPen(Qt::black),QBrush(Qt::NoBrush));
1521 frame->setZValue(0);
1526 double paperAspect = (double)printer->width() / (double)printer->height();
1527 double mapAspect = (double)mapRect.width() / (double)mapRect.height();
1529 if (mapAspect>=paperAspect)
1531 // Fit horizontally to paper width
1532 //pp.setViewport(0,0, printer->width(),(int)(printer->width()/mapAspect) );
1533 viewBottom=(int)(printer->width()/mapAspect);
1536 // Fit vertically to paper height
1537 //pp.setViewport(0,0,(int)(printer->height()*mapAspect),printer->height());
1538 viewBottom=printer->height();
1543 // Print footer below map
1545 font.setPointSize(10);
1547 QRectF footerBox(0,viewBottom,printer->width(),15);
1548 pp.drawText ( footerBox,Qt::AlignLeft,"VYM - " +fileName);
1549 pp.drawText ( footerBox, Qt::AlignRight, QDate::currentDate().toString(Qt::TextDate));
1553 QRectF (0,0,printer->width(),printer->height()-15),
1554 QRectF(mapRect.x(),mapRect.y(),mapRect.width(),mapRect.height())
1557 // Viewport has paper dimension
1558 if (frame) delete (frame);
1560 // Restore selection
1561 xelection.reselect();
1563 // Save settings in vymrc
1564 settings.writeEntry("/mainwindow/printerName",printer->printerName());
1565 settings.writeEntry("/mainwindow/printerFormat",printer->outputFormat());
1566 settings.writeEntry("/mainwindow/printerFileName",printer->outputFileName());
1570 void MapEditor::setAntiAlias (bool b)
1572 setRenderHint(QPainter::Antialiasing,b);
1575 void MapEditor::setSmoothPixmap(bool b)
1577 setRenderHint(QPainter::SmoothPixmapTransform,b);
1580 QPixmap MapEditor::getPixmap()
1582 QRectF mapRect=mapCenter->getTotalBBox();
1583 QPixmap pix((int)mapRect.width()+2,(int)mapRect.height()+2);
1586 pp.setRenderHints(renderHints());
1588 // Don't print the visualisation of selection
1589 xelection.unselect();
1591 mapScene->render ( &pp,
1592 QRectF(0,0,mapRect.width()+2,mapRect.height()+2),
1593 QRectF(mapRect.x(),mapRect.y(),mapRect.width(),mapRect.height() ));
1595 // Restore selection
1596 xelection.reselect();
1601 void MapEditor::setHideTmpMode (BranchObj::HideTmpMode mode)
1604 mapCenter->setHideTmp (hidemode);
1605 mapCenter->reposition();
1609 BranchObj::HideTmpMode MapEditor::getHideTmpMode()
1614 void MapEditor::exportImage(QString fn)
1616 setExportMode (true);
1617 QPixmap pix (getPixmap());
1618 pix.save(fn, "PNG");
1619 setExportMode (false);
1622 void MapEditor::setExportMode (bool b)
1624 // should be called before and after exports
1625 // depending on the settings
1626 if (b && settings.value("/export/useHideExport","yes")=="yes")
1627 setHideTmpMode (BranchObj::HideExport);
1629 setHideTmpMode (BranchObj::HideNone);
1632 void MapEditor::exportImage(QString fn, QString format)
1634 setExportMode (true);
1635 QPixmap pix (getPixmap());
1636 pix.save(fn, format);
1637 setExportMode (false);
1640 void MapEditor::exportOOPresentation(const QString &fn, const QString &cf)
1644 ex.setMapCenter(mapCenter);
1645 if (ex.setConfigFile(cf))
1647 setExportMode (true);
1648 ex.exportPresentation();
1649 setExportMode (false);
1655 void MapEditor::exportXML(const QString &dir)
1657 // Hide stuff during export, if settings want this
1658 setExportMode (true);
1660 // Create subdirectories
1663 // write to directory
1664 QString saveFile=saveToDir (dir,mapName+"-",true,mapCenter->getTotalBBox().topLeft() ,NULL);
1667 file.setName ( dir + "/"+mapName+".xml");
1668 if ( !file.open( QIODevice::WriteOnly ) )
1670 // This should neverever happen
1671 QMessageBox::critical (0,tr("Critical Export Error"),tr("MapEditor::exportXML couldn't open %1").arg(file.name()));
1675 // Write it finally, and write in UTF8, no matter what
1676 QTextStream ts( &file );
1677 ts.setEncoding (QTextStream::UnicodeUTF8);
1681 // Now write image, too
1682 exportImage (dir+"/images/"+mapName+".png");
1684 setExportMode (false);
1687 void MapEditor::clear()
1689 xelection.unselect();
1693 void MapEditor::copy()
1695 LinkableMapObj *sel=xelection.single();
1698 if (redosAvail == 0)
1701 QString s=sel->getSelectString();
1702 saveState (PartOfMap, s, "nop ()", s, "copy ()","Copy to clipboard",sel );
1703 curClipboard=curStep;
1706 // Copy also to global clipboard, because we are at last step in history
1707 QString bakMapName=QDir::convertSeparators (QString("history-%1").arg(curStep));
1708 QString bakMapDir=QDir::convertSeparators (tmpMapDir +"/"+bakMapName);
1709 copyDir (bakMapDir,clipboardDir );
1711 clipboardEmpty=false;
1716 void MapEditor::redo()
1718 // Can we undo at all?
1719 if (redosAvail<1) return;
1721 bool blockSaveStateOrg=blockSaveState;
1722 blockSaveState=true;
1726 if (undosAvail<stepsTotal) undosAvail++;
1728 if (curStep>stepsTotal) curStep=1;
1729 QString undoCommand= undoSet.readEntry (QString("/history/step-%1/undoCommand").arg(curStep));
1730 QString undoSelection=undoSet.readEntry (QString("/history/step-%1/undoSelection").arg(curStep));
1731 QString redoCommand= undoSet.readEntry (QString("/history/step-%1/redoCommand").arg(curStep));
1732 QString redoSelection=undoSet.readEntry (QString("/history/step-%1/redoSelection").arg(curStep));
1733 QString comment=undoSet.readEntry (QString("/history/step-%1/comment").arg(curStep));
1734 QString version=undoSet.readEntry ("/history/version");
1736 if (!checkVersion(version))
1737 QMessageBox::warning(0,tr("Warning"),
1738 tr("Version %1 of saved undo/redo data\ndoes not match current vym version %2.").arg(version).arg(vymVersion));
1741 // Find out current undo directory
1742 QString bakMapDir=QDir::convertSeparators (QString(tmpMapDir+"/undo-%1").arg(curStep));
1746 cout << "ME::redo() begin\n";
1747 cout << " undosAvail="<<undosAvail<<endl;
1748 cout << " redosAvail="<<redosAvail<<endl;
1749 cout << " curStep="<<curStep<<endl;
1750 cout << " ---------------------------"<<endl;
1751 cout << " comment="<<comment.toStdString()<<endl;
1752 cout << " undoCom="<<undoCommand.toStdString()<<endl;
1753 cout << " undoSel="<<undoSelection.toStdString()<<endl;
1754 cout << " redoCom="<<redoCommand.toStdString()<<endl;
1755 cout << " redoSel="<<redoSelection.toStdString()<<endl;
1756 cout << " ---------------------------"<<endl<<endl;
1759 // select object before redo
1760 if (!redoSelection.isEmpty())
1761 select (redoSelection);
1764 parseAtom (redoCommand);
1765 mapCenter->reposition();
1767 blockSaveState=blockSaveStateOrg;
1769 undoSet.setEntry ("/history/undosAvail",QString::number(undosAvail));
1770 undoSet.setEntry ("/history/redosAvail",QString::number(redosAvail));
1771 undoSet.setEntry ("/history/curStep",QString::number(curStep));
1772 undoSet.writeSettings(histPath);
1774 mainWindow->updateHistory (undoSet);
1777 /* TODO remove testing
1778 cout << "ME::redo() end\n";
1779 cout << " undosAvail="<<undosAvail<<endl;
1780 cout << " redosAvail="<<redosAvail<<endl;
1781 cout << " curStep="<<curStep<<endl;
1782 cout << " ---------------------------"<<endl<<endl;
1788 bool MapEditor::isRedoAvailable()
1790 if (undoSet.readNumEntry("/history/redosAvail",0)>0)
1796 void MapEditor::undo()
1798 // Can we undo at all?
1799 if (undosAvail<1) return;
1801 mainWindow->statusMessage (tr("Autosave disabled during undo."));
1803 bool blockSaveStateOrg=blockSaveState;
1804 blockSaveState=true;
1806 QString undoCommand= undoSet.readEntry (QString("/history/step-%1/undoCommand").arg(curStep));
1807 QString undoSelection=undoSet.readEntry (QString("/history/step-%1/undoSelection").arg(curStep));
1808 QString redoCommand= undoSet.readEntry (QString("/history/step-%1/redoCommand").arg(curStep));
1809 QString redoSelection=undoSet.readEntry (QString("/history/step-%1/redoSelection").arg(curStep));
1810 QString comment=undoSet.readEntry (QString("/history/step-%1/comment").arg(curStep));
1811 QString version=undoSet.readEntry ("/history/version");
1813 if (!checkVersion(version))
1814 QMessageBox::warning(0,tr("Warning"),
1815 tr("Version %1 of saved undo/redo data\ndoes not match current vym version %2.").arg(version).arg(vymVersion));
1817 // Find out current undo directory
1818 QString bakMapDir=QDir::convertSeparators (QString(tmpMapDir+"/undo-%1").arg(curStep));
1820 // select object before undo
1821 if (!undoSelection.isEmpty())
1822 select (undoSelection);
1826 cout << "ME::undo() begin\n";
1827 cout << " undosAvail="<<undosAvail<<endl;
1828 cout << " redosAvail="<<redosAvail<<endl;
1829 cout << " curStep="<<curStep<<endl;
1830 cout << " ---------------------------"<<endl;
1831 cout << " comment="<<comment.toStdString()<<endl;
1832 cout << " undoCom="<<undoCommand.toStdString()<<endl;
1833 cout << " undoSel="<<undoSelection.toStdString()<<endl;
1834 cout << " redoCom="<<redoCommand.toStdString()<<endl;
1835 cout << " redoSel="<<redoSelection.toStdString()<<endl;
1836 cout << " ---------------------------"<<endl<<endl;
1838 parseAtom (undoCommand);
1839 mapCenter->reposition();
1843 if (curStep<1) curStep=stepsTotal;
1847 blockSaveState=blockSaveStateOrg;
1848 /* TODO remove testing
1849 cout << "ME::undo() end\n";
1850 cout << " undosAvail="<<undosAvail<<endl;
1851 cout << " redosAvail="<<redosAvail<<endl;
1852 cout << " curStep="<<curStep<<endl;
1853 cout << " ---------------------------"<<endl<<endl;
1856 undoSet.setEntry ("/history/undosAvail",QString::number(undosAvail));
1857 undoSet.setEntry ("/history/redosAvail",QString::number(redosAvail));
1858 undoSet.setEntry ("/history/curStep",QString::number(curStep));
1859 undoSet.writeSettings(histPath);
1861 mainWindow->updateHistory (undoSet);
1864 ensureSelectionVisible();
1867 bool MapEditor::isUndoAvailable()
1869 if (undoSet.readNumEntry("/history/undosAvail",0)>0)
1875 void MapEditor::gotoHistoryStep (int i)
1877 // Restore variables
1878 int undosAvail=undoSet.readNumEntry (QString("/history/undosAvail"));
1879 int redosAvail=undoSet.readNumEntry (QString("/history/redosAvail"));
1881 if (i<0) i=undosAvail+redosAvail;
1883 // Clicking above current step makes us undo things
1886 for (int j=0; j<undosAvail-i; j++) undo();
1889 // Clicking below current step makes us redo things
1891 for (int j=undosAvail; j<i; j++)
1893 cout << "redo "<<j<<"/"<<undosAvail<<" i="<<i<<endl;
1897 // And ignore clicking the current row ;-)
1900 void MapEditor::addMapReplaceInt(const QString &undoSel, const QString &path)
1902 QString pathDir=path.left(path.findRev("/"));
1908 // We need to parse saved XML data
1909 mapBuilderHandler handler;
1910 QXmlInputSource source( file);
1911 QXmlSimpleReader reader;
1912 reader.setContentHandler( &handler );
1913 reader.setErrorHandler( &handler );
1914 handler.setMapEditor( this );
1915 handler.setTmpDir ( pathDir ); // needed to load files with rel. path
1916 if (undoSel.isEmpty())
1920 handler.setLoadMode (NewMap);
1924 handler.setLoadMode (ImportReplace);
1926 blockReposition=true;
1927 bool ok = reader.parse( source );
1928 blockReposition=false;
1931 // This should never ever happen
1932 QMessageBox::critical( 0, tr( "Critical Parse Error while reading %1").arg(path),
1933 handler.errorProtocol());
1936 QMessageBox::critical( 0, tr( "Critical Error" ), tr("Could not read %1").arg(path));
1939 void MapEditor::addMapInsertInt (const QString &path, int pos)
1941 BranchObj *sel=xelection.getBranch();
1944 QString pathDir=path.left(path.findRev("/"));
1950 // We need to parse saved XML data
1951 mapBuilderHandler handler;
1952 QXmlInputSource source( file);
1953 QXmlSimpleReader reader;
1954 reader.setContentHandler( &handler );
1955 reader.setErrorHandler( &handler );
1956 handler.setMapEditor( this );
1957 handler.setTmpDir ( pathDir ); // needed to load files with rel. path
1958 handler.setLoadMode (ImportAdd);
1959 blockReposition=true;
1960 bool ok = reader.parse( source );
1961 blockReposition=false;
1964 // This should never ever happen
1965 QMessageBox::critical( 0, tr( "Critical Parse Error while reading %1").arg(path),
1966 handler.errorProtocol());
1969 sel->getLastBranch()->linkTo (sel,pos);
1971 QMessageBox::critical( 0, tr( "Critical Error" ), tr("Could not read %1").arg(path));
1975 void MapEditor::pasteNoSave(const int &n)
1977 bool old=blockSaveState;
1978 blockSaveState=true;
1979 if (redosAvail > 0 || n!=0)
1981 // Use the "historical" buffer
1982 QString bakMapName=QDir::convertSeparators (QString("history-%1").arg(n));
1983 QString bakMapDir=QDir::convertSeparators (tmpMapDir +"/"+bakMapName);
1984 load (bakMapDir+"/"+clipboardFile,ImportAdd);
1986 // Use the global buffer
1987 load (clipboardDir+"/"+clipboardFile,ImportAdd);
1991 void MapEditor::paste()
1993 BranchObj *sel=xelection.getBranch();
1996 saveStateChangingPart(
1999 QString ("paste (%1)").arg(curClipboard),
2000 QString("Paste to %1").arg( getName(sel))
2003 mapCenter->reposition();
2007 void MapEditor::cut()
2009 LinkableMapObj *sel=xelection.single();
2010 if ( sel && (xelection.type() == Selection::Branch ||
2011 xelection.type()==Selection::MapCenter ||
2012 xelection.type()==Selection::FloatImage))
2014 /* No savestate! savestate is called in cutNoSave
2015 saveStateChangingPart(
2019 QString("Cut %1").arg(getName(sel ))
2024 mapCenter->reposition();
2028 void MapEditor::move(const int &x, const int &y)
2030 LinkableMapObj *sel=xelection.single();
2033 QString ps=qpointfToString (sel->getAbsPos());
2034 QString s=xelection.single()->getSelectString();
2037 s, "move "+qpointfToString (QPointF (x,y)),
2038 QString("Move %1 to %2").arg(getName(sel)).arg(ps));
2040 mapCenter->reposition();
2046 void MapEditor::moveRel (const int &x, const int &y)
2048 LinkableMapObj *sel=xelection.single();
2051 QString ps=qpointfToString (sel->getRelPos());
2052 QString s=sel->getSelectString();
2055 s, "moveRel "+qpointfToString (QPointF (x,y)),
2056 QString("Move %1 to relativ position %2").arg(getName(sel)).arg(ps));
2057 ((OrnamentedObj*)sel)->move2RelPos (x,y);
2058 mapCenter->reposition();
2064 void MapEditor::moveBranchUp()
2066 BranchObj* bo=xelection.getBranch();
2070 if (!bo->canMoveBranchUp()) return;
2071 par=(BranchObj*)(bo->getParObj());
2072 BranchObj *obo=par->moveBranchUp (bo); // bo will be the one below selection
2073 saveState (bo->getSelectString(),"moveBranchDown ()",obo->getSelectString(),"moveBranchUp ()",QString("Move up %1").arg(getName(bo)));
2074 mapCenter->reposition();
2077 ensureSelectionVisible();
2081 void MapEditor::moveBranchDown()
2083 BranchObj* bo=xelection.getBranch();
2087 if (!bo->canMoveBranchDown()) return;
2088 par=(BranchObj*)(bo->getParObj());
2089 BranchObj *obo=par->moveBranchDown(bo); // bo will be the one above selection
2090 saveState(bo->getSelectString(),"moveBranchUp ()",obo->getSelectString(),"moveBranchDown ()",QString("Move down %1").arg(getName(bo)));
2091 mapCenter->reposition();
2094 ensureSelectionVisible();
2098 void MapEditor::linkTo(const QString &dstString)
2100 FloatImageObj *fio=xelection.getFloatImage();
2103 BranchObj *dst=(BranchObj*)(mapCenter->findObjBySelect(dstString));
2104 if (dst && (typeid(*dst)==typeid (BranchObj) ||
2105 typeid(*dst)==typeid (MapCenterObj)))
2107 LinkableMapObj *dstPar=dst->getParObj();
2108 QString parString=dstPar->getSelectString();
2109 QString fioPreSelectString=fio->getSelectString();
2110 QString fioPreParentSelectString=fio->getParObj()->getSelectString();
2111 ((BranchObj*)(dst))->addFloatImage (fio);
2112 xelection.unselect();
2113 ((BranchObj*)(fio->getParObj()))->removeFloatImage (fio);
2114 fio=((BranchObj*)(dst))->getLastFloatImage();
2117 xelection.select(fio);
2119 fio->getSelectString(),
2120 QString("linkTo (\"%1\")").arg(fioPreParentSelectString),
2122 QString ("linkTo (\"%1\")").arg(dstString),
2123 QString ("Link floatimage to %1").arg(getName(dst)));
2128 QString MapEditor::getHeading(bool &ok, QPoint &p)
2130 BranchObj *bo=xelection.getBranch();
2134 p=mapFromScene(bo->getAbsPos());
2135 return bo->getHeading();
2141 void MapEditor::setHeading(const QString &s)
2143 BranchObj *sel=xelection.getBranch();
2148 "setHeading (\""+sel->getHeading()+"\")",
2150 "setHeading (\""+s+"\")",
2151 QString("Set heading of %1 to \"%2\"").arg(getName(sel)).arg(s) );
2152 sel->setHeading(s );
2153 mapCenter->reposition();
2155 ensureSelectionVisible();
2159 void MapEditor::setHeadingInt(const QString &s)
2161 BranchObj *bo=xelection.getBranch();
2165 mapCenter->reposition();
2167 ensureSelectionVisible();
2171 void MapEditor::setVymLinkInt (const QString &s)
2173 // Internal function, no saveState needed
2174 BranchObj *bo=xelection.getBranch();
2178 mapCenter->reposition();
2181 ensureSelectionVisible();
2185 BranchObj* MapEditor::addNewBranchInt(int num)
2187 // Depending on pos:
2188 // -3 insert in childs of parent above selection
2189 // -2 add branch to selection
2190 // -1 insert in childs of parent below selection
2191 // 0..n insert in childs of parent at pos
2192 BranchObj *newbo=NULL;
2193 BranchObj *bo=xelection.getBranch();
2198 // save scroll state. If scrolled, automatically select
2199 // new branch in order to tmp unscroll parent...
2200 return bo->addBranch();
2205 bo=(BranchObj*)bo->getParObj();
2209 bo=(BranchObj*)bo->getParObj();
2212 newbo=bo->insertBranch(num);
2217 BranchObj* MapEditor::addNewBranch(int pos)
2219 // Different meaning than num in addNewBranchInt!
2223 BranchObj *bo = xelection.getBranch();
2224 BranchObj *newbo=NULL;
2228 setCursor (Qt::ArrowCursor);
2230 newbo=addNewBranchInt (pos-2);
2238 QString ("addBranch (%1)").arg(pos-2),
2239 QString ("Add new branch to %1").arg(getName(bo)));
2241 mapCenter->reposition();
2249 BranchObj* MapEditor::addNewBranchBefore()
2251 BranchObj *newbo=NULL;
2252 BranchObj *bo = xelection.getBranch();
2253 if (bo && xelection.type()==Selection::Branch)
2254 // We accept no MapCenterObj here, so we _have_ a parent
2256 QPointF p=bo->getRelPos();
2259 BranchObj *parbo=(BranchObj*)(bo->getParObj());
2261 // add below selection
2262 newbo=parbo->insertBranch(bo->getNum()+1);
2265 newbo->move2RelPos (p);
2267 // Move selection to new branch
2268 bo->linkTo (newbo,-1);
2270 saveState (newbo, "deleteKeepChilds ()", newbo, "addBranchBefore ()",
2271 QString ("Add branch before %1").arg(getName(bo)));
2273 mapCenter->reposition();
2280 void MapEditor::deleteSelection()
2282 BranchObj *bo = xelection.getBranch();
2283 if (bo && xelection.type()==Selection::Branch)
2285 BranchObj* par=(BranchObj*)(bo->getParObj());
2286 xelection.unselect();
2287 saveStateRemovingPart (bo, QString ("Delete %1").arg(getName(bo)));
2288 par->removeBranch(bo);
2289 xelection.select (par);
2290 ensureSelectionVisible();
2291 mapCenter->reposition();
2296 FloatImageObj *fio=xelection.getFloatImage();
2299 BranchObj* par=(BranchObj*)(fio->getParObj());
2300 saveStateChangingPart(
2304 QString("Delete %1").arg(getName(fio))
2306 xelection.unselect();
2307 par->removeFloatImage(fio);
2308 xelection.select (par);
2309 mapCenter->reposition();
2311 ensureSelectionVisible();
2316 LinkableMapObj* MapEditor::getSelection()
2318 return xelection.single();
2321 BranchObj* MapEditor::getSelectedBranch()
2323 return xelection.getBranch();
2326 FloatImageObj* MapEditor::getSelectedFloatImage()
2328 return xelection.getFloatImage();
2331 void MapEditor::unselect()
2333 xelection.unselect();
2336 void MapEditor::reselect()
2338 xelection.reselect();
2341 bool MapEditor::select (const QString &s)
2343 LinkableMapObj *lmo=mapCenter->findObjBySelect(s);
2345 // Finally select the found object
2348 xelection.unselect();
2349 xelection.select(lmo);
2351 ensureSelectionVisible();
2357 QString MapEditor::getSelectString()
2359 return xelection.getSelectString();
2362 void MapEditor::selectInt (LinkableMapObj *lmo)
2364 if (lmo && xelection.single()!= lmo && isSelectBlocked()==false )
2366 xelection.select(lmo);
2371 void MapEditor::selectNextBranchInt()
2373 // Increase number of branch
2374 LinkableMapObj *sel=xelection.single();
2377 QString s=sel->getSelectString();
2383 part=s.section(",",-1);
2385 num=part.right(part.length() - 3);
2387 s=s.left (s.length() -num.length());
2390 num=QString ("%1").arg(num.toUInt()+1);
2394 // Try to select this one
2395 if (select (s)) return;
2397 // We have no direct successor,
2398 // try to increase the parental number in order to
2399 // find a successor with same depth
2401 int d=xelection.single()->getDepth();
2406 while (!found && d>0)
2408 s=s.section (",",0,d-1);
2409 // replace substring of current depth in s with "1"
2410 part=s.section(",",-1);
2412 num=part.right(part.length() - 3);
2416 // increase number of parent
2417 num=QString ("%1").arg(num.toUInt()+1);
2418 s=s.section (",",0,d-2) + ","+ typ+num;
2421 // Special case, look at orientation
2422 if (xelection.single()->getOrientation()==LinkableMapObj::RightOfCenter)
2423 num=QString ("%1").arg(num.toUInt()+1);
2425 num=QString ("%1").arg(num.toUInt()-1);
2430 // pad to oldDepth, select the first branch for each depth
2431 for (i=d;i<oldDepth;i++)
2436 if ( xelection.getBranch()->countBranches()>0)
2444 // try to select the freshly built string
2452 void MapEditor::selectPrevBranchInt()
2454 // Decrease number of branch
2455 BranchObj *bo=xelection.getBranch();
2458 QString s=bo->getSelectString();
2464 part=s.section(",",-1);
2466 num=part.right(part.length() - 3);
2468 s=s.left (s.length() -num.length());
2470 int n=num.toInt()-1;
2473 num=QString ("%1").arg(n);
2476 // Try to select this one
2477 if (n>=0 && select (s)) return;
2479 // We have no direct precessor,
2480 // try to decrease the parental number in order to
2481 // find a precessor with same depth
2483 int d=xelection.single()->getDepth();
2488 while (!found && d>0)
2490 s=s.section (",",0,d-1);
2491 // replace substring of current depth in s with "1"
2492 part=s.section(",",-1);
2494 num=part.right(part.length() - 3);
2498 // decrease number of parent
2499 num=QString ("%1").arg(num.toInt()-1);
2500 s=s.section (",",0,d-2) + ","+ typ+num;
2503 // Special case, look at orientation
2504 if (xelection.single()->getOrientation()==LinkableMapObj::RightOfCenter)
2505 num=QString ("%1").arg(num.toInt()-1);
2507 num=QString ("%1").arg(num.toInt()+1);
2512 // pad to oldDepth, select the last branch for each depth
2513 for (i=d;i<oldDepth;i++)
2517 if ( xelection.getBranch()->countBranches()>0)
2518 s+=",bo:"+ QString ("%1").arg( xelection.getBranch()->countBranches()-1 );
2525 // try to select the freshly built string
2533 void MapEditor::selectUpperBranch()
2535 if (isSelectBlocked() ) return;
2537 BranchObj *bo=xelection.getBranch();
2538 if (bo && xelection.type()==Selection::Branch)
2540 if (bo->getOrientation()==LinkableMapObj::RightOfCenter)
2541 selectPrevBranchInt();
2543 if (bo->getDepth()==1)
2544 selectNextBranchInt();
2546 selectPrevBranchInt();
2550 void MapEditor::selectLowerBranch()
2552 if (isSelectBlocked() ) return;
2554 BranchObj *bo=xelection.getBranch();
2555 if (bo && xelection.type()==Selection::Branch)
2556 if (bo->getOrientation()==LinkableMapObj::RightOfCenter)
2557 selectNextBranchInt();
2559 if (bo->getDepth()==1)
2560 selectPrevBranchInt();
2562 selectNextBranchInt();
2566 void MapEditor::selectLeftBranch()
2568 if (isSelectBlocked() ) return;
2572 LinkableMapObj *sel=xelection.single();
2575 if (xelection.type()== Selection::MapCenter)
2577 par=xelection.getBranch();
2578 bo=par->getLastSelectedBranch();
2581 // Workaround for reselecting on left and right side
2582 if (bo->getOrientation()==LinkableMapObj::RightOfCenter)
2583 bo=par->getLastBranch();
2586 bo=par->getLastBranch();
2587 xelection.select(bo);
2589 ensureSelectionVisible();
2594 par=(BranchObj*)(sel->getParObj());
2595 if (sel->getOrientation()==LinkableMapObj::RightOfCenter)
2597 if (xelection.type() == Selection::Branch ||
2598 xelection.type() == Selection::FloatImage)
2600 xelection.select(par);
2602 ensureSelectionVisible();
2606 if (xelection.type() == Selection::Branch )
2608 bo=xelection.getBranch()->getLastSelectedBranch();
2611 xelection.select(bo);
2613 ensureSelectionVisible();
2621 void MapEditor::selectRightBranch()
2623 if (isSelectBlocked() ) return;
2627 LinkableMapObj *sel=xelection.single();
2630 if (xelection.type()==Selection::MapCenter)
2632 par=xelection.getBranch();
2633 bo=par->getLastSelectedBranch();
2636 // Workaround for reselecting on left and right side
2637 if (bo->getOrientation()==LinkableMapObj::LeftOfCenter)
2638 bo=par->getFirstBranch();
2641 xelection.select(bo);
2643 ensureSelectionVisible();
2648 par=(BranchObj*)(xelection.single()->getParObj());
2649 if (xelection.single()->getOrientation()==LinkableMapObj::LeftOfCenter)
2651 if (xelection.type() == Selection::Branch ||
2652 xelection.type() == Selection::FloatImage)
2654 xelection.select(par);
2656 ensureSelectionVisible();
2660 if (xelection.type() == Selection::Branch)
2662 bo=xelection.getBranch()->getLastSelectedBranch();
2665 xelection.select(bo);
2667 ensureSelectionVisible();
2675 void MapEditor::selectFirstBranch()
2677 BranchObj *bo1=xelection.getBranch();
2682 par=(BranchObj*)(bo1->getParObj());
2683 bo2=par->getFirstBranch();
2685 xelection.select(bo2);
2687 ensureSelectionVisible();
2692 void MapEditor::selectLastBranch()
2694 BranchObj *bo1=xelection.getBranch();
2699 par=(BranchObj*)(bo1->getParObj());
2700 bo2=par->getLastBranch();
2703 xelection.select(bo2);
2705 ensureSelectionVisible();
2710 void MapEditor::selectMapBackgroundImage ()
2712 Q3FileDialog *fd=new Q3FileDialog( this);
2713 fd->setMode (Q3FileDialog::ExistingFile);
2714 fd->addFilter (QString (tr("Images") + " (*.png *.bmp *.xbm *.jpg *.png *.xpm *.gif *.pnm)"));
2715 ImagePreview *p =new ImagePreview (fd);
2716 fd->setContentsPreviewEnabled( TRUE );
2717 fd->setContentsPreview( p, p );
2718 fd->setPreviewMode( Q3FileDialog::Contents );
2719 fd->setCaption(vymName+" - " +tr("Load background image"));
2720 fd->setDir (lastImageDir);
2723 if ( fd->exec() == QDialog::Accepted )
2725 // TODO selectMapBackgroundImg in QT4 use: lastImageDir=fd->directory();
2726 lastImageDir=QDir (fd->dirPath());
2727 setMapBackgroundImage (fd->selectedFile());
2731 void MapEditor::setMapBackgroundImage (const QString &fn) //FIXME missing savestate
2733 QColor oldcol=mapScene->backgroundBrush().color();
2737 QString ("setMapBackgroundImage (%1)").arg(oldcol.name()),
2739 QString ("setMapBackgroundImage (%1)").arg(col.name()),
2740 QString("Set background color of map to %1").arg(col.name()));
2743 brush.setTextureImage (QPixmap (fn));
2744 mapScene->setBackgroundBrush(brush);
2747 void MapEditor::selectMapBackgroundColor()
2749 QColor col = QColorDialog::getColor( mapScene->backgroundBrush().color(), this );
2750 if ( !col.isValid() ) return;
2751 setMapBackgroundColor( col );
2755 void MapEditor::setMapBackgroundColor(QColor col)
2757 QColor oldcol=mapScene->backgroundBrush().color();
2760 QString ("setMapBackgroundColor (\"%1\")").arg(oldcol.name()),
2762 QString ("setMapBackgroundColor (\"%1\")").arg(col.name()),
2763 QString("Set background color of map to %1").arg(col.name()));
2764 mapScene->setBackgroundBrush(col);
2767 QColor MapEditor::getMapBackgroundColor()
2769 return mapScene->backgroundBrush().color();
2772 QColor MapEditor::getCurrentHeadingColor()
2774 BranchObj *bo=xelection.getBranch();
2775 if (bo) return bo->getColor();
2777 QMessageBox::warning(0,tr("Warning"),tr("Can't get color of heading,\nthere's no branch selected"));
2781 void MapEditor::colorBranch (QColor c)
2783 BranchObj *bo=xelection.getBranch();
2788 QString ("colorBranch (\"%1\")").arg(bo->getColor().name()),
2790 QString ("colorBranch (\"%1\")").arg(c.name()),
2791 QString("Set color of %1 to %2").arg(getName(bo)).arg(c.name())
2793 bo->setColor(c); // color branch
2797 void MapEditor::colorSubtree (QColor c)
2799 BranchObj *bo=xelection.getBranch();
2802 saveStateChangingPart(
2805 QString ("colorSubtree (\"%1\")").arg(c.name()),
2806 QString ("Set color of %1 and childs to %2").arg(getName(bo)).arg(c.name())
2808 bo->setColorSubtree (c); // color links, color childs
2813 void MapEditor::toggleStandardFlag(QString f)
2815 BranchObj *bo=xelection.getBranch();
2819 if (bo->isSetStandardFlag(f))
2831 QString("%1 (\"%2\")").arg(u).arg(f),
2833 QString("%1 (\"%2\")").arg(r).arg(f),
2834 QString("Toggling standard flag \"%1\" of %2").arg(f).arg(getName(bo)));
2835 bo->toggleStandardFlag (f,mainWindow->useFlagGroups());
2841 BranchObj* MapEditor::findText (QString s, bool cs)
2843 QTextDocument::FindFlags flags=0;
2844 if (cs) flags=QTextDocument::FindCaseSensitively;
2847 { // Nothing found or new find process
2849 // nothing found, start again
2851 itFind=mapCenter->first();
2853 bool searching=true;
2854 bool foundNote=false;
2855 while (searching && !EOFind)
2859 // Searching in Note
2860 if (itFind->getNote().contains(s,cs))
2862 if (xelection.single()!=itFind)
2864 xelection.select(itFind);
2865 ensureSelectionVisible();
2867 if (textEditor->findText(s,flags))
2873 // Searching in Heading
2874 if (searching && itFind->getHeading().contains (s,cs) )
2876 xelection.select(itFind);
2877 ensureSelectionVisible();
2883 itFind=itFind->next();
2884 if (!itFind) EOFind=true;
2888 return xelection.getBranch();
2893 void MapEditor::findReset()
2894 { // Necessary if text to find changes during a find process
2898 void MapEditor::setURL(const QString &url)
2900 BranchObj *bo=xelection.getBranch();
2903 QString oldurl=bo->getURL();
2907 QString ("setURL (\"%1\")").arg(oldurl),
2909 QString ("setURL (\"%1\")").arg(url),
2910 QString ("set URL of %1 to %2").arg(getName(bo)).arg(url)
2913 mapCenter->reposition();
2915 ensureSelectionVisible();
2919 void MapEditor::editURL()
2921 BranchObj *bo=xelection.getBranch();
2925 QString text = QInputDialog::getText(
2926 "VYM", tr("Enter URL:"), QLineEdit::Normal,
2927 bo->getURL(), &ok, this );
2929 // user entered something and pressed OK
2934 QString MapEditor::getURL()
2936 BranchObj *bo=xelection.getBranch();
2938 return bo->getURL();
2943 QStringList MapEditor::getURLs()
2946 BranchObj *bo=xelection.getBranch();
2952 if (!bo->getURL().isEmpty()) urls.append( bo->getURL());
2960 void MapEditor::editHeading2URL()
2962 BranchObj *bo=xelection.getBranch();
2964 setURL (bo->getHeading());
2967 void MapEditor::editBugzilla2URL()
2969 BranchObj *bo=xelection.getBranch();
2972 QString url= "https://bugzilla.novell.com/show_bug.cgi?id="+bo->getHeading();
2977 void MapEditor::editFATE2URL()
2979 BranchObj *bo=xelection.getBranch();
2982 QString url= "http://keeper.suse.de:8080/webfate/match/id?value=ID"+bo->getHeading();
2985 "setURL (\""+bo->getURL()+"\")",
2987 "setURL (\""+url+"\")",
2988 QString("Use heading of %1 as link to FATE").arg(getName(bo))
2995 void MapEditor::editVymLink()
2997 BranchObj *bo=xelection.getBranch();
3000 QStringList filters;
3001 filters <<"VYM map (*.vym)";
3002 QFileDialog *fd=new QFileDialog( this,vymName+" - " +tr("Link to another map"));
3003 fd->setFilters (filters);
3004 fd->setCaption(vymName+" - " +tr("Link to another map"));
3005 fd->setDirectory (lastFileDir);
3006 if (! bo->getVymLink().isEmpty() )
3007 fd->selectFile( bo->getVymLink() );
3011 if ( fd->exec() == QDialog::Accepted )
3013 lastFileDir=QDir (fd->directory().path());
3016 "setVymLink (\""+bo->getVymLink()+"\")",
3018 "setVymLink (\""+fd->selectedFile()+"\")",
3019 QString("Set vymlink of %1 to %2").arg(getName(bo)).arg(fd->selectedFile())
3021 setVymLinkInt (fd->selectedFile() );
3026 void MapEditor::deleteVymLink()
3028 BranchObj *bo=xelection.getBranch();
3033 "setVymLink (\""+bo->getVymLink()+"\")",
3035 "setVymLink (\"\")",
3036 QString("Unset vymlink of %1").arg(getName(bo))
3038 bo->setVymLink ("" );
3040 mapCenter->reposition();
3045 void MapEditor::setHideExport(bool b)
3047 BranchObj *bo=xelection.getBranch();
3050 bo->setHideInExport (b);
3051 QString u= b ? "false" : "true";
3052 QString r=!b ? "false" : "true";
3056 QString ("setHideExport (%1)").arg(u),
3058 QString ("setHideExport (%1)").arg(r),
3059 QString ("Set HideExport flag of %1 to %2").arg(getName(bo)).arg (r)
3062 mapCenter->reposition();
3068 void MapEditor::toggleHideExport()
3070 BranchObj *bo=xelection.getBranch();
3072 setHideExport ( !bo->hideInExport() );
3075 QString MapEditor::getVymLink()
3077 BranchObj *bo=xelection.getBranch();
3079 return bo->getVymLink();
3085 QStringList MapEditor::getVymLinks()
3088 BranchObj *bo=xelection.getBranch();
3094 if (!bo->getVymLink().isEmpty()) links.append( bo->getVymLink());
3102 void MapEditor::deleteKeepChilds()
3104 BranchObj *bo=xelection.getBranch();
3108 par=(BranchObj*)(bo->getParObj());
3109 QPointF p=bo->getRelPos();
3110 saveStateChangingPart(
3113 "deleteKeepChilds ()",
3114 QString("Remove %1 and keep its childs").arg(getName(bo))
3117 QString sel=bo->getSelectString();
3119 par->removeBranchHere(bo);
3120 mapCenter->reposition();
3122 xelection.getBranch()->move2RelPos (p);
3123 mapCenter->reposition();
3127 void MapEditor::deleteChilds()
3129 BranchObj *bo=xelection.getBranch();
3132 saveStateChangingPart(
3136 QString( "Remove childs of branch %1").arg(getName(bo))
3139 mapCenter->reposition();
3143 void MapEditor::editMapInfo()
3145 ExtraInfoDialog dia;
3146 dia.setMapName (getFileName() );
3147 dia.setAuthor (mapCenter->getAuthor() );
3148 dia.setComment(mapCenter->getComment() );
3152 stats+=tr("%1 items on map\n","Info about map").arg (mapScene->items().size(),6);
3159 bo=mapCenter->first();
3162 if (!bo->getNote().isEmpty() ) n++;
3163 f+= bo->countFloatImages();
3165 xl+=bo->countXLinks();
3168 stats+=QString ("%1 branches\n").arg (b-1,6);
3169 stats+=QString ("%1 xLinks \n").arg (xl,6);
3170 stats+=QString ("%1 notes\n").arg (n,6);
3171 stats+=QString ("%1 images\n").arg (f,6);
3172 dia.setStats (stats);
3174 // Finally show dialog
3175 if (dia.exec() == QDialog::Accepted)
3177 setMapAuthor (dia.getAuthor() );
3178 setMapComment (dia.getComment() );
3182 void MapEditor::ensureSelectionVisible()
3184 LinkableMapObj *lmo=xelection.single();
3185 if (lmo) ensureVisible (lmo->getBBox() );
3189 void MapEditor::updateSelection()
3191 // Tell selection to update geometries
3195 void MapEditor::updateActions()
3197 // Tell mainwindow to update states of actions
3198 mainWindow->updateActions();
3199 // TODO maybe don't update if blockReposition is set
3202 void MapEditor::updateNoteFlag()
3205 BranchObj *bo=xelection.getBranch();
3208 bo->updateNoteFlag();
3209 mainWindow->updateActions();
3213 void MapEditor::setMapAuthor (const QString &s)
3217 QString ("setMapAuthor (\"%1\")").arg(mapCenter->getAuthor()),
3219 QString ("setMapAuthor (\"%1\")").arg(s),
3220 QString ("Set author of map to \"%1\"").arg(s)
3222 mapCenter->setAuthor (s);
3225 void MapEditor::setMapComment (const QString &s)
3229 QString ("setMapComment (\"%1\")").arg(mapCenter->getComment()),
3231 QString ("setMapComment (\"%1\")").arg(s),
3232 QString ("Set comment of map")
3234 mapCenter->setComment (s);
3237 void MapEditor::setMapLinkStyle (const QString & s)
3239 saveStateChangingPart (
3242 QString("setMapLinkStyle (\"%1\")").arg(s),
3243 QString("Set map link style (\"%1\")").arg(s)
3247 linkstyle=LinkableMapObj::Line;
3248 else if (s=="StyleParabel")
3249 linkstyle=LinkableMapObj::Parabel;
3250 else if (s=="StylePolyLine")
3251 linkstyle=LinkableMapObj::PolyLine;
3253 linkstyle=LinkableMapObj::PolyParabel;
3256 bo=mapCenter->first();
3260 bo->setLinkStyle(bo->getDefLinkStyle());
3263 mapCenter->reposition();
3266 LinkableMapObj::Style MapEditor::getMapLinkStyle ()
3271 void MapEditor::setMapDefLinkColor(QColor c)
3275 bo=mapCenter->first();
3284 void MapEditor::setMapLinkColorHintInt()
3286 // called from setMapLinkColorHint(lch) or at end of parse
3288 bo=mapCenter->first();
3296 void MapEditor::setMapLinkColorHint(LinkableMapObj::ColorHint lch)
3299 setMapLinkColorHintInt();
3302 void MapEditor::toggleMapLinkColorHint()
3304 if (linkcolorhint==LinkableMapObj::HeadingColor)
3305 linkcolorhint=LinkableMapObj::DefaultColor;
3307 linkcolorhint=LinkableMapObj::HeadingColor;
3309 bo=mapCenter->first();
3317 LinkableMapObj::ColorHint MapEditor::getMapLinkColorHint()
3319 return linkcolorhint;
3322 QColor MapEditor::getMapDefLinkColor()
3324 return defLinkColor;
3327 void MapEditor::setMapDefXLinkColor(QColor col)
3332 QColor MapEditor::getMapDefXLinkColor()
3334 return defXLinkColor;
3337 void MapEditor::setMapDefXLinkWidth (int w)
3342 int MapEditor::getMapDefXLinkWidth()
3344 return defXLinkWidth;
3347 void MapEditor::selectMapLinkColor()
3349 QColor col = QColorDialog::getColor( defLinkColor, this );
3350 if ( !col.isValid() ) return;
3353 QString("setMapDefLinkColor (\"%1\")").arg(getMapDefLinkColor().name()),
3355 QString("setMapDefLinkColor (\"%1\")").arg(col.name()),
3356 QString("Set map link color to %1").arg(col.name())
3358 setMapDefLinkColor( col );
3361 void MapEditor::selectMapSelectionColor()
3363 QColor col = QColorDialog::getColor( defLinkColor, this );
3364 setSelectionColor (col);
3367 void MapEditor::setSelectionColorInt (QColor col)
3369 if ( !col.isValid() ) return;
3370 xelection.setColor (col);
3373 void MapEditor::setSelectionColor(QColor col)
3375 if ( !col.isValid() ) return;
3378 QString("setSelectionColor (%1)").arg(xelection.getColor().name()),
3380 QString("setSelectionColor (%1)").arg(col.name()),
3381 QString("Set color of selection box to %1").arg(col.name())
3383 setSelectionColorInt (col);
3386 QColor MapEditor::getSelectionColor()
3388 return xelection.getColor();
3391 bool MapEditor::scrollBranch(BranchObj *bo)
3395 if (bo->isScrolled()) return false;
3396 if (bo->countBranches()==0) return false;
3397 if (bo->getDepth()==0) return false;
3403 QString ("%1 ()").arg(u),
3405 QString ("%1 ()").arg(r),
3406 QString ("%1 %2").arg(r).arg(getName(bo))
3416 bool MapEditor::unscrollBranch(BranchObj *bo)
3420 if (!bo->isScrolled()) return false;
3421 if (bo->countBranches()==0) return false;
3422 if (bo->getDepth()==0) return false;
3428 QString ("%1 ()").arg(u),
3430 QString ("%1 ()").arg(r),
3431 QString ("%1 %2").arg(r).arg(getName(bo))
3441 void MapEditor::toggleScroll()
3443 BranchObj *bo=xelection.getBranch();
3444 if (xelection.type()==Selection::Branch )
3446 if (bo->isScrolled())
3447 unscrollBranch (bo);
3453 void MapEditor::unscrollChilds()
3455 BranchObj *bo=xelection.getBranch();
3461 if (bo->isScrolled()) unscrollBranch (bo);
3467 FloatImageObj* MapEditor::loadFloatImageInt (QString fn)
3469 BranchObj *bo=xelection.getBranch();
3473 bo->addFloatImage();
3474 fio=bo->getLastFloatImage();
3476 mapCenter->reposition();
3483 void MapEditor::loadFloatImage ()
3485 BranchObj *bo=xelection.getBranch();
3489 Q3FileDialog *fd=new Q3FileDialog( this);
3490 fd->setMode (Q3FileDialog::ExistingFiles);
3491 fd->addFilter (QString (tr("Images") + " (*.png *.bmp *.xbm *.jpg *.png *.xpm *.gif *.pnm)"));
3492 ImagePreview *p =new ImagePreview (fd);
3493 fd->setContentsPreviewEnabled( TRUE );
3494 fd->setContentsPreview( p, p );
3495 fd->setPreviewMode( Q3FileDialog::Contents );
3496 fd->setCaption(vymName+" - " +tr("Load image"));
3497 fd->setDir (lastImageDir);
3500 if ( fd->exec() == QDialog::Accepted )
3502 // TODO loadFIO in QT4 use: lastImageDir=fd->directory();
3503 lastImageDir=QDir (fd->dirPath());
3506 for (int j=0; j<fd->selectedFiles().count(); j++)
3508 s=fd->selectedFiles().at(j);
3509 fio=loadFloatImageInt (s);
3512 (LinkableMapObj*)fio,
3515 QString ("loadImage (%1)").arg(s ),
3516 QString("Add image %1 to %2").arg(s).arg(getName(bo))
3519 // TODO loadFIO error handling
3520 qWarning ("Failed to load "+s);
3528 void MapEditor::saveFloatImageInt (FloatImageObj *fio, const QString &type, const QString &fn)
3530 fio->save (fn,type);
3533 void MapEditor::saveFloatImage ()
3535 FloatImageObj *fio=xelection.getFloatImage();
3538 QFileDialog *fd=new QFileDialog( this);
3539 fd->setFilters (imageIO.getFilters());
3540 fd->setCaption(vymName+" - " +tr("Save image"));
3541 fd->setFileMode( QFileDialog::AnyFile );
3542 fd->setDirectory (lastImageDir);
3543 // fd->setSelection (fio->getOriginalFilename());
3547 if ( fd->exec() == QDialog::Accepted && fd->selectedFiles().count()==1)
3549 fn=fd->selectedFiles().at(0);
3550 if (QFile (fn).exists() )
3552 QMessageBox mb( vymName,
3553 tr("The file %1 exists already.\n"
3554 "Do you want to overwrite it?").arg(fn),
3555 QMessageBox::Warning,
3556 QMessageBox::Yes | QMessageBox::Default,
3557 QMessageBox::Cancel | QMessageBox::Escape,
3558 QMessageBox::QMessageBox::NoButton );
3560 mb.setButtonText( QMessageBox::Yes, tr("Overwrite") );
3561 mb.setButtonText( QMessageBox::No, tr("Cancel"));
3564 case QMessageBox::Yes:
3567 case QMessageBox::Cancel:
3574 saveFloatImageInt (fio,fd->selectedFilter(),fn );
3580 void MapEditor::setFrameType(const FrameObj::FrameType &t)
3582 BranchObj *bo=xelection.getBranch();
3585 QString s=bo->getFrameTypeName();
3586 bo->setFrameType (t);
3587 saveState (bo, QString("setFrameType (\"%1\")").arg(s),
3588 bo, QString ("setFrameType (\"%1\")").arg(bo->getFrameTypeName()),QString ("set type of frame to %1").arg(s));
3589 mapCenter->reposition();
3594 void MapEditor::setFrameType(const QString &s)
3596 BranchObj *bo=xelection.getBranch();
3599 saveState (bo, QString("setFrameType (\"%1\")").arg(bo->getFrameTypeName()),
3600 bo, QString ("setFrameType (\"%1\")").arg(s),QString ("set type of frame to %1").arg(s));
3601 bo->setFrameType (s);
3602 mapCenter->reposition();
3607 void MapEditor::setFramePenColor(const QColor &c)
3609 BranchObj *bo=xelection.getBranch();
3612 saveState (bo, QString("setFramePenColor (\"%1\")").arg(bo->getFramePenColor().name() ),
3613 bo, QString ("setFramePenColor (\"%1\")").arg(c.name() ),QString ("set pen color of frame to %1").arg(c.name() ));
3614 bo->setFramePenColor (c);
3618 void MapEditor::setFrameBrushColor(const QColor &c)
3620 BranchObj *bo=xelection.getBranch();
3623 saveState (bo, QString("setFrameBrushColor (\"%1\")").arg(bo->getFrameBrushColor().name() ),
3624 bo, QString ("setFrameBrushColor (\"%1\")").arg(c.name() ),QString ("set brush color of frame to %1").arg(c.name() ));
3625 bo->setFrameBrushColor (c);
3629 void MapEditor::setFramePadding (const int &i)
3631 BranchObj *bo=xelection.getBranch();
3634 saveState (bo, QString("setFramePadding (\"%1\")").arg(bo->getFramePadding() ),
3635 bo, QString ("setFramePadding (\"%1\")").arg(i),QString ("set brush color of frame to %1").arg(i));
3636 bo->setFramePadding (i);
3637 mapCenter->reposition();
3642 void MapEditor::setFrameBorderWidth(const int &i)
3644 BranchObj *bo=xelection.getBranch();
3647 saveState (bo, QString("setFrameBorderWidth (\"%1\")").arg(bo->getFrameBorderWidth() ),
3648 bo, QString ("setFrameBorderWidth (\"%1\")").arg(i),QString ("set border width of frame to %1").arg(i));
3649 bo->setFrameBorderWidth (i);
3650 mapCenter->reposition();
3655 void MapEditor::setIncludeImagesVer(bool b)
3657 BranchObj *bo=xelection.getBranch();
3660 QString u= b ? "false" : "true";
3661 QString r=!b ? "false" : "true";
3665 QString("setIncludeImagesVertically (%1)").arg(u),
3667 QString("setIncludeImagesVertically (%1)").arg(r),
3668 QString("Include images vertically in %1").arg(getName(bo))
3670 bo->setIncludeImagesVer(b);
3671 mapCenter->reposition();
3675 void MapEditor::setIncludeImagesHor(bool b)
3677 BranchObj *bo=xelection.getBranch();
3680 QString u= b ? "false" : "true";
3681 QString r=!b ? "false" : "true";
3685 QString("setIncludeImagesHorizontally (%1)").arg(u),
3687 QString("setIncludeImagesHorizontally (%1)").arg(r),
3688 QString("Include images horizontally in %1").arg(getName(bo))
3690 bo->setIncludeImagesHor(b);
3691 mapCenter->reposition();
3695 void MapEditor::setHideLinkUnselected (bool b)
3697 LinkableMapObj *sel=xelection.single();
3699 (xelection.type() == Selection::Branch ||
3700 xelection.type() == Selection::MapCenter ||
3701 xelection.type() == Selection::FloatImage ))
3703 QString u= b ? "false" : "true";
3704 QString r=!b ? "false" : "true";
3708 QString("setHideLinkUnselected (%1)").arg(u),
3710 QString("setHideLinkUnselected (%1)").arg(r),
3711 QString("Hide link of %1 if unselected").arg(getName(sel))
3713 sel->setHideLinkUnselected(b);
3717 void MapEditor::importDirInt(BranchObj *dst, QDir d)
3719 BranchObj *bo=xelection.getBranch();
3722 // Traverse directories
3723 d.setFilter( QDir::Dirs| QDir::Hidden | QDir::NoSymLinks );
3724 QFileInfoList list = d.entryInfoList();
3727 for (int i = 0; i < list.size(); ++i)
3730 if (fi.fileName() != "." && fi.fileName() != ".." )
3733 bo=dst->getLastBranch();
3734 bo->setHeading (fi.fileName() );
3735 bo->setColor (QColor("blue"));
3737 if ( !d.cd(fi.fileName()) )
3738 QMessageBox::critical (0,tr("Critical Import Error"),tr("Cannot find the directory %1").arg(fi.fileName()));
3741 // Recursively add subdirs
3742 importDirInt (bo,d);
3748 d.setFilter( QDir::Files| QDir::Hidden | QDir::NoSymLinks );
3749 list = d.entryInfoList();
3751 for (int i = 0; i < list.size(); ++i)
3755 bo=dst->getLastBranch();
3756 bo->setHeading (fi.fileName() );
3757 bo->setColor (QColor("black"));
3758 if (fi.fileName().right(4) == ".vym" )
3759 bo->setVymLink (fi.filePath());
3764 void MapEditor::importDirInt (const QString &s)
3766 BranchObj *bo=xelection.getBranch();
3769 saveStateChangingPart (bo,bo,QString ("importDir (\"%1\")").arg(s),QString("Import directory structure from %1").arg(s));
3772 importDirInt (bo,d);
3776 void MapEditor::importDir()
3778 BranchObj *bo=xelection.getBranch();
3781 QStringList filters;
3782 filters <<"VYM map (*.vym)";
3783 QFileDialog *fd=new QFileDialog( this,vymName+ " - " +tr("Choose directory structure to import"));
3784 fd->setMode (QFileDialog::DirectoryOnly);
3785 fd->setFilters (filters);
3786 fd->setCaption(vymName+" - " +tr("Choose directory structure to import"));
3790 if ( fd->exec() == QDialog::Accepted )
3792 importDirInt (fd->selectedFile() );
3793 mapCenter->reposition();
3799 void MapEditor::followXLink(int i)
3801 BranchObj *bo=xelection.getBranch();
3804 bo=bo->XLinkTargetAt(i);
3807 xelection.select(bo);
3808 ensureSelectionVisible();
3813 void MapEditor::editXLink(int i) // FIXME missing saveState
3815 BranchObj *bo=xelection.getBranch();
3818 XLinkObj *xlo=bo->XLinkAt(i);
3821 EditXLinkDialog dia;
3823 dia.setSelection(bo);
3824 if (dia.exec() == QDialog::Accepted)
3826 if (dia.useSettingsGlobal() )
3828 setMapDefXLinkColor (xlo->getColor() );
3829 setMapDefXLinkWidth (xlo->getWidth() );
3831 if (dia.deleteXLink())
3832 bo->deleteXLinkAt(i);
3838 void MapEditor::testFunction()
3840 mainWindow->statusMessage("Biiiiiiiiiiiiiiing!");
3843 BranchObj *bo=xelection.getBranch();
3844 if (bo) animObjList.append( bo );
3848 dia.showCancelButton (true);
3849 dia.setText("This is a longer \nWarning");
3850 dia.setCaption("Warning: Flux problem");
3851 dia.setShowAgainName("mapeditor/testDialog");
3852 if (dia.exec()==QDialog::Accepted)
3853 cout << "accepted!\n";
3855 cout << "canceled!\n";
3859 /* TODO Hide hidden stuff temporary, maybe add this as regular function somewhere
3860 if (hidemode==HideNone)
3862 setHideTmpMode (HideExport);
3863 mapCenter->calcBBoxSizeWithChilds();
3864 QRectF totalBBox=mapCenter->getTotalBBox();
3865 QRectF mapRect=totalBBox;
3866 QCanvasRectangle *frame=NULL;
3868 cout << " map has =("<<totalBBox.x()<<","<<totalBBox.y()<<","<<totalBBox.width()<<","<<totalBBox.height()<<")\n";
3870 mapRect.setRect (totalBBox.x(), totalBBox.y(),
3871 totalBBox.width(), totalBBox.height());
3872 frame=new QCanvasRectangle (mapRect,mapScene);
3873 frame->setBrush (QColor(white));
3874 frame->setPen (QColor(black));
3875 frame->setZValue(0);
3880 setHideTmpMode (HideNone);
3882 cout <<" hidemode="<<hidemode<<endl;
3886 void MapEditor::contextMenuEvent ( QContextMenuEvent * e )
3888 // Lineedits are already closed by preceding
3889 // mouseEvent, we don't need to close here.
3891 QPointF p = mapToScene(e->pos());
3892 LinkableMapObj* lmo=mapCenter->findMapObj(p, NULL);
3895 { // MapObj was found
3896 if (xelection.single() != lmo)
3898 // select the MapObj
3899 xelection.select(lmo);
3902 if (xelection.getBranch() )
3904 // Context Menu on branch or mapcenter
3906 branchContextMenu->popup(e->globalPos() );
3909 if (xelection.getFloatImage() )
3911 // Context Menu on floatimage
3913 floatimageContextMenu->popup(e->globalPos() );
3917 { // No MapObj found, we are on the Canvas itself
3918 // Context Menu on scene
3920 canvasContextMenu->popup(e->globalPos() );
3925 void MapEditor::keyPressEvent(QKeyEvent* e)
3927 if (e->modifiers() & Qt::ControlModifier)
3929 switch (mainWindow->getModMode())
3931 case Main::ModModeColor:
3932 setCursor (PickColorCursor);
3934 case Main::ModModeCopy:
3935 setCursor (CopyCursor);
3937 case Main::ModModeXLink:
3938 setCursor (XLinkCursor);
3941 setCursor (Qt::ArrowCursor);
3947 void MapEditor::keyReleaseEvent(QKeyEvent* e)
3949 if (!(e->modifiers() & Qt::ControlModifier))
3950 setCursor (Qt::ArrowCursor);
3953 void MapEditor::mousePressEvent(QMouseEvent* e)
3955 // Ignore right clicks, these will go to context menus
3956 if (e->button() == Qt::RightButton )
3962 //Ignore clicks while editing heading
3963 if (isSelectBlocked() )
3969 QPointF p = mapToScene(e->pos());
3970 LinkableMapObj* lmo=mapCenter->findMapObj(p, NULL);
3974 //Take care of system flags _or_ modifier modes
3976 if (lmo && (typeid(*lmo)==typeid(BranchObj) ||
3977 typeid(*lmo)==typeid(MapCenterObj) ))
3979 QString foname=((BranchObj*)lmo)->getSystemFlagName(p);
3980 if (!foname.isEmpty())
3982 // systemFlag clicked
3986 if (e->state() & Qt::ControlModifier)
3987 mainWindow->editOpenURLTab();
3989 mainWindow->editOpenURL();
3991 else if (foname=="vymLink")
3993 mainWindow->editOpenVymLink();
3994 // tabWidget may change, better return now
3995 // before segfaulting...
3996 } else if (foname=="note")
3997 mainWindow->windowToggleNoteEditor();
3998 else if (foname=="hideInExport")
4005 // No system flag clicked, take care of modmodes (CTRL-Click)
4006 if (e->state() & Qt::ControlModifier)
4008 if (mainWindow->getModMode()==Main::ModModeColor)
4011 setCursor (PickColorCursor);
4014 if (mainWindow->getModMode()==Main::ModModeXLink)
4016 BranchObj *bo_begin=NULL;
4018 bo_begin=(BranchObj*)(lmo);
4020 if (xelection.getBranch() )
4021 bo_begin=xelection.getBranch();
4025 linkingObj_src=bo_begin;
4026 tmpXLink=new XLinkObj (mapScene);
4027 tmpXLink->setBegin (bo_begin);
4028 tmpXLink->setEnd (p);
4029 tmpXLink->setColor(defXLinkColor);
4030 tmpXLink->setWidth(defXLinkWidth);
4031 tmpXLink->updateXLink();
4032 tmpXLink->setVisibility (true);
4036 } // End of modmodes
4040 // Select the clicked object
4043 // Left Button Move Branches
4044 if (e->button() == Qt::LeftButton )
4046 //movingObj_start.setX( p.x() - selection->x() );// TODO replaced selection->lmo here
4047 //movingObj_start.setY( p.y() - selection->y() );
4048 movingObj_start.setX( p.x() - lmo->x() );
4049 movingObj_start.setY( p.y() - lmo->y() );
4050 movingObj_orgPos.setX (lmo->x() );
4051 movingObj_orgPos.setY (lmo->y() );
4052 movingObj_orgRelPos=lmo->getRelPos();
4054 // If modMode==copy, then we want to "move" the _new_ object around
4055 // then we need the offset from p to the _old_ selection, because of tmp
4056 if (mainWindow->getModMode()==Main::ModModeCopy &&
4057 e->state() & Qt::ControlModifier)
4059 if (xelection.type()==Selection::Branch)
4062 mapCenter->addBranch ((BranchObj*)xelection.single());
4064 xelection.select(mapCenter->getLastBranch());
4065 mapCenter->reposition();
4069 movingObj=xelection.single();
4071 // Middle Button Toggle Scroll
4072 // (On Mac OS X this won't work, but we still have
4073 // a button in the toolbar)
4074 if (e->button() == Qt::MidButton )
4079 { // No MapObj found, we are on the scene itself
4080 // Left Button move Pos of sceneView
4081 if (e->button() == Qt::LeftButton )
4083 movingObj=NULL; // move Content not Obj
4084 movingObj_start=e->globalPos();
4085 movingCont_start=QPointF (
4086 horizontalScrollBar()->value(),
4087 verticalScrollBar()->value());
4088 movingVec=QPointF(0,0);
4089 setCursor(HandOpenCursor);
4094 void MapEditor::mouseMoveEvent(QMouseEvent* e)
4096 QPointF p = mapToScene(e->pos());
4097 LinkableMapObj *lmosel=xelection.single();
4099 // Move the selected MapObj
4100 if ( lmosel && movingObj)
4102 // reset cursor if we are moving and don't copy
4103 if (mainWindow->getModMode()!=Main::ModModeCopy)
4104 setCursor (Qt::ArrowCursor);
4106 // To avoid jumping of the sceneView, only
4107 // ensureSelectionVisible, if not tmp linked
4108 if (!lmosel->hasParObjTmp())
4109 ensureSelectionVisible ();
4111 // Now move the selection, but add relative position
4112 // (movingObj_start) where selection was chosen with
4113 // mousepointer. (This avoids flickering resp. jumping
4114 // of selection back to absPos)
4116 // Check if we could link
4117 LinkableMapObj* lmo=mapCenter->findMapObj(p, lmosel);
4120 FloatObj *fio=xelection.getFloatImage();
4123 fio->move (p.x() -movingObj_start.x(), p.y()-movingObj_start.y() );
4125 fio->updateLink(); //no need for reposition, if we update link here
4128 // Relink float to new mapcenter or branch, if shift is pressed
4129 // Only relink, if selection really has a new parent
4130 if ( (e->modifiers()==Qt::ShiftModifier) && lmo &&
4131 ( (typeid(*lmo)==typeid(BranchObj)) ||
4132 (typeid(*lmo)==typeid(MapCenterObj)) ) &&
4133 ( lmo != fio->getParObj())
4136 if (typeid(*fio) == typeid(FloatImageObj) &&
4137 ( (typeid(*lmo)==typeid(BranchObj) ||
4138 typeid(*lmo)==typeid(MapCenterObj)) ))
4141 // Also save the move which was done so far
4142 QString pold=qpointfToString(movingObj_orgRelPos);
4143 QString pnow=qpointfToString(fio->getRelPos());
4149 QString("Move %1 to relativ position %2").arg(getName(fio)).arg(pnow));
4150 fio->getParObj()->requestReposition();
4151 mapCenter->reposition();
4153 linkTo (lmo->getSelectString());
4155 //movingObj_orgRelPos=lmosel->getRelPos();
4157 mapCenter->reposition();
4161 { // selection != a FloatObj
4162 if (lmosel->getDepth()==0)
4165 if (e->buttons()== Qt::LeftButton && e->modifiers()==Qt::ShiftModifier)
4166 mapCenter->moveAll(p.x() -movingObj_start.x(), p.y()-movingObj_start.y() );
4168 mapCenter->move (p.x() -movingObj_start.x(), p.y()-movingObj_start.y() );
4169 mapCenter->updateRelPositions();
4172 if (lmosel->getDepth()==1)
4175 lmosel->move(p.x() -movingObj_start.x(), p.y()-movingObj_start.y() );
4176 lmosel->setRelPos();
4179 // Move ordinary branch
4180 if (lmosel->getOrientation() == LinkableMapObj::LeftOfCenter)
4181 // Add width of bbox here, otherwise alignRelTo will cause jumping around
4182 lmosel->move(p.x() -movingObj_start.x()+lmosel->getBBox().width(),
4183 p.y()-movingObj_start.y() +lmosel->getTopPad() );
4185 lmosel->move(p.x() -movingObj_start.x(), p.y()-movingObj_start.y() -lmosel->getTopPad());
4188 // Maybe we can relink temporary?
4189 if (lmo && (lmo!=lmosel) && xelection.getBranch() &&
4190 (typeid(*lmo)==typeid(BranchObj) ||
4191 typeid(*lmo)==typeid(MapCenterObj)) )
4194 if (e->modifiers()==Qt::ControlModifier)
4196 // Special case: CTRL to link below lmo
4197 lmosel->setParObjTmp (lmo,p,+1);
4199 else if (e->modifiers()==Qt::ShiftModifier)
4200 lmosel->setParObjTmp (lmo,p,-1);
4202 lmosel->setParObjTmp (lmo,p,0);
4205 lmosel->unsetParObjTmp();
4207 // reposition subbranch
4208 lmosel->reposition();
4212 } // no FloatImageObj
4216 } // selection && moving_obj
4218 // Draw a link from one branch to another
4221 tmpXLink->setEnd (p);
4222 tmpXLink->updateXLink();
4226 if (!movingObj && !pickingColor &&!drawingLink && e->buttons() == Qt::LeftButton )
4228 QPointF p=e->globalPos();
4229 movingVec.setX(-p.x() + movingObj_start.x() );
4230 movingVec.setY(-p.y() + movingObj_start.y() );
4231 horizontalScrollBar()->setSliderPosition((int)( movingCont_start.x()+movingVec.x() ));
4232 verticalScrollBar()->setSliderPosition((int)( movingCont_start.y()+movingVec.y() ) );
4237 void MapEditor::mouseReleaseEvent(QMouseEvent* e)
4239 QPointF p = mapToScene(e->pos());
4240 LinkableMapObj *dst;
4241 LinkableMapObj *lmosel=xelection.single();
4242 // Have we been picking color?
4246 setCursor (Qt::ArrowCursor);
4247 // Check if we are over another branch
4248 dst=mapCenter->findMapObj(p, NULL);
4251 if (e->state() & Qt::ShiftModifier)
4252 colorBranch (((BranchObj*)(dst))->getColor());
4254 colorSubtree (((BranchObj*)(dst))->getColor());
4259 // Have we been drawing a link?
4263 // Check if we are over another branch
4264 dst=mapCenter->findMapObj(p, NULL);
4267 tmpXLink->setEnd ( ((BranchObj*)(dst)) );
4268 tmpXLink->updateXLink();
4269 tmpXLink->activate(); //FIXME savestate missing
4270 //saveStateComplete(QString("Activate xLink from %1 to %2").arg(getName(tmpXLink->getBegin())).arg(getName(tmpXLink->getEnd())) );
4279 // Have we been moving something?
4280 if ( lmosel && movingObj )
4282 FloatImageObj *fo=xelection.getFloatImage();
4285 // Moved FloatObj. Maybe we need to reposition
4286 QString pold=qpointfToString(movingObj_orgRelPos);
4287 QString pnow=qpointfToString(fo->getRelPos());
4293 QString("Move %1 to relativ position %2").arg(getName(fo)).arg(pnow));
4295 fo->getParObj()->requestReposition();
4296 mapCenter->reposition();
4299 // Check if we are over another branch, but ignore
4300 // any found LMOs, which are FloatObjs
4301 dst=mapCenter->findMapObj(mapToScene(e->pos() ), lmosel);
4303 if (dst && (typeid(*dst)!=typeid(BranchObj) && typeid(*dst)!=typeid(MapCenterObj)))
4306 if (xelection.type() == Selection::MapCenter )
4308 // TODO: Check for problems if graphicsview is resized for
4310 QString pold=qpointfToString(movingObj_orgPos);
4311 QString pnow=qpointfToString(mapCenter->getAbsPos());
4317 QString("Move mapcenter %1 to position %2").arg(getName(mapCenter)).arg(pnow));
4320 if (xelection.type() == Selection::Branch )
4321 { // A branch was moved
4323 // save the position in case we link to mapcenter
4324 QPointF savePos=QPointF (lmosel->getAbsPos() );
4326 // Reset the temporary drawn link to the original one
4327 lmosel->unsetParObjTmp();
4329 // For Redo we may need to save original selection
4330 QString preSelStr=lmosel->getSelectString();
4335 BranchObj* bsel=xelection.getBranch();
4336 BranchObj* bdst=(BranchObj*)dst;
4338 QString preParStr=(bsel->getParObj())->getSelectString();
4339 QString preNum=QString::number (bsel->getNum(),10);
4340 QString preDstParStr;
4342 if (e->state() & Qt::ShiftModifier && dst->getParObj())
4344 preDstParStr=dst->getParObj()->getSelectString();
4345 bsel->linkTo ( (BranchObj*)(bdst->getParObj()), bdst->getNum());
4347 if (e->state() & Qt::ControlModifier && dst->getParObj())
4350 preDstParStr=dst->getParObj()->getSelectString();
4351 bsel->linkTo ( (BranchObj*)(bdst->getParObj()), bdst->getNum()+1);
4354 preDstParStr=dst->getSelectString();
4355 bsel->linkTo (bdst,-1);
4356 if (dst->getDepth()==0) bsel->move (savePos);
4358 QString postSelStr=lmosel->getSelectString();
4359 QString postNum=QString::number (bsel->getNum(),10);
4361 QString undoCom="linkTo (\""+
4362 preParStr+ "\"," + preNum +"," +
4363 QString ("%1,%2").arg(movingObj_orgPos.x()).arg(movingObj_orgPos.y())+ ")";
4365 QString redoCom="linkTo (\""+
4366 preDstParStr + "\"," + postNum + "," +
4367 QString ("%1,%2").arg(savePos.x()).arg(savePos.y())+ ")";
4372 QString("Relink %1 to %2").arg(getName(bsel)).arg(getName(dst)) );
4374 if (lmosel->getDepth()==1)
4376 // The select string might be different _after_ moving around.
4377 // Therefor reposition and then use string of old selection, too
4378 mapCenter->reposition();
4380 QString ps=qpointfToString ( lmosel->getRelPos() );
4382 lmosel->getSelectString(), "moveRel "+qpointfToString(movingObj_orgRelPos),
4383 preSelStr, "moveRel "+ps,
4384 QString("Move %1 to relative position %2").arg(getName(lmosel)).arg(ps));
4387 // Draw the original link, before selection was moved around
4388 mapCenter->reposition();
4391 // Finally resize scene, if needed
4395 // Just make sure, that actions are still ok,e.g. the move branch up/down buttons...
4398 // maybe we moved View: set old cursor
4399 setCursor (Qt::ArrowCursor);
4403 void MapEditor::mouseDoubleClickEvent(QMouseEvent* e)
4405 if (isSelectBlocked() )
4411 if (e->button() == Qt::LeftButton )
4413 QPointF p = mapToScene(e->pos());
4414 LinkableMapObj *lmo=mapCenter->findMapObj(p, NULL);
4415 if (lmo) { // MapObj was found
4416 // First select the MapObj than edit heading
4417 xelection.select(lmo);
4418 mainWindow->editHeading();
4423 void MapEditor::resizeEvent (QResizeEvent* e)
4425 QGraphicsView::resizeEvent( e );
4428 void MapEditor::dragEnterEvent(QDragEnterEvent *event)
4430 //for (unsigned int i=0;event->format(i);i++) // Debug mime type
4431 // cerr << event->format(i) << endl;
4433 if (event->mimeData()->hasImage())
4434 event->acceptProposedAction();
4436 if (event->mimeData()->hasUrls())
4437 event->acceptProposedAction();
4440 void MapEditor::dragMoveEvent(QDragMoveEvent *event)
4444 void MapEditor::dragLeaveEvent(QDragLeaveEvent *event)
4449 void MapEditor::dropEvent(QDropEvent *event)
4451 BranchObj *sel=xelection.getBranch();
4454 foreach (QString format,event->mimeData()->formats())
4456 cout << "Dropped format: "<<format.ascii()<<endl;
4461 if (event->mimeData()->hasImage())
4463 QVariant imageData = event->mimeData()->imageData();
4464 addFloatImageInt (qvariant_cast<QPixmap>(imageData));
4466 if (event->mimeData()->hasUrls())
4467 uris=event->mimeData()->urls();
4475 for (int i=0; i<uris.count();i++)
4477 // Workaround to avoid adding empty branches
4478 if (!uris.at(i).toString().isEmpty())
4480 bo=sel->addBranch();
4483 s=uris.at(i).toLocalFile();
4486 QString file = QDir::convertSeparators(s);
4487 heading = QFileInfo(file).baseName();
4489 if (file.endsWith(".vym", false))
4490 bo->setVymLink(file);
4492 bo->setURL(uris.at(i).toString());
4495 bo->setURL(uris.at(i).toString());
4498 if (!heading.isEmpty())
4499 bo->setHeading(heading);
4501 bo->setHeading(uris.at(i).toString());
4505 mapCenter->reposition();
4508 event->acceptProposedAction();
4511 void MapEditor::timerEvent(QTimerEvent *event) //TODO animation
4515 cout << "ME::timerEvent\n";
4517 for (int i=0; i<animObjList.size(); ++i)
4519 animObjList.at(i)->animate();
4520 ((BranchObj*)animObjList.at(i))->move2RelPos (((BranchObj*)animObjList.at(i))->getRelPos() );
4522 mapCenter->reposition();
4525 void MapEditor::autosave()
4527 // Disable autosave, while we have gone back in history
4528 int redosAvail=undoSet.readNumEntry (QString("/history/redosAvail"));
4529 if (redosAvail>0) return;
4532 if (mapUnsaved &&mapChanged && settings.value ("/mapeditor/autosave/use",true).toBool() )
4533 mainWindow->fileSave (this);
4537 /*TODO not needed? void MapEditor::contentsDropEvent(QDropEvent *event)
4540 } else if (event->provides("application/x-moz-file-promise-url") &&
4541 event->provides("application/x-moz-nativeimage"))
4543 // Contains url to the img src in unicode16
4544 QByteArray d = event->encodedData("application/x-moz-file-promise-url");
4545 QString url = QString((const QChar*)d.data(),d.size()/2);
4549 } else if (event->provides ("text/uri-list"))
4550 { // Uris provided e.g. by konqueror
4551 Q3UriDrag::decode (event,uris);
4552 } else if (event->provides ("_NETSCAPE_URL"))
4553 { // Uris provided by Mozilla
4554 QStringList l = QStringList::split("\n", event->encodedData("_NETSCAPE_URL"));
4557 } else if (event->provides("text/html")) {
4559 // Handels text mime types
4560 // Look like firefox allways handle text as unicode16 (2 bytes per char.)
4561 QByteArray d = event->encodedData("text/html");
4564 text = QString((const QChar*)d.data(),d.size()/2);
4568 textEditor->setText(text);
4572 } else if (event->provides("text/plain")) {
4573 QByteArray d = event->encodedData("text/plain");
4576 text = QString((const QChar*)d.data(),d.size()/2);
4580 textEditor->setText(text);
4590 bool isUnicode16(const QByteArray &d)
4592 // TODO: make more precise check for unicode 16.
4593 // Guess unicode16 if any of second bytes are zero
4594 unsigned int length = max(0,d.size()-2)/2;
4595 for (unsigned int i = 0; i<length ; i++)
4596 if (d.at(i*2+1)==0) return true;
4600 void MapEditor::addFloatImageInt (const QPixmap &img)
4602 BranchObj *bo=xelection.getBranch();
4605 FloatImageObj *fio=bo->addFloatImage();
4607 fio->setOriginalFilename("Image added by Drag and Drop"); // FIXME savestate missing
4608 mapCenter->reposition();
4615 void MapEditor::imageDataFetched(const QByteArray &a, Q3NetworkOperation * / *nop* /)
4617 if (!imageBuffer) imageBuffer = new QBuffer();
4618 if (!imageBuffer->isOpen()) {
4619 imageBuffer->open(QIODevice::WriteOnly | QIODevice::Append);
4621 imageBuffer->at(imageBuffer->at()+imageBuffer->writeBlock(a));
4625 void MapEditor::imageDataFinished(Q3NetworkOperation *nop)
4627 if (nop->state()==Q3NetworkProtocol::StDone) {
4628 QPixmap img(imageBuffer->buffer());
4629 addFloatImageInt (img);
4633 imageBuffer->close();
4635 imageBuffer->close();
4642 void MapEditor::fetchImage(const QString &url)
4645 urlOperator->stop();
4646 disconnect(urlOperator);
4650 urlOperator = new Q3UrlOperator(url);
4651 connect(urlOperator, SIGNAL(finished(Q3NetworkOperation *)),
4652 this, SLOT(imageDataFinished(Q3NetworkOperation*)));
4654 connect(urlOperator, SIGNAL(data(const QByteArray &, Q3NetworkOperation *)),
4655 this, SLOT(imageDataFetched(const QByteArray &, Q3NetworkOperation *)));