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 bool clipboardEmpty;
31 extern FlagRowObj *standardFlagsDefault;
33 extern QMenu* branchContextMenu;
34 extern QMenu* branchAddContextMenu;
35 extern QMenu* branchRemoveContextMenu;
36 extern QMenu* branchLinksContextMenu;
37 extern QMenu* branchXLinksContextMenuEdit;
38 extern QMenu* branchXLinksContextMenuFollow;
39 extern QMenu* floatimageContextMenu;
40 extern QMenu* canvasContextMenu;
43 extern Settings settings;
44 extern ImageIO imageIO;
46 extern QString vymName;
47 extern QString vymVersion;
49 extern QString iconPath;
50 extern QDir vymBaseDir;
51 extern QDir lastImageDir;
52 extern QDir lastFileDir;
54 int MapEditor::mapNum=0; // make instance
56 ///////////////////////////////////////////////////////////////////////
57 ///////////////////////////////////////////////////////////////////////
58 MapEditor::MapEditor( QWidget* parent) :
61 //cout << "Constructor ME "<<this<<endl;
65 mapScene= new QGraphicsScene(parent);
66 //mapScene= new QGraphicsScene(QRectF(0,0,width(),height()), parent);
67 mapScene->setBackgroundBrush (QBrush(Qt::white, Qt::SolidPattern));
72 mapCenter = new MapCenterObj(mapScene);
73 mapCenter->setVisibility (true);
74 mapCenter->setMapEditor (this);
75 mapCenter->setHeading (tr("New Map","Heading of mapcenter in new map"));
76 //mapCenter->move(mapScene->width()/2-mapCenter->width()/2,mapScene->height()/2-mapCenter->height()/2);
81 defLinkColor=QColor (0,0,255);
82 defXLinkColor=QColor (180,180,180);
83 linkcolorhint=LinkableMapObj::DefaultColor;
84 linkstyle=LinkableMapObj::PolyParabel;
86 // Create bitmap cursors, platform dependant
87 HandOpenCursor=QCursor (QPixmap(iconPath+"cursorhandopen.png"),1,1);
88 PickColorCursor=QCursor ( QPixmap(iconPath+"cursorcolorpicker.png"), 5,27 );
89 CopyCursor=QCursor ( QPixmap(iconPath+"cursorcopy.png"), 1,1 );
90 XLinkCursor=QCursor ( QPixmap(iconPath+"cursorxlink.png"), 1,7 );
92 setFocusPolicy (Qt::StrongFocus);
101 xelection.setMapEditor (this);
102 xelection.unselect();
105 defXLinkColor=QColor (230,230,230);
113 fileName=tr("unnamed");
116 stepsTotal=settings.readNumEntry("/mapeditor/stepsTotal",100);
117 undoSet.setEntry ("/history/stepsTotal",QString::number(stepsTotal));
119 // Initialize find routine
126 blockReposition=false;
127 blockSaveState=false;
129 hidemode=BranchObj::HideNone;
131 // Create temporary files
134 setAcceptDrops (true);
136 mapCenter->reposition(); // for positioning heading
140 //timerId = startTimer(100);
143 autosaveTimer=new QTimer (this);
144 connect(autosaveTimer, SIGNAL(timeout()), this, SLOT(autosave()));
147 MapEditor::~MapEditor()
149 //cout <<"Destructor MapEditor\n";
150 autosaveTimer->stop();
153 MapCenterObj* MapEditor::getMapCenter()
158 QGraphicsScene * MapEditor::getScene()
163 bool MapEditor::isRepositionBlocked()
165 return blockReposition;
168 void MapEditor::setSaveStateBlocked(bool b)
173 QString MapEditor::getName (const LinkableMapObj *lmo)
176 if (!lmo) return QString("Error: NULL has no name!");
178 if ((typeid(*lmo) == typeid(BranchObj) ||
179 typeid(*lmo) == typeid(MapCenterObj)))
182 s=(((BranchObj*)lmo)->getHeading());
183 if (s=="") s="unnamed";
184 return QString("branch (%1)").arg(s);
185 //return QString("branch (<font color=\"#0000ff\">%1</font>)").arg(s);
187 if ((typeid(*lmo) == typeid(FloatImageObj) ))
188 return QString ("floatimage [%1]").arg(((FloatImageObj*)lmo)->getOriginalFilename());
189 //return QString ("floatimage [<font color=\"#0000ff\">%1</font>]").arg(((FloatImageObj*)lmo)->getOriginalFilename());
190 return QString("Unknown type has no name!");
193 void MapEditor::makeTmpDirs()
195 // Create unique temporary directories
196 tmpMapDir=QDir::convertSeparators (tmpVymDir+QString("/mapeditor-%1").arg(mapNum));
197 histPath=QDir::convertSeparators (tmpMapDir+"/history");
202 QString MapEditor::saveToDir(const QString &tmpdir, const QString &prefix, bool writeflags, const QPointF &offset, LinkableMapObj *saveSel)
204 // tmpdir temporary directory to which data will be written
205 // prefix mapname, which will be appended to images etc.
206 // writeflags Only write flags for "real" save of map, not undo
207 // offset offset of bbox of whole map in scene.
208 // Needed for XML export
214 case LinkableMapObj::Line:
217 case LinkableMapObj::Parabel:
220 case LinkableMapObj::PolyLine:
224 ls="StylePolyParabel";
228 QString s="<?xml version=\"1.0\" encoding=\"utf-8\"?><!DOCTYPE vymmap>\n";
230 if (linkcolorhint==LinkableMapObj::HeadingColor)
231 colhint=attribut("linkColorHint","HeadingColor");
233 QString mapAttr=attribut("version",vymVersion);
234 if (!saveSel || saveSel==mapCenter)
235 mapAttr+= attribut("author",mapCenter->getAuthor()) +
236 attribut("comment",mapCenter->getComment()) +
237 attribut("date",mapCenter->getDate()) +
238 attribut("backgroundColor", mapScene->backgroundBrush().color().name() ) +
239 attribut("selectionColor", xelection.getColor().name() ) +
240 attribut("linkStyle", ls ) +
241 attribut("linkColor", defLinkColor.name() ) +
242 attribut("defXLinkColor", defXLinkColor.name() ) +
243 attribut("defXLinkWidth", QString().setNum(defXLinkWidth,10) ) +
245 s+=beginElement("vymmap",mapAttr);
248 // Find the used flags while traversing the tree
249 standardFlagsDefault->resetUsedCounter();
251 // Reset the counters before saving
252 // TODO constr. of FIO creates lots of objects, better do this in some other way...
253 FloatImageObj (mapScene).resetSaveCounter();
255 // Build xml recursivly
256 if (!saveSel || typeid (*saveSel) == typeid (MapCenterObj))
257 // Save complete map, if saveSel not set
258 s+=mapCenter->saveToDir(tmpdir,prefix,writeflags,offset);
261 if ( typeid(*saveSel) == typeid(BranchObj) )
263 s+=((BranchObj*)(saveSel))->saveToDir(tmpdir,prefix,offset);
264 else if ( typeid(*saveSel) == typeid(FloatImageObj) )
266 s+=((FloatImageObj*)(saveSel))->saveToDir(tmpdir,prefix);
269 // Save local settings
270 s+=settings.getXMLData (destPath);
273 if (!xelection.isEmpty() && !saveSel )
274 s+=valueElement("select",xelection.getSelectString());
277 s+=endElement("vymmap");
280 standardFlagsDefault->saveToDir (tmpdir+"/flags/","",writeflags);
284 void MapEditor::saveStateChangingPart(LinkableMapObj *undoSel, LinkableMapObj* redoSel, const QString &rc, const QString &comment)
286 // save the selected part of the map, Undo will replace part of map
287 QString undoSelection="";
289 undoSelection=undoSel->getSelectString();
291 qWarning ("MapEditor::saveStateChangingPart no undoSel given!");
292 QString redoSelection="";
294 redoSelection=undoSel->getSelectString();
296 qWarning ("MapEditor::saveStateChangingPart no redoSel given!");
299 saveState (PartOfMap,
300 undoSelection, "addMapReplace (\"PATH\")",
306 void MapEditor::saveStateRemovingPart(LinkableMapObj *redoSel, const QString &comment)
310 qWarning ("MapEditor::saveStateRemovingPart no redoSel given!");
313 QString undoSelection=redoSel->getParObj()->getSelectString();
314 QString redoSelection=redoSel->getSelectString();
315 if (typeid(*redoSel) == typeid(BranchObj) )
317 // save the selected branch of the map, Undo will insert part of map
318 saveState (PartOfMap,
319 undoSelection, QString("addMapInsert (\"PATH\",%1)").arg(((BranchObj*)redoSel)->getNum()),
320 redoSelection, "delete ()",
327 void MapEditor::saveState(LinkableMapObj *undoSel, const QString &uc, LinkableMapObj *redoSel, const QString &rc, const QString &comment)
329 // "Normal" savestate: save commands, selections and comment
330 // so just save commands for undo and redo
331 // and use current selection
333 QString redoSelection="";
334 if (redoSel) redoSelection=redoSel->getSelectString();
335 QString undoSelection="";
336 if (undoSel) undoSelection=undoSel->getSelectString();
338 saveState (UndoCommand,
345 void MapEditor::saveState(const QString &undoSel, const QString &uc, const QString &redoSel, const QString &rc, const QString &comment)
347 // "Normal" savestate: save commands, selections and comment
348 // so just save commands for undo and redo
349 // and use current selection
350 saveState (UndoCommand,
358 void MapEditor::saveState(const SaveMode &savemode, const QString &undoSelection, const QString &undoCom, const QString &redoSelection, const QString &redoCom, const QString &comment, LinkableMapObj *saveSel)
362 if (blockSaveState) return;
364 /* TODO remove after testing
366 if (debug) cout << "ME::saveState() for "<<mapName.ascii()<<endl;
368 int undosAvail=undoSet.readNumEntry ("/history/undosAvail",0);
369 int redosAvail=undoSet.readNumEntry ("/history/redosAvail",0);
370 int curStep=undoSet.readNumEntry ("/history/curStep",0);
371 // Find out current undo directory
372 if (undosAvail<stepsTotal) undosAvail++;
374 if (curStep>stepsTotal) curStep=1;
376 QString backupXML="";
377 QString bakMapName=QDir::convertSeparators (QString("history-%1").arg(curStep));
378 QString bakMapDir=QDir::convertSeparators (tmpMapDir +"/"+bakMapName);
379 QString bakMapPath=QDir::convertSeparators(bakMapDir+"/map.xml");
381 // Create bakMapDir if not available
384 makeSubDirs (bakMapDir);
386 // Save depending on how much needs to be saved
388 backupXML=saveToDir (bakMapDir,mapName+"-",false, QPointF (),saveSel);
390 QString undoCommand="";
391 if (savemode==UndoCommand)
395 else if (savemode==PartOfMap )
398 undoCommand.replace ("PATH",bakMapPath);
401 if (!backupXML.isEmpty())
402 // Write XML Data to disk
403 saveStringToDisk (QString(bakMapPath),backupXML);
405 // We would have to save all actions in a tree, to keep track of
406 // possible redos after a action. Possible, but we are too lazy: forget about redos.
409 // Write the current state to disk
410 undoSet.setEntry ("/history/undosAvail",QString::number(undosAvail));
411 undoSet.setEntry ("/history/redosAvail",QString::number(redosAvail));
412 undoSet.setEntry ("/history/curStep",QString::number(curStep));
413 undoSet.setEntry (QString("/history/step-%1/undoCommand").arg(curStep),undoCommand);
414 undoSet.setEntry (QString("/history/step-%1/undoSelection").arg(curStep),undoSelection);
415 undoSet.setEntry (QString("/history/step-%1/redoCommand").arg(curStep),redoCom);
416 undoSet.setEntry (QString("/history/step-%1/redoSelection").arg(curStep),redoSelection);
417 undoSet.setEntry (QString("/history/step-%1/comment").arg(curStep),comment);
418 undoSet.setEntry (QString("/history/version"),vymVersion);
419 undoSet.writeSettings(histPath);
423 // TODO remove after testing
424 //cout << " into="<< histPath.toStdString()<<endl;
425 cout << " stepsTotal="<<stepsTotal<<
426 ", undosAvail="<<undosAvail<<
427 ", redosAvail="<<redosAvail<<
428 ", curStep="<<curStep<<endl;
429 cout << " ---------------------------"<<endl;
430 cout << " comment="<<comment.toStdString()<<endl;
431 cout << " undoCom="<<undoCommand.toStdString()<<endl;
432 cout << " undoSel="<<undoSelection.toStdString()<<endl;
433 cout << " redoCom="<<redoCom.toStdString()<<endl;
434 cout << " redoSel="<<redoSelection.toStdString()<<endl;
435 if (saveSel) cout << " saveSel="<<saveSel->getSelectString().ascii()<<endl;
436 cout << " ---------------------------"<<endl;
439 mainWindow->updateHistory (undoSet);
444 void MapEditor::parseAtom(const QString &atom)
446 BranchObj *selb=xelection.getBranch();
451 // Split string s into command and parameters
452 parser.parseAtom (atom);
453 QString com=parser.getCommand();
456 if (com=="addBranch")
458 if (xelection.isEmpty())
460 parser.setError (Aborted,"Nothing selected");
463 parser.setError (Aborted,"Type of selection is not a branch");
468 if (parser.checkParamCount(pl))
470 if (parser.paramCount()==0)
471 addNewBranchInt (-2);
474 y=parser.parInt (ok,0);
475 if (ok ) addNewBranchInt (y);
479 } else if (com=="addBranchBefore")
481 if (xelection.isEmpty())
483 parser.setError (Aborted,"Nothing selected");
486 parser.setError (Aborted,"Type of selection is not a branch");
489 if (parser.paramCount()==0)
491 addNewBranchBefore ();
494 } else if (com==QString("addMapReplace"))
496 if (xelection.isEmpty())
498 parser.setError (Aborted,"Nothing selected");
501 parser.setError (Aborted,"Type of selection is not a branch");
502 } else if (parser.checkParamCount(1))
504 //s=parser.parString (ok,0); // selection
505 t=parser.parString (ok,0); // path to map
506 if (QDir::isRelativePath(t)) t=QDir::convertSeparators (tmpMapDir + "/"+t);
507 addMapReplaceInt(selb->getSelectString(),t);
509 } else if (com==QString("addMapInsert"))
511 if (xelection.isEmpty())
513 parser.setError (Aborted,"Nothing selected");
516 parser.setError (Aborted,"Type of selection is not a branch");
519 if (parser.checkParamCount(2))
521 t=parser.parString (ok,0); // path to map
522 y=parser.parInt(ok,1); // position
523 if (QDir::isRelativePath(t)) t=QDir::convertSeparators (tmpMapDir + "/"+t);
524 addMapInsertInt(t,y);
527 } else if (com=="clearFlags")
529 if (xelection.isEmpty() )
531 parser.setError (Aborted,"Nothing selected");
534 parser.setError (Aborted,"Type of selection is not a branch");
535 } else if (parser.checkParamCount(0))
537 selb->clearStandardFlags();
538 selb->updateFlagsToolbar();
540 } else if (com=="colorBranch")
542 if (xelection.isEmpty())
544 parser.setError (Aborted,"Nothing selected");
547 parser.setError (Aborted,"Type of selection is not a branch");
548 } else if (parser.checkParamCount(1))
550 QColor c=parser.parColor (ok,0);
551 if (ok) colorBranch (c);
553 } else if (com=="colorSubtree")
555 if (xelection.isEmpty())
557 parser.setError (Aborted,"Nothing selected");
560 parser.setError (Aborted,"Type of selection is not a branch");
561 } else if (parser.checkParamCount(1))
563 QColor c=parser.parColor (ok,0);
564 if (ok) colorSubtree (c);
566 } else if (com=="cut")
568 if (xelection.isEmpty())
570 parser.setError (Aborted,"Nothing selected");
571 } else if ( xelection.type()!=Branch &&
572 xelection.type()!=MapCenter &&
573 xelection.type()!=FloatImage )
575 parser.setError (Aborted,"Type of selection is not a branch or floatimage");
576 } else if (parser.checkParamCount(0))
580 } else if (com=="delete")
582 if (xelection.isEmpty())
584 parser.setError (Aborted,"Nothing selected");
585 } else if (xelection.type() != Branch && xelection.type() != FloatImage )
587 parser.setError (Aborted,"Type of selection is wrong.");
588 } else if (parser.checkParamCount(0))
592 } else if (com=="deleteKeepChilds")
594 if (xelection.isEmpty())
596 parser.setError (Aborted,"Nothing selected");
599 parser.setError (Aborted,"Type of selection is not a branch");
600 } else if (parser.checkParamCount(0))
604 } else if (com=="deleteChilds")
606 if (xelection.isEmpty())
608 parser.setError (Aborted,"Nothing selected");
611 parser.setError (Aborted,"Type of selection is not a branch");
612 } else if (parser.checkParamCount(0))
616 } else if (com=="linkTo")
618 if (xelection.isEmpty())
620 parser.setError (Aborted,"Nothing selected");
623 if (parser.checkParamCount(4))
625 // 0 selectstring of parent
626 // 1 num in parent (for branches)
627 // 2,3 x,y of mainbranch or mapcenter
628 s=parser.parString(ok,0);
629 LinkableMapObj *dst=mapCenter->findObjBySelect (s);
632 if (typeid(*dst) == typeid(BranchObj) )
634 // Get number in parent
635 x=parser.parInt (ok,1);
637 selb->linkTo ((BranchObj*)(dst),x);
638 } else if (typeid(*dst) == typeid(MapCenterObj) )
640 selb->linkTo ((BranchObj*)(dst),-1);
641 // Get coordinates of mainbranch
642 x=parser.parInt (ok,2);
645 y=parser.parInt (ok,3);
646 if (ok) selb->move (x,y);
651 } else if ( xelection.type() == FloatImage)
653 if (parser.checkParamCount(1))
655 // 0 selectstring of parent
656 s=parser.parString(ok,0);
657 LinkableMapObj *dst=mapCenter->findObjBySelect (s);
660 if (typeid(*dst) == typeid(BranchObj) ||
661 typeid(*dst) == typeid(MapCenterObj))
662 linkTo (dst->getSelectString());
664 parser.setError (Aborted,"Destination is not a branch");
667 parser.setError (Aborted,"Type of selection is not a floatimage or branch");
668 } else if (com=="loadImage")
670 if (xelection.isEmpty())
672 parser.setError (Aborted,"Nothing selected");
675 parser.setError (Aborted,"Type of selection is not a branch");
676 } else if (parser.checkParamCount(1))
678 s=parser.parString(ok,0);
679 if (ok) loadFloatImageInt (s);
681 } else if (com=="moveBranchUp")
683 if (xelection.isEmpty() )
685 parser.setError (Aborted,"Nothing selected");
688 parser.setError (Aborted,"Type of selection is not a branch");
689 } else if (parser.checkParamCount(0))
693 } else if (com=="moveBranchDown")
695 if (xelection.isEmpty() )
697 parser.setError (Aborted,"Nothing selected");
700 parser.setError (Aborted,"Type of selection is not a branch");
701 } else if (parser.checkParamCount(0))
705 } else if (com=="move")
707 if (xelection.isEmpty() )
709 parser.setError (Aborted,"Nothing selected");
710 } else if ( xelection.type()!=Branch &&
711 xelection.type()!=MapCenter &&
712 xelection.type()!=FloatImage )
714 parser.setError (Aborted,"Type of selection is not a branch or floatimage");
715 } else if (parser.checkParamCount(2))
717 x=parser.parInt (ok,0);
720 y=parser.parInt (ok,1);
724 } else if (com=="moveRel")
726 if (xelection.isEmpty() )
728 parser.setError (Aborted,"Nothing selected");
729 } else if ( xelection.type()!=Branch &&
730 xelection.type()!=MapCenter &&
731 xelection.type()!=FloatImage )
733 parser.setError (Aborted,"Type of selection is not a branch or floatimage");
734 } else if (parser.checkParamCount(2))
736 x=parser.parInt (ok,0);
739 y=parser.parInt (ok,1);
740 if (ok) moveRel (x,y);
743 } else if (com=="paste")
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=="saveImage")
757 FloatImageObj *fio=xelection.getFloatImage();
760 parser.setError (Aborted,"Type of selection is not an image");
761 } else if (parser.checkParamCount(2))
763 s=parser.parString(ok,0);
766 t=parser.parString(ok,1);
767 if (ok) saveFloatImageInt (fio,t,s);
770 } else if (com=="scroll")
772 if (xelection.isEmpty() )
774 parser.setError (Aborted,"Nothing selected");
777 parser.setError (Aborted,"Type of selection is not a branch");
778 } else if (parser.checkParamCount(0))
780 if (!scrollBranch (selb))
781 parser.setError (Aborted,"Could not scroll branch");
783 } else if (com=="select")
785 if (parser.checkParamCount(1))
787 s=parser.parString(ok,0);
790 } else if (com=="selectLastBranch")
792 if (xelection.isEmpty() )
794 parser.setError (Aborted,"Nothing selected");
797 parser.setError (Aborted,"Type of selection is not a branch");
798 } else if (parser.checkParamCount(0))
800 BranchObj *bo=selb->getLastBranch();
802 parser.setError (Aborted,"Could not select last branch");
806 } else if (com=="selectLastImage")
808 if (xelection.isEmpty() )
810 parser.setError (Aborted,"Nothing selected");
813 parser.setError (Aborted,"Type of selection is not a branch");
814 } else if (parser.checkParamCount(0))
816 FloatImageObj *fio=selb->getLastFloatImage();
818 parser.setError (Aborted,"Could not select last image");
822 } else if (com=="setFrameType")
824 if ( xelection.type()!=Branch && xelection.type()!= MapCenter && xelection.type()!=FloatImage)
826 parser.setError (Aborted,"Type of selection does not allow setting frame type");
828 else if (parser.checkParamCount(1))
830 s=parser.parString(ok,0);
831 if (ok) setFrameType (s);
833 } else if (com=="setMapAuthor")
835 if (parser.checkParamCount(1))
837 s=parser.parString(ok,0);
838 if (ok) setMapAuthor (s);
840 } else if (com=="setMapComment")
842 if (parser.checkParamCount(1))
844 s=parser.parString(ok,0);
845 if (ok) setMapComment(s);
847 } else if (com=="setMapBackgroundColor")
849 if (xelection.isEmpty() )
851 parser.setError (Aborted,"Nothing selected");
852 } else if (! xelection.getBranch() )
854 parser.setError (Aborted,"Type of selection is not a branch");
855 } else if (parser.checkParamCount(1))
857 QColor c=parser.parColor (ok,0);
858 if (ok) setMapBackgroundColor (c);
860 } else if (com=="setMapDefLinkColor")
862 if (xelection.isEmpty() )
864 parser.setError (Aborted,"Nothing selected");
867 parser.setError (Aborted,"Type of selection is not a branch");
868 } else if (parser.checkParamCount(1))
870 QColor c=parser.parColor (ok,0);
871 if (ok) setMapDefLinkColor (c);
873 } else if (com=="setMapLinkStyle")
875 if (parser.checkParamCount(1))
877 s=parser.parString (ok,0);
878 if (ok) setMapLinkStyle(s);
880 } else if (com=="setHeading")
882 if (xelection.isEmpty() )
884 parser.setError (Aborted,"Nothing selected");
887 parser.setError (Aborted,"Type of selection is not a branch");
888 } else if (parser.checkParamCount(1))
890 s=parser.parString (ok,0);
894 } else if (com=="setHideExport")
896 if (xelection.isEmpty() )
898 parser.setError (Aborted,"Nothing selected");
899 } else if (xelection.type()!=Branch && xelection.type() != MapCenter &&xelection.type()!=FloatImage)
901 parser.setError (Aborted,"Type of selection is not a branch or floatimage");
902 } else if (parser.checkParamCount(1))
904 b=parser.parBool(ok,0);
905 if (ok) setHideExport (b);
907 } else if (com=="setIncludeImagesHorizontally")
909 if (xelection.isEmpty() )
911 parser.setError (Aborted,"Nothing selected");
914 parser.setError (Aborted,"Type of selection is not a branch");
915 } else if (parser.checkParamCount(1))
917 b=parser.parBool(ok,0);
918 if (ok) setIncludeImagesHor(b);
920 } else if (com=="setIncludeImagesVertically")
922 if (xelection.isEmpty() )
924 parser.setError (Aborted,"Nothing selected");
927 parser.setError (Aborted,"Type of selection is not a branch");
928 } else if (parser.checkParamCount(1))
930 b=parser.parBool(ok,0);
931 if (ok) setIncludeImagesVer(b);
933 } else if (com=="setSelectionColor")
935 if (parser.checkParamCount(1))
937 QColor c=parser.parColor (ok,0);
938 if (ok) setSelectionColorInt (c);
940 } else if (com=="setURL")
942 if (xelection.isEmpty() )
944 parser.setError (Aborted,"Nothing selected");
947 parser.setError (Aborted,"Type of selection is not a branch");
948 } else if (parser.checkParamCount(1))
950 s=parser.parString (ok,0);
951 if (ok) setURLInt(s);
953 } else if (com=="setVymLink")
955 if (xelection.isEmpty() )
957 parser.setError (Aborted,"Nothing selected");
960 parser.setError (Aborted,"Type of selection is not a branch");
961 } else if (parser.checkParamCount(1))
963 s=parser.parString (ok,0);
964 if (ok) setVymLinkInt(s);
967 else if (com=="setFlag")
969 if (xelection.isEmpty() )
971 parser.setError (Aborted,"Nothing selected");
974 parser.setError (Aborted,"Type of selection is not a branch");
975 } else if (parser.checkParamCount(1))
977 s=parser.parString(ok,0);
980 selb->activateStandardFlag(s);
981 selb->updateFlagsToolbar();
984 } else if (com=="setFrameType")
986 if (xelection.isEmpty() )
988 parser.setError (Aborted,"Nothing selected");
991 parser.setError (Aborted,"Type of selection is not a branch");
992 } else if (parser.checkParamCount(1))
994 s=parser.parString(ok,0);
998 } else if (com=="toggleFlag")
1000 if (xelection.isEmpty() )
1002 parser.setError (Aborted,"Nothing selected");
1005 parser.setError (Aborted,"Type of selection is not a branch");
1006 } else if (parser.checkParamCount(1))
1008 s=parser.parString(ok,0);
1011 selb->toggleStandardFlag(s);
1012 selb->updateFlagsToolbar();
1015 } else if (com=="unscroll")
1017 if (xelection.isEmpty() )
1019 parser.setError (Aborted,"Nothing selected");
1022 parser.setError (Aborted,"Type of selection is not a branch");
1023 } else if (parser.checkParamCount(0))
1025 if (!unscrollBranch (selb))
1026 parser.setError (Aborted,"Could not unscroll branch");
1028 } else if (com=="unscrollChilds")
1030 if (xelection.isEmpty() )
1032 parser.setError (Aborted,"Nothing selected");
1035 parser.setError (Aborted,"Type of selection is not a branch");
1036 } else if (parser.checkParamCount(0))
1040 } else if (com=="unsetFlag")
1042 if (xelection.isEmpty() )
1044 parser.setError (Aborted,"Nothing selected");
1047 parser.setError (Aborted,"Type of selection is not a branch");
1048 } else if (parser.checkParamCount(1))
1050 s=parser.parString(ok,0);
1053 selb->deactivateStandardFlag(s);
1054 selb->updateFlagsToolbar();
1058 parser.setError (Aborted,"Unknown command");
1061 if (parser.errorLevel()==NoError)
1064 mapCenter->reposition();
1068 // TODO Error handling
1069 qWarning("MapEditor::parseAtom: Error!");
1070 qWarning(parser.errorMessage());
1074 void MapEditor::runScript (QString script)
1076 parser.setScript (script);
1078 while (parser.next() )
1079 parseAtom(parser.getAtom());
1082 bool MapEditor::isDefault()
1087 bool MapEditor::isUnsaved()
1092 bool MapEditor::hasChanged()
1097 void MapEditor::setChanged()
1100 autosaveTimer->start(settings.value("/mapeditor/autosave/ms/",300000).toInt());
1108 void MapEditor::closeMap()
1110 // Unselect before disabling the toolbar actions
1111 if (!xelection.isEmpty() ) xelection.unselect();
1119 void MapEditor::setFilePath(QString fname)
1121 setFilePath (fname,fname);
1124 void MapEditor::setFilePath(QString fname, QString destname)
1126 if (fname.isEmpty() || fname=="")
1133 filePath=fname; // becomes absolute path
1134 fileName=fname; // gets stripped of path
1135 destPath=destname; // needed for vymlinks
1137 // If fname is not an absolute path, complete it
1138 filePath=QDir(fname).absPath();
1139 fileDir=filePath.left (1+filePath.findRev ("/"));
1141 // Set short name, too. Search from behind:
1142 int i=fileName.findRev("/");
1143 if (i>=0) fileName=fileName.remove (0,i+1);
1145 // Forget the .vym (or .xml) for name of map
1146 mapName=fileName.left(fileName.findRev(".",-1,true) );
1150 QString MapEditor::getFilePath()
1155 QString MapEditor::getFileName()
1160 QString MapEditor::getMapName()
1165 QString MapEditor::getDestPath()
1170 ErrorCode MapEditor::load (QString fname, LoadMode lmode)
1172 ErrorCode err=success;
1176 if (xelection.isEmpty() ) xelection.unselect();
1179 mapCenter->setMapEditor(this);
1180 // (map state is set later at end of load...)
1183 BranchObj *bo=xelection.getBranch();
1184 if (!bo) return aborted;
1185 if (lmode==ImportAdd)
1186 saveStateChangingPart(
1189 QString("addMapInsert (%1)").arg(fname),
1190 QString("Add map %1 to %2").arg(fname).arg(getName(bo)));
1192 saveStateChangingPart(
1195 QString("addMapReplace(%1)").arg(fname),
1196 QString("Add map %1 to %2").arg(fname).arg(getName(bo)));
1200 mapBuilderHandler handler;
1201 QFile file( fname );
1203 // I am paranoid: file should exist anyway
1204 // according to check in mainwindow.
1205 if (!file.exists() )
1207 QMessageBox::critical( 0, tr( "Critical Parse Error" ),
1208 tr("Couldn't open map " +fname)+".");
1212 bool blockSaveStateOrg=blockSaveState;
1213 blockReposition=true;
1214 blockSaveState=true;
1215 QXmlInputSource source( file);
1216 QXmlSimpleReader reader;
1217 reader.setContentHandler( &handler );
1218 reader.setErrorHandler( &handler );
1219 handler.setMapEditor( this );
1220 handler.setTmpDir (filePath.left(filePath.findRev("/",-1))); // needed to load files with rel. path
1221 handler.setInputFile (file.name());
1222 handler.setLoadMode (lmode);
1223 bool ok = reader.parse( source );
1224 blockReposition=false;
1225 blockSaveState=blockSaveStateOrg;
1229 mapCenter->reposition();
1236 autosaveTimer->stop();
1240 QMessageBox::critical( 0, tr( "Critical Parse Error" ),
1241 tr( handler.errorProtocol() ) );
1243 // Still return "success": the map maybe at least
1244 // partially read by the parser
1251 int MapEditor::save (const SaveMode &savemode)
1255 // Create mapName and fileDir
1256 makeSubDirs (fileDir);
1260 fname=mapName+".xml";
1262 // use name given by user, even if he chooses .doc
1267 if (savemode==CompleteMap || xelection.isEmpty())
1268 saveFile=saveToDir (fileDir,mapName+"-",true,QPointF(),NULL);
1270 //save () FIXME check FIO
1271 saveFile=saveToDir (fileDir,mapName+"-",true,QPointF(),xelection.getBranch());
1273 if (!saveStringToDisk(fileDir+fname,saveFile))
1280 autosaveTimer->stop();
1287 void MapEditor::setZipped (bool z)
1292 bool MapEditor::saveZipped ()
1297 void MapEditor::print()
1301 printer = new QPrinter;
1302 printer->setColorMode (QPrinter::Color);
1303 printer->setPrinterName (settings.value("/mainwindow/printerName",printer->printerName()).toString());
1304 printer->setOutputFormat((QPrinter::OutputFormat)settings.value("/mainwindow/printerFormat",printer->outputFormat()).toInt());
1305 printer->setOutputFileName(settings.value("/mainwindow/printerFileName",printer->outputFileName()).toString());
1308 QRectF totalBBox=mapCenter->getTotalBBox();
1310 // Try to set orientation automagically
1311 // Note: Interpretation of generated postscript is amibiguous, if
1312 // there are problems with landscape mode, see
1313 // http://sdb.suse.de/de/sdb/html/jsmeix_print-cups-landscape-81.html
1315 if (totalBBox.width()>totalBBox.height())
1316 // recommend landscape
1317 printer->setOrientation (QPrinter::Landscape);
1319 // recommend portrait
1320 printer->setOrientation (QPrinter::Portrait);
1322 if ( printer->setup(this) )
1323 // returns false, if printing is canceled
1325 QPainter pp(printer);
1327 pp.setRenderHint(QPainter::Antialiasing,true);
1329 // Don't print the visualisation of selection
1330 xelection.unselect();
1332 QRectF mapRect=totalBBox;
1333 QGraphicsRectItem *frame=NULL;
1337 // Print frame around map
1338 mapRect.setRect (totalBBox.x()-10, totalBBox.y()-10,
1339 totalBBox.width()+20, totalBBox.height()+20);
1340 frame=mapScene->addRect (mapRect, QPen(Qt::black),QBrush(Qt::NoBrush));
1341 frame->setZValue(0);
1346 double paperAspect = (double)printer->width() / (double)printer->height();
1347 double mapAspect = (double)mapRect.width() / (double)mapRect.height();
1349 if (mapAspect>=paperAspect)
1351 // Fit horizontally to paper width
1352 //pp.setViewport(0,0, printer->width(),(int)(printer->width()/mapAspect) );
1353 viewBottom=(int)(printer->width()/mapAspect);
1356 // Fit vertically to paper height
1357 //pp.setViewport(0,0,(int)(printer->height()*mapAspect),printer->height());
1358 viewBottom=printer->height();
1363 // Print footer below map
1365 font.setPointSize(10);
1367 QRectF footerBox(0,viewBottom,printer->width(),15);
1368 pp.drawText ( footerBox,Qt::AlignLeft,"VYM - " +fileName);
1369 pp.drawText ( footerBox, Qt::AlignRight, QDate::currentDate().toString(Qt::TextDate));
1373 QRectF (0,0,printer->width(),printer->height()-15),
1374 QRectF(mapRect.x(),mapRect.y(),mapRect.width(),mapRect.height())
1377 // Viewport has paper dimension
1378 if (frame) delete (frame);
1380 // Restore selection
1381 xelection.reselect();
1383 // Save settings in vymrc
1384 settings.writeEntry("/mainwindow/printerName",printer->printerName());
1385 settings.writeEntry("/mainwindow/printerFormat",printer->outputFormat());
1386 settings.writeEntry("/mainwindow/printerFileName",printer->outputFileName());
1390 void MapEditor::setAntiAlias (bool b)
1392 setRenderHint(QPainter::Antialiasing,b);
1395 void MapEditor::setSmoothPixmap(bool b)
1397 setRenderHint(QPainter::SmoothPixmapTransform,b);
1400 QPixmap MapEditor::getPixmap()
1402 QRectF mapRect=mapCenter->getTotalBBox();
1403 QPixmap pix((int)mapRect.width()+2,(int)mapRect.height()+2);
1406 pp.setRenderHints(renderHints());
1408 // Don't print the visualisation of selection
1409 xelection.unselect();
1411 mapScene->render ( &pp,
1412 QRectF(0,0,mapRect.width()+2,mapRect.height()+2),
1413 QRectF(mapRect.x(),mapRect.y(),mapRect.width(),mapRect.height() ));
1415 // Restore selection
1416 xelection.reselect();
1421 void MapEditor::setHideTmpMode (BranchObj::HideTmpMode mode)
1424 mapCenter->setHideTmp (hidemode);
1425 mapCenter->reposition();
1429 BranchObj::HideTmpMode MapEditor::getHideTmpMode()
1434 void MapEditor::exportImage(QString fn)
1436 setExportMode (true);
1437 QPixmap pix (getPixmap());
1438 pix.save(fn, "PNG");
1439 setExportMode (false);
1442 void MapEditor::setExportMode (bool b)
1444 // should be called before and after exports
1445 // depending on the settings
1446 if (b && settings.value("/export/useHideExport","yes")=="yes")
1447 setHideTmpMode (BranchObj::HideExport);
1449 setHideTmpMode (BranchObj::HideNone);
1452 void MapEditor::exportImage(QString fn, QString format)
1454 setExportMode (true);
1455 QPixmap pix (getPixmap());
1456 pix.save(fn, format);
1457 setExportMode (false);
1460 void MapEditor::exportOOPresentation(const QString &fn, const QString &cf)
1464 ex.setMapCenter(mapCenter);
1465 if (ex.setConfigFile(cf))
1467 setExportMode (true);
1468 ex.exportPresentation();
1469 setExportMode (false);
1475 void MapEditor::exportXML(const QString &dir)
1477 // Hide stuff during export, if settings want this
1478 setExportMode (true);
1480 // Create subdirectories
1483 // write to directory
1484 QString saveFile=saveToDir (dir,mapName+"-",true,mapCenter->getTotalBBox().topLeft() ,NULL);
1487 file.setName ( dir + "/"+mapName+".xml");
1488 if ( !file.open( QIODevice::WriteOnly ) )
1490 // This should neverever happen
1491 QMessageBox::critical (0,tr("Critical Export Error"),tr("MapEditor::exportXML couldn't open %1").arg(file.name()));
1495 // Write it finally, and write in UTF8, no matter what
1496 QTextStream ts( &file );
1497 ts.setEncoding (QTextStream::UnicodeUTF8);
1501 // Now write image, too
1502 exportImage (dir+"/images/"+mapName+".png");
1504 setExportMode (false);
1507 void MapEditor::clear()
1509 xelection.unselect();
1513 void MapEditor::copy()
1515 LinkableMapObj *sel=xelection.single();
1518 // write to directory
1519 QString clipfile="part";
1520 QString saveFile=saveToDir (fileDir,clipfile+"-",true,QPointF(),sel ); // FIXME check FIO
1523 file.setName ( clipboardDir + "/"+clipfile+".xml");
1524 if ( !file.open( QIODevice::WriteOnly ) )
1526 // This should neverever happen
1527 QMessageBox::critical (0,tr("Critical Export Error"),tr("MapEditor::exportXML couldn't open %1").arg(file.name()));
1531 // Write it finally, and write in UTF8, no matter what
1532 QTextStream ts( &file );
1533 ts.setEncoding (QTextStream::UnicodeUTF8);
1537 clipboardEmpty=false;
1542 void MapEditor::redo()
1544 // Restore variables
1545 int curStep=undoSet.readNumEntry (QString("/history/curStep"));
1546 int undosAvail=undoSet.readNumEntry (QString("/history/undosAvail"));
1547 int redosAvail=undoSet.readNumEntry (QString("/history/redosAvail"));
1548 // Can we undo at all?
1549 if (redosAvail<1) return;
1551 bool blockSaveStateOrg=blockSaveState;
1552 blockSaveState=true;
1556 if (undosAvail<stepsTotal) undosAvail++;
1558 if (curStep>stepsTotal) curStep=1;
1559 QString undoCommand= undoSet.readEntry (QString("/history/step-%1/undoCommand").arg(curStep));
1560 QString undoSelection=undoSet.readEntry (QString("/history/step-%1/undoSelection").arg(curStep));
1561 QString redoCommand= undoSet.readEntry (QString("/history/step-%1/redoCommand").arg(curStep));
1562 QString redoSelection=undoSet.readEntry (QString("/history/step-%1/redoSelection").arg(curStep));
1563 QString comment=undoSet.readEntry (QString("/history/step-%1/comment").arg(curStep));
1564 QString version=undoSet.readEntry ("/history/version");
1566 if (!checkVersion(version))
1567 QMessageBox::warning(0,tr("Warning"),
1568 tr("Version %1 of saved undo/redo data\ndoes not match current vym version %2.").arg(version).arg(vymVersion));
1571 // Find out current undo directory
1572 QString bakMapDir=QDir::convertSeparators (QString(tmpMapDir+"/undo-%1").arg(curStep));
1576 cout << "ME::redo() begin\n";
1577 cout << " undosAvail="<<undosAvail<<endl;
1578 cout << " redosAvail="<<redosAvail<<endl;
1579 cout << " curStep="<<curStep<<endl;
1580 cout << " ---------------------------"<<endl;
1581 cout << " comment="<<comment.toStdString()<<endl;
1582 cout << " undoCom="<<undoCommand.toStdString()<<endl;
1583 cout << " undoSel="<<undoSelection.toStdString()<<endl;
1584 cout << " redoCom="<<redoCommand.toStdString()<<endl;
1585 cout << " redoSel="<<redoSelection.toStdString()<<endl;
1586 cout << " ---------------------------"<<endl<<endl;
1589 // select object before redo
1590 if (!redoSelection.isEmpty())
1591 select (redoSelection);
1594 parseAtom (redoCommand);
1595 mapCenter->reposition();
1597 blockSaveState=blockSaveStateOrg;
1599 undoSet.setEntry ("/history/undosAvail",QString::number(undosAvail));
1600 undoSet.setEntry ("/history/redosAvail",QString::number(redosAvail));
1601 undoSet.setEntry ("/history/curStep",QString::number(curStep));
1602 undoSet.writeSettings(histPath);
1604 mainWindow->updateHistory (undoSet);
1607 /* TODO remove testing
1608 cout << "ME::redo() end\n";
1609 cout << " undosAvail="<<undosAvail<<endl;
1610 cout << " redosAvail="<<redosAvail<<endl;
1611 cout << " curStep="<<curStep<<endl;
1612 cout << " ---------------------------"<<endl<<endl;
1618 bool MapEditor::isRedoAvailable()
1620 if (undoSet.readNumEntry("/history/redosAvail",0)>0)
1626 void MapEditor::undo()
1628 // Restore variables
1629 int curStep=undoSet.readNumEntry (QString("/history/curStep"));
1630 int undosAvail=undoSet.readNumEntry (QString("/history/undosAvail"));
1631 int redosAvail=undoSet.readNumEntry (QString("/history/redosAvail"));
1633 // Can we undo at all?
1634 if (undosAvail<1) return;
1636 bool blockSaveStateOrg=blockSaveState;
1637 blockSaveState=true;
1639 QString undoCommand= undoSet.readEntry (QString("/history/step-%1/undoCommand").arg(curStep));
1640 QString undoSelection=undoSet.readEntry (QString("/history/step-%1/undoSelection").arg(curStep));
1641 QString redoCommand= undoSet.readEntry (QString("/history/step-%1/redoCommand").arg(curStep));
1642 QString redoSelection=undoSet.readEntry (QString("/history/step-%1/redoSelection").arg(curStep));
1643 QString comment=undoSet.readEntry (QString("/history/step-%1/comment").arg(curStep));
1644 QString version=undoSet.readEntry ("/history/version");
1646 if (!checkVersion(version))
1647 QMessageBox::warning(0,tr("Warning"),
1648 tr("Version %1 of saved undo/redo data\ndoes not match current vym version %2.").arg(version).arg(vymVersion));
1650 // Find out current undo directory
1651 QString bakMapDir=QDir::convertSeparators (QString(tmpMapDir+"/undo-%1").arg(curStep));
1653 // select object before undo
1654 if (!undoSelection.isEmpty())
1655 select (undoSelection);
1659 cout << "ME::undo() begin\n";
1660 cout << " undosAvail="<<undosAvail<<endl;
1661 cout << " redosAvail="<<redosAvail<<endl;
1662 cout << " curStep="<<curStep<<endl;
1663 cout << " ---------------------------"<<endl;
1664 cout << " comment="<<comment.toStdString()<<endl;
1665 cout << " undoCom="<<undoCommand.toStdString()<<endl;
1666 cout << " undoSel="<<undoSelection.toStdString()<<endl;
1667 cout << " redoCom="<<redoCommand.toStdString()<<endl;
1668 cout << " redoSel="<<redoSelection.toStdString()<<endl;
1669 cout << " ---------------------------"<<endl<<endl;
1671 parseAtom (undoCommand);
1672 mapCenter->reposition();
1676 if (curStep<1) curStep=stepsTotal;
1680 blockSaveState=blockSaveStateOrg;
1681 /* TODO remove testing
1682 cout << "ME::undo() end\n";
1683 cout << " undosAvail="<<undosAvail<<endl;
1684 cout << " redosAvail="<<redosAvail<<endl;
1685 cout << " curStep="<<curStep<<endl;
1686 cout << " ---------------------------"<<endl<<endl;
1689 undoSet.setEntry ("/history/undosAvail",QString::number(undosAvail));
1690 undoSet.setEntry ("/history/redosAvail",QString::number(redosAvail));
1691 undoSet.setEntry ("/history/curStep",QString::number(curStep));
1692 undoSet.writeSettings(histPath);
1694 mainWindow->updateHistory (undoSet);
1697 ensureSelectionVisible();
1700 bool MapEditor::isUndoAvailable()
1702 if (undoSet.readNumEntry("/history/undosAvail",0)>0)
1708 void MapEditor::gotoHistoryStep (int i)
1710 // Restore variables
1711 int undosAvail=undoSet.readNumEntry (QString("/history/undosAvail"));
1712 int redosAvail=undoSet.readNumEntry (QString("/history/redosAvail"));
1714 if (i<0) i=undosAvail+redosAvail;
1716 // Clicking above current step makes us undo things
1719 for (int j=0; j<undosAvail-i; j++) undo();
1722 // Clicking below current step makes us redo things
1724 for (int j=undosAvail; j<i; j++) redo();
1726 // And ignore clicking the current row ;-)
1729 void MapEditor::addMapReplaceInt(const QString &undoSel, const QString &path)
1731 QString pathDir=path.left(path.findRev("/"));
1737 // We need to parse saved XML data
1738 mapBuilderHandler handler;
1739 QXmlInputSource source( file);
1740 QXmlSimpleReader reader;
1741 reader.setContentHandler( &handler );
1742 reader.setErrorHandler( &handler );
1743 handler.setMapEditor( this );
1744 handler.setTmpDir ( pathDir ); // needed to load files with rel. path
1745 if (undoSel.isEmpty())
1749 handler.setLoadMode (NewMap);
1753 handler.setLoadMode (ImportReplace);
1755 blockReposition=true;
1756 bool ok = reader.parse( source );
1757 blockReposition=false;
1760 // This should never ever happen
1761 QMessageBox::critical( 0, tr( "Critical Parse Error while reading %1").arg(path),
1762 handler.errorProtocol());
1765 QMessageBox::critical( 0, tr( "Critical Error" ), tr("Could not read %1").arg(path));
1768 void MapEditor::addMapInsertInt (const QString &path, int pos)
1770 BranchObj *sel=xelection.getBranch();
1773 QString pathDir=path.left(path.findRev("/"));
1779 // We need to parse saved XML data
1780 mapBuilderHandler handler;
1781 QXmlInputSource source( file);
1782 QXmlSimpleReader reader;
1783 reader.setContentHandler( &handler );
1784 reader.setErrorHandler( &handler );
1785 handler.setMapEditor( this );
1786 handler.setTmpDir ( pathDir ); // needed to load files with rel. path
1787 handler.setLoadMode (ImportAdd);
1788 blockReposition=true;
1789 bool ok = reader.parse( source );
1790 blockReposition=false;
1793 // This should never ever happen
1794 QMessageBox::critical( 0, tr( "Critical Parse Error while reading %1").arg(path),
1795 handler.errorProtocol());
1798 sel->getLastBranch()->linkTo (sel,pos);
1800 QMessageBox::critical( 0, tr( "Critical Error" ), tr("Could not read %1").arg(path));
1804 void MapEditor::pasteNoSave()
1806 load (clipboardDir+"/part.xml",ImportAdd);
1809 void MapEditor::cutNoSave()
1815 void MapEditor::paste() // FIXME no pasting of FIO ???
1817 BranchObj *sel=xelection.getBranch();
1821 saveStateChangingPart(
1825 QString("Paste to %1").arg( getName(sel))
1827 mapCenter->reposition();
1831 void MapEditor::cut()
1833 LinkableMapObj *sel=xelection.single();
1834 if ( sel && (xelection.type() == Branch ||
1835 xelection.type()==MapCenter ||
1836 xelection.type()==FloatImage))
1838 saveStateChangingPart(
1842 QString("Cut %1").arg(getName(sel ))
1846 mapCenter->reposition();
1850 void MapEditor::move(const int &x, const int &y)
1852 LinkableMapObj *sel=xelection.single();
1855 QString ps=qpointfToString (sel->getAbsPos());
1856 QString s=xelection.single()->getSelectString();
1859 s, "move "+qpointfToString (QPointF (x,y)),
1860 QString("Move %1 to %2").arg(getName(sel)).arg(ps));
1862 mapCenter->reposition();
1868 void MapEditor::moveRel (const int &x, const int &y)
1870 LinkableMapObj *sel=xelection.single();
1873 QString ps=qpointfToString (sel->getRelPos());
1874 QString s=sel->getSelectString();
1877 s, "moveRel "+qpointfToString (QPointF (x,y)),
1878 QString("Move %1 to relativ position %2").arg(getName(sel)).arg(ps));
1879 ((OrnamentedObj*)sel)->move2RelPos (x,y);
1880 mapCenter->reposition();
1886 void MapEditor::moveBranchUp()
1888 BranchObj* bo=xelection.getBranch();
1892 if (!bo->canMoveBranchUp()) return;
1893 par=(BranchObj*)(bo->getParObj());
1894 BranchObj *obo=par->moveBranchUp (bo); // bo will be the one below selection
1895 saveState (bo->getSelectString(),"moveBranchDown ()",obo->getSelectString(),"moveBranchUp ()",QString("Move up %1").arg(getName(bo)));
1896 mapCenter->reposition();
1899 ensureSelectionVisible();
1903 void MapEditor::moveBranchDown()
1905 BranchObj* bo=xelection.getBranch();
1909 if (!bo->canMoveBranchDown()) return;
1910 par=(BranchObj*)(bo->getParObj());
1911 BranchObj *obo=par->moveBranchDown(bo); // bo will be the one above selection
1912 saveState(bo->getSelectString(),"moveBranchUp ()",obo->getSelectString(),"moveBranchDown ()",QString("Move down %1").arg(getName(bo)));
1913 mapCenter->reposition();
1916 ensureSelectionVisible();
1920 void MapEditor::linkTo(const QString &dstString) // FIXME needed? only for FIO ??
1922 FloatImageObj *fio=xelection.getFloatImage();
1925 BranchObj *dst=(BranchObj*)(mapCenter->findObjBySelect(dstString));
1926 if (dst && (typeid(*dst)==typeid (BranchObj) ||
1927 typeid(*dst)==typeid (MapCenterObj)))
1929 LinkableMapObj *dstPar=dst->getParObj();
1930 QString parString=dstPar->getSelectString();
1931 QString fioPreSelectString=fio->getSelectString();
1932 QString fioPreParentSelectString=fio->getParObj()->getSelectString();
1933 ((BranchObj*)(dst))->addFloatImage (fio);
1934 xelection.unselect();
1935 ((BranchObj*)(fio->getParObj()))->removeFloatImage (fio);
1936 fio=((BranchObj*)(dst))->getLastFloatImage();
1939 xelection.select(fio);
1941 fio->getSelectString(),
1942 QString("linkTo (\"%1\")").arg(fioPreParentSelectString),
1944 QString ("linkTo (\"%1\")").arg(dstString),
1945 QString ("Link floatimage to %1").arg(getName(dst)));
1950 QString MapEditor::getHeading(bool &ok, QPoint &p)
1952 BranchObj *bo=xelection.getBranch();
1956 p=mapFromScene(bo->getAbsPos());
1957 return bo->getHeading();
1963 void MapEditor::setHeading(const QString &s)
1965 BranchObj *sel=xelection.getBranch();
1970 "setHeading (\""+sel->getHeading()+"\")",
1972 "setHeading (\""+s+"\")",
1973 QString("Set heading of %1 to \"%2\"").arg(getName(sel)).arg(s) );
1974 sel->setHeading(s );
1975 mapCenter->reposition();
1977 ensureSelectionVisible();
1981 void MapEditor::setURLInt (const QString &s)
1983 // Internal function, no saveState needed
1984 BranchObj *bo=xelection.getBranch();
1988 mapCenter->reposition();
1990 ensureSelectionVisible();
1994 void MapEditor::setHeadingInt(const QString &s)
1996 BranchObj *bo=xelection.getBranch();
2000 mapCenter->reposition();
2002 ensureSelectionVisible();
2006 void MapEditor::setVymLinkInt (const QString &s)
2008 // Internal function, no saveState needed
2009 BranchObj *bo=xelection.getBranch();
2013 mapCenter->reposition();
2015 ensureSelectionVisible();
2019 BranchObj* MapEditor::addNewBranchInt(int num)
2021 // Depending on pos:
2022 // -3 insert in childs of parent above selection
2023 // -2 add branch to selection
2024 // -1 insert in childs of parent below selection
2025 // 0..n insert in childs of parent at pos
2026 BranchObj *newbo=NULL;
2027 BranchObj *bo=xelection.getBranch();
2032 // save scroll state. If scrolled, automatically select
2033 // new branch in order to tmp unscroll parent...
2034 return bo->addBranch();
2039 bo=(BranchObj*)bo->getParObj();
2043 bo=(BranchObj*)bo->getParObj();
2046 newbo=bo->insertBranch(num);
2051 BranchObj* MapEditor::addNewBranch(int pos)
2053 // Different meaning than num in addNewBranchInt!
2057 BranchObj *bo = xelection.getBranch();
2058 BranchObj *newbo=NULL;
2062 setCursor (Qt::ArrowCursor);
2064 newbo=addNewBranchInt (pos-2);
2072 QString ("addBranch (%1)").arg(pos-2),
2073 QString ("Add new branch to %1").arg(getName(bo)));
2075 mapCenter->reposition();
2083 BranchObj* MapEditor::addNewBranchBefore()
2085 BranchObj *newbo=NULL;
2086 BranchObj *bo = xelection.getBranch();
2087 if (bo && xelection.type()==Branch)
2088 // We accept no MapCenterObj here, so we _have_ a parent
2090 QPointF p=bo->getRelPos();
2093 BranchObj *parbo=(BranchObj*)(bo->getParObj());
2095 // add below selection
2096 newbo=parbo->insertBranch(bo->getNum()+1);
2099 newbo->move2RelPos (p);
2101 // Move selection to new branch
2102 bo->linkTo (newbo,-1);
2104 saveState (newbo, "deleteKeepChilds ()", newbo, "addBranchBefore ()",
2105 QString ("Add branch before %1").arg(getName(bo)));
2107 mapCenter->reposition();
2114 void MapEditor::deleteSelection()
2116 BranchObj *bo = xelection.getBranch();
2117 if (bo && xelection.type()==Branch)
2119 BranchObj* par=(BranchObj*)(bo->getParObj());
2120 xelection.unselect();
2121 saveStateRemovingPart (bo, QString ("Delete %1").arg(getName(bo)));
2122 par->removeBranch(bo);
2123 xelection.select (par);
2124 ensureSelectionVisible();
2125 mapCenter->reposition();
2130 FloatImageObj *fio=xelection.getFloatImage();
2133 BranchObj* par=(BranchObj*)(fio->getParObj());
2134 saveStateChangingPart(
2138 QString("Delete %1").arg(getName(fio))
2140 xelection.unselect();
2141 par->removeFloatImage(fio);
2142 xelection.select (par);
2143 mapCenter->reposition();
2145 ensureSelectionVisible();
2150 LinkableMapObj* MapEditor::getSelection()
2152 return xelection.single();
2155 BranchObj* MapEditor::getSelectedBranch()
2157 return xelection.getBranch();
2160 FloatImageObj* MapEditor::getSelectedFloatImage()
2162 return xelection.getFloatImage();
2165 void MapEditor::unselect()
2167 xelection.unselect();
2170 void MapEditor::reselect()
2172 xelection.reselect();
2175 bool MapEditor::select (const QString &s)
2177 LinkableMapObj *lmo=mapCenter->findObjBySelect(s);
2179 // Finally select the found object
2182 xelection.unselect();
2183 xelection.select(lmo);
2185 ensureSelectionVisible();
2191 QString MapEditor::getSelectString()
2193 return xelection.getSelectString();
2196 void MapEditor::selectInt (LinkableMapObj *lmo)
2198 if (lmo && xelection.single()!= lmo)
2200 xelection.select(lmo);
2205 void MapEditor::selectNextBranchInt()
2207 // Increase number of branch
2208 LinkableMapObj *sel=xelection.single();
2211 QString s=sel->getSelectString();
2217 part=s.section(",",-1);
2219 num=part.right(part.length() - 3);
2221 s=s.left (s.length() -num.length());
2224 num=QString ("%1").arg(num.toUInt()+1);
2228 // Try to select this one
2229 if (select (s)) return;
2231 // We have no direct successor,
2232 // try to increase the parental number in order to
2233 // find a successor with same depth
2235 int d=xelection.single()->getDepth();
2240 while (!found && d>0)
2242 s=s.section (",",0,d-1);
2243 // replace substring of current depth in s with "1"
2244 part=s.section(",",-1);
2246 num=part.right(part.length() - 3);
2250 // increase number of parent
2251 num=QString ("%1").arg(num.toUInt()+1);
2252 s=s.section (",",0,d-2) + ","+ typ+num;
2255 // Special case, look at orientation
2256 if (xelection.single()->getOrientation()==LinkableMapObj::RightOfCenter)
2257 num=QString ("%1").arg(num.toUInt()+1);
2259 num=QString ("%1").arg(num.toUInt()-1);
2264 // pad to oldDepth, select the first branch for each depth
2265 for (i=d;i<oldDepth;i++)
2270 if ( xelection.getBranch()->countBranches()>0)
2278 // try to select the freshly built string
2286 void MapEditor::selectPrevBranchInt()
2288 // Decrease number of branch
2289 BranchObj *bo=xelection.getBranch();
2292 QString s=bo->getSelectString();
2298 part=s.section(",",-1);
2300 num=part.right(part.length() - 3);
2302 s=s.left (s.length() -num.length());
2304 int n=num.toInt()-1;
2307 num=QString ("%1").arg(n);
2310 // Try to select this one
2311 if (n>=0 && select (s)) return;
2313 // We have no direct precessor,
2314 // try to decrease the parental number in order to
2315 // find a precessor with same depth
2317 int d=xelection.single()->getDepth();
2322 while (!found && d>0)
2324 s=s.section (",",0,d-1);
2325 // replace substring of current depth in s with "1"
2326 part=s.section(",",-1);
2328 num=part.right(part.length() - 3);
2332 // decrease number of parent
2333 num=QString ("%1").arg(num.toInt()-1);
2334 s=s.section (",",0,d-2) + ","+ typ+num;
2337 // Special case, look at orientation
2338 if (xelection.single()->getOrientation()==LinkableMapObj::RightOfCenter)
2339 num=QString ("%1").arg(num.toInt()-1);
2341 num=QString ("%1").arg(num.toInt()+1);
2346 // pad to oldDepth, select the last branch for each depth
2347 for (i=d;i<oldDepth;i++)
2351 if ( xelection.getBranch()->countBranches()>0)
2352 s+=",bo:"+ QString ("%1").arg( xelection.getBranch()->countBranches()-1 );
2359 // try to select the freshly built string
2367 void MapEditor::selectUpperBranch()
2369 BranchObj *bo=xelection.getBranch();
2370 if (bo && xelection.type()==Branch)
2372 if (bo->getOrientation()==LinkableMapObj::RightOfCenter)
2373 selectPrevBranchInt();
2375 if (bo->getDepth()==1)
2376 selectNextBranchInt();
2378 selectPrevBranchInt();
2382 void MapEditor::selectLowerBranch()
2384 BranchObj *bo=xelection.getBranch();
2385 if (bo && xelection.type()==Branch)
2386 if (bo->getOrientation()==LinkableMapObj::RightOfCenter)
2387 selectNextBranchInt();
2389 if (bo->getDepth()==1)
2390 selectPrevBranchInt();
2392 selectNextBranchInt();
2396 void MapEditor::selectLeftBranch()
2400 LinkableMapObj *sel=xelection.single();
2403 if (xelection.type()== MapCenter)
2405 par=xelection.getBranch();
2406 bo=par->getLastSelectedBranch();
2409 // Workaround for reselecting on left and right side
2410 if (bo->getOrientation()==LinkableMapObj::RightOfCenter)
2411 bo=par->getLastBranch();
2414 bo=par->getLastBranch();
2415 xelection.select(bo);
2417 ensureSelectionVisible();
2422 par=(BranchObj*)(sel->getParObj());
2423 if (sel->getOrientation()==LinkableMapObj::RightOfCenter)
2425 if (xelection.type() == Branch ||
2426 xelection.type() == FloatImage)
2428 xelection.select(par);
2430 ensureSelectionVisible();
2434 if (xelection.type() == Branch )
2436 bo=xelection.getBranch()->getLastSelectedBranch();
2439 xelection.select(bo);
2441 ensureSelectionVisible();
2449 void MapEditor::selectRightBranch()
2453 LinkableMapObj *sel=xelection.single();
2456 if (xelection.type()==MapCenter)
2458 par=xelection.getBranch();
2459 bo=par->getLastSelectedBranch();
2462 // Workaround for reselecting on left and right side
2463 if (bo->getOrientation()==LinkableMapObj::LeftOfCenter)
2464 bo=par->getFirstBranch();
2467 xelection.select(bo);
2469 ensureSelectionVisible();
2474 par=(BranchObj*)(xelection.single()->getParObj());
2475 if (xelection.single()->getOrientation()==LinkableMapObj::LeftOfCenter)
2477 if (xelection.type() == Branch ||
2478 xelection.type() == FloatImage)
2480 xelection.select(par);
2482 ensureSelectionVisible();
2486 if (xelection.type() == Branch)
2488 bo=xelection.getBranch()->getLastSelectedBranch();
2491 xelection.select(bo);
2493 ensureSelectionVisible();
2501 void MapEditor::selectFirstBranch()
2503 BranchObj *bo1=xelection.getBranch();
2508 par=(BranchObj*)(bo1->getParObj());
2509 bo2=par->getFirstBranch();
2511 xelection.select(bo2);
2513 ensureSelectionVisible();
2518 void MapEditor::selectLastBranch()
2520 BranchObj *bo1=xelection.getBranch();
2525 par=(BranchObj*)(bo1->getParObj());
2526 bo2=par->getLastBranch();
2529 xelection.select(bo2);
2531 ensureSelectionVisible();
2536 void MapEditor::selectMapBackgroundImage ()
2538 Q3FileDialog *fd=new Q3FileDialog( this);
2539 fd->setMode (Q3FileDialog::ExistingFile);
2540 fd->addFilter (QString (tr("Images") + " (*.png *.bmp *.xbm *.jpg *.png *.xpm *.gif *.pnm)"));
2541 ImagePreview *p =new ImagePreview (fd);
2542 fd->setContentsPreviewEnabled( TRUE );
2543 fd->setContentsPreview( p, p );
2544 fd->setPreviewMode( Q3FileDialog::Contents );
2545 fd->setCaption(vymName+" - " +tr("Load background image"));
2546 fd->setDir (lastImageDir);
2549 if ( fd->exec() == QDialog::Accepted )
2551 // TODO selectMapBackgroundImg in QT4 use: lastImageDir=fd->directory();
2552 lastImageDir=QDir (fd->dirPath());
2553 setMapBackgroundImage (fd->selectedFile());
2557 void MapEditor::setMapBackgroundImage (const QString &fn) //FIXME missing savestate
2559 QColor oldcol=mapScene->backgroundBrush().color();
2563 QString ("setMapBackgroundImage (%1)").arg(oldcol.name()),
2565 QString ("setMapBackgroundImage (%1)").arg(col.name()),
2566 QString("Set background color of map to %1").arg(col.name()));
2569 brush.setTextureImage (QPixmap (fn));
2570 mapScene->setBackgroundBrush(brush);
2573 void MapEditor::selectMapBackgroundColor()
2575 QColor col = QColorDialog::getColor( mapScene->backgroundBrush().color(), this );
2576 if ( !col.isValid() ) return;
2577 setMapBackgroundColor( col );
2581 void MapEditor::setMapBackgroundColor(QColor col)
2583 QColor oldcol=mapScene->backgroundBrush().color();
2586 QString ("setMapBackgroundColor (\"%1\")").arg(oldcol.name()),
2588 QString ("setMapBackgroundColor (\"%1\")").arg(col.name()),
2589 QString("Set background color of map to %1").arg(col.name()));
2590 mapScene->setBackgroundBrush(col);
2593 QColor MapEditor::getMapBackgroundColor()
2595 return mapScene->backgroundBrush().color();
2598 QColor MapEditor::getCurrentHeadingColor()
2600 BranchObj *bo=xelection.getBranch();
2601 if (bo) return bo->getColor();
2603 QMessageBox::warning(0,tr("Warning"),tr("Can't get color of heading,\nthere's no branch selected"));
2607 void MapEditor::colorBranch (QColor c)
2609 BranchObj *bo=xelection.getBranch();
2614 QString ("colorBranch (\"%1\")").arg(bo->getColor().name()),
2616 QString ("colorBranch (\"%1\")").arg(c.name()),
2617 QString("Set color of %1 to %2").arg(getName(bo)).arg(c.name())
2619 bo->setColor(c); // color branch
2623 void MapEditor::colorSubtree (QColor c)
2625 BranchObj *bo=xelection.getBranch();
2628 saveStateChangingPart(
2631 QString ("colorSubtree (\"%1\")").arg(c.name()),
2632 QString ("Set color of %1 and childs to %2").arg(getName(bo)).arg(c.name())
2634 bo->setColorSubtree (c); // color links, color childs
2639 void MapEditor::toggleStandardFlag(QString f)
2641 BranchObj *bo=xelection.getBranch();
2645 if (bo->isSetStandardFlag(f))
2657 QString("%1 (\"%2\")").arg(u).arg(f),
2659 QString("%1 (\"%2\")").arg(r).arg(f),
2660 QString("Toggling standard flag \"%1\" of %2").arg(f).arg(getName(bo)));
2661 bo->toggleStandardFlag (f,mainWindow->useFlagGroups());
2667 BranchObj* MapEditor::findText (QString s, bool cs)
2669 QTextDocument::FindFlags flags=0;
2670 if (cs) flags=QTextDocument::FindCaseSensitively;
2673 { // Nothing found or new find process
2675 // nothing found, start again
2677 itFind=mapCenter->first();
2679 bool searching=true;
2680 bool foundNote=false;
2681 while (searching && !EOFind)
2685 // Searching in Note
2686 if (itFind->getNote().contains(s,cs))
2688 if (xelection.single()!=itFind)
2690 xelection.select(itFind);
2691 ensureSelectionVisible();
2693 if (textEditor->findText(s,flags))
2699 // Searching in Heading
2700 if (searching && itFind->getHeading().contains (s,cs) )
2702 xelection.select(itFind);
2703 ensureSelectionVisible();
2709 itFind=itFind->next();
2710 if (!itFind) EOFind=true;
2714 return xelection.getBranch();
2719 void MapEditor::findReset()
2720 { // Necessary if text to find changes during a find process
2724 void MapEditor::setURL(const QString &url)
2726 BranchObj *bo=xelection.getBranch();
2729 QString oldurl=bo->getURL();
2733 QString ("setURL (\"%1\")").arg(oldurl),
2735 QString ("setURL (\"%1\")").arg(url),
2736 QString ("set URL of %1 to %2").arg(getName(bo)).arg(url)
2742 void MapEditor::editURL()
2744 BranchObj *bo=xelection.getBranch();
2748 QString text = QInputDialog::getText(
2749 "VYM", tr("Enter URL:"), QLineEdit::Normal,
2750 bo->getURL(), &ok, this );
2752 // user entered something and pressed OK
2757 QString MapEditor::getURL()
2759 BranchObj *bo=xelection.getBranch();
2761 return bo->getURL();
2766 QStringList MapEditor::getURLs()
2769 BranchObj *bo=xelection.getBranch();
2775 if (!bo->getURL().isEmpty()) urls.append( bo->getURL());
2783 void MapEditor::editHeading2URL()
2785 BranchObj *bo=xelection.getBranch();
2787 setURL (bo->getHeading());
2790 void MapEditor::editBugzilla2URL()
2792 BranchObj *bo=xelection.getBranch();
2795 QString url= "https://bugzilla.novell.com/show_bug.cgi?id="+bo->getHeading();
2800 void MapEditor::editFATE2URL()
2802 BranchObj *bo=xelection.getBranch();
2805 QString url= "http://keeper.suse.de:8080/webfate/match/id?value=ID"+bo->getHeading();
2808 "setURL (\""+bo->getURL()+"\")",
2810 "setURL (\""+url+"\")",
2811 QString("Use heading of %1 as link to FATE").arg(getName(bo))
2818 void MapEditor::editVymLink()
2820 BranchObj *bo=xelection.getBranch();
2823 QStringList filters;
2824 filters <<"VYM map (*.vym)";
2825 QFileDialog *fd=new QFileDialog( this,vymName+" - " +tr("Link to another map"));
2826 fd->setFilters (filters);
2827 fd->setCaption(vymName+" - " +tr("Link to another map"));
2828 fd->setDirectory (lastFileDir);
2829 if (! bo->getVymLink().isEmpty() )
2830 fd->selectFile( bo->getVymLink() );
2834 if ( fd->exec() == QDialog::Accepted )
2836 lastFileDir=QDir (fd->directory().path());
2839 "setVymLink (\""+bo->getVymLink()+"\")",
2841 "setVymLink (\""+fd->selectedFile()+"\")",
2842 QString("Set vymlink of %1 to %2").arg(getName(bo)).arg(fd->selectedFile())
2844 bo->setVymLink (fd->selectedFile() );
2846 mapCenter->reposition();
2852 void MapEditor::deleteVymLink()
2854 BranchObj *bo=xelection.getBranch();
2859 "setVymLink (\""+bo->getVymLink()+"\")",
2861 "setVymLink (\"\")",
2862 QString("Unset vymlink of %1").arg(getName(bo))
2864 bo->setVymLink ("" );
2866 mapCenter->reposition();
2871 void MapEditor::setHideExport(bool b)
2873 BranchObj *bo=xelection.getBranch();
2876 bo->setHideInExport (b);
2877 QString u= b ? "false" : "true";
2878 QString r=!b ? "false" : "true";
2882 QString ("setHideExport (%1)").arg(u),
2884 QString ("setHideExport (%1)").arg(r),
2885 QString ("Set HideExport flag of %1 to %2").arg(getName(bo)).arg (r)
2888 mapCenter->reposition();
2893 void MapEditor::toggleHideExport()
2895 BranchObj *bo=xelection.getBranch();
2897 setHideExport ( !bo->hideInExport() );
2900 QString MapEditor::getVymLink()
2902 BranchObj *bo=xelection.getBranch();
2904 return bo->getVymLink();
2910 QStringList MapEditor::getVymLinks()
2913 BranchObj *bo=xelection.getBranch();
2919 if (!bo->getVymLink().isEmpty()) links.append( bo->getVymLink());
2927 void MapEditor::deleteKeepChilds()
2929 BranchObj *bo=xelection.getBranch();
2933 par=(BranchObj*)(bo->getParObj());
2934 QPointF p=bo->getRelPos();
2935 saveStateChangingPart(
2938 "deleteKeepChilds ()",
2939 QString("Remove %1 and keep its childs").arg(getName(bo))
2942 QString sel=bo->getSelectString();
2944 par->removeBranchHere(bo);
2945 mapCenter->reposition();
2947 xelection.getBranch()->move2RelPos (p);
2948 mapCenter->reposition();
2952 void MapEditor::deleteChilds()
2954 BranchObj *bo=xelection.getBranch();
2957 saveStateChangingPart(
2961 QString( "Remove childs of branch %1").arg(getName(bo))
2964 mapCenter->reposition();
2968 void MapEditor::editMapInfo()
2970 ExtraInfoDialog dia;
2971 dia.setMapName (getFileName() );
2972 dia.setAuthor (mapCenter->getAuthor() );
2973 dia.setComment(mapCenter->getComment() );
2977 stats+=tr("%1 items on map\n","Info about map").arg (mapScene->items().size(),6);
2984 bo=mapCenter->first();
2987 if (!bo->getNote().isEmpty() ) n++;
2988 f+= bo->countFloatImages();
2990 xl+=bo->countXLinks();
2993 stats+=QString ("%1 branches\n").arg (b-1,6);
2994 stats+=QString ("%1 xLinks \n").arg (xl,6);
2995 stats+=QString ("%1 notes\n").arg (n,6);
2996 stats+=QString ("%1 images\n").arg (f,6);
2997 dia.setStats (stats);
2999 // Finally show dialog
3000 if (dia.exec() == QDialog::Accepted)
3002 setMapAuthor (dia.getAuthor() );
3003 setMapComment (dia.getComment() );
3007 void MapEditor::ensureSelectionVisible()
3009 LinkableMapObj *lmo=xelection.single();
3010 if (lmo) ensureVisible (lmo->getBBox() );
3014 void MapEditor::updateSelection()
3016 // Tell selection to update geometries
3020 void MapEditor::updateActions()
3022 // Tell mainwindow to update states of actions
3023 mainWindow->updateActions();
3024 // TODO maybe don't update if blockReposition is set
3027 void MapEditor::updateNoteFlag()
3030 BranchObj *bo=xelection.getBranch();
3033 bo->updateNoteFlag();
3034 mainWindow->updateActions();
3038 void MapEditor::setMapAuthor (const QString &s)
3042 QString ("setMapAuthor (\"%1\")").arg(mapCenter->getAuthor()),
3044 QString ("setMapAuthor (\"%1\")").arg(s),
3045 QString ("Set author of map to \"%1\"").arg(s)
3047 mapCenter->setAuthor (s);
3050 void MapEditor::setMapComment (const QString &s)
3054 QString ("setMapComment (\"%1\")").arg(mapCenter->getComment()),
3056 QString ("setMapComment (\"%1\")").arg(s),
3057 QString ("Set comment of map")
3059 mapCenter->setComment (s);
3062 void MapEditor::setMapLinkStyle (const QString & s)
3064 saveStateChangingPart (
3067 QString("setMapLinkStyle (\"%1\")").arg(s),
3068 QString("Set map link style (\"%1\")").arg(s)
3072 linkstyle=LinkableMapObj::Line;
3073 else if (s=="StyleParabel")
3074 linkstyle=LinkableMapObj::Parabel;
3075 else if (s=="StylePolyLine")
3076 linkstyle=LinkableMapObj::PolyLine;
3078 linkstyle=LinkableMapObj::PolyParabel;
3081 bo=mapCenter->first();
3085 bo->setLinkStyle(bo->getDefLinkStyle());
3088 mapCenter->reposition();
3091 LinkableMapObj::Style MapEditor::getMapLinkStyle ()
3096 void MapEditor::setMapDefLinkColor(QColor c)
3102 void MapEditor::setMapLinkColorHintInt()
3104 // called from setMapLinkColorHint(lch) or at end of parse
3106 bo=mapCenter->first();
3114 void MapEditor::setMapLinkColorHint(LinkableMapObj::ColorHint lch)
3117 setMapLinkColorHintInt();
3120 void MapEditor::toggleMapLinkColorHint()
3122 if (linkcolorhint==LinkableMapObj::HeadingColor)
3123 linkcolorhint=LinkableMapObj::DefaultColor;
3125 linkcolorhint=LinkableMapObj::HeadingColor;
3127 bo=mapCenter->first();
3135 LinkableMapObj::ColorHint MapEditor::getMapLinkColorHint()
3137 return linkcolorhint;
3140 QColor MapEditor::getMapDefLinkColor()
3142 return defLinkColor;
3145 void MapEditor::setMapDefXLinkColor(QColor col)
3150 QColor MapEditor::getMapDefXLinkColor()
3152 return defXLinkColor;
3155 void MapEditor::setMapDefXLinkWidth (int w)
3160 int MapEditor::getMapDefXLinkWidth()
3162 return defXLinkWidth;
3165 void MapEditor::selectMapLinkColor()
3167 QColor col = QColorDialog::getColor( defLinkColor, this );
3168 if ( !col.isValid() ) return;
3171 QString("setMapDefLinkColor (\"%1\")").arg(getMapDefLinkColor().name()),
3173 QString("setMapDefLinkColor (\"%1\")").arg(col.name()),
3174 QString("Set link color to %1").arg(col.name())
3176 setMapDefLinkColor( col );
3179 void MapEditor::selectMapSelectionColor()
3181 QColor col = QColorDialog::getColor( defLinkColor, this );
3182 setSelectionColor (col);
3185 void MapEditor::setSelectionColorInt (QColor col)
3187 if ( !col.isValid() ) return;
3188 xelection.setColor (col);
3191 void MapEditor::setSelectionColor(QColor col)
3193 if ( !col.isValid() ) return;
3196 QString("setSelectionColor (%1)").arg(xelection.getColor().name()),
3198 QString("setSelectionColor (%1)").arg(col.name()),
3199 QString("Set color of selection box to %1").arg(col.name())
3201 setSelectionColorInt (col);
3204 QColor MapEditor::getSelectionColor()
3206 return xelection.getColor();
3209 bool MapEditor::scrollBranch(BranchObj *bo)
3213 if (bo->isScrolled()) return false;
3214 if (bo->countBranches()==0) return false;
3215 if (bo->getDepth()==0) return false;
3221 QString ("%1 ()").arg(u),
3223 QString ("%1 ()").arg(r),
3224 QString ("%1 %2").arg(r).arg(getName(bo))
3233 bool MapEditor::unscrollBranch(BranchObj *bo)
3237 if (!bo->isScrolled()) return false;
3238 if (bo->countBranches()==0) return false;
3239 if (bo->getDepth()==0) return false;
3245 QString ("%1 ()").arg(u),
3247 QString ("%1 ()").arg(r),
3248 QString ("%1 %2").arg(r).arg(getName(bo))
3257 void MapEditor::toggleScroll()
3259 BranchObj *bo=xelection.getBranch();
3260 if (xelection.type()==Branch )
3262 if (bo->isScrolled())
3263 unscrollBranch (bo);
3269 void MapEditor::unscrollChilds()
3271 BranchObj *bo=xelection.getBranch();
3277 if (bo->isScrolled()) unscrollBranch (bo);
3283 FloatImageObj* MapEditor::loadFloatImageInt (QString fn)
3285 BranchObj *bo=xelection.getBranch();
3289 bo->addFloatImage();
3290 fio=bo->getLastFloatImage();
3292 mapCenter->reposition();
3299 void MapEditor::loadFloatImage ()
3301 BranchObj *bo=xelection.getBranch();
3305 Q3FileDialog *fd=new Q3FileDialog( this);
3306 fd->setMode (Q3FileDialog::ExistingFiles);
3307 fd->addFilter (QString (tr("Images") + " (*.png *.bmp *.xbm *.jpg *.png *.xpm *.gif *.pnm)"));
3308 ImagePreview *p =new ImagePreview (fd);
3309 fd->setContentsPreviewEnabled( TRUE );
3310 fd->setContentsPreview( p, p );
3311 fd->setPreviewMode( Q3FileDialog::Contents );
3312 fd->setCaption(vymName+" - " +tr("Load image"));
3313 fd->setDir (lastImageDir);
3316 if ( fd->exec() == QDialog::Accepted )
3318 // FIXME loadFIO in QT4 use: lastImageDir=fd->directory();
3319 lastImageDir=QDir (fd->dirPath());
3322 for (int j=0; j<fd->selectedFiles().count(); j++)
3324 s=fd->selectedFiles().at(j);
3325 fio=loadFloatImageInt (s);
3328 (LinkableMapObj*)fio,
3331 QString ("loadImage (%1)").arg(s ),
3332 QString("Add image %1 to %2").arg(s).arg(getName(bo))
3335 // FIXME loadFIO error handling
3336 qWarning ("Failed to load "+s);
3344 void MapEditor::saveFloatImageInt (FloatImageObj *fio, const QString &type, const QString &fn)
3346 fio->save (fn,type);
3349 void MapEditor::saveFloatImage ()
3351 FloatImageObj *fio=xelection.getFloatImage();
3354 QFileDialog *fd=new QFileDialog( this);
3355 fd->setFilters (imageIO.getFilters());
3356 fd->setCaption(vymName+" - " +tr("Save image"));
3357 fd->setFileMode( QFileDialog::AnyFile );
3358 fd->setDirectory (lastImageDir);
3359 // fd->setSelection (fio->getOriginalFilename());
3363 if ( fd->exec() == QDialog::Accepted && fd->selectedFiles().count()==1)
3365 fn=fd->selectedFiles().at(0);
3366 if (QFile (fn).exists() )
3368 QMessageBox mb( vymName,
3369 tr("The file %1 exists already.\n"
3370 "Do you want to overwrite it?").arg(fn),
3371 QMessageBox::Warning,
3372 QMessageBox::Yes | QMessageBox::Default,
3373 QMessageBox::Cancel | QMessageBox::Escape,
3374 QMessageBox::QMessageBox::NoButton );
3376 mb.setButtonText( QMessageBox::Yes, tr("Overwrite") );
3377 mb.setButtonText( QMessageBox::No, tr("Cancel"));
3380 case QMessageBox::Yes:
3383 case QMessageBox::Cancel:
3390 saveFloatImageInt (fio,fd->selectedFilter(),fn );
3396 void MapEditor::setFrameType(const FrameObj::FrameType &t)
3398 BranchObj *bo=xelection.getBranch();
3401 QString s=bo->getFrameTypeName();
3402 bo->setFrameType (t);
3403 saveState (bo, QString("setFrameType (\"%1\")").arg(s),
3404 bo, QString ("setFrameType (\"%1\")").arg(bo->getFrameTypeName()),QString ("set type of frame to %1").arg(s));
3405 mapCenter->reposition();
3410 void MapEditor::setFrameType(const QString &s)
3412 BranchObj *bo=xelection.getBranch();
3415 saveState (bo, QString("setFrameType (\"%1\")").arg(bo->getFrameTypeName()),
3416 bo, QString ("setFrameType (\"%1\")").arg(s),QString ("set type of frame to %1").arg(s));
3417 bo->setFrameType (s);
3418 mapCenter->reposition();
3423 void MapEditor::setFramePenColor(const QColor &c)
3425 BranchObj *bo=xelection.getBranch();
3428 saveState (bo, QString("setFramePenColor (\"%1\")").arg(bo->getFramePenColor().name() ),
3429 bo, QString ("setFramePenColor (\"%1\")").arg(c.name() ),QString ("set pen color of frame to %1").arg(c.name() ));
3430 bo->setFramePenColor (c);
3434 void MapEditor::setFrameBrushColor(const QColor &c)
3436 BranchObj *bo=xelection.getBranch();
3439 saveState (bo, QString("setFrameBrushColor (\"%1\")").arg(bo->getFrameBrushColor().name() ),
3440 bo, QString ("setFrameBrushColor (\"%1\")").arg(c.name() ),QString ("set brush color of frame to %1").arg(c.name() ));
3441 bo->setFrameBrushColor (c);
3445 void MapEditor::setFramePadding (const int &)
3447 BranchObj *bo=xelection.getBranch();
3451 saveState (bo, QString("setFrameBrushColor (\"%1\")").arg(bo->getFrameBrushColor().name() ),
3452 bo, QString ("setFrameBrushColor (\"%1\")").arg(c.name() ),QString ("set brush color of frame to %1").arg(c.name() ));
3453 bo->setFrameBrushColor (c);
3458 void MapEditor::setFrameBorderWidth(const int &)
3460 BranchObj *bo=xelection.getBranch();
3464 saveState (bo, QString("setFrameBrushColor (\"%1\")").arg(bo->getFrameBrushColor().name() ),
3465 bo, QString ("setFrameBrushColor (\"%1\")").arg(c.name() ),QString ("set brush color of frame to %1").arg(c.name() ));
3466 bo->setFrameBrushColor (c);
3471 void MapEditor::setIncludeImagesVer(bool b)
3473 BranchObj *bo=xelection.getBranch();
3476 QString u= b ? "false" : "true";
3477 QString r=!b ? "false" : "true";
3481 QString("setIncludeImagesVertically (%1)").arg(u),
3483 QString("setIncludeImagesVertically (%1)").arg(r),
3484 QString("Include images vertically in %1").arg(getName(bo))
3486 bo->setIncludeImagesVer(b);
3487 mapCenter->reposition();
3491 void MapEditor::setIncludeImagesHor(bool b)
3493 BranchObj *bo=xelection.getBranch();
3496 QString u= b ? "false" : "true";
3497 QString r=!b ? "false" : "true";
3501 QString("setIncludeImagesHorizontally (%1)").arg(u),
3503 QString("setIncludeImagesHorizontally (%1)").arg(r),
3504 QString("Include images horizontally in %1").arg(getName(bo))
3506 bo->setIncludeImagesHor(b);
3507 mapCenter->reposition();
3511 void MapEditor::setHideLinkUnselected (bool b) // FIXME missing saveState
3513 LinkableMapObj *sel=xelection.single();
3515 (xelection.type() == Branch ||
3516 xelection.type() == MapCenter ||
3517 xelection.type() == FloatImage ))
3518 sel->setHideLinkUnselected(b);
3521 void MapEditor::importDirInt(BranchObj *dst, QDir d) // FIXME missing saveState
3523 BranchObj *bo=xelection.getBranch();
3526 // Traverse directories
3527 d.setFilter( QDir::Dirs| QDir::Hidden | QDir::NoSymLinks );
3528 QFileInfoList list = d.entryInfoList();
3531 for (int i = 0; i < list.size(); ++i)
3534 if (fi.fileName() != "." && fi.fileName() != ".." )
3537 bo=dst->getLastBranch();
3538 bo->setHeading (fi.fileName() );
3539 bo->setColor (QColor("blue"));
3541 if ( !d.cd(fi.fileName()) )
3542 QMessageBox::critical (0,tr("Critical Import Error"),tr("Cannot find the directory %1").arg(fi.fileName()));
3545 // Recursively add subdirs
3546 importDirInt (bo,d);
3552 d.setFilter( QDir::Files| QDir::Hidden | QDir::NoSymLinks );
3553 list = d.entryInfoList();
3555 for (int i = 0; i < list.size(); ++i)
3559 bo=dst->getLastBranch();
3560 bo->setHeading (fi.fileName() );
3561 bo->setColor (QColor("black"));
3562 if (fi.fileName().right(4) == ".vym" )
3563 bo->setVymLink (fi.filePath());
3568 void MapEditor::importDir()
3570 BranchObj *bo=xelection.getBranch();
3573 QStringList filters;
3574 filters <<"VYM map (*.vym)";
3575 QFileDialog *fd=new QFileDialog( this,vymName+ " - " +tr("Choose directory structure to import"));
3576 fd->setMode (QFileDialog::DirectoryOnly);
3577 fd->setFilters (filters);
3578 fd->setCaption(vymName+" - " +tr("Choose directory structure to import"));
3582 if ( fd->exec() == QDialog::Accepted )
3584 importDirInt (bo,QDir(fd->selectedFile()) );
3585 mapCenter->reposition();
3591 void MapEditor::followXLink(int i)
3593 BranchObj *bo=xelection.getBranch();
3596 bo=bo->XLinkTargetAt(i);
3599 xelection.select(bo);
3600 ensureSelectionVisible();
3605 void MapEditor::editXLink(int i) // FIXME missing saveState
3607 BranchObj *bo=xelection.getBranch();
3610 XLinkObj *xlo=bo->XLinkAt(i);
3613 EditXLinkDialog dia;
3615 dia.setSelection(bo);
3616 if (dia.exec() == QDialog::Accepted)
3618 if (dia.useSettingsGlobal() )
3620 setMapDefXLinkColor (xlo->getColor() );
3621 setMapDefXLinkWidth (xlo->getWidth() );
3623 if (dia.deleteXLink())
3624 bo->deleteXLinkAt(i);
3630 void MapEditor::testFunction()
3632 // This is the playground
3634 BranchObj *bo=xelection.getBranch();
3635 if (bo) animObjList.append( bo );
3639 dia.showCancelButton (true);
3640 dia.setText("This is a longer \nWarning");
3641 dia.setCaption("Warning: Flux problem");
3642 dia.setShowAgainName("mapeditor/testDialog");
3643 if (dia.exec()==QDialog::Accepted)
3644 cout << "accepted!\n";
3646 cout << "canceled!\n";
3650 /* TODO Hide hidden stuff temporary, maybe add this as regular function somewhere
3651 if (hidemode==HideNone)
3653 setHideTmpMode (HideExport);
3654 mapCenter->calcBBoxSizeWithChilds();
3655 QRectF totalBBox=mapCenter->getTotalBBox();
3656 QRectF mapRect=totalBBox;
3657 QCanvasRectangle *frame=NULL;
3659 cout << " map has =("<<totalBBox.x()<<","<<totalBBox.y()<<","<<totalBBox.width()<<","<<totalBBox.height()<<")\n";
3661 mapRect.setRect (totalBBox.x(), totalBBox.y(),
3662 totalBBox.width(), totalBBox.height());
3663 frame=new QCanvasRectangle (mapRect,mapScene);
3664 frame->setBrush (QColor(white));
3665 frame->setPen (QColor(black));
3666 frame->setZValue(0);
3671 setHideTmpMode (HideNone);
3673 cout <<" hidemode="<<hidemode<<endl;
3677 void MapEditor::contextMenuEvent ( QContextMenuEvent * e )
3679 // Lineedits are already closed by preceding
3680 // mouseEvent, we don't need to close here.
3682 QPointF p = mapToScene(e->pos());
3683 LinkableMapObj* lmo=mapCenter->findMapObj(p, NULL);
3686 { // MapObj was found
3687 if (xelection.single() != lmo)
3689 // select the MapObj
3690 xelection.select(lmo);
3693 if (xelection.getBranch() )
3695 // Context Menu on branch or mapcenter
3697 branchContextMenu->popup(e->globalPos() );
3700 if (xelection.getFloatImage() )
3702 // Context Menu on floatimage
3704 floatimageContextMenu->popup(e->globalPos() );
3708 { // No MapObj found, we are on the Canvas itself
3709 // Context Menu on scene
3711 canvasContextMenu->popup(e->globalPos() );
3716 void MapEditor::keyPressEvent(QKeyEvent* e)
3718 if (e->modifiers() & Qt::ControlModifier)
3720 switch (mainWindow->getModMode())
3722 case Main::ModModeColor:
3723 setCursor (PickColorCursor);
3725 case Main::ModModeCopy:
3726 setCursor (CopyCursor);
3728 case Main::ModModeXLink:
3729 setCursor (XLinkCursor);
3732 setCursor (Qt::ArrowCursor);
3738 void MapEditor::keyReleaseEvent(QKeyEvent* e)
3740 if (!(e->modifiers() & Qt::ControlModifier))
3741 setCursor (Qt::ArrowCursor);
3744 void MapEditor::mousePressEvent(QMouseEvent* e)
3746 // Ignore right clicks, these will go to context menus
3747 if (e->button() == Qt::RightButton )
3753 QPointF p = mapToScene(e->pos());
3754 LinkableMapObj* lmo=mapCenter->findMapObj(p, NULL);
3758 //Take care of system flags _or_ modifier modes
3760 if (lmo && (typeid(*lmo)==typeid(BranchObj) ||
3761 typeid(*lmo)==typeid(MapCenterObj) ))
3763 QString foname=((BranchObj*)lmo)->getSystemFlagName(p);
3764 if (!foname.isEmpty())
3766 // systemFlag clicked
3770 if (e->state() & Qt::ControlModifier)
3771 mainWindow->editOpenURLTab();
3773 mainWindow->editOpenURL();
3775 else if (foname=="vymLink")
3777 mainWindow->editOpenVymLink();
3778 // tabWidget may change, better return now
3779 // before segfaulting...
3780 } else if (foname=="note")
3781 mainWindow->windowToggleNoteEditor();
3782 else if (foname=="hideInExport")
3789 // No system flag clicked, take care of modmodes (CTRL-Click)
3790 if (e->state() & Qt::ControlModifier)
3792 if (mainWindow->getModMode()==Main::ModModeColor)
3795 setCursor (PickColorCursor);
3798 if (mainWindow->getModMode()==Main::ModModeXLink)
3800 BranchObj *bo_begin=NULL;
3802 bo_begin=(BranchObj*)(lmo);
3804 if (xelection.getBranch() )
3805 bo_begin=xelection.getBranch();
3809 linkingObj_src=bo_begin;
3810 tmpXLink=new XLinkObj (mapScene);
3811 tmpXLink->setBegin (bo_begin);
3812 tmpXLink->setEnd (p);
3813 tmpXLink->setColor(defXLinkColor);
3814 tmpXLink->setWidth(defXLinkWidth);
3815 tmpXLink->updateXLink();
3816 tmpXLink->setVisibility (true);
3820 } // End of modmodes
3824 // Select the clicked object
3827 // Left Button Move Branches
3828 if (e->button() == Qt::LeftButton )
3830 //movingObj_start.setX( p.x() - selection->x() );// TODO replaced selection->lmo here
3831 //movingObj_start.setY( p.y() - selection->y() );
3832 movingObj_start.setX( p.x() - lmo->x() );
3833 movingObj_start.setY( p.y() - lmo->y() );
3834 movingObj_orgPos.setX (lmo->x() );
3835 movingObj_orgPos.setY (lmo->y() );
3836 movingObj_orgRelPos=lmo->getRelPos();
3838 // If modMode==copy, then we want to "move" the _new_ object around
3839 // then we need the offset from p to the _old_ selection, because of tmp
3840 if (mainWindow->getModMode()==Main::ModModeCopy &&
3841 e->state() & Qt::ControlModifier)
3843 if (xelection.type()==Branch)
3846 mapCenter->addBranch ((BranchObj*)xelection.single());
3848 xelection.select(mapCenter->getLastBranch());
3849 mapCenter->reposition();
3853 movingObj=xelection.single();
3855 // Middle Button Toggle Scroll
3856 // (On Mac OS X this won't work, but we still have
3857 // a button in the toolbar)
3858 if (e->button() == Qt::MidButton )
3863 { // No MapObj found, we are on the scene itself
3864 // Left Button move Pos of sceneView
3865 if (e->button() == Qt::LeftButton )
3867 movingObj=NULL; // move Content not Obj
3868 movingObj_start=e->globalPos();
3869 movingCont_start=QPointF (
3870 horizontalScrollBar()->value(),
3871 verticalScrollBar()->value());
3872 movingVec=QPointF(0,0);
3873 setCursor(HandOpenCursor);
3878 void MapEditor::mouseMoveEvent(QMouseEvent* e)
3880 QPointF p = mapToScene(e->pos());
3881 LinkableMapObj *lmosel=xelection.single();
3883 // Move the selected MapObj
3884 if ( lmosel && movingObj)
3886 // reset cursor if we are moving and don't copy
3887 if (mainWindow->getModMode()!=Main::ModModeCopy)
3888 setCursor (Qt::ArrowCursor);
3890 // To avoid jumping of the sceneView, only
3891 // ensureSelectionVisible, if not tmp linked
3892 if (!lmosel->hasParObjTmp())
3893 ensureSelectionVisible ();
3895 // Now move the selection, but add relative position
3896 // (movingObj_start) where selection was chosen with
3897 // mousepointer. (This avoids flickering resp. jumping
3898 // of selection back to absPos)
3900 // Check if we could link
3901 LinkableMapObj* lmo=mapCenter->findMapObj(p, lmosel);
3904 FloatObj *fio=xelection.getFloatImage();
3907 fio->move (p.x() -movingObj_start.x(), p.y()-movingObj_start.y() );
3909 fio->updateLink(); //no need for reposition, if we update link here
3912 // Relink float to new mapcenter or branch, if shift is pressed
3913 // Only relink, if selection really has a new parent
3914 if ( (e->modifiers()==Qt::ShiftModifier) && lmo &&
3915 ( (typeid(*lmo)==typeid(BranchObj)) ||
3916 (typeid(*lmo)==typeid(MapCenterObj)) ) &&
3917 ( lmo != fio->getParObj())
3920 if (typeid(*fio) == typeid(FloatImageObj) &&
3921 ( (typeid(*lmo)==typeid(BranchObj) ||
3922 typeid(*lmo)==typeid(MapCenterObj)) ))
3925 // Also save the move which was done so far
3926 QString pold=qpointfToString(movingObj_orgRelPos);
3927 QString pnow=qpointfToString(fio->getRelPos());
3933 QString("Move %1 to relativ position %2").arg(getName(fio)).arg(pnow));
3934 fio->getParObj()->requestReposition();
3935 mapCenter->reposition();
3937 linkTo (lmo->getSelectString());
3939 //movingObj_orgRelPos=lmosel->getRelPos();
3941 mapCenter->reposition();
3945 { // selection != a FloatObj
3946 if (lmosel->getDepth()==0)
3949 if (e->buttons()== Qt::LeftButton && e->modifiers()==Qt::ShiftModifier)
3950 mapCenter->moveAll(p.x() -movingObj_start.x(), p.y()-movingObj_start.y() );
3952 mapCenter->move (p.x() -movingObj_start.x(), p.y()-movingObj_start.y() );
3953 mapCenter->updateRelPositions();
3956 if (lmosel->getDepth()==1)
3959 lmosel->move(p.x() -movingObj_start.x(), p.y()-movingObj_start.y() );
3960 lmosel->setRelPos();
3963 // Move ordinary branch
3964 if (lmosel->getOrientation() == LinkableMapObj::LeftOfCenter)
3965 // Add width of bbox here, otherwise alignRelTo will cause jumping around
3966 lmosel->move(p.x() -movingObj_start.x()+lmosel->getBBox().width(),
3967 p.y()-movingObj_start.y() +lmosel->getTopPad() );
3969 lmosel->move(p.x() -movingObj_start.x(), p.y()-movingObj_start.y() -lmosel->getTopPad());
3972 // Maybe we can relink temporary?
3973 if (lmo && (lmo!=lmosel) && xelection.getBranch() &&
3974 (typeid(*lmo)==typeid(BranchObj) ||
3975 typeid(*lmo)==typeid(MapCenterObj)) )
3978 if (e->modifiers()==Qt::ControlModifier)
3980 // Special case: CTRL to link below lmo
3981 lmosel->setParObjTmp (lmo,p,+1);
3983 else if (e->modifiers()==Qt::ShiftModifier)
3984 lmosel->setParObjTmp (lmo,p,-1);
3986 lmosel->setParObjTmp (lmo,p,0);
3989 lmosel->unsetParObjTmp();
3991 // reposition subbranch
3992 lmosel->reposition();
3996 } // no FloatImageObj
4000 } // selection && moving_obj
4002 // Draw a link from one branch to another
4005 tmpXLink->setEnd (p);
4006 tmpXLink->updateXLink();
4010 if (!movingObj && !pickingColor &&!drawingLink && e->buttons() == Qt::LeftButton )
4012 QPointF p=e->globalPos();
4013 movingVec.setX(-p.x() + movingObj_start.x() );
4014 movingVec.setY(-p.y() + movingObj_start.y() );
4015 horizontalScrollBar()->setSliderPosition((int)( movingCont_start.x()+movingVec.x() ));
4016 verticalScrollBar()->setSliderPosition((int)( movingCont_start.y()+movingVec.y() ) );
4021 void MapEditor::mouseReleaseEvent(QMouseEvent* e)
4023 QPointF p = mapToScene(e->pos());
4024 LinkableMapObj *dst;
4025 LinkableMapObj *lmosel=xelection.single();
4026 // Have we been picking color?
4030 setCursor (Qt::ArrowCursor);
4031 // Check if we are over another branch
4032 dst=mapCenter->findMapObj(p, NULL);
4035 if (e->state() & Qt::ShiftModifier)
4036 colorBranch (((BranchObj*)(dst))->getColor());
4038 colorSubtree (((BranchObj*)(dst))->getColor());
4043 // Have we been drawing a link?
4044 if (drawingLink) //FIXME savestate missing
4047 // Check if we are over another branch
4048 dst=mapCenter->findMapObj(p, NULL);
4051 tmpXLink->setEnd ( ((BranchObj*)(dst)) );
4052 tmpXLink->updateXLink();
4053 tmpXLink->activate();
4054 //saveStateComplete(QString("Activate xLink from %1 to %2").arg(getName(tmpXLink->getBegin())).arg(getName(tmpXLink->getEnd())) );
4063 // Have we been moving something?
4064 if ( lmosel && movingObj )
4066 FloatImageObj *fo=xelection.getFloatImage();
4069 // Moved FloatObj. Maybe we need to reposition
4070 QString pold=qpointfToString(movingObj_orgRelPos);
4071 QString pnow=qpointfToString(fo->getRelPos());
4077 QString("Move %1 to relativ position %2").arg(getName(fo)).arg(pnow));
4079 fo->getParObj()->requestReposition();
4080 mapCenter->reposition();
4083 // Check if we are over another branch, but ignore
4084 // any found LMOs, which are FloatObjs
4085 dst=mapCenter->findMapObj(mapToScene(e->pos() ), lmosel);
4087 if (dst && (typeid(*dst)!=typeid(BranchObj) && typeid(*dst)!=typeid(MapCenterObj)))
4090 if (xelection.type() == MapCenter )
4091 { // FIXME The MapCenter was moved, no savestate yet
4094 if (xelection.type() == Branch )
4095 { // A branch was moved
4097 // save the position in case we link to mapcenter
4098 QPointF savePos=QPointF (lmosel->getAbsPos() );
4100 // Reset the temporary drawn link to the original one
4101 lmosel->unsetParObjTmp();
4103 // For Redo we may need to save original selection
4104 QString preSelStr=lmosel->getSelectString();
4109 BranchObj* bsel=xelection.getBranch();
4110 BranchObj* bdst=(BranchObj*)dst;
4112 QString preParStr=(bsel->getParObj())->getSelectString();
4113 QString preNum=QString::number (bsel->getNum(),10);
4114 QString preDstParStr;
4116 if (e->state() & Qt::ShiftModifier && dst->getParObj())
4118 preDstParStr=dst->getParObj()->getSelectString();
4119 bsel->linkTo ( (BranchObj*)(bdst->getParObj()), bdst->getNum());
4121 if (e->state() & Qt::ControlModifier && dst->getParObj())
4124 preDstParStr=dst->getParObj()->getSelectString();
4125 bsel->linkTo ( (BranchObj*)(bdst->getParObj()), bdst->getNum()+1);
4128 preDstParStr=dst->getSelectString();
4129 bsel->linkTo (bdst,-1);
4130 if (dst->getDepth()==0) bsel->move (savePos);
4132 QString postSelStr=lmosel->getSelectString();
4133 QString postNum=QString::number (bsel->getNum(),10);
4135 QString undoCom="linkTo (\""+
4136 preParStr+ "\"," + preNum +"," +
4137 QString ("%1,%2").arg(movingObj_orgPos.x()).arg(movingObj_orgPos.y())+ ")";
4139 QString redoCom="linkTo (\""+
4140 preDstParStr + "\"," + postNum + "," +
4141 QString ("%1,%2").arg(savePos.x()).arg(savePos.y())+ ")";
4146 QString("Relink %1 to %2").arg(getName(bsel)).arg(getName(dst)) );
4148 if (lmosel->getDepth()==1)
4150 // The select string might be different _after_ moving around.
4151 // Therefor reposition and then use string of old selection, too
4152 mapCenter->reposition();
4154 QString ps=qpointfToString ( lmosel->getRelPos() );
4156 lmosel->getSelectString(), "moveRel "+qpointfToString(movingObj_orgRelPos),
4157 preSelStr, "moveRel "+ps,
4158 QString("Move %1 to relative position %2").arg(getName(lmosel)).arg(ps));
4161 // Draw the original link, before selection was moved around
4162 mapCenter->reposition();
4165 // Finally resize scene, if needed
4169 // Just make sure, that actions are still ok,e.g. the move branch up/down buttons...
4172 // maybe we moved View: set old cursor
4173 setCursor (Qt::ArrowCursor);
4177 void MapEditor::mouseDoubleClickEvent(QMouseEvent* e)
4179 if (e->button() == Qt::LeftButton )
4181 QPointF p = mapToScene(e->pos());
4182 LinkableMapObj *lmo=mapCenter->findMapObj(p, NULL);
4183 if (lmo) { // MapObj was found
4184 // First select the MapObj than edit heading
4185 xelection.select(lmo);
4186 mainWindow->editHeading();
4191 void MapEditor::resizeEvent (QResizeEvent* e)
4193 QGraphicsView::resizeEvent( e );
4196 void MapEditor::dragEnterEvent(QDragEnterEvent *event)
4198 //for (unsigned int i=0;event->format(i);i++) // Debug mime type
4199 // cerr << event->format(i) << endl;
4201 if (event->mimeData()->hasImage())
4202 event->acceptProposedAction();
4204 if (event->mimeData()->hasUrls())
4205 event->acceptProposedAction();
4208 void MapEditor::dragMoveEvent(QDragMoveEvent *event)
4212 void MapEditor::dragLeaveEvent(QDragLeaveEvent *event)
4217 void MapEditor::dropEvent(QDropEvent *event)
4219 BranchObj *sel=xelection.getBranch();
4223 if (event->mimeData()->hasImage())
4225 QVariant imageData = event->mimeData()->imageData();
4226 addFloatImageInt (qvariant_cast<QPixmap>(imageData));
4228 if (event->mimeData()->hasUrls())
4229 uris=event->mimeData()->urls();
4237 for (int i=0; i<uris.count();i++)
4239 // Workaround to avoid adding empty branches
4240 if (!uris.at(i).toString().isEmpty())
4242 bo=sel->addBranch();
4245 s=uris.at(i).toLocalFile();
4248 QString file = QDir::convertSeparators(s);
4249 heading = QFileInfo(file).baseName();
4251 if (file.endsWith(".vym", false))
4252 bo->setVymLink(file);
4254 bo->setURL(uris.at(i).toString());
4257 bo->setURL(uris.at(i).toString());
4260 if (!heading.isEmpty())
4261 bo->setHeading(heading);
4263 bo->setHeading(uris.at(i).toString());
4267 mapCenter->reposition();
4270 event->acceptProposedAction();
4273 void MapEditor::timerEvent(QTimerEvent *event) //FIXME testing
4277 cout << "ME::timerEvent\n";
4279 for (int i=0; i<animObjList.size(); ++i)
4281 animObjList.at(i)->animate();
4282 ((BranchObj*)animObjList.at(i))->move2RelPos (((BranchObj*)animObjList.at(i))->getRelPos() );
4284 mapCenter->reposition();
4287 void MapEditor::autosave()
4289 if (mapUnsaved &&mapChanged && settings.value ("/mapeditor/autosave/used",true).toBool() )
4290 mainWindow->fileSave (this);
4294 /*FIXME not needed? void MapEditor::contentsDropEvent(QDropEvent *event)
4297 } else if (event->provides("application/x-moz-file-promise-url") &&
4298 event->provides("application/x-moz-nativeimage"))
4300 // Contains url to the img src in unicode16
4301 QByteArray d = event->encodedData("application/x-moz-file-promise-url");
4302 QString url = QString((const QChar*)d.data(),d.size()/2);
4306 } else if (event->provides ("text/uri-list"))
4307 { // Uris provided e.g. by konqueror
4308 Q3UriDrag::decode (event,uris);
4309 } else if (event->provides ("_NETSCAPE_URL"))
4310 { // Uris provided by Mozilla
4311 QStringList l = QStringList::split("\n", event->encodedData("_NETSCAPE_URL"));
4314 } else if (event->provides("text/html")) {
4316 // Handels text mime types
4317 // Look like firefox allways handle text as unicode16 (2 bytes per char.)
4318 QByteArray d = event->encodedData("text/html");
4321 text = QString((const QChar*)d.data(),d.size()/2);
4325 textEditor->setText(text);
4329 } else if (event->provides("text/plain")) {
4330 QByteArray d = event->encodedData("text/plain");
4333 text = QString((const QChar*)d.data(),d.size()/2);
4337 textEditor->setText(text);
4347 bool isUnicode16(const QByteArray &d)
4349 // TODO: make more precise check for unicode 16.
4350 // Guess unicode16 if any of second bytes are zero
4351 unsigned int length = max(0,d.size()-2)/2;
4352 for (unsigned int i = 0; i<length ; i++)
4353 if (d.at(i*2+1)==0) return true;
4357 void MapEditor::addFloatImageInt (const QPixmap &img)
4359 BranchObj *bo=xelection.getBranch();
4362 FloatImageObj *fio=bo->addFloatImage();
4364 fio->setOriginalFilename("Image added by Drag and Drop"); // FIXME savestate
4365 mapCenter->reposition();
4372 void MapEditor::imageDataFetched(const QByteArray &a, Q3NetworkOperation * / *nop* /)
4374 if (!imageBuffer) imageBuffer = new QBuffer();
4375 if (!imageBuffer->isOpen()) {
4376 imageBuffer->open(QIODevice::WriteOnly | QIODevice::Append);
4378 imageBuffer->at(imageBuffer->at()+imageBuffer->writeBlock(a));
4382 void MapEditor::imageDataFinished(Q3NetworkOperation *nop)
4384 if (nop->state()==Q3NetworkProtocol::StDone) {
4385 QPixmap img(imageBuffer->buffer());
4386 addFloatImageInt (img);
4390 imageBuffer->close();
4392 imageBuffer->close();
4399 void MapEditor::fetchImage(const QString &url)
4402 urlOperator->stop();
4403 disconnect(urlOperator);
4407 urlOperator = new Q3UrlOperator(url);
4408 connect(urlOperator, SIGNAL(finished(Q3NetworkOperation *)),
4409 this, SLOT(imageDataFinished(Q3NetworkOperation*)));
4411 connect(urlOperator, SIGNAL(data(const QByteArray &, Q3NetworkOperation *)),
4412 this, SLOT(imageDataFetched(const QByteArray &, Q3NetworkOperation *)));