3 #include <q3filedialog.h>
12 #include "editxlinkdialog.h"
14 #include "extrainfodialog.h"
16 #include "linkablemapobj.h"
17 #include "mainwindow.h"
19 #include "texteditor.h"
20 #include "warningdialog.h"
24 extern TextEditor *textEditor;
25 extern int statusbarTime;
26 extern Main *mainWindow;
27 extern QString tmpVymDir;
28 extern QString clipboardDir;
29 extern QString clipboardFile;
30 extern bool clipboardEmpty;
32 extern FlagRowObj *standardFlagsDefault;
34 extern QMenu* branchContextMenu;
35 extern QMenu* branchAddContextMenu;
36 extern QMenu* branchRemoveContextMenu;
37 extern QMenu* branchLinksContextMenu;
38 extern QMenu* branchXLinksContextMenuEdit;
39 extern QMenu* branchXLinksContextMenuFollow;
40 extern QMenu* floatimageContextMenu;
41 extern QMenu* canvasContextMenu;
44 extern Settings settings;
45 extern ImageIO imageIO;
47 extern QString vymName;
48 extern QString vymVersion;
50 extern QString iconPath;
51 extern QDir vymBaseDir;
52 extern QDir lastImageDir;
53 extern QDir lastFileDir;
55 int MapEditor::mapNum=0; // make instance
57 ///////////////////////////////////////////////////////////////////////
58 ///////////////////////////////////////////////////////////////////////
59 MapEditor::MapEditor( QWidget* parent) :
62 //cout << "Constructor ME "<<this<<endl;
66 mapScene= new QGraphicsScene(parent);
67 //mapScene= new QGraphicsScene(QRectF(0,0,width(),height()), parent);
68 mapScene->setBackgroundBrush (QBrush(Qt::white, Qt::SolidPattern));
73 mapCenter = new MapCenterObj(mapScene);
74 mapCenter->setVisibility (true);
75 mapCenter->setMapEditor (this);
76 mapCenter->setHeading (tr("New Map","Heading of mapcenter in new map"));
77 //mapCenter->move(mapScene->width()/2-mapCenter->width()/2,mapScene->height()/2-mapCenter->height()/2);
82 defLinkColor=QColor (0,0,255);
83 defXLinkColor=QColor (180,180,180);
84 linkcolorhint=LinkableMapObj::DefaultColor;
85 linkstyle=LinkableMapObj::PolyParabel;
87 // Create bitmap cursors, platform dependant
88 HandOpenCursor=QCursor (QPixmap(iconPath+"cursorhandopen.png"),1,1);
89 PickColorCursor=QCursor ( QPixmap(iconPath+"cursorcolorpicker.png"), 5,27 );
90 CopyCursor=QCursor ( QPixmap(iconPath+"cursorcopy.png"), 1,1 );
91 XLinkCursor=QCursor ( QPixmap(iconPath+"cursorxlink.png"), 1,7 );
93 setFocusPolicy (Qt::StrongFocus);
102 xelection.setMapEditor (this);
103 xelection.unselect();
106 defXLinkColor=QColor (230,230,230);
114 fileName=tr("unnamed");
117 stepsTotal=settings.readNumEntry("/mapeditor/stepsTotal",100);
118 undoSet.setEntry ("/history/stepsTotal",QString::number(stepsTotal));
119 mainWindow->updateHistory (undoSet);
121 // Initialize find routine
128 blockReposition=false;
129 blockSaveState=false;
131 hidemode=BranchObj::HideNone;
133 // Create temporary files
140 setAcceptDrops (true);
142 mapCenter->reposition(); // for positioning heading
146 //timerId = startTimer(100);
149 autosaveTimer=new QTimer (this);
150 connect(autosaveTimer, SIGNAL(timeout()), this, SLOT(autosave()));
153 MapEditor::~MapEditor()
155 //cout <<"Destructor MapEditor\n";
156 autosaveTimer->stop();
159 MapCenterObj* MapEditor::getMapCenter()
164 QGraphicsScene * MapEditor::getScene()
169 MapEditor::State MapEditor::getState()
174 void MapEditor::setStateEditHeading(bool s)
178 if (state==Idle) state=EditHeading;
184 bool MapEditor::isRepositionBlocked()
186 return blockReposition;
189 void MapEditor::setSaveStateBlocked(bool b)
194 bool MapEditor::isSelectBlocked()
196 if (state==EditHeading)
202 QString MapEditor::getName (const LinkableMapObj *lmo)
205 if (!lmo) return QString("Error: NULL has no name!");
207 if ((typeid(*lmo) == typeid(BranchObj) ||
208 typeid(*lmo) == typeid(MapCenterObj)))
211 s=(((BranchObj*)lmo)->getHeading());
212 if (s=="") s="unnamed";
213 return QString("branch (%1)").arg(s);
214 //return QString("branch (<font color=\"#0000ff\">%1</font>)").arg(s);
216 if ((typeid(*lmo) == typeid(FloatImageObj) ))
217 return QString ("floatimage [%1]").arg(((FloatImageObj*)lmo)->getOriginalFilename());
218 //return QString ("floatimage [<font color=\"#0000ff\">%1</font>]").arg(((FloatImageObj*)lmo)->getOriginalFilename());
219 return QString("Unknown type has no name!");
222 void MapEditor::makeTmpDirs()
224 // Create unique temporary directories
225 tmpMapDir=QDir::convertSeparators (tmpVymDir+QString("/mapeditor-%1").arg(mapNum));
226 histPath=QDir::convertSeparators (tmpMapDir+"/history");
231 QString MapEditor::saveToDir(const QString &tmpdir, const QString &prefix, bool writeflags, const QPointF &offset, LinkableMapObj *saveSel)
233 // tmpdir temporary directory to which data will be written
234 // prefix mapname, which will be appended to images etc.
235 // writeflags Only write flags for "real" save of map, not undo
236 // offset offset of bbox of whole map in scene.
237 // Needed for XML export
243 case LinkableMapObj::Line:
246 case LinkableMapObj::Parabel:
249 case LinkableMapObj::PolyLine:
253 ls="StylePolyParabel";
257 QString s="<?xml version=\"1.0\" encoding=\"utf-8\"?><!DOCTYPE vymmap>\n";
259 if (linkcolorhint==LinkableMapObj::HeadingColor)
260 colhint=attribut("linkColorHint","HeadingColor");
262 QString mapAttr=attribut("version",vymVersion);
263 if (!saveSel || saveSel==mapCenter)
264 mapAttr+= attribut("author",mapCenter->getAuthor()) +
265 attribut("comment",mapCenter->getComment()) +
266 attribut("date",mapCenter->getDate()) +
267 attribut("backgroundColor", mapScene->backgroundBrush().color().name() ) +
268 attribut("selectionColor", xelection.getColor().name() ) +
269 attribut("linkStyle", ls ) +
270 attribut("linkColor", defLinkColor.name() ) +
271 attribut("defXLinkColor", defXLinkColor.name() ) +
272 attribut("defXLinkWidth", QString().setNum(defXLinkWidth,10) ) +
274 s+=beginElement("vymmap",mapAttr);
277 // Find the used flags while traversing the tree
278 standardFlagsDefault->resetUsedCounter();
280 // Reset the counters before saving
281 // TODO constr. of FIO creates lots of objects, better do this in some other way...
282 FloatImageObj (mapScene).resetSaveCounter();
284 // Build xml recursivly
285 if (!saveSel || typeid (*saveSel) == typeid (MapCenterObj))
286 // Save complete map, if saveSel not set
287 s+=mapCenter->saveToDir(tmpdir,prefix,writeflags,offset);
290 if ( typeid(*saveSel) == typeid(BranchObj) )
292 s+=((BranchObj*)(saveSel))->saveToDir(tmpdir,prefix,offset);
293 else if ( typeid(*saveSel) == typeid(FloatImageObj) )
295 s+=((FloatImageObj*)(saveSel))->saveToDir(tmpdir,prefix);
298 // Save local settings
299 s+=settings.getXMLData (destPath);
302 if (!xelection.isEmpty() && !saveSel )
303 s+=valueElement("select",xelection.getSelectString());
306 s+=endElement("vymmap");
309 standardFlagsDefault->saveToDir (tmpdir+"/flags/","",writeflags);
313 QString MapEditor::getHistoryDir()
315 QString histName=QDir::convertSeparators (QString("history-%1").arg(curStep));
316 return QDir::convertSeparators (tmpMapDir +"/"+histName);
319 void MapEditor::saveState(const SaveMode &savemode, const QString &undoSelection, const QString &undoCom, const QString &redoSelection, const QString &redoCom, const QString &comment, LinkableMapObj *saveSel)
323 if (blockSaveState) return;
325 if (debug) cout << "ME::saveState() for "<<mapName.ascii()<<endl;
327 // Find out current undo directory
328 if (undosAvail<stepsTotal) undosAvail++;
330 if (curStep>stepsTotal) curStep=1;
332 QString backupXML="";
333 QString histDir=getHistoryDir();
334 QString bakMapPath=QDir::convertSeparators(histDir+"/map.xml");
336 // Create histDir if not available
339 makeSubDirs (histDir);
341 // Save depending on how much needs to be saved
343 backupXML=saveToDir (histDir,mapName+"-",false, QPointF (),saveSel);
345 QString undoCommand="";
346 if (savemode==UndoCommand)
350 else if (savemode==PartOfMap )
353 undoCommand.replace ("PATH",bakMapPath);
356 if (!backupXML.isEmpty())
357 // Write XML Data to disk
358 saveStringToDisk (QString(bakMapPath),backupXML);
360 // We would have to save all actions in a tree, to keep track of
361 // possible redos after a action. Possible, but we are too lazy: forget about redos.
364 // Write the current state to disk
365 undoSet.setEntry ("/history/undosAvail",QString::number(undosAvail));
366 undoSet.setEntry ("/history/redosAvail",QString::number(redosAvail));
367 undoSet.setEntry ("/history/curStep",QString::number(curStep));
368 undoSet.setEntry (QString("/history/step-%1/undoCommand").arg(curStep),undoCommand);
369 undoSet.setEntry (QString("/history/step-%1/undoSelection").arg(curStep),undoSelection);
370 undoSet.setEntry (QString("/history/step-%1/redoCommand").arg(curStep),redoCom);
371 undoSet.setEntry (QString("/history/step-%1/redoSelection").arg(curStep),redoSelection);
372 undoSet.setEntry (QString("/history/step-%1/comment").arg(curStep),comment);
373 undoSet.setEntry (QString("/history/version"),vymVersion);
374 undoSet.writeSettings(histPath);
378 // TODO remove after testing
379 //cout << " into="<< histPath.toStdString()<<endl;
380 cout << " stepsTotal="<<stepsTotal<<
381 ", undosAvail="<<undosAvail<<
382 ", redosAvail="<<redosAvail<<
383 ", curStep="<<curStep<<endl;
384 cout << " ---------------------------"<<endl;
385 cout << " comment="<<comment.toStdString()<<endl;
386 cout << " undoCom="<<undoCommand.toStdString()<<endl;
387 cout << " undoSel="<<undoSelection.toStdString()<<endl;
388 cout << " redoCom="<<redoCom.toStdString()<<endl;
389 cout << " redoSel="<<redoSelection.toStdString()<<endl;
390 if (saveSel) cout << " saveSel="<<saveSel->getSelectString().ascii()<<endl;
391 cout << " ---------------------------"<<endl;
394 mainWindow->updateHistory (undoSet);
400 void MapEditor::saveStateChangingPart(LinkableMapObj *undoSel, LinkableMapObj* redoSel, const QString &rc, const QString &comment)
402 // save the selected part of the map, Undo will replace part of map
403 QString undoSelection="";
405 undoSelection=undoSel->getSelectString();
407 qWarning ("MapEditor::saveStateChangingPart no undoSel given!");
408 QString redoSelection="";
410 redoSelection=undoSel->getSelectString();
412 qWarning ("MapEditor::saveStateChangingPart no redoSel given!");
415 saveState (PartOfMap,
416 undoSelection, "addMapReplace (\"PATH\")",
422 void MapEditor::saveStateRemovingPart(LinkableMapObj *redoSel, const QString &comment)
426 qWarning ("MapEditor::saveStateRemovingPart no redoSel given!");
429 QString undoSelection=redoSel->getParObj()->getSelectString();
430 QString redoSelection=redoSel->getSelectString();
431 if (typeid(*redoSel) == typeid(BranchObj) )
433 // save the selected branch of the map, Undo will insert part of map
434 saveState (PartOfMap,
435 undoSelection, QString("addMapInsert (\"PATH\",%1)").arg(((BranchObj*)redoSel)->getNum()),
436 redoSelection, "delete ()",
443 void MapEditor::saveState(LinkableMapObj *undoSel, const QString &uc, LinkableMapObj *redoSel, const QString &rc, const QString &comment)
445 // "Normal" savestate: save commands, selections and comment
446 // so just save commands for undo and redo
447 // and use current selection
449 QString redoSelection="";
450 if (redoSel) redoSelection=redoSel->getSelectString();
451 QString undoSelection="";
452 if (undoSel) undoSelection=undoSel->getSelectString();
454 saveState (UndoCommand,
461 void MapEditor::saveState(const QString &undoSel, const QString &uc, const QString &redoSel, const QString &rc, const QString &comment)
463 // "Normal" savestate: save commands, selections and comment
464 // so just save commands for undo and redo
465 // and use current selection
466 saveState (UndoCommand,
474 void MapEditor::parseAtom(const QString &atom)
476 BranchObj *selb=xelection.getBranch();
481 // Split string s into command and parameters
482 parser.parseAtom (atom);
483 QString com=parser.getCommand();
486 /////////////////////////////////////////////////////////////////////
487 if (com=="addBranch")
489 if (xelection.isEmpty())
491 parser.setError (Aborted,"Nothing selected");
494 parser.setError (Aborted,"Type of selection is not a branch");
499 if (parser.checkParCount(pl))
501 if (parser.parCount()==0)
502 addNewBranchInt (-2);
505 y=parser.parInt (ok,0);
506 if (ok ) addNewBranchInt (y);
510 /////////////////////////////////////////////////////////////////////
511 } else if (com=="addBranchBefore")
513 if (xelection.isEmpty())
515 parser.setError (Aborted,"Nothing selected");
518 parser.setError (Aborted,"Type of selection is not a branch");
521 if (parser.parCount()==0)
523 addNewBranchBefore ();
526 /////////////////////////////////////////////////////////////////////
527 } else if (com==QString("addMapReplace"))
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.checkParCount(1))
537 //s=parser.parString (ok,0); // selection
538 t=parser.parString (ok,0); // path to map
539 if (QDir::isRelativePath(t)) t=QDir::convertSeparators (tmpMapDir + "/"+t);
540 addMapReplaceInt(selb->getSelectString(),t);
542 /////////////////////////////////////////////////////////////////////
543 } else if (com==QString("addMapInsert"))
545 if (xelection.isEmpty())
547 parser.setError (Aborted,"Nothing selected");
550 parser.setError (Aborted,"Type of selection is not a branch");
553 if (parser.checkParCount(2))
555 t=parser.parString (ok,0); // path to map
556 y=parser.parInt(ok,1); // position
557 if (QDir::isRelativePath(t)) t=QDir::convertSeparators (tmpMapDir + "/"+t);
558 addMapInsertInt(t,y);
561 /////////////////////////////////////////////////////////////////////
562 } else if (com=="clearFlags")
564 if (xelection.isEmpty() )
566 parser.setError (Aborted,"Nothing selected");
569 parser.setError (Aborted,"Type of selection is not a branch");
570 } else if (parser.checkParCount(0))
572 selb->clearStandardFlags();
573 selb->updateFlagsToolbar();
575 /////////////////////////////////////////////////////////////////////
576 } else if (com=="colorBranch")
578 if (xelection.isEmpty())
580 parser.setError (Aborted,"Nothing selected");
583 parser.setError (Aborted,"Type of selection is not a branch");
584 } else if (parser.checkParCount(1))
586 QColor c=parser.parColor (ok,0);
587 if (ok) colorBranch (c);
589 /////////////////////////////////////////////////////////////////////
590 } else if (com=="colorSubtree")
592 if (xelection.isEmpty())
594 parser.setError (Aborted,"Nothing selected");
597 parser.setError (Aborted,"Type of selection is not a branch");
598 } else if (parser.checkParCount(1))
600 QColor c=parser.parColor (ok,0);
601 if (ok) colorSubtree (c);
603 /////////////////////////////////////////////////////////////////////
604 } else if (com=="copy")
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.checkParCount(0))
614 //FIXME missing action for copy
616 /////////////////////////////////////////////////////////////////////
617 } else if (com=="cut")
619 if (xelection.isEmpty())
621 parser.setError (Aborted,"Nothing selected");
622 } else if ( xelection.type()!=Selection::Branch &&
623 xelection.type()!=Selection::MapCenter &&
624 xelection.type()!=Selection::FloatImage )
626 parser.setError (Aborted,"Type of selection is not a branch or floatimage");
627 } else if (parser.checkParCount(0))
631 /////////////////////////////////////////////////////////////////////
632 } else if (com=="delete")
634 if (xelection.isEmpty())
636 parser.setError (Aborted,"Nothing selected");
637 } else if (xelection.type() != Selection::Branch && xelection.type() != Selection::FloatImage )
639 parser.setError (Aborted,"Type of selection is wrong.");
640 } else if (parser.checkParCount(0))
644 /////////////////////////////////////////////////////////////////////
645 } else if (com=="deleteKeepChilds")
647 if (xelection.isEmpty())
649 parser.setError (Aborted,"Nothing selected");
652 parser.setError (Aborted,"Type of selection is not a branch");
653 } else if (parser.checkParCount(0))
657 /////////////////////////////////////////////////////////////////////
658 } else if (com=="deleteChilds")
660 if (xelection.isEmpty())
662 parser.setError (Aborted,"Nothing selected");
665 parser.setError (Aborted,"Type of selection is not a branch");
666 } else if (parser.checkParCount(0))
670 /////////////////////////////////////////////////////////////////////
671 } else if (com=="export")
674 if (xelection.isEmpty())
676 parser.setError (Aborted,"Nothing selected");
679 parser.setError (Aborted,"Type of selection is not a branch");
682 if (parser.parCount()==0)
684 parser.setError (Aborted,"No output format given");
687 // At least one parameter, which is the outFormat
688 QString outFormat=parser.parString (ok,0);
691 parser.setError (Aborted,QString("Unknown export type: %1").arg(outFormat));
696 if (parser.parCount()>=2)
697 // Hey, we even have a filename
698 fname=parser.parString(ok,1);
701 parser.setError (Aborted,"Could not read filename");
704 if (outFormat == "ascii")
706 exportASCII (fname,false);
707 } else if (outFormat == "image")
709 QString format="PNG";
710 if (parser.parCount()>2)
712 format=parser.parString(ok,2);
714 exportImage (fname,false,format);
717 parser.setError (Aborted,QString("Unknown export type: %1").arg(outFormat));
722 /////////////////////////////////////////////////////////////////////
723 } else if (com=="importDir")
725 if (xelection.isEmpty())
727 parser.setError (Aborted,"Nothing selected");
730 parser.setError (Aborted,"Type of selection is not a branch");
731 } else if (parser.checkParCount(1))
733 s=parser.parString(ok,0);
734 if (ok) importDirInt(s);
736 /////////////////////////////////////////////////////////////////////
737 } else if (com=="linkTo")
739 if (xelection.isEmpty())
741 parser.setError (Aborted,"Nothing selected");
744 if (parser.checkParCount(4))
746 // 0 selectstring of parent
747 // 1 num in parent (for branches)
748 // 2,3 x,y of mainbranch or mapcenter
749 s=parser.parString(ok,0);
750 LinkableMapObj *dst=mapCenter->findObjBySelect (s);
753 if (typeid(*dst) == typeid(BranchObj) )
755 // Get number in parent
756 x=parser.parInt (ok,1);
758 selb->linkTo ((BranchObj*)(dst),x);
759 } else if (typeid(*dst) == typeid(MapCenterObj) )
761 selb->linkTo ((BranchObj*)(dst),-1);
762 // Get coordinates of mainbranch
763 x=parser.parInt (ok,2);
766 y=parser.parInt (ok,3);
767 if (ok) selb->move (x,y);
772 } else if ( xelection.type() == Selection::FloatImage)
774 if (parser.checkParCount(1))
776 // 0 selectstring of parent
777 s=parser.parString(ok,0);
778 LinkableMapObj *dst=mapCenter->findObjBySelect (s);
781 if (typeid(*dst) == typeid(BranchObj) ||
782 typeid(*dst) == typeid(MapCenterObj))
783 linkTo (dst->getSelectString());
785 parser.setError (Aborted,"Destination is not a branch");
788 parser.setError (Aborted,"Type of selection is not a floatimage or branch");
789 /////////////////////////////////////////////////////////////////////
790 } else if (com=="loadImage")
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.checkParCount(1))
800 s=parser.parString(ok,0);
801 if (ok) loadFloatImageInt (s);
803 /////////////////////////////////////////////////////////////////////
804 } else if (com=="moveBranchUp")
806 if (xelection.isEmpty() )
808 parser.setError (Aborted,"Nothing selected");
811 parser.setError (Aborted,"Type of selection is not a branch");
812 } else if (parser.checkParCount(0))
816 /////////////////////////////////////////////////////////////////////
817 } else if (com=="moveBranchDown")
819 if (xelection.isEmpty() )
821 parser.setError (Aborted,"Nothing selected");
824 parser.setError (Aborted,"Type of selection is not a branch");
825 } else if (parser.checkParCount(0))
829 /////////////////////////////////////////////////////////////////////
830 } else if (com=="move")
832 if (xelection.isEmpty() )
834 parser.setError (Aborted,"Nothing selected");
835 } else if ( xelection.type()!=Selection::Branch &&
836 xelection.type()!=Selection::MapCenter &&
837 xelection.type()!=Selection::FloatImage )
839 parser.setError (Aborted,"Type of selection is not a branch or floatimage");
840 } else if (parser.checkParCount(2))
842 x=parser.parInt (ok,0);
845 y=parser.parInt (ok,1);
849 /////////////////////////////////////////////////////////////////////
850 } else if (com=="moveRel")
852 if (xelection.isEmpty() )
854 parser.setError (Aborted,"Nothing selected");
855 } else if ( xelection.type()!=Selection::Selection::Branch &&
856 xelection.type()!=Selection::Selection::MapCenter &&
857 xelection.type()!=Selection::Selection::FloatImage )
859 parser.setError (Aborted,"Type of selection is not a branch or floatimage");
860 } else if (parser.checkParCount(2))
862 x=parser.parInt (ok,0);
865 y=parser.parInt (ok,1);
866 if (ok) moveRel (x,y);
869 /////////////////////////////////////////////////////////////////////
870 } else if (com=="nop")
872 /////////////////////////////////////////////////////////////////////
873 } else if (com=="paste")
875 if (xelection.isEmpty() )
877 parser.setError (Aborted,"Nothing selected");
880 parser.setError (Aborted,"Type of selection is not a branch");
881 } else if (parser.checkParCount(1))
883 x=parser.parInt (ok,0);
884 if (ok) pasteNoSave(x);
886 /////////////////////////////////////////////////////////////////////
887 } else if (com=="qa")
889 if (xelection.isEmpty() )
891 parser.setError (Aborted,"Nothing selected");
894 parser.setError (Aborted,"Type of selection is not a branch");
895 } else if (parser.checkParCount(4))
898 c=parser.parString (ok,0);
901 parser.setError (Aborted,"No comment given");
904 s=parser.parString (ok,1);
907 parser.setError (Aborted,"First parameter is not a string");
910 t=parser.parString (ok,2);
913 parser.setError (Aborted,"Condition is not a string");
916 u=parser.parString (ok,3);
919 parser.setError (Aborted,"Third parameter is not a string");
924 parser.setError (Aborted,"Unknown type: "+s);
929 parser.setError (Aborted,"Unknown operator: "+t);
934 parser.setError (Aborted,"Type of selection is not a branch");
937 if (selb->getHeading() == u)
939 cout << "PASSED: " << c.ascii() << endl;
942 cout << "FAILED: " << c.ascii() << endl;
952 /////////////////////////////////////////////////////////////////////
953 } else if (com=="saveImage")
955 FloatImageObj *fio=xelection.getFloatImage();
958 parser.setError (Aborted,"Type of selection is not an image");
959 } else if (parser.checkParCount(2))
961 s=parser.parString(ok,0);
964 t=parser.parString(ok,1);
965 if (ok) saveFloatImageInt (fio,t,s);
968 /////////////////////////////////////////////////////////////////////
969 } else if (com=="scroll")
971 if (xelection.isEmpty() )
973 parser.setError (Aborted,"Nothing selected");
976 parser.setError (Aborted,"Type of selection is not a branch");
977 } else if (parser.checkParCount(0))
979 if (!scrollBranch (selb))
980 parser.setError (Aborted,"Could not scroll branch");
982 /////////////////////////////////////////////////////////////////////
983 } else if (com=="select")
985 if (parser.checkParCount(1))
987 s=parser.parString(ok,0);
990 /////////////////////////////////////////////////////////////////////
991 } else if (com=="selectLastBranch")
993 if (xelection.isEmpty() )
995 parser.setError (Aborted,"Nothing selected");
998 parser.setError (Aborted,"Type of selection is not a branch");
999 } else if (parser.checkParCount(0))
1001 BranchObj *bo=selb->getLastBranch();
1003 parser.setError (Aborted,"Could not select last branch");
1007 /////////////////////////////////////////////////////////////////////
1008 } else if (com=="selectLastImage")
1010 if (xelection.isEmpty() )
1012 parser.setError (Aborted,"Nothing selected");
1015 parser.setError (Aborted,"Type of selection is not a branch");
1016 } else if (parser.checkParCount(0))
1018 FloatImageObj *fio=selb->getLastFloatImage();
1020 parser.setError (Aborted,"Could not select last image");
1024 /////////////////////////////////////////////////////////////////////
1025 } else if (com=="setFrameType")
1027 if ( xelection.type()!=Selection::Branch && xelection.type()!= Selection::MapCenter && xelection.type()!=Selection::FloatImage)
1029 parser.setError (Aborted,"Type of selection does not allow setting frame type");
1031 else if (parser.checkParCount(1))
1033 s=parser.parString(ok,0);
1034 if (ok) setFrameType (s);
1036 /////////////////////////////////////////////////////////////////////
1037 } else if (com=="setFramePenColor")
1039 if ( xelection.type()!=Selection::Branch && xelection.type()!= Selection::MapCenter && xelection.type()!=Selection::FloatImage)
1041 parser.setError (Aborted,"Type of selection does not allow setting of pen color");
1043 else if (parser.checkParCount(1))
1045 QColor c=parser.parColor(ok,0);
1046 if (ok) setFramePenColor (c);
1048 /////////////////////////////////////////////////////////////////////
1049 } else if (com=="setFrameBrushColor")
1051 if ( xelection.type()!=Selection::Branch && xelection.type()!= Selection::MapCenter && xelection.type()!=Selection::FloatImage)
1053 parser.setError (Aborted,"Type of selection does not allow setting brush color");
1055 else if (parser.checkParCount(1))
1057 QColor c=parser.parColor(ok,0);
1058 if (ok) setFrameBrushColor (c);
1060 /////////////////////////////////////////////////////////////////////
1061 } else if (com=="setFramePadding")
1063 if ( xelection.type()!=Selection::Branch && xelection.type()!= Selection::MapCenter && xelection.type()!=Selection::FloatImage)
1065 parser.setError (Aborted,"Type of selection does not allow setting frame padding");
1067 else if (parser.checkParCount(1))
1069 x=parser.parInt(ok,0);
1070 if (ok) setFramePadding(x);
1072 /////////////////////////////////////////////////////////////////////
1073 } else if (com=="setFrameBorderWidth")
1075 if ( xelection.type()!=Selection::Branch && xelection.type()!= Selection::MapCenter && xelection.type()!=Selection::FloatImage)
1077 parser.setError (Aborted,"Type of selection does not allow setting frame border width");
1079 else if (parser.checkParCount(1))
1081 x=parser.parInt(ok,0);
1082 if (ok) setFrameBorderWidth (x);
1084 /////////////////////////////////////////////////////////////////////
1085 } else if (com=="setMapAuthor")
1087 if (parser.checkParCount(1))
1089 s=parser.parString(ok,0);
1090 if (ok) setMapAuthor (s);
1092 /////////////////////////////////////////////////////////////////////
1093 } else if (com=="setMapComment")
1095 if (parser.checkParCount(1))
1097 s=parser.parString(ok,0);
1098 if (ok) setMapComment(s);
1100 /////////////////////////////////////////////////////////////////////
1101 } else if (com=="setMapBackgroundColor")
1103 if (xelection.isEmpty() )
1105 parser.setError (Aborted,"Nothing selected");
1106 } else if (! xelection.getBranch() )
1108 parser.setError (Aborted,"Type of selection is not a branch");
1109 } else if (parser.checkParCount(1))
1111 QColor c=parser.parColor (ok,0);
1112 if (ok) setMapBackgroundColor (c);
1114 /////////////////////////////////////////////////////////////////////
1115 } else if (com=="setMapDefLinkColor")
1117 if (xelection.isEmpty() )
1119 parser.setError (Aborted,"Nothing selected");
1122 parser.setError (Aborted,"Type of selection is not a branch");
1123 } else if (parser.checkParCount(1))
1125 QColor c=parser.parColor (ok,0);
1126 if (ok) setMapDefLinkColor (c);
1128 /////////////////////////////////////////////////////////////////////
1129 } else if (com=="setMapLinkStyle")
1131 if (parser.checkParCount(1))
1133 s=parser.parString (ok,0);
1134 if (ok) setMapLinkStyle(s);
1136 /////////////////////////////////////////////////////////////////////
1137 } else if (com=="setHeading")
1139 if (xelection.isEmpty() )
1141 parser.setError (Aborted,"Nothing selected");
1144 parser.setError (Aborted,"Type of selection is not a branch");
1145 } else if (parser.checkParCount(1))
1147 s=parser.parString (ok,0);
1151 /////////////////////////////////////////////////////////////////////
1152 } else if (com=="setHideExport")
1154 if (xelection.isEmpty() )
1156 parser.setError (Aborted,"Nothing selected");
1157 } else if (xelection.type()!=Selection::Branch && xelection.type() != Selection::MapCenter &&xelection.type()!=Selection::FloatImage)
1159 parser.setError (Aborted,"Type of selection is not a branch or floatimage");
1160 } else if (parser.checkParCount(1))
1162 b=parser.parBool(ok,0);
1163 if (ok) setHideExport (b);
1165 /////////////////////////////////////////////////////////////////////
1166 } else if (com=="setIncludeImagesHorizontally")
1168 if (xelection.isEmpty() )
1170 parser.setError (Aborted,"Nothing selected");
1173 parser.setError (Aborted,"Type of selection is not a branch");
1174 } else if (parser.checkParCount(1))
1176 b=parser.parBool(ok,0);
1177 if (ok) setIncludeImagesHor(b);
1179 /////////////////////////////////////////////////////////////////////
1180 } else if (com=="setIncludeImagesVertically")
1182 if (xelection.isEmpty() )
1184 parser.setError (Aborted,"Nothing selected");
1187 parser.setError (Aborted,"Type of selection is not a branch");
1188 } else if (parser.checkParCount(1))
1190 b=parser.parBool(ok,0);
1191 if (ok) setIncludeImagesVer(b);
1193 /////////////////////////////////////////////////////////////////////
1194 } else if (com=="setHideLinkUnselected")
1196 if (xelection.isEmpty() )
1198 parser.setError (Aborted,"Nothing selected");
1199 } else if ( xelection.type()!=Selection::Branch && xelection.type()!= Selection::MapCenter && xelection.type()!=Selection::FloatImage)
1201 parser.setError (Aborted,"Type of selection does not allow hiding the link");
1202 } else if (parser.checkParCount(1))
1204 b=parser.parBool(ok,0);
1205 if (ok) setHideLinkUnselected(b);
1207 /////////////////////////////////////////////////////////////////////
1208 } else if (com=="setSelectionColor")
1210 if (parser.checkParCount(1))
1212 QColor c=parser.parColor (ok,0);
1213 if (ok) setSelectionColorInt (c);
1215 /////////////////////////////////////////////////////////////////////
1216 } else if (com=="setURL")
1218 if (xelection.isEmpty() )
1220 parser.setError (Aborted,"Nothing selected");
1223 parser.setError (Aborted,"Type of selection is not a branch");
1224 } else if (parser.checkParCount(1))
1226 s=parser.parString (ok,0);
1229 /////////////////////////////////////////////////////////////////////
1230 } else if (com=="setVymLink")
1232 if (xelection.isEmpty() )
1234 parser.setError (Aborted,"Nothing selected");
1237 parser.setError (Aborted,"Type of selection is not a branch");
1238 } else if (parser.checkParCount(1))
1240 s=parser.parString (ok,0);
1241 if (ok) setVymLinkInt(s);
1244 /////////////////////////////////////////////////////////////////////
1245 else if (com=="setFlag")
1247 if (xelection.isEmpty() )
1249 parser.setError (Aborted,"Nothing selected");
1252 parser.setError (Aborted,"Type of selection is not a branch");
1253 } else if (parser.checkParCount(1))
1255 s=parser.parString(ok,0);
1258 selb->activateStandardFlag(s);
1259 selb->updateFlagsToolbar();
1262 /////////////////////////////////////////////////////////////////////
1263 } else if (com=="setFrameType")
1265 if (xelection.isEmpty() )
1267 parser.setError (Aborted,"Nothing selected");
1270 parser.setError (Aborted,"Type of selection is not a branch");
1271 } else if (parser.checkParCount(1))
1273 s=parser.parString(ok,0);
1277 /////////////////////////////////////////////////////////////////////
1278 } else if (com=="toggleFlag")
1280 if (xelection.isEmpty() )
1282 parser.setError (Aborted,"Nothing selected");
1285 parser.setError (Aborted,"Type of selection is not a branch");
1286 } else if (parser.checkParCount(1))
1288 s=parser.parString(ok,0);
1291 selb->toggleStandardFlag(s);
1292 selb->updateFlagsToolbar();
1295 /////////////////////////////////////////////////////////////////////
1296 } else if (com=="unscroll")
1298 if (xelection.isEmpty() )
1300 parser.setError (Aborted,"Nothing selected");
1303 parser.setError (Aborted,"Type of selection is not a branch");
1304 } else if (parser.checkParCount(0))
1306 if (!unscrollBranch (selb))
1307 parser.setError (Aborted,"Could not unscroll branch");
1309 /////////////////////////////////////////////////////////////////////
1310 } else if (com=="unscrollChilds")
1312 if (xelection.isEmpty() )
1314 parser.setError (Aborted,"Nothing selected");
1317 parser.setError (Aborted,"Type of selection is not a branch");
1318 } else if (parser.checkParCount(0))
1322 /////////////////////////////////////////////////////////////////////
1323 } else if (com=="unsetFlag")
1325 if (xelection.isEmpty() )
1327 parser.setError (Aborted,"Nothing selected");
1330 parser.setError (Aborted,"Type of selection is not a branch");
1331 } else if (parser.checkParCount(1))
1333 s=parser.parString(ok,0);
1336 selb->deactivateStandardFlag(s);
1337 selb->updateFlagsToolbar();
1341 parser.setError (Aborted,"Unknown command");
1344 if (parser.errorLevel()==NoError)
1347 mapCenter->reposition();
1351 // TODO Error handling
1352 qWarning("MapEditor::parseAtom: Error!");
1353 qWarning(parser.errorMessage());
1357 void MapEditor::runScript (QString script)
1359 parser.setScript (script);
1361 while (parser.next() )
1362 parseAtom(parser.getAtom());
1365 bool MapEditor::isDefault()
1370 bool MapEditor::hasChanged()
1375 void MapEditor::setChanged()
1378 autosaveTimer->start(settings.value("/mapeditor/autosave/ms/",300000).toInt());
1386 void MapEditor::closeMap()
1388 // Unselect before disabling the toolbar actions
1389 if (!xelection.isEmpty() ) xelection.unselect();
1397 void MapEditor::setFilePath(QString fpath, QString destname)
1399 if (fpath.isEmpty() || fpath=="")
1406 filePath=fpath; // becomes absolute path
1407 fileName=fpath; // gets stripped of path
1408 destPath=destname; // needed for vymlinks
1410 // If fpath is not an absolute path, complete it
1411 filePath=QDir(fpath).absPath();
1412 fileDir=filePath.left (1+filePath.findRev ("/"));
1414 // Set short name, too. Search from behind:
1415 int i=fileName.findRev("/");
1416 if (i>=0) fileName=fileName.remove (0,i+1);
1418 // Forget the .vym (or .xml) for name of map
1419 mapName=fileName.left(fileName.findRev(".",-1,true) );
1423 void MapEditor::setFilePath(QString fpath)
1425 setFilePath (fpath,fpath);
1428 QString MapEditor::getFilePath()
1433 QString MapEditor::getFileName()
1438 QString MapEditor::getMapName()
1443 QString MapEditor::getDestPath()
1448 ErrorCode MapEditor::load (QString fname, LoadMode lmode)
1450 ErrorCode err=success;
1454 if (xelection.isEmpty() ) xelection.unselect();
1457 mapCenter->setMapEditor(this);
1458 // (map state is set later at end of load...)
1461 BranchObj *bo=xelection.getBranch();
1462 if (!bo) return aborted;
1463 if (lmode==ImportAdd)
1464 saveStateChangingPart(
1467 QString("addMapInsert (%1)").arg(fname),
1468 QString("Add map %1 to %2").arg(fname).arg(getName(bo)));
1470 saveStateChangingPart(
1473 QString("addMapReplace(%1)").arg(fname),
1474 QString("Add map %1 to %2").arg(fname).arg(getName(bo)));
1478 mapBuilderHandler handler;
1479 QFile file( fname );
1481 // I am paranoid: file should exist anyway
1482 // according to check in mainwindow.
1483 if (!file.exists() )
1485 QMessageBox::critical( 0, tr( "Critical Parse Error" ),
1486 tr("Couldn't open map " +fname)+".");
1490 bool blockSaveStateOrg=blockSaveState;
1491 blockReposition=true;
1492 blockSaveState=true;
1493 QXmlInputSource source( file);
1494 QXmlSimpleReader reader;
1495 reader.setContentHandler( &handler );
1496 reader.setErrorHandler( &handler );
1497 handler.setMapEditor( this );
1500 // We need to set the tmpDir in order to load files with rel. path
1501 QString tmpdir= fname.left(fname.findRev("/",-1));
1502 handler.setTmpDir (tmpdir);
1503 handler.setInputFile (file.name());
1504 handler.setLoadMode (lmode);
1505 bool ok = reader.parse( source );
1506 blockReposition=false;
1507 blockSaveState=blockSaveStateOrg;
1511 mapCenter->reposition();
1518 autosaveTimer->stop();
1522 QMessageBox::critical( 0, tr( "Critical Parse Error" ),
1523 tr( handler.errorProtocol() ) );
1525 // Still return "success": the map maybe at least
1526 // partially read by the parser
1533 int MapEditor::save (const SaveMode &savemode)
1537 // Create mapName and fileDir
1538 makeSubDirs (fileDir);
1542 fname=mapName+".xml";
1544 // use name given by user, even if he chooses .doc
1549 if (savemode==CompleteMap || xelection.isEmpty())
1550 saveFile=saveToDir (fileDir,mapName+"-",true,QPointF(),NULL);
1553 // TODO take care of multiselections
1554 if (xelection.type()==Selection::FloatImage)
1557 saveFile=saveToDir (fileDir,mapName+"-",true,QPointF(),xelection.getBranch());
1560 if (!saveStringToDisk(fileDir+fname,saveFile))
1567 autosaveTimer->stop();
1574 void MapEditor::setZipped (bool z)
1579 bool MapEditor::saveZipped ()
1584 void MapEditor::print()
1588 printer = new QPrinter;
1589 printer->setColorMode (QPrinter::Color);
1590 printer->setPrinterName (settings.value("/mainwindow/printerName",printer->printerName()).toString());
1591 printer->setOutputFormat((QPrinter::OutputFormat)settings.value("/mainwindow/printerFormat",printer->outputFormat()).toInt());
1592 printer->setOutputFileName(settings.value("/mainwindow/printerFileName",printer->outputFileName()).toString());
1595 QRectF totalBBox=mapCenter->getTotalBBox();
1597 // Try to set orientation automagically
1598 // Note: Interpretation of generated postscript is amibiguous, if
1599 // there are problems with landscape mode, see
1600 // http://sdb.suse.de/de/sdb/html/jsmeix_print-cups-landscape-81.html
1602 if (totalBBox.width()>totalBBox.height())
1603 // recommend landscape
1604 printer->setOrientation (QPrinter::Landscape);
1606 // recommend portrait
1607 printer->setOrientation (QPrinter::Portrait);
1609 if ( printer->setup(this) )
1610 // returns false, if printing is canceled
1612 QPainter pp(printer);
1614 pp.setRenderHint(QPainter::Antialiasing,true);
1616 // Don't print the visualisation of selection
1617 xelection.unselect();
1619 QRectF mapRect=totalBBox;
1620 QGraphicsRectItem *frame=NULL;
1624 // Print frame around map
1625 mapRect.setRect (totalBBox.x()-10, totalBBox.y()-10,
1626 totalBBox.width()+20, totalBBox.height()+20);
1627 frame=mapScene->addRect (mapRect, QPen(Qt::black),QBrush(Qt::NoBrush));
1628 frame->setZValue(0);
1633 double paperAspect = (double)printer->width() / (double)printer->height();
1634 double mapAspect = (double)mapRect.width() / (double)mapRect.height();
1636 if (mapAspect>=paperAspect)
1638 // Fit horizontally to paper width
1639 //pp.setViewport(0,0, printer->width(),(int)(printer->width()/mapAspect) );
1640 viewBottom=(int)(printer->width()/mapAspect);
1643 // Fit vertically to paper height
1644 //pp.setViewport(0,0,(int)(printer->height()*mapAspect),printer->height());
1645 viewBottom=printer->height();
1650 // Print footer below map
1652 font.setPointSize(10);
1654 QRectF footerBox(0,viewBottom,printer->width(),15);
1655 pp.drawText ( footerBox,Qt::AlignLeft,"VYM - " +fileName);
1656 pp.drawText ( footerBox, Qt::AlignRight, QDate::currentDate().toString(Qt::TextDate));
1660 QRectF (0,0,printer->width(),printer->height()-15),
1661 QRectF(mapRect.x(),mapRect.y(),mapRect.width(),mapRect.height())
1664 // Viewport has paper dimension
1665 if (frame) delete (frame);
1667 // Restore selection
1668 xelection.reselect();
1670 // Save settings in vymrc
1671 settings.writeEntry("/mainwindow/printerName",printer->printerName());
1672 settings.writeEntry("/mainwindow/printerFormat",printer->outputFormat());
1673 settings.writeEntry("/mainwindow/printerFileName",printer->outputFileName());
1677 void MapEditor::setAntiAlias (bool b)
1679 setRenderHint(QPainter::Antialiasing,b);
1682 void MapEditor::setSmoothPixmap(bool b)
1684 setRenderHint(QPainter::SmoothPixmapTransform,b);
1687 QPixmap MapEditor::getPixmap()
1689 QRectF mapRect=mapCenter->getTotalBBox();
1690 QPixmap pix((int)mapRect.width()+2,(int)mapRect.height()+2);
1693 pp.setRenderHints(renderHints());
1695 // Don't print the visualisation of selection
1696 xelection.unselect();
1698 mapScene->render ( &pp,
1699 QRectF(0,0,mapRect.width()+2,mapRect.height()+2),
1700 QRectF(mapRect.x(),mapRect.y(),mapRect.width(),mapRect.height() ));
1702 // Restore selection
1703 xelection.reselect();
1708 void MapEditor::setHideTmpMode (BranchObj::HideTmpMode mode)
1711 mapCenter->setHideTmp (hidemode);
1712 mapCenter->reposition();
1716 BranchObj::HideTmpMode MapEditor::getHideTmpMode()
1721 void MapEditor::setExportMode (bool b)
1723 // should be called before and after exports
1724 // depending on the settings
1725 if (b && settings.value("/export/useHideExport","yes")=="yes")
1726 setHideTmpMode (BranchObj::HideExport);
1728 setHideTmpMode (BranchObj::HideNone);
1731 void MapEditor::exportASCII(QString fname,bool askName)
1734 ex.setMapCenter(mapCenter);
1736 ex.setFile (mapName+".txt");
1742 //ex.addFilter ("TXT (*.txt)");
1743 ex.setDir(lastImageDir);
1744 //ex.setCaption(vymName+ " -" +tr("Export as ASCII")+" "+tr("(still experimental)"));
1749 setExportMode(true);
1751 setExportMode(false);
1755 void MapEditor::exportImage(QString fname, bool askName, QString format)
1759 fname=mapName+".png";
1766 QFileDialog *fd=new QFileDialog (this);
1767 fd->setCaption (tr("Export map as image"));
1768 fd->setDirectory (lastImageDir);
1769 fd->setFileMode(QFileDialog::AnyFile);
1770 fd->setFilters (imageIO.getFilters() );
1773 fl=fd->selectedFiles();
1775 format=imageIO.getType(fd->selectedFilter());
1779 setExportMode (true);
1780 QPixmap pix (getPixmap());
1781 pix.save(fname, format);
1782 setExportMode (false);
1785 void MapEditor::exportOOPresentation(const QString &fn, const QString &cf)
1789 ex.setMapCenter(mapCenter);
1790 if (ex.setConfigFile(cf))
1792 setExportMode (true);
1793 ex.exportPresentation();
1794 setExportMode (false);
1800 void MapEditor::exportXML(const QString &dir)
1802 // Hide stuff during export, if settings want this
1803 setExportMode (true);
1805 // Create subdirectories
1808 // write to directory
1809 QString saveFile=saveToDir (dir,mapName+"-",true,mapCenter->getTotalBBox().topLeft() ,NULL);
1812 file.setName ( dir + "/"+mapName+".xml");
1813 if ( !file.open( QIODevice::WriteOnly ) )
1815 // This should neverever happen
1816 QMessageBox::critical (0,tr("Critical Export Error"),tr("MapEditor::exportXML couldn't open %1").arg(file.name()));
1820 // Write it finally, and write in UTF8, no matter what
1821 QTextStream ts( &file );
1822 ts.setEncoding (QTextStream::UnicodeUTF8);
1826 // Now write image, too
1827 exportImage (dir+"/images/"+mapName+".png","PNG");
1829 setExportMode (false);
1832 void MapEditor::clear()
1834 xelection.unselect();
1838 void MapEditor::copy()
1840 LinkableMapObj *sel=xelection.single();
1843 if (redosAvail == 0)
1846 QString s=sel->getSelectString();
1847 saveState (PartOfMap, s, "nop ()", s, "copy ()","Copy selection to clipboard",sel );
1848 curClipboard=curStep;
1851 // Copy also to global clipboard, because we are at last step in history
1852 QString bakMapName=QDir::convertSeparators (QString("history-%1").arg(curStep));
1853 QString bakMapDir=QDir::convertSeparators (tmpMapDir +"/"+bakMapName);
1854 copyDir (bakMapDir,clipboardDir );
1856 clipboardEmpty=false;
1861 void MapEditor::redo()
1863 // Can we undo at all?
1864 if (redosAvail<1) return;
1866 bool blockSaveStateOrg=blockSaveState;
1867 blockSaveState=true;
1871 if (undosAvail<stepsTotal) undosAvail++;
1873 if (curStep>stepsTotal) curStep=1;
1874 QString undoCommand= undoSet.readEntry (QString("/history/step-%1/undoCommand").arg(curStep));
1875 QString undoSelection=undoSet.readEntry (QString("/history/step-%1/undoSelection").arg(curStep));
1876 QString redoCommand= undoSet.readEntry (QString("/history/step-%1/redoCommand").arg(curStep));
1877 QString redoSelection=undoSet.readEntry (QString("/history/step-%1/redoSelection").arg(curStep));
1878 QString comment=undoSet.readEntry (QString("/history/step-%1/comment").arg(curStep));
1879 QString version=undoSet.readEntry ("/history/version");
1881 if (!checkVersion(version))
1882 QMessageBox::warning(0,tr("Warning"),
1883 tr("Version %1 of saved undo/redo data\ndoes not match current vym version %2.").arg(version).arg(vymVersion));
1886 // Find out current undo directory
1887 QString bakMapDir=QDir::convertSeparators (QString(tmpMapDir+"/undo-%1").arg(curStep));
1891 cout << "ME::redo() begin\n";
1892 cout << " undosAvail="<<undosAvail<<endl;
1893 cout << " redosAvail="<<redosAvail<<endl;
1894 cout << " curStep="<<curStep<<endl;
1895 cout << " ---------------------------"<<endl;
1896 cout << " comment="<<comment.toStdString()<<endl;
1897 cout << " undoCom="<<undoCommand.toStdString()<<endl;
1898 cout << " undoSel="<<undoSelection.toStdString()<<endl;
1899 cout << " redoCom="<<redoCommand.toStdString()<<endl;
1900 cout << " redoSel="<<redoSelection.toStdString()<<endl;
1901 cout << " ---------------------------"<<endl<<endl;
1904 // select object before redo
1905 if (!redoSelection.isEmpty())
1906 select (redoSelection);
1909 parseAtom (redoCommand);
1910 mapCenter->reposition();
1912 blockSaveState=blockSaveStateOrg;
1914 undoSet.setEntry ("/history/undosAvail",QString::number(undosAvail));
1915 undoSet.setEntry ("/history/redosAvail",QString::number(redosAvail));
1916 undoSet.setEntry ("/history/curStep",QString::number(curStep));
1917 undoSet.writeSettings(histPath);
1919 mainWindow->updateHistory (undoSet);
1922 /* TODO remove testing
1923 cout << "ME::redo() end\n";
1924 cout << " undosAvail="<<undosAvail<<endl;
1925 cout << " redosAvail="<<redosAvail<<endl;
1926 cout << " curStep="<<curStep<<endl;
1927 cout << " ---------------------------"<<endl<<endl;
1933 bool MapEditor::isRedoAvailable()
1935 if (undoSet.readNumEntry("/history/redosAvail",0)>0)
1941 void MapEditor::undo()
1943 // Can we undo at all?
1944 if (undosAvail<1) return;
1946 mainWindow->statusMessage (tr("Autosave disabled during undo."));
1948 bool blockSaveStateOrg=blockSaveState;
1949 blockSaveState=true;
1951 QString undoCommand= undoSet.readEntry (QString("/history/step-%1/undoCommand").arg(curStep));
1952 QString undoSelection=undoSet.readEntry (QString("/history/step-%1/undoSelection").arg(curStep));
1953 QString redoCommand= undoSet.readEntry (QString("/history/step-%1/redoCommand").arg(curStep));
1954 QString redoSelection=undoSet.readEntry (QString("/history/step-%1/redoSelection").arg(curStep));
1955 QString comment=undoSet.readEntry (QString("/history/step-%1/comment").arg(curStep));
1956 QString version=undoSet.readEntry ("/history/version");
1958 if (!checkVersion(version))
1959 QMessageBox::warning(0,tr("Warning"),
1960 tr("Version %1 of saved undo/redo data\ndoes not match current vym version %2.").arg(version).arg(vymVersion));
1962 // Find out current undo directory
1963 QString bakMapDir=QDir::convertSeparators (QString(tmpMapDir+"/undo-%1").arg(curStep));
1965 // select object before undo
1966 if (!undoSelection.isEmpty())
1967 select (undoSelection);
1971 cout << "ME::undo() begin\n";
1972 cout << " undosAvail="<<undosAvail<<endl;
1973 cout << " redosAvail="<<redosAvail<<endl;
1974 cout << " curStep="<<curStep<<endl;
1975 cout << " ---------------------------"<<endl;
1976 cout << " comment="<<comment.toStdString()<<endl;
1977 cout << " undoCom="<<undoCommand.toStdString()<<endl;
1978 cout << " undoSel="<<undoSelection.toStdString()<<endl;
1979 cout << " redoCom="<<redoCommand.toStdString()<<endl;
1980 cout << " redoSel="<<redoSelection.toStdString()<<endl;
1981 cout << " ---------------------------"<<endl<<endl;
1983 parseAtom (undoCommand);
1984 mapCenter->reposition();
1988 if (curStep<1) curStep=stepsTotal;
1992 blockSaveState=blockSaveStateOrg;
1993 /* TODO remove testing
1994 cout << "ME::undo() end\n";
1995 cout << " undosAvail="<<undosAvail<<endl;
1996 cout << " redosAvail="<<redosAvail<<endl;
1997 cout << " curStep="<<curStep<<endl;
1998 cout << " ---------------------------"<<endl<<endl;
2001 undoSet.setEntry ("/history/undosAvail",QString::number(undosAvail));
2002 undoSet.setEntry ("/history/redosAvail",QString::number(redosAvail));
2003 undoSet.setEntry ("/history/curStep",QString::number(curStep));
2004 undoSet.writeSettings(histPath);
2006 mainWindow->updateHistory (undoSet);
2009 ensureSelectionVisible();
2012 bool MapEditor::isUndoAvailable()
2014 if (undoSet.readNumEntry("/history/undosAvail",0)>0)
2020 void MapEditor::gotoHistoryStep (int i)
2022 // Restore variables
2023 int undosAvail=undoSet.readNumEntry (QString("/history/undosAvail"));
2024 int redosAvail=undoSet.readNumEntry (QString("/history/redosAvail"));
2026 if (i<0) i=undosAvail+redosAvail;
2028 // Clicking above current step makes us undo things
2031 for (int j=0; j<undosAvail-i; j++) undo();
2034 // Clicking below current step makes us redo things
2036 for (int j=undosAvail; j<i; j++)
2038 cout << "redo "<<j<<"/"<<undosAvail<<" i="<<i<<endl;
2042 // And ignore clicking the current row ;-)
2045 void MapEditor::addMapReplaceInt(const QString &undoSel, const QString &path)
2047 QString pathDir=path.left(path.findRev("/"));
2053 // We need to parse saved XML data
2054 mapBuilderHandler handler;
2055 QXmlInputSource source( file);
2056 QXmlSimpleReader reader;
2057 reader.setContentHandler( &handler );
2058 reader.setErrorHandler( &handler );
2059 handler.setMapEditor( this );
2060 handler.setTmpDir ( pathDir ); // needed to load files with rel. path
2061 if (undoSel.isEmpty())
2065 handler.setLoadMode (NewMap);
2069 handler.setLoadMode (ImportReplace);
2071 blockReposition=true;
2072 bool ok = reader.parse( source );
2073 blockReposition=false;
2076 // This should never ever happen
2077 QMessageBox::critical( 0, tr( "Critical Parse Error while reading %1").arg(path),
2078 handler.errorProtocol());
2081 QMessageBox::critical( 0, tr( "Critical Error" ), tr("Could not read %1").arg(path));
2084 void MapEditor::addMapInsertInt (const QString &path, int pos)
2086 BranchObj *sel=xelection.getBranch();
2089 QString pathDir=path.left(path.findRev("/"));
2095 // We need to parse saved XML data
2096 mapBuilderHandler handler;
2097 QXmlInputSource source( file);
2098 QXmlSimpleReader reader;
2099 reader.setContentHandler( &handler );
2100 reader.setErrorHandler( &handler );
2101 handler.setMapEditor( this );
2102 handler.setTmpDir ( pathDir ); // needed to load files with rel. path
2103 handler.setLoadMode (ImportAdd);
2104 blockReposition=true;
2105 bool ok = reader.parse( source );
2106 blockReposition=false;
2109 // This should never ever happen
2110 QMessageBox::critical( 0, tr( "Critical Parse Error while reading %1").arg(path),
2111 handler.errorProtocol());
2114 sel->getLastBranch()->linkTo (sel,pos);
2116 QMessageBox::critical( 0, tr( "Critical Error" ), tr("Could not read %1").arg(path));
2120 void MapEditor::pasteNoSave(const int &n)
2122 bool old=blockSaveState;
2123 blockSaveState=true;
2124 if (redosAvail > 0 || n!=0)
2126 // Use the "historical" buffer
2127 QString bakMapName=QDir::convertSeparators (QString("history-%1").arg(n));
2128 QString bakMapDir=QDir::convertSeparators (tmpMapDir +"/"+bakMapName);
2129 load (bakMapDir+"/"+clipboardFile,ImportAdd);
2131 // Use the global buffer
2132 load (clipboardDir+"/"+clipboardFile,ImportAdd);
2136 void MapEditor::paste()
2138 BranchObj *sel=xelection.getBranch();
2141 saveStateChangingPart(
2144 QString ("paste (%1)").arg(curClipboard),
2145 QString("Paste to %1").arg( getName(sel))
2148 mapCenter->reposition();
2152 void MapEditor::cut()
2154 LinkableMapObj *sel=xelection.single();
2155 if ( sel && (xelection.type() == Selection::Branch ||
2156 xelection.type()==Selection::MapCenter ||
2157 xelection.type()==Selection::FloatImage))
2159 /* No savestate! savestate is called in cutNoSave
2160 saveStateChangingPart(
2164 QString("Cut %1").arg(getName(sel ))
2169 mapCenter->reposition();
2173 void MapEditor::move(const int &x, const int &y)
2175 LinkableMapObj *sel=xelection.single();
2178 QString ps=qpointfToString (sel->getAbsPos());
2179 QString s=xelection.single()->getSelectString();
2182 s, "move "+qpointfToString (QPointF (x,y)),
2183 QString("Move %1 to %2").arg(getName(sel)).arg(ps));
2185 mapCenter->reposition();
2191 void MapEditor::moveRel (const int &x, const int &y)
2193 LinkableMapObj *sel=xelection.single();
2196 QString ps=qpointfToString (sel->getRelPos());
2197 QString s=sel->getSelectString();
2200 s, "moveRel "+qpointfToString (QPointF (x,y)),
2201 QString("Move %1 to relativ position %2").arg(getName(sel)).arg(ps));
2202 ((OrnamentedObj*)sel)->move2RelPos (x,y);
2203 mapCenter->reposition();
2209 void MapEditor::moveBranchUp()
2211 BranchObj* bo=xelection.getBranch();
2215 if (!bo->canMoveBranchUp()) return;
2216 par=(BranchObj*)(bo->getParObj());
2217 BranchObj *obo=par->moveBranchUp (bo); // bo will be the one below selection
2218 saveState (bo->getSelectString(),"moveBranchDown ()",obo->getSelectString(),"moveBranchUp ()",QString("Move up %1").arg(getName(bo)));
2219 mapCenter->reposition();
2222 ensureSelectionVisible();
2226 void MapEditor::moveBranchDown()
2228 BranchObj* bo=xelection.getBranch();
2232 if (!bo->canMoveBranchDown()) return;
2233 par=(BranchObj*)(bo->getParObj());
2234 BranchObj *obo=par->moveBranchDown(bo); // bo will be the one above selection
2235 saveState(bo->getSelectString(),"moveBranchUp ()",obo->getSelectString(),"moveBranchDown ()",QString("Move down %1").arg(getName(bo)));
2236 mapCenter->reposition();
2239 ensureSelectionVisible();
2243 void MapEditor::linkTo(const QString &dstString)
2245 FloatImageObj *fio=xelection.getFloatImage();
2248 BranchObj *dst=(BranchObj*)(mapCenter->findObjBySelect(dstString));
2249 if (dst && (typeid(*dst)==typeid (BranchObj) ||
2250 typeid(*dst)==typeid (MapCenterObj)))
2252 LinkableMapObj *dstPar=dst->getParObj();
2253 QString parString=dstPar->getSelectString();
2254 QString fioPreSelectString=fio->getSelectString();
2255 QString fioPreParentSelectString=fio->getParObj()->getSelectString();
2256 ((BranchObj*)(dst))->addFloatImage (fio);
2257 xelection.unselect();
2258 ((BranchObj*)(fio->getParObj()))->removeFloatImage (fio);
2259 fio=((BranchObj*)(dst))->getLastFloatImage();
2262 xelection.select(fio);
2264 fio->getSelectString(),
2265 QString("linkTo (\"%1\")").arg(fioPreParentSelectString),
2267 QString ("linkTo (\"%1\")").arg(dstString),
2268 QString ("Link floatimage to %1").arg(getName(dst)));
2273 QString MapEditor::getHeading(bool &ok, QPoint &p)
2275 BranchObj *bo=xelection.getBranch();
2279 p=mapFromScene(bo->getAbsPos());
2280 return bo->getHeading();
2286 void MapEditor::setHeading(const QString &s)
2288 BranchObj *sel=xelection.getBranch();
2293 "setHeading (\""+sel->getHeading()+"\")",
2295 "setHeading (\""+s+"\")",
2296 QString("Set heading of %1 to \"%2\"").arg(getName(sel)).arg(s) );
2297 sel->setHeading(s );
2298 mapCenter->reposition();
2300 ensureSelectionVisible();
2304 void MapEditor::setHeadingInt(const QString &s)
2306 BranchObj *bo=xelection.getBranch();
2310 mapCenter->reposition();
2312 ensureSelectionVisible();
2316 void MapEditor::setVymLinkInt (const QString &s)
2318 // Internal function, no saveState needed
2319 BranchObj *bo=xelection.getBranch();
2323 mapCenter->reposition();
2326 ensureSelectionVisible();
2330 BranchObj* MapEditor::addNewBranchInt(int num)
2332 // Depending on pos:
2333 // -3 insert in childs of parent above selection
2334 // -2 add branch to selection
2335 // -1 insert in childs of parent below selection
2336 // 0..n insert in childs of parent at pos
2337 BranchObj *newbo=NULL;
2338 BranchObj *bo=xelection.getBranch();
2343 // save scroll state. If scrolled, automatically select
2344 // new branch in order to tmp unscroll parent...
2345 return bo->addBranch();
2350 bo=(BranchObj*)bo->getParObj();
2354 bo=(BranchObj*)bo->getParObj();
2357 newbo=bo->insertBranch(num);
2362 BranchObj* MapEditor::addNewBranch(int pos)
2364 // Different meaning than num in addNewBranchInt!
2368 BranchObj *bo = xelection.getBranch();
2369 BranchObj *newbo=NULL;
2373 setCursor (Qt::ArrowCursor);
2375 newbo=addNewBranchInt (pos-2);
2383 QString ("addBranch (%1)").arg(pos-2),
2384 QString ("Add new branch to %1").arg(getName(bo)));
2386 mapCenter->reposition();
2394 BranchObj* MapEditor::addNewBranchBefore()
2396 BranchObj *newbo=NULL;
2397 BranchObj *bo = xelection.getBranch();
2398 if (bo && xelection.type()==Selection::Branch)
2399 // We accept no MapCenterObj here, so we _have_ a parent
2401 QPointF p=bo->getRelPos();
2404 BranchObj *parbo=(BranchObj*)(bo->getParObj());
2406 // add below selection
2407 newbo=parbo->insertBranch(bo->getNum()+1);
2410 newbo->move2RelPos (p);
2412 // Move selection to new branch
2413 bo->linkTo (newbo,-1);
2415 saveState (newbo, "deleteKeepChilds ()", newbo, "addBranchBefore ()",
2416 QString ("Add branch before %1").arg(getName(bo)));
2418 mapCenter->reposition();
2425 void MapEditor::deleteSelection()
2427 BranchObj *bo = xelection.getBranch();
2428 if (bo && xelection.type()==Selection::Branch)
2430 BranchObj* par=(BranchObj*)(bo->getParObj());
2431 xelection.unselect();
2432 saveStateRemovingPart (bo, QString ("Delete %1").arg(getName(bo)));
2433 par->removeBranch(bo);
2434 xelection.select (par);
2435 ensureSelectionVisible();
2436 mapCenter->reposition();
2441 FloatImageObj *fio=xelection.getFloatImage();
2444 BranchObj* par=(BranchObj*)(fio->getParObj());
2445 saveStateChangingPart(
2449 QString("Delete %1").arg(getName(fio))
2451 xelection.unselect();
2452 par->removeFloatImage(fio);
2453 xelection.select (par);
2454 mapCenter->reposition();
2456 ensureSelectionVisible();
2461 LinkableMapObj* MapEditor::getSelection()
2463 return xelection.single();
2466 BranchObj* MapEditor::getSelectedBranch()
2468 return xelection.getBranch();
2471 FloatImageObj* MapEditor::getSelectedFloatImage()
2473 return xelection.getFloatImage();
2476 void MapEditor::unselect()
2478 xelection.unselect();
2481 void MapEditor::reselect()
2483 xelection.reselect();
2486 bool MapEditor::select (const QString &s)
2488 LinkableMapObj *lmo=mapCenter->findObjBySelect(s);
2490 // Finally select the found object
2493 xelection.unselect();
2494 xelection.select(lmo);
2496 ensureSelectionVisible();
2502 QString MapEditor::getSelectString()
2504 return xelection.getSelectString();
2507 void MapEditor::selectInt (LinkableMapObj *lmo)
2509 if (lmo && xelection.single()!= lmo && isSelectBlocked()==false )
2511 xelection.select(lmo);
2516 void MapEditor::selectNextBranchInt()
2518 // Increase number of branch
2519 LinkableMapObj *sel=xelection.single();
2522 QString s=sel->getSelectString();
2528 part=s.section(",",-1);
2530 num=part.right(part.length() - 3);
2532 s=s.left (s.length() -num.length());
2535 num=QString ("%1").arg(num.toUInt()+1);
2539 // Try to select this one
2540 if (select (s)) return;
2542 // We have no direct successor,
2543 // try to increase the parental number in order to
2544 // find a successor with same depth
2546 int d=xelection.single()->getDepth();
2551 while (!found && d>0)
2553 s=s.section (",",0,d-1);
2554 // replace substring of current depth in s with "1"
2555 part=s.section(",",-1);
2557 num=part.right(part.length() - 3);
2561 // increase number of parent
2562 num=QString ("%1").arg(num.toUInt()+1);
2563 s=s.section (",",0,d-2) + ","+ typ+num;
2566 // Special case, look at orientation
2567 if (xelection.single()->getOrientation()==LinkableMapObj::RightOfCenter)
2568 num=QString ("%1").arg(num.toUInt()+1);
2570 num=QString ("%1").arg(num.toUInt()-1);
2575 // pad to oldDepth, select the first branch for each depth
2576 for (i=d;i<oldDepth;i++)
2581 if ( xelection.getBranch()->countBranches()>0)
2589 // try to select the freshly built string
2597 void MapEditor::selectPrevBranchInt()
2599 // Decrease number of branch
2600 BranchObj *bo=xelection.getBranch();
2603 QString s=bo->getSelectString();
2609 part=s.section(",",-1);
2611 num=part.right(part.length() - 3);
2613 s=s.left (s.length() -num.length());
2615 int n=num.toInt()-1;
2618 num=QString ("%1").arg(n);
2621 // Try to select this one
2622 if (n>=0 && select (s)) return;
2624 // We have no direct precessor,
2625 // try to decrease the parental number in order to
2626 // find a precessor with same depth
2628 int d=xelection.single()->getDepth();
2633 while (!found && d>0)
2635 s=s.section (",",0,d-1);
2636 // replace substring of current depth in s with "1"
2637 part=s.section(",",-1);
2639 num=part.right(part.length() - 3);
2643 // decrease number of parent
2644 num=QString ("%1").arg(num.toInt()-1);
2645 s=s.section (",",0,d-2) + ","+ typ+num;
2648 // Special case, look at orientation
2649 if (xelection.single()->getOrientation()==LinkableMapObj::RightOfCenter)
2650 num=QString ("%1").arg(num.toInt()-1);
2652 num=QString ("%1").arg(num.toInt()+1);
2657 // pad to oldDepth, select the last branch for each depth
2658 for (i=d;i<oldDepth;i++)
2662 if ( xelection.getBranch()->countBranches()>0)
2663 s+=",bo:"+ QString ("%1").arg( xelection.getBranch()->countBranches()-1 );
2670 // try to select the freshly built string
2678 void MapEditor::selectUpperBranch()
2680 if (isSelectBlocked() ) return;
2682 BranchObj *bo=xelection.getBranch();
2683 if (bo && xelection.type()==Selection::Branch)
2685 if (bo->getOrientation()==LinkableMapObj::RightOfCenter)
2686 selectPrevBranchInt();
2688 if (bo->getDepth()==1)
2689 selectNextBranchInt();
2691 selectPrevBranchInt();
2695 void MapEditor::selectLowerBranch()
2697 if (isSelectBlocked() ) return;
2699 BranchObj *bo=xelection.getBranch();
2700 if (bo && xelection.type()==Selection::Branch)
2701 if (bo->getOrientation()==LinkableMapObj::RightOfCenter)
2702 selectNextBranchInt();
2704 if (bo->getDepth()==1)
2705 selectPrevBranchInt();
2707 selectNextBranchInt();
2711 void MapEditor::selectLeftBranch()
2713 if (isSelectBlocked() ) return;
2717 LinkableMapObj *sel=xelection.single();
2720 if (xelection.type()== Selection::MapCenter)
2722 par=xelection.getBranch();
2723 bo=par->getLastSelectedBranch();
2726 // Workaround for reselecting on left and right side
2727 if (bo->getOrientation()==LinkableMapObj::RightOfCenter)
2728 bo=par->getLastBranch();
2731 bo=par->getLastBranch();
2732 xelection.select(bo);
2734 ensureSelectionVisible();
2739 par=(BranchObj*)(sel->getParObj());
2740 if (sel->getOrientation()==LinkableMapObj::RightOfCenter)
2742 if (xelection.type() == Selection::Branch ||
2743 xelection.type() == Selection::FloatImage)
2745 xelection.select(par);
2747 ensureSelectionVisible();
2751 if (xelection.type() == Selection::Branch )
2753 bo=xelection.getBranch()->getLastSelectedBranch();
2756 xelection.select(bo);
2758 ensureSelectionVisible();
2766 void MapEditor::selectRightBranch()
2768 if (isSelectBlocked() ) return;
2772 LinkableMapObj *sel=xelection.single();
2775 if (xelection.type()==Selection::MapCenter)
2777 par=xelection.getBranch();
2778 bo=par->getLastSelectedBranch();
2781 // Workaround for reselecting on left and right side
2782 if (bo->getOrientation()==LinkableMapObj::LeftOfCenter)
2783 bo=par->getFirstBranch();
2786 xelection.select(bo);
2788 ensureSelectionVisible();
2793 par=(BranchObj*)(xelection.single()->getParObj());
2794 if (xelection.single()->getOrientation()==LinkableMapObj::LeftOfCenter)
2796 if (xelection.type() == Selection::Branch ||
2797 xelection.type() == Selection::FloatImage)
2799 xelection.select(par);
2801 ensureSelectionVisible();
2805 if (xelection.type() == Selection::Branch)
2807 bo=xelection.getBranch()->getLastSelectedBranch();
2810 xelection.select(bo);
2812 ensureSelectionVisible();
2820 void MapEditor::selectFirstBranch()
2822 BranchObj *bo1=xelection.getBranch();
2827 par=(BranchObj*)(bo1->getParObj());
2828 bo2=par->getFirstBranch();
2830 xelection.select(bo2);
2832 ensureSelectionVisible();
2837 void MapEditor::selectLastBranch()
2839 BranchObj *bo1=xelection.getBranch();
2844 par=(BranchObj*)(bo1->getParObj());
2845 bo2=par->getLastBranch();
2848 xelection.select(bo2);
2850 ensureSelectionVisible();
2855 void MapEditor::selectMapBackgroundImage ()
2857 Q3FileDialog *fd=new Q3FileDialog( this);
2858 fd->setMode (Q3FileDialog::ExistingFile);
2859 fd->addFilter (QString (tr("Images") + " (*.png *.bmp *.xbm *.jpg *.png *.xpm *.gif *.pnm)"));
2860 ImagePreview *p =new ImagePreview (fd);
2861 fd->setContentsPreviewEnabled( TRUE );
2862 fd->setContentsPreview( p, p );
2863 fd->setPreviewMode( Q3FileDialog::Contents );
2864 fd->setCaption(vymName+" - " +tr("Load background image"));
2865 fd->setDir (lastImageDir);
2868 if ( fd->exec() == QDialog::Accepted )
2870 // TODO selectMapBackgroundImg in QT4 use: lastImageDir=fd->directory();
2871 lastImageDir=QDir (fd->dirPath());
2872 setMapBackgroundImage (fd->selectedFile());
2876 void MapEditor::setMapBackgroundImage (const QString &fn) //FIXME missing savestate
2878 QColor oldcol=mapScene->backgroundBrush().color();
2882 QString ("setMapBackgroundImage (%1)").arg(oldcol.name()),
2884 QString ("setMapBackgroundImage (%1)").arg(col.name()),
2885 QString("Set background color of map to %1").arg(col.name()));
2888 brush.setTextureImage (QPixmap (fn));
2889 mapScene->setBackgroundBrush(brush);
2892 void MapEditor::selectMapBackgroundColor()
2894 QColor col = QColorDialog::getColor( mapScene->backgroundBrush().color(), this );
2895 if ( !col.isValid() ) return;
2896 setMapBackgroundColor( col );
2900 void MapEditor::setMapBackgroundColor(QColor col)
2902 QColor oldcol=mapScene->backgroundBrush().color();
2905 QString ("setMapBackgroundColor (\"%1\")").arg(oldcol.name()),
2907 QString ("setMapBackgroundColor (\"%1\")").arg(col.name()),
2908 QString("Set background color of map to %1").arg(col.name()));
2909 mapScene->setBackgroundBrush(col);
2912 QColor MapEditor::getMapBackgroundColor()
2914 return mapScene->backgroundBrush().color();
2917 QColor MapEditor::getCurrentHeadingColor()
2919 BranchObj *bo=xelection.getBranch();
2920 if (bo) return bo->getColor();
2922 QMessageBox::warning(0,tr("Warning"),tr("Can't get color of heading,\nthere's no branch selected"));
2926 void MapEditor::colorBranch (QColor c)
2928 BranchObj *bo=xelection.getBranch();
2933 QString ("colorBranch (\"%1\")").arg(bo->getColor().name()),
2935 QString ("colorBranch (\"%1\")").arg(c.name()),
2936 QString("Set color of %1 to %2").arg(getName(bo)).arg(c.name())
2938 bo->setColor(c); // color branch
2942 void MapEditor::colorSubtree (QColor c)
2944 BranchObj *bo=xelection.getBranch();
2947 saveStateChangingPart(
2950 QString ("colorSubtree (\"%1\")").arg(c.name()),
2951 QString ("Set color of %1 and childs to %2").arg(getName(bo)).arg(c.name())
2953 bo->setColorSubtree (c); // color links, color childs
2958 void MapEditor::toggleStandardFlag(QString f)
2960 BranchObj *bo=xelection.getBranch();
2964 if (bo->isSetStandardFlag(f))
2976 QString("%1 (\"%2\")").arg(u).arg(f),
2978 QString("%1 (\"%2\")").arg(r).arg(f),
2979 QString("Toggling standard flag \"%1\" of %2").arg(f).arg(getName(bo)));
2980 bo->toggleStandardFlag (f,mainWindow->useFlagGroups());
2986 BranchObj* MapEditor::findText (QString s, bool cs)
2988 QTextDocument::FindFlags flags=0;
2989 if (cs) flags=QTextDocument::FindCaseSensitively;
2992 { // Nothing found or new find process
2994 // nothing found, start again
2996 itFind=mapCenter->first();
2998 bool searching=true;
2999 bool foundNote=false;
3000 while (searching && !EOFind)
3004 // Searching in Note
3005 if (itFind->getNote().contains(s,cs))
3007 if (xelection.single()!=itFind)
3009 xelection.select(itFind);
3010 ensureSelectionVisible();
3012 if (textEditor->findText(s,flags))
3018 // Searching in Heading
3019 if (searching && itFind->getHeading().contains (s,cs) )
3021 xelection.select(itFind);
3022 ensureSelectionVisible();
3028 itFind=itFind->next();
3029 if (!itFind) EOFind=true;
3033 return xelection.getBranch();
3038 void MapEditor::findReset()
3039 { // Necessary if text to find changes during a find process
3043 void MapEditor::setURL(const QString &url)
3045 BranchObj *bo=xelection.getBranch();
3048 QString oldurl=bo->getURL();
3052 QString ("setURL (\"%1\")").arg(oldurl),
3054 QString ("setURL (\"%1\")").arg(url),
3055 QString ("set URL of %1 to %2").arg(getName(bo)).arg(url)
3058 mapCenter->reposition();
3060 ensureSelectionVisible();
3064 void MapEditor::editURL()
3066 BranchObj *bo=xelection.getBranch();
3070 QString text = QInputDialog::getText(
3071 "VYM", tr("Enter URL:"), QLineEdit::Normal,
3072 bo->getURL(), &ok, this );
3074 // user entered something and pressed OK
3079 QString MapEditor::getURL()
3081 BranchObj *bo=xelection.getBranch();
3083 return bo->getURL();
3088 QStringList MapEditor::getURLs()
3091 BranchObj *bo=xelection.getBranch();
3097 if (!bo->getURL().isEmpty()) urls.append( bo->getURL());
3105 void MapEditor::editHeading2URL()
3107 BranchObj *bo=xelection.getBranch();
3109 setURL (bo->getHeading());
3112 void MapEditor::editBugzilla2URL()
3114 BranchObj *bo=xelection.getBranch();
3117 QString url= "https://bugzilla.novell.com/show_bug.cgi?id="+bo->getHeading();
3122 void MapEditor::editFATE2URL()
3124 BranchObj *bo=xelection.getBranch();
3127 QString url= "http://keeper.suse.de:8080/webfate/match/id?value=ID"+bo->getHeading();
3130 "setURL (\""+bo->getURL()+"\")",
3132 "setURL (\""+url+"\")",
3133 QString("Use heading of %1 as link to FATE").arg(getName(bo))
3140 void MapEditor::editVymLink()
3142 BranchObj *bo=xelection.getBranch();
3145 QStringList filters;
3146 filters <<"VYM map (*.vym)";
3147 QFileDialog *fd=new QFileDialog( this,vymName+" - " +tr("Link to another map"));
3148 fd->setFilters (filters);
3149 fd->setCaption(vymName+" - " +tr("Link to another map"));
3150 fd->setDirectory (lastFileDir);
3151 if (! bo->getVymLink().isEmpty() )
3152 fd->selectFile( bo->getVymLink() );
3156 if ( fd->exec() == QDialog::Accepted )
3158 lastFileDir=QDir (fd->directory().path());
3161 "setVymLink (\""+bo->getVymLink()+"\")",
3163 "setVymLink (\""+fd->selectedFile()+"\")",
3164 QString("Set vymlink of %1 to %2").arg(getName(bo)).arg(fd->selectedFile())
3166 setVymLinkInt (fd->selectedFile() );
3171 void MapEditor::deleteVymLink()
3173 BranchObj *bo=xelection.getBranch();
3178 "setVymLink (\""+bo->getVymLink()+"\")",
3180 "setVymLink (\"\")",
3181 QString("Unset vymlink of %1").arg(getName(bo))
3183 bo->setVymLink ("" );
3185 mapCenter->reposition();
3190 void MapEditor::setHideExport(bool b)
3192 BranchObj *bo=xelection.getBranch();
3195 bo->setHideInExport (b);
3196 QString u= b ? "false" : "true";
3197 QString r=!b ? "false" : "true";
3201 QString ("setHideExport (%1)").arg(u),
3203 QString ("setHideExport (%1)").arg(r),
3204 QString ("Set HideExport flag of %1 to %2").arg(getName(bo)).arg (r)
3207 mapCenter->reposition();
3213 void MapEditor::toggleHideExport()
3215 BranchObj *bo=xelection.getBranch();
3217 setHideExport ( !bo->hideInExport() );
3220 QString MapEditor::getVymLink()
3222 BranchObj *bo=xelection.getBranch();
3224 return bo->getVymLink();
3230 QStringList MapEditor::getVymLinks()
3233 BranchObj *bo=xelection.getBranch();
3239 if (!bo->getVymLink().isEmpty()) links.append( bo->getVymLink());
3247 void MapEditor::deleteKeepChilds()
3249 BranchObj *bo=xelection.getBranch();
3253 par=(BranchObj*)(bo->getParObj());
3254 QPointF p=bo->getRelPos();
3255 saveStateChangingPart(
3258 "deleteKeepChilds ()",
3259 QString("Remove %1 and keep its childs").arg(getName(bo))
3262 QString sel=bo->getSelectString();
3264 par->removeBranchHere(bo);
3265 mapCenter->reposition();
3267 xelection.getBranch()->move2RelPos (p);
3268 mapCenter->reposition();
3272 void MapEditor::deleteChilds()
3274 BranchObj *bo=xelection.getBranch();
3277 saveStateChangingPart(
3281 QString( "Remove childs of branch %1").arg(getName(bo))
3284 mapCenter->reposition();
3288 void MapEditor::editMapInfo()
3290 ExtraInfoDialog dia;
3291 dia.setMapName (getFileName() );
3292 dia.setAuthor (mapCenter->getAuthor() );
3293 dia.setComment(mapCenter->getComment() );
3297 stats+=tr("%1 items on map\n","Info about map").arg (mapScene->items().size(),6);
3304 bo=mapCenter->first();
3307 if (!bo->getNote().isEmpty() ) n++;
3308 f+= bo->countFloatImages();
3310 xl+=bo->countXLinks();
3313 stats+=QString ("%1 branches\n").arg (b-1,6);
3314 stats+=QString ("%1 xLinks \n").arg (xl,6);
3315 stats+=QString ("%1 notes\n").arg (n,6);
3316 stats+=QString ("%1 images\n").arg (f,6);
3317 dia.setStats (stats);
3319 // Finally show dialog
3320 if (dia.exec() == QDialog::Accepted)
3322 setMapAuthor (dia.getAuthor() );
3323 setMapComment (dia.getComment() );
3327 void MapEditor::ensureSelectionVisible()
3329 LinkableMapObj *lmo=xelection.single();
3330 if (lmo) ensureVisible (lmo->getBBox() );
3334 void MapEditor::updateSelection()
3336 // Tell selection to update geometries
3340 void MapEditor::updateActions()
3342 // Tell mainwindow to update states of actions
3343 mainWindow->updateActions();
3344 // TODO maybe don't update if blockReposition is set
3347 void MapEditor::updateNoteFlag()
3350 BranchObj *bo=xelection.getBranch();
3353 bo->updateNoteFlag();
3354 mainWindow->updateActions();
3358 void MapEditor::setMapAuthor (const QString &s)
3362 QString ("setMapAuthor (\"%1\")").arg(mapCenter->getAuthor()),
3364 QString ("setMapAuthor (\"%1\")").arg(s),
3365 QString ("Set author of map to \"%1\"").arg(s)
3367 mapCenter->setAuthor (s);
3370 void MapEditor::setMapComment (const QString &s)
3374 QString ("setMapComment (\"%1\")").arg(mapCenter->getComment()),
3376 QString ("setMapComment (\"%1\")").arg(s),
3377 QString ("Set comment of map")
3379 mapCenter->setComment (s);
3382 void MapEditor::setMapLinkStyle (const QString & s)
3384 saveStateChangingPart (
3387 QString("setMapLinkStyle (\"%1\")").arg(s),
3388 QString("Set map link style (\"%1\")").arg(s)
3392 linkstyle=LinkableMapObj::Line;
3393 else if (s=="StyleParabel")
3394 linkstyle=LinkableMapObj::Parabel;
3395 else if (s=="StylePolyLine")
3396 linkstyle=LinkableMapObj::PolyLine;
3398 linkstyle=LinkableMapObj::PolyParabel;
3401 bo=mapCenter->first();
3405 bo->setLinkStyle(bo->getDefLinkStyle());
3408 mapCenter->reposition();
3411 LinkableMapObj::Style MapEditor::getMapLinkStyle ()
3416 void MapEditor::setMapDefLinkColor(QColor c)
3420 bo=mapCenter->first();
3429 void MapEditor::setMapLinkColorHintInt()
3431 // called from setMapLinkColorHint(lch) or at end of parse
3433 bo=mapCenter->first();
3441 void MapEditor::setMapLinkColorHint(LinkableMapObj::ColorHint lch)
3444 setMapLinkColorHintInt();
3447 void MapEditor::toggleMapLinkColorHint()
3449 if (linkcolorhint==LinkableMapObj::HeadingColor)
3450 linkcolorhint=LinkableMapObj::DefaultColor;
3452 linkcolorhint=LinkableMapObj::HeadingColor;
3454 bo=mapCenter->first();
3462 LinkableMapObj::ColorHint MapEditor::getMapLinkColorHint()
3464 return linkcolorhint;
3467 QColor MapEditor::getMapDefLinkColor()
3469 return defLinkColor;
3472 void MapEditor::setMapDefXLinkColor(QColor col)
3477 QColor MapEditor::getMapDefXLinkColor()
3479 return defXLinkColor;
3482 void MapEditor::setMapDefXLinkWidth (int w)
3487 int MapEditor::getMapDefXLinkWidth()
3489 return defXLinkWidth;
3492 void MapEditor::selectMapLinkColor()
3494 QColor col = QColorDialog::getColor( defLinkColor, this );
3495 if ( !col.isValid() ) return;
3498 QString("setMapDefLinkColor (\"%1\")").arg(getMapDefLinkColor().name()),
3500 QString("setMapDefLinkColor (\"%1\")").arg(col.name()),
3501 QString("Set map link color to %1").arg(col.name())
3503 setMapDefLinkColor( col );
3506 void MapEditor::selectMapSelectionColor()
3508 QColor col = QColorDialog::getColor( defLinkColor, this );
3509 setSelectionColor (col);
3512 void MapEditor::setSelectionColorInt (QColor col)
3514 if ( !col.isValid() ) return;
3515 xelection.setColor (col);
3518 void MapEditor::setSelectionColor(QColor col)
3520 if ( !col.isValid() ) return;
3523 QString("setSelectionColor (%1)").arg(xelection.getColor().name()),
3525 QString("setSelectionColor (%1)").arg(col.name()),
3526 QString("Set color of selection box to %1").arg(col.name())
3528 setSelectionColorInt (col);
3531 QColor MapEditor::getSelectionColor()
3533 return xelection.getColor();
3536 bool MapEditor::scrollBranch(BranchObj *bo)
3540 if (bo->isScrolled()) return false;
3541 if (bo->countBranches()==0) return false;
3542 if (bo->getDepth()==0) return false;
3548 QString ("%1 ()").arg(u),
3550 QString ("%1 ()").arg(r),
3551 QString ("%1 %2").arg(r).arg(getName(bo))
3561 bool MapEditor::unscrollBranch(BranchObj *bo)
3565 if (!bo->isScrolled()) return false;
3566 if (bo->countBranches()==0) return false;
3567 if (bo->getDepth()==0) return false;
3573 QString ("%1 ()").arg(u),
3575 QString ("%1 ()").arg(r),
3576 QString ("%1 %2").arg(r).arg(getName(bo))
3586 void MapEditor::toggleScroll()
3588 BranchObj *bo=xelection.getBranch();
3589 if (xelection.type()==Selection::Branch )
3591 if (bo->isScrolled())
3592 unscrollBranch (bo);
3598 void MapEditor::unscrollChilds()
3600 BranchObj *bo=xelection.getBranch();
3606 if (bo->isScrolled()) unscrollBranch (bo);
3612 FloatImageObj* MapEditor::loadFloatImageInt (QString fn)
3614 BranchObj *bo=xelection.getBranch();
3618 bo->addFloatImage();
3619 fio=bo->getLastFloatImage();
3621 mapCenter->reposition();
3628 void MapEditor::loadFloatImage ()
3630 BranchObj *bo=xelection.getBranch();
3634 Q3FileDialog *fd=new Q3FileDialog( this);
3635 fd->setMode (Q3FileDialog::ExistingFiles);
3636 fd->addFilter (QString (tr("Images") + " (*.png *.bmp *.xbm *.jpg *.png *.xpm *.gif *.pnm)"));
3637 ImagePreview *p =new ImagePreview (fd);
3638 fd->setContentsPreviewEnabled( TRUE );
3639 fd->setContentsPreview( p, p );
3640 fd->setPreviewMode( Q3FileDialog::Contents );
3641 fd->setCaption(vymName+" - " +tr("Load image"));
3642 fd->setDir (lastImageDir);
3645 if ( fd->exec() == QDialog::Accepted )
3647 // TODO loadFIO in QT4 use: lastImageDir=fd->directory();
3648 lastImageDir=QDir (fd->dirPath());
3651 for (int j=0; j<fd->selectedFiles().count(); j++)
3653 s=fd->selectedFiles().at(j);
3654 fio=loadFloatImageInt (s);
3657 (LinkableMapObj*)fio,
3660 QString ("loadImage (%1)").arg(s ),
3661 QString("Add image %1 to %2").arg(s).arg(getName(bo))
3664 // TODO loadFIO error handling
3665 qWarning ("Failed to load "+s);
3673 void MapEditor::saveFloatImageInt (FloatImageObj *fio, const QString &type, const QString &fn)
3675 fio->save (fn,type);
3678 void MapEditor::saveFloatImage ()
3680 FloatImageObj *fio=xelection.getFloatImage();
3683 QFileDialog *fd=new QFileDialog( this);
3684 fd->setFilters (imageIO.getFilters());
3685 fd->setCaption(vymName+" - " +tr("Save image"));
3686 fd->setFileMode( QFileDialog::AnyFile );
3687 fd->setDirectory (lastImageDir);
3688 // fd->setSelection (fio->getOriginalFilename());
3692 if ( fd->exec() == QDialog::Accepted && fd->selectedFiles().count()==1)
3694 fn=fd->selectedFiles().at(0);
3695 if (QFile (fn).exists() )
3697 QMessageBox mb( vymName,
3698 tr("The file %1 exists already.\n"
3699 "Do you want to overwrite it?").arg(fn),
3700 QMessageBox::Warning,
3701 QMessageBox::Yes | QMessageBox::Default,
3702 QMessageBox::Cancel | QMessageBox::Escape,
3703 QMessageBox::QMessageBox::NoButton );
3705 mb.setButtonText( QMessageBox::Yes, tr("Overwrite") );
3706 mb.setButtonText( QMessageBox::No, tr("Cancel"));
3709 case QMessageBox::Yes:
3712 case QMessageBox::Cancel:
3719 saveFloatImageInt (fio,fd->selectedFilter(),fn );
3725 void MapEditor::setFrameType(const FrameObj::FrameType &t)
3727 BranchObj *bo=xelection.getBranch();
3730 QString s=bo->getFrameTypeName();
3731 bo->setFrameType (t);
3732 saveState (bo, QString("setFrameType (\"%1\")").arg(s),
3733 bo, QString ("setFrameType (\"%1\")").arg(bo->getFrameTypeName()),QString ("set type of frame to %1").arg(s));
3734 mapCenter->reposition();
3739 void MapEditor::setFrameType(const QString &s)
3741 BranchObj *bo=xelection.getBranch();
3744 saveState (bo, QString("setFrameType (\"%1\")").arg(bo->getFrameTypeName()),
3745 bo, QString ("setFrameType (\"%1\")").arg(s),QString ("set type of frame to %1").arg(s));
3746 bo->setFrameType (s);
3747 mapCenter->reposition();
3752 void MapEditor::setFramePenColor(const QColor &c)
3754 BranchObj *bo=xelection.getBranch();
3757 saveState (bo, QString("setFramePenColor (\"%1\")").arg(bo->getFramePenColor().name() ),
3758 bo, QString ("setFramePenColor (\"%1\")").arg(c.name() ),QString ("set pen color of frame to %1").arg(c.name() ));
3759 bo->setFramePenColor (c);
3763 void MapEditor::setFrameBrushColor(const QColor &c)
3765 BranchObj *bo=xelection.getBranch();
3768 saveState (bo, QString("setFrameBrushColor (\"%1\")").arg(bo->getFrameBrushColor().name() ),
3769 bo, QString ("setFrameBrushColor (\"%1\")").arg(c.name() ),QString ("set brush color of frame to %1").arg(c.name() ));
3770 bo->setFrameBrushColor (c);
3774 void MapEditor::setFramePadding (const int &i)
3776 BranchObj *bo=xelection.getBranch();
3779 saveState (bo, QString("setFramePadding (\"%1\")").arg(bo->getFramePadding() ),
3780 bo, QString ("setFramePadding (\"%1\")").arg(i),QString ("set brush color of frame to %1").arg(i));
3781 bo->setFramePadding (i);
3782 mapCenter->reposition();
3787 void MapEditor::setFrameBorderWidth(const int &i)
3789 BranchObj *bo=xelection.getBranch();
3792 saveState (bo, QString("setFrameBorderWidth (\"%1\")").arg(bo->getFrameBorderWidth() ),
3793 bo, QString ("setFrameBorderWidth (\"%1\")").arg(i),QString ("set border width of frame to %1").arg(i));
3794 bo->setFrameBorderWidth (i);
3795 mapCenter->reposition();
3800 void MapEditor::setIncludeImagesVer(bool b)
3802 BranchObj *bo=xelection.getBranch();
3805 QString u= b ? "false" : "true";
3806 QString r=!b ? "false" : "true";
3810 QString("setIncludeImagesVertically (%1)").arg(u),
3812 QString("setIncludeImagesVertically (%1)").arg(r),
3813 QString("Include images vertically in %1").arg(getName(bo))
3815 bo->setIncludeImagesVer(b);
3816 mapCenter->reposition();
3820 void MapEditor::setIncludeImagesHor(bool b)
3822 BranchObj *bo=xelection.getBranch();
3825 QString u= b ? "false" : "true";
3826 QString r=!b ? "false" : "true";
3830 QString("setIncludeImagesHorizontally (%1)").arg(u),
3832 QString("setIncludeImagesHorizontally (%1)").arg(r),
3833 QString("Include images horizontally in %1").arg(getName(bo))
3835 bo->setIncludeImagesHor(b);
3836 mapCenter->reposition();
3840 void MapEditor::setHideLinkUnselected (bool b)
3842 LinkableMapObj *sel=xelection.single();
3844 (xelection.type() == Selection::Branch ||
3845 xelection.type() == Selection::MapCenter ||
3846 xelection.type() == Selection::FloatImage ))
3848 QString u= b ? "false" : "true";
3849 QString r=!b ? "false" : "true";
3853 QString("setHideLinkUnselected (%1)").arg(u),
3855 QString("setHideLinkUnselected (%1)").arg(r),
3856 QString("Hide link of %1 if unselected").arg(getName(sel))
3858 sel->setHideLinkUnselected(b);
3862 void MapEditor::importDirInt(BranchObj *dst, QDir d)
3864 BranchObj *bo=xelection.getBranch();
3867 // Traverse directories
3868 d.setFilter( QDir::Dirs| QDir::Hidden | QDir::NoSymLinks );
3869 QFileInfoList list = d.entryInfoList();
3872 for (int i = 0; i < list.size(); ++i)
3875 if (fi.fileName() != "." && fi.fileName() != ".." )
3878 bo=dst->getLastBranch();
3879 bo->setHeading (fi.fileName() );
3880 bo->setColor (QColor("blue"));
3882 if ( !d.cd(fi.fileName()) )
3883 QMessageBox::critical (0,tr("Critical Import Error"),tr("Cannot find the directory %1").arg(fi.fileName()));
3886 // Recursively add subdirs
3887 importDirInt (bo,d);
3893 d.setFilter( QDir::Files| QDir::Hidden | QDir::NoSymLinks );
3894 list = d.entryInfoList();
3896 for (int i = 0; i < list.size(); ++i)
3900 bo=dst->getLastBranch();
3901 bo->setHeading (fi.fileName() );
3902 bo->setColor (QColor("black"));
3903 if (fi.fileName().right(4) == ".vym" )
3904 bo->setVymLink (fi.filePath());
3909 void MapEditor::importDirInt (const QString &s)
3911 BranchObj *bo=xelection.getBranch();
3914 saveStateChangingPart (bo,bo,QString ("importDir (\"%1\")").arg(s),QString("Import directory structure from %1").arg(s));
3917 importDirInt (bo,d);
3921 void MapEditor::importDir()
3923 BranchObj *bo=xelection.getBranch();
3926 QStringList filters;
3927 filters <<"VYM map (*.vym)";
3928 QFileDialog *fd=new QFileDialog( this,vymName+ " - " +tr("Choose directory structure to import"));
3929 fd->setMode (QFileDialog::DirectoryOnly);
3930 fd->setFilters (filters);
3931 fd->setCaption(vymName+" - " +tr("Choose directory structure to import"));
3935 if ( fd->exec() == QDialog::Accepted )
3937 importDirInt (fd->selectedFile() );
3938 mapCenter->reposition();
3944 void MapEditor::followXLink(int i)
3946 BranchObj *bo=xelection.getBranch();
3949 bo=bo->XLinkTargetAt(i);
3952 xelection.select(bo);
3953 ensureSelectionVisible();
3958 void MapEditor::editXLink(int i) // FIXME missing saveState
3960 BranchObj *bo=xelection.getBranch();
3963 XLinkObj *xlo=bo->XLinkAt(i);
3966 EditXLinkDialog dia;
3968 dia.setSelection(bo);
3969 if (dia.exec() == QDialog::Accepted)
3971 if (dia.useSettingsGlobal() )
3973 setMapDefXLinkColor (xlo->getColor() );
3974 setMapDefXLinkWidth (xlo->getWidth() );
3976 if (dia.deleteXLink())
3977 bo->deleteXLinkAt(i);
3983 void MapEditor::testFunction()
3985 mainWindow->statusMessage("Biiiiiiiiiiiiiiing!");
3988 BranchObj *bo=xelection.getBranch();
3989 if (bo) animObjList.append( bo );
3993 dia.showCancelButton (true);
3994 dia.setText("This is a longer \nWarning");
3995 dia.setCaption("Warning: Flux problem");
3996 dia.setShowAgainName("mapeditor/testDialog");
3997 if (dia.exec()==QDialog::Accepted)
3998 cout << "accepted!\n";
4000 cout << "canceled!\n";
4004 /* TODO Hide hidden stuff temporary, maybe add this as regular function somewhere
4005 if (hidemode==HideNone)
4007 setHideTmpMode (HideExport);
4008 mapCenter->calcBBoxSizeWithChilds();
4009 QRectF totalBBox=mapCenter->getTotalBBox();
4010 QRectF mapRect=totalBBox;
4011 QCanvasRectangle *frame=NULL;
4013 cout << " map has =("<<totalBBox.x()<<","<<totalBBox.y()<<","<<totalBBox.width()<<","<<totalBBox.height()<<")\n";
4015 mapRect.setRect (totalBBox.x(), totalBBox.y(),
4016 totalBBox.width(), totalBBox.height());
4017 frame=new QCanvasRectangle (mapRect,mapScene);
4018 frame->setBrush (QColor(white));
4019 frame->setPen (QColor(black));
4020 frame->setZValue(0);
4025 setHideTmpMode (HideNone);
4027 cout <<" hidemode="<<hidemode<<endl;
4031 void MapEditor::contextMenuEvent ( QContextMenuEvent * e )
4033 // Lineedits are already closed by preceding
4034 // mouseEvent, we don't need to close here.
4036 QPointF p = mapToScene(e->pos());
4037 LinkableMapObj* lmo=mapCenter->findMapObj(p, NULL);
4040 { // MapObj was found
4041 if (xelection.single() != lmo)
4043 // select the MapObj
4044 xelection.select(lmo);
4047 if (xelection.getBranch() )
4049 // Context Menu on branch or mapcenter
4051 branchContextMenu->popup(e->globalPos() );
4054 if (xelection.getFloatImage() )
4056 // Context Menu on floatimage
4058 floatimageContextMenu->popup(e->globalPos() );
4062 { // No MapObj found, we are on the Canvas itself
4063 // Context Menu on scene
4065 canvasContextMenu->popup(e->globalPos() );
4070 void MapEditor::keyPressEvent(QKeyEvent* e)
4072 if (e->modifiers() & Qt::ControlModifier)
4074 switch (mainWindow->getModMode())
4076 case Main::ModModeColor:
4077 setCursor (PickColorCursor);
4079 case Main::ModModeCopy:
4080 setCursor (CopyCursor);
4082 case Main::ModModeXLink:
4083 setCursor (XLinkCursor);
4086 setCursor (Qt::ArrowCursor);
4092 void MapEditor::keyReleaseEvent(QKeyEvent* e)
4094 if (!(e->modifiers() & Qt::ControlModifier))
4095 setCursor (Qt::ArrowCursor);
4098 void MapEditor::mousePressEvent(QMouseEvent* e)
4100 // Ignore right clicks, these will go to context menus
4101 if (e->button() == Qt::RightButton )
4107 //Ignore clicks while editing heading
4108 if (isSelectBlocked() )
4114 QPointF p = mapToScene(e->pos());
4115 LinkableMapObj* lmo=mapCenter->findMapObj(p, NULL);
4119 //Take care of system flags _or_ modifier modes
4121 if (lmo && (typeid(*lmo)==typeid(BranchObj) ||
4122 typeid(*lmo)==typeid(MapCenterObj) ))
4124 QString foname=((BranchObj*)lmo)->getSystemFlagName(p);
4125 if (!foname.isEmpty())
4127 // systemFlag clicked
4131 if (e->state() & Qt::ControlModifier)
4132 mainWindow->editOpenURLTab();
4134 mainWindow->editOpenURL();
4136 else if (foname=="vymLink")
4138 mainWindow->editOpenVymLink();
4139 // tabWidget may change, better return now
4140 // before segfaulting...
4141 } else if (foname=="note")
4142 mainWindow->windowToggleNoteEditor();
4143 else if (foname=="hideInExport")
4150 // No system flag clicked, take care of modmodes (CTRL-Click)
4151 if (e->state() & Qt::ControlModifier)
4153 if (mainWindow->getModMode()==Main::ModModeColor)
4156 setCursor (PickColorCursor);
4159 if (mainWindow->getModMode()==Main::ModModeXLink)
4161 BranchObj *bo_begin=NULL;
4163 bo_begin=(BranchObj*)(lmo);
4165 if (xelection.getBranch() )
4166 bo_begin=xelection.getBranch();
4170 linkingObj_src=bo_begin;
4171 tmpXLink=new XLinkObj (mapScene);
4172 tmpXLink->setBegin (bo_begin);
4173 tmpXLink->setEnd (p);
4174 tmpXLink->setColor(defXLinkColor);
4175 tmpXLink->setWidth(defXLinkWidth);
4176 tmpXLink->updateXLink();
4177 tmpXLink->setVisibility (true);
4181 } // End of modmodes
4185 // Select the clicked object
4188 // Left Button Move Branches
4189 if (e->button() == Qt::LeftButton )
4191 //movingObj_start.setX( p.x() - selection->x() );// TODO replaced selection->lmo here
4192 //movingObj_start.setY( p.y() - selection->y() );
4193 movingObj_start.setX( p.x() - lmo->x() );
4194 movingObj_start.setY( p.y() - lmo->y() );
4195 movingObj_orgPos.setX (lmo->x() );
4196 movingObj_orgPos.setY (lmo->y() );
4197 movingObj_orgRelPos=lmo->getRelPos();
4199 // If modMode==copy, then we want to "move" the _new_ object around
4200 // then we need the offset from p to the _old_ selection, because of tmp
4201 if (mainWindow->getModMode()==Main::ModModeCopy &&
4202 e->state() & Qt::ControlModifier)
4204 if (xelection.type()==Selection::Branch)
4207 mapCenter->addBranch ((BranchObj*)xelection.single());
4209 xelection.select(mapCenter->getLastBranch());
4210 mapCenter->reposition();
4214 movingObj=xelection.single();
4216 // Middle Button Toggle Scroll
4217 // (On Mac OS X this won't work, but we still have
4218 // a button in the toolbar)
4219 if (e->button() == Qt::MidButton )
4224 { // No MapObj found, we are on the scene itself
4225 // Left Button move Pos of sceneView
4226 if (e->button() == Qt::LeftButton )
4228 movingObj=NULL; // move Content not Obj
4229 movingObj_start=e->globalPos();
4230 movingCont_start=QPointF (
4231 horizontalScrollBar()->value(),
4232 verticalScrollBar()->value());
4233 movingVec=QPointF(0,0);
4234 setCursor(HandOpenCursor);
4239 void MapEditor::mouseMoveEvent(QMouseEvent* e)
4241 QPointF p = mapToScene(e->pos());
4242 LinkableMapObj *lmosel=xelection.single();
4244 // Move the selected MapObj
4245 if ( lmosel && movingObj)
4247 // reset cursor if we are moving and don't copy
4248 if (mainWindow->getModMode()!=Main::ModModeCopy)
4249 setCursor (Qt::ArrowCursor);
4251 // To avoid jumping of the sceneView, only
4252 // ensureSelectionVisible, if not tmp linked
4253 if (!lmosel->hasParObjTmp())
4254 ensureSelectionVisible ();
4256 // Now move the selection, but add relative position
4257 // (movingObj_start) where selection was chosen with
4258 // mousepointer. (This avoids flickering resp. jumping
4259 // of selection back to absPos)
4261 // Check if we could link
4262 LinkableMapObj* lmo=mapCenter->findMapObj(p, lmosel);
4265 FloatObj *fio=xelection.getFloatImage();
4268 fio->move (p.x() -movingObj_start.x(), p.y()-movingObj_start.y() );
4270 fio->updateLink(); //no need for reposition, if we update link here
4273 // Relink float to new mapcenter or branch, if shift is pressed
4274 // Only relink, if selection really has a new parent
4275 if ( (e->modifiers()==Qt::ShiftModifier) && lmo &&
4276 ( (typeid(*lmo)==typeid(BranchObj)) ||
4277 (typeid(*lmo)==typeid(MapCenterObj)) ) &&
4278 ( lmo != fio->getParObj())
4281 if (typeid(*fio) == typeid(FloatImageObj) &&
4282 ( (typeid(*lmo)==typeid(BranchObj) ||
4283 typeid(*lmo)==typeid(MapCenterObj)) ))
4286 // Also save the move which was done so far
4287 QString pold=qpointfToString(movingObj_orgRelPos);
4288 QString pnow=qpointfToString(fio->getRelPos());
4294 QString("Move %1 to relativ position %2").arg(getName(fio)).arg(pnow));
4295 fio->getParObj()->requestReposition();
4296 mapCenter->reposition();
4298 linkTo (lmo->getSelectString());
4300 //movingObj_orgRelPos=lmosel->getRelPos();
4302 mapCenter->reposition();
4306 { // selection != a FloatObj
4307 if (lmosel->getDepth()==0)
4310 if (e->buttons()== Qt::LeftButton && e->modifiers()==Qt::ShiftModifier)
4311 mapCenter->moveAll(p.x() -movingObj_start.x(), p.y()-movingObj_start.y() );
4313 mapCenter->move (p.x() -movingObj_start.x(), p.y()-movingObj_start.y() );
4314 mapCenter->updateRelPositions();
4317 if (lmosel->getDepth()==1)
4320 lmosel->move(p.x() -movingObj_start.x(), p.y()-movingObj_start.y() );
4321 lmosel->setRelPos();
4324 // Move ordinary branch
4325 if (lmosel->getOrientation() == LinkableMapObj::LeftOfCenter)
4326 // Add width of bbox here, otherwise alignRelTo will cause jumping around
4327 lmosel->move(p.x() -movingObj_start.x()+lmosel->getBBox().width(),
4328 p.y()-movingObj_start.y() +lmosel->getTopPad() );
4330 lmosel->move(p.x() -movingObj_start.x(), p.y()-movingObj_start.y() -lmosel->getTopPad());
4333 // Maybe we can relink temporary?
4334 if (lmo && (lmo!=lmosel) && xelection.getBranch() &&
4335 (typeid(*lmo)==typeid(BranchObj) ||
4336 typeid(*lmo)==typeid(MapCenterObj)) )
4339 if (e->modifiers()==Qt::ControlModifier)
4341 // Special case: CTRL to link below lmo
4342 lmosel->setParObjTmp (lmo,p,+1);
4344 else if (e->modifiers()==Qt::ShiftModifier)
4345 lmosel->setParObjTmp (lmo,p,-1);
4347 lmosel->setParObjTmp (lmo,p,0);
4350 lmosel->unsetParObjTmp();
4352 // reposition subbranch
4353 lmosel->reposition();
4357 } // no FloatImageObj
4361 } // selection && moving_obj
4363 // Draw a link from one branch to another
4366 tmpXLink->setEnd (p);
4367 tmpXLink->updateXLink();
4371 if (!movingObj && !pickingColor &&!drawingLink && e->buttons() == Qt::LeftButton )
4373 QPointF p=e->globalPos();
4374 movingVec.setX(-p.x() + movingObj_start.x() );
4375 movingVec.setY(-p.y() + movingObj_start.y() );
4376 horizontalScrollBar()->setSliderPosition((int)( movingCont_start.x()+movingVec.x() ));
4377 verticalScrollBar()->setSliderPosition((int)( movingCont_start.y()+movingVec.y() ) );
4382 void MapEditor::mouseReleaseEvent(QMouseEvent* e)
4384 QPointF p = mapToScene(e->pos());
4385 LinkableMapObj *dst;
4386 LinkableMapObj *lmosel=xelection.single();
4387 // Have we been picking color?
4391 setCursor (Qt::ArrowCursor);
4392 // Check if we are over another branch
4393 dst=mapCenter->findMapObj(p, NULL);
4396 if (e->state() & Qt::ShiftModifier)
4397 colorBranch (((BranchObj*)(dst))->getColor());
4399 colorSubtree (((BranchObj*)(dst))->getColor());
4404 // Have we been drawing a link?
4408 // Check if we are over another branch
4409 dst=mapCenter->findMapObj(p, NULL);
4412 tmpXLink->setEnd ( ((BranchObj*)(dst)) );
4413 tmpXLink->updateXLink();
4414 tmpXLink->activate(); //FIXME savestate missing
4415 //saveStateComplete(QString("Activate xLink from %1 to %2").arg(getName(tmpXLink->getBegin())).arg(getName(tmpXLink->getEnd())) );
4424 // Have we been moving something?
4425 if ( lmosel && movingObj )
4427 FloatImageObj *fo=xelection.getFloatImage();
4430 // Moved FloatObj. Maybe we need to reposition
4431 QString pold=qpointfToString(movingObj_orgRelPos);
4432 QString pnow=qpointfToString(fo->getRelPos());
4438 QString("Move %1 to relativ position %2").arg(getName(fo)).arg(pnow));
4440 fo->getParObj()->requestReposition();
4441 mapCenter->reposition();
4444 // Check if we are over another branch, but ignore
4445 // any found LMOs, which are FloatObjs
4446 dst=mapCenter->findMapObj(mapToScene(e->pos() ), lmosel);
4448 if (dst && (typeid(*dst)!=typeid(BranchObj) && typeid(*dst)!=typeid(MapCenterObj)))
4451 if (xelection.type() == Selection::MapCenter )
4453 // TODO: Check for problems if graphicsview is resized for
4455 QString pold=qpointfToString(movingObj_orgPos);
4456 QString pnow=qpointfToString(mapCenter->getAbsPos());
4462 QString("Move mapcenter %1 to position %2").arg(getName(mapCenter)).arg(pnow));
4465 if (xelection.type() == Selection::Branch )
4466 { // A branch was moved
4468 // save the position in case we link to mapcenter
4469 QPointF savePos=QPointF (lmosel->getAbsPos() );
4471 // Reset the temporary drawn link to the original one
4472 lmosel->unsetParObjTmp();
4474 // For Redo we may need to save original selection
4475 QString preSelStr=lmosel->getSelectString();
4480 BranchObj* bsel=xelection.getBranch();
4481 BranchObj* bdst=(BranchObj*)dst;
4483 QString preParStr=(bsel->getParObj())->getSelectString();
4484 QString preNum=QString::number (bsel->getNum(),10);
4485 QString preDstParStr;
4487 if (e->state() & Qt::ShiftModifier && dst->getParObj())
4489 preDstParStr=dst->getParObj()->getSelectString();
4490 bsel->linkTo ( (BranchObj*)(bdst->getParObj()), bdst->getNum());
4492 if (e->state() & Qt::ControlModifier && dst->getParObj())
4495 preDstParStr=dst->getParObj()->getSelectString();
4496 bsel->linkTo ( (BranchObj*)(bdst->getParObj()), bdst->getNum()+1);
4499 preDstParStr=dst->getSelectString();
4500 bsel->linkTo (bdst,-1);
4501 if (dst->getDepth()==0) bsel->move (savePos);
4503 QString postSelStr=lmosel->getSelectString();
4504 QString postNum=QString::number (bsel->getNum(),10);
4506 QString undoCom="linkTo (\""+
4507 preParStr+ "\"," + preNum +"," +
4508 QString ("%1,%2").arg(movingObj_orgPos.x()).arg(movingObj_orgPos.y())+ ")";
4510 QString redoCom="linkTo (\""+
4511 preDstParStr + "\"," + postNum + "," +
4512 QString ("%1,%2").arg(savePos.x()).arg(savePos.y())+ ")";
4517 QString("Relink %1 to %2").arg(getName(bsel)).arg(getName(dst)) );
4519 if (lmosel->getDepth()==1)
4521 // The select string might be different _after_ moving around.
4522 // Therefor reposition and then use string of old selection, too
4523 mapCenter->reposition();
4525 QString ps=qpointfToString ( lmosel->getRelPos() );
4527 lmosel->getSelectString(), "moveRel "+qpointfToString(movingObj_orgRelPos),
4528 preSelStr, "moveRel "+ps,
4529 QString("Move %1 to relative position %2").arg(getName(lmosel)).arg(ps));
4532 // Draw the original link, before selection was moved around
4533 mapCenter->reposition();
4536 // Finally resize scene, if needed
4540 // Just make sure, that actions are still ok,e.g. the move branch up/down buttons...
4543 // maybe we moved View: set old cursor
4544 setCursor (Qt::ArrowCursor);
4548 void MapEditor::mouseDoubleClickEvent(QMouseEvent* e)
4550 if (isSelectBlocked() )
4556 if (e->button() == Qt::LeftButton )
4558 QPointF p = mapToScene(e->pos());
4559 LinkableMapObj *lmo=mapCenter->findMapObj(p, NULL);
4560 if (lmo) { // MapObj was found
4561 // First select the MapObj than edit heading
4562 xelection.select(lmo);
4563 mainWindow->editHeading();
4568 void MapEditor::resizeEvent (QResizeEvent* e)
4570 QGraphicsView::resizeEvent( e );
4573 void MapEditor::dragEnterEvent(QDragEnterEvent *event)
4575 //for (unsigned int i=0;event->format(i);i++) // Debug mime type
4576 // cerr << event->format(i) << endl;
4578 if (event->mimeData()->hasImage())
4579 event->acceptProposedAction();
4581 if (event->mimeData()->hasUrls())
4582 event->acceptProposedAction();
4585 void MapEditor::dragMoveEvent(QDragMoveEvent *event)
4589 void MapEditor::dragLeaveEvent(QDragLeaveEvent *event)
4594 void MapEditor::dropEvent(QDropEvent *event)
4596 BranchObj *sel=xelection.getBranch();
4600 foreach (QString format,event->mimeData()->formats())
4601 cout << "MapEditor: Dropped format: "<<format.ascii()<<endl;
4605 if (event->mimeData()->hasImage())
4607 QVariant imageData = event->mimeData()->imageData();
4608 addFloatImageInt (qvariant_cast<QPixmap>(imageData));
4610 if (event->mimeData()->hasUrls())
4611 uris=event->mimeData()->urls();
4619 for (int i=0; i<uris.count();i++)
4621 // Workaround to avoid adding empty branches
4622 if (!uris.at(i).toString().isEmpty())
4624 bo=sel->addBranch();
4627 s=uris.at(i).toLocalFile();
4630 QString file = QDir::convertSeparators(s);
4631 heading = QFileInfo(file).baseName();
4633 if (file.endsWith(".vym", false))
4634 bo->setVymLink(file);
4636 bo->setURL(uris.at(i).toString());
4639 bo->setURL(uris.at(i).toString());
4642 if (!heading.isEmpty())
4643 bo->setHeading(heading);
4645 bo->setHeading(uris.at(i).toString());
4649 mapCenter->reposition();
4652 event->acceptProposedAction();
4655 void MapEditor::timerEvent(QTimerEvent *event) //TODO animation
4659 cout << "ME::timerEvent\n";
4661 for (int i=0; i<animObjList.size(); ++i)
4663 animObjList.at(i)->animate();
4664 ((BranchObj*)animObjList.at(i))->move2RelPos (((BranchObj*)animObjList.at(i))->getRelPos() );
4666 mapCenter->reposition();
4669 void MapEditor::autosave()
4671 // Disable autosave, while we have gone back in history
4672 int redosAvail=undoSet.readNumEntry (QString("/history/redosAvail"));
4673 if (redosAvail>0) return;
4676 if (mapUnsaved &&mapChanged && settings.value ("/mapeditor/autosave/use",true).toBool() )
4677 mainWindow->fileSave (this);
4681 /*TODO not needed? void MapEditor::contentsDropEvent(QDropEvent *event)
4684 } else if (event->provides("application/x-moz-file-promise-url") &&
4685 event->provides("application/x-moz-nativeimage"))
4687 // Contains url to the img src in unicode16
4688 QByteArray d = event->encodedData("application/x-moz-file-promise-url");
4689 QString url = QString((const QChar*)d.data(),d.size()/2);
4693 } else if (event->provides ("text/uri-list"))
4694 { // Uris provided e.g. by konqueror
4695 Q3UriDrag::decode (event,uris);
4696 } else if (event->provides ("_NETSCAPE_URL"))
4697 { // Uris provided by Mozilla
4698 QStringList l = QStringList::split("\n", event->encodedData("_NETSCAPE_URL"));
4701 } else if (event->provides("text/html")) {
4703 // Handels text mime types
4704 // Look like firefox allways handle text as unicode16 (2 bytes per char.)
4705 QByteArray d = event->encodedData("text/html");
4708 text = QString((const QChar*)d.data(),d.size()/2);
4712 textEditor->setText(text);
4716 } else if (event->provides("text/plain")) {
4717 QByteArray d = event->encodedData("text/plain");
4720 text = QString((const QChar*)d.data(),d.size()/2);
4724 textEditor->setText(text);
4734 bool isUnicode16(const QByteArray &d)
4736 // TODO: make more precise check for unicode 16.
4737 // Guess unicode16 if any of second bytes are zero
4738 unsigned int length = max(0,d.size()-2)/2;
4739 for (unsigned int i = 0; i<length ; i++)
4740 if (d.at(i*2+1)==0) return true;
4744 void MapEditor::addFloatImageInt (const QPixmap &img)
4746 BranchObj *bo=xelection.getBranch();
4749 FloatImageObj *fio=bo->addFloatImage();
4751 fio->setOriginalFilename("No original filename (image added by dropevent)");
4752 QString s=bo->getSelectString();
4753 saveState (PartOfMap, s, "nop ()", s, "copy ()","Copy dropped image to clipboard",fio );
4754 saveState (fio,"delete ()", bo,QString("paste(%1)").arg(curStep),"Pasting dropped image");
4755 mapCenter->reposition();
4762 void MapEditor::imageDataFetched(const QByteArray &a, Q3NetworkOperation * / *nop* /)
4764 if (!imageBuffer) imageBuffer = new QBuffer();
4765 if (!imageBuffer->isOpen()) {
4766 imageBuffer->open(QIODevice::WriteOnly | QIODevice::Append);
4768 imageBuffer->at(imageBuffer->at()+imageBuffer->writeBlock(a));
4772 void MapEditor::imageDataFinished(Q3NetworkOperation *nop)
4774 if (nop->state()==Q3NetworkProtocol::StDone) {
4775 QPixmap img(imageBuffer->buffer());
4776 addFloatImageInt (img);
4780 imageBuffer->close();
4782 imageBuffer->close();
4789 void MapEditor::fetchImage(const QString &url)
4792 urlOperator->stop();
4793 disconnect(urlOperator);
4797 urlOperator = new Q3UrlOperator(url);
4798 connect(urlOperator, SIGNAL(finished(Q3NetworkOperation *)),
4799 this, SLOT(imageDataFinished(Q3NetworkOperation*)));
4801 connect(urlOperator, SIGNAL(data(const QByteArray &, Q3NetworkOperation *)),
4802 this, SLOT(imageDataFetched(const QByteArray &, Q3NetworkOperation *)));