3 #include <q3dragobject.h>
4 #include <q3urloperator.h>
5 #include <q3networkprotocol.h>
6 #include <q3paintdevicemetrics.h>
7 #include <q3filedialog.h>
16 #include "editxlinkdialog.h"
18 #include "extrainfodialog.h"
20 #include "linkablemapobj.h"
21 #include "mainwindow.h"
23 #include "texteditor.h"
24 #include "warningdialog.h"
28 extern TextEditor *textEditor;
29 extern int statusbarTime;
30 extern Main *mainWindow;
31 extern QString tmpVymDir;
32 extern QString clipboardDir;
33 extern bool clipboardEmpty;
34 extern FlagRowObj *standardFlagsDefault;
36 extern QMenu* branchContextMenu;
37 extern QMenu* branchAddContextMenu;
38 extern QMenu* branchRemoveContextMenu;
39 extern QMenu* branchLinksContextMenu;
40 extern QMenu* branchXLinksContextMenuEdit;
41 extern QMenu* branchXLinksContextMenuFollow;
42 extern QMenu* floatimageContextMenu;
43 extern QMenu* saveImageFormatMenu;
44 extern QMenu* canvasContextMenu;
45 extern QMenu* lastMapsMenu;
46 extern QMenu* importMenu;
47 extern QMenu* exportMenu;
50 extern Settings settings;
51 extern ImageIO imageIO;
53 extern QString iconPath;
54 extern QDir vymBaseDir;
55 extern QDir lastImageDir;
57 int MapEditor::mapNum=0; // make instance
59 ///////////////////////////////////////////////////////////////////////
60 ///////////////////////////////////////////////////////////////////////
62 QWidget* parent, const char* name, Qt::WFlags f) :
63 Q3CanvasView(parent,name,f), urlOperator(0), imageBuffer(0)
65 //cout << "Constructor ME "<<this<<endl;
68 viewport()->setAcceptDrops(true);
70 mapCanvas = new Q3Canvas(width(),height());
71 mapCanvas->setAdvancePeriod(30);
72 mapCanvas->setBackgroundColor (Qt::white);
74 setCanvas (mapCanvas);
76 // Always show scroll bars (automatic would flicker sometimes)
77 setVScrollBarMode ( Q3ScrollView::AlwaysOn );
78 setHScrollBarMode ( Q3ScrollView::AlwaysOn );
80 mapCenter = new MapCenterObj(mapCanvas);
81 mapCenter->setVisibility (true);
82 mapCenter->setMapEditor (this);
83 mapCenter->setHeading (tr("New Map","Heading of mapcenter in new map"));
84 mapCenter->move(mapCanvas->width()/2-mapCenter->width()/2,mapCanvas->height()/2-mapCenter->height()/2);
88 defLinkColor=QColor (0,0,255);
89 defXLinkColor=QColor (180,180,180);
90 linkcolorhint=DefaultColor;
91 linkstyle=StylePolyParabel;
93 // Create bitmap cursors, platform dependant
94 // FIXME should now work also on Mac...
95 //#if defined(Q_OS_MACX)
96 // HandOpenCursor=QCursor ( QPixmap(iconPath+"cursorhandopen16.png"),1,1 );
97 // PickColorCursor=QCursor ( QPixmap (iconPath+"cursorcolorpicker16.png"), 1,15 );
99 HandOpenCursor=QCursor (QPixmap(iconPath+"cursorhandopen.png"),1,1);
100 PickColorCursor=QCursor ( QPixmap(iconPath+"cursorcolorpicker.png"), 5,27 );
101 CopyCursor=QCursor ( QPixmap(iconPath+"cursorcopy.png"), 5,5 );
102 XLinkCursor=QCursor ( QPixmap(iconPath+"cursorxlink.png"), 5,27 );
105 setFocusPolicy (Qt::StrongFocus);
116 xelection.setMapCenter (mapCenter);
119 defXLinkColor=QColor (230,230,230);
127 fileName=tr("unnamed");
130 stepsTotal=settings.readNumEntry("/mapeditor/stepsTotal",100);
131 undoSet.setEntry ("/history/stepsTotal",QString::number(stepsTotal));
133 // Initialize find routine
140 blockReposition=false;
141 blockSaveState=false;
145 // Create temporary files
148 // Initially set movingCentre
151 mapCenter->reposition(); // for positioning heading
153 // Initialize history window;
154 historyWindow.setME(this);
155 historyWindow.setStepsTotal(stepsTotal);
156 historyWindow.update (undoSet);
159 MapEditor::~MapEditor()
161 if (imageBuffer) delete imageBuffer;
167 //cout <<"Destructor MapEditor\n";
170 MapCenterObj* MapEditor::getMapCenter()
175 Q3Canvas* MapEditor::getCanvas()
180 void MapEditor::adjustCanvasSize()
182 // To adjust the canvas to map, viewport size and position, we have to
183 // do some coordinate magic...
185 // Get rectangle of (scroll-)view.
186 // We want to be in canvas coords, so
187 // we map. Important if view is zoomed...
188 QRect view = inverseWorldMatrix().mapRect( QRect( contentsX(), contentsY(),
189 visibleWidth(), visibleHeight()) );
191 // Now we need the bounding box of view AND map to calc the correct canvas size.
192 // Why? Because if the map itself is moved out of view, the view has to be enlarged
193 // to avoid jumping aroung...
194 QRect map=mapCenter->getTotalBBox();
196 // right edge - left edge
197 int cw= max(map.x() + map.width(), view.x() + view.width()) - min(map.x(), view.x());
198 int ch= max(map.y() + map.height(), view.y() + view.height()) - min(map.y(), view.y());
201 if ( (cw!=mapCanvas->width()) || (ch!=mapCanvas->height()) ||
202 !mapCanvas->onCanvas (map.topLeft()) || !mapCanvas->onCanvas (map.bottomRight())
205 // move the map on canvas (in order to not move it on screen) this is neccessary
206 // a) if topleft corner of canvas is left or above topleft corner of view and also left of
207 // above topleft corner of map. E.g. if map is completly inside view, but it would be possible
208 // to scroll to an empty area of canvas to the left.
209 // b) if topleft corner of map left of or above topleft of canvas
213 if (cw > mapCanvas->width() )
215 if (map.x()<0) dx=-map.x();
217 if (cw < mapCanvas->width() )
218 dx=-min (view.x(),map.x());
219 if (ch > mapCanvas->height() )
221 if (map.y()<0) dy=-map.y();
223 if (ch < mapCanvas->height() )
225 dy=-min (view.y(),map.y());
227 // We really have to resize now. Let's go...
228 mapCanvas->resize (cw,ch);
229 if ( (dx!=0) || (dy!=0) )
231 mapCenter->moveAllBy(dx,dy);
232 mapCenter->reposition();
233 // mapCenter->positionBBox(); // To move float
235 // scroll the view (in order to not move map on screen)
241 bool MapEditor::isRepositionBlocked()
243 return blockReposition;
246 QString MapEditor::getName (LinkableMapObj *lmo)
249 if (!lmo) return QString("Error: NULL has no name!");
251 if ((typeid(*lmo) == typeid(BranchObj) ||
252 typeid(*lmo) == typeid(MapCenterObj)))
255 s=(((BranchObj*)lmo)->getHeading());
256 if (s=="") s="unnamed";
257 return QString("branch (%1)").arg(s);
258 //return QString("branch (<font color=\"#0000ff\">%1</font>)").arg(s);
260 if ((typeid(*lmo) == typeid(FloatImageObj) ))
261 return QString ("floatimage [%1]").arg(((FloatImageObj*)lmo)->getOriginalFilename());
262 //return QString ("floatimage [<font color=\"#0000ff\">%1</font>]").arg(((FloatImageObj*)lmo)->getOriginalFilename());
263 return QString("Unknown type has no name!");
266 void MapEditor::makeTmpDirs()
268 // Create unique temporary directories
269 tmpMapDir=QDir::convertSeparators (tmpVymDir+QString("/mapeditor-%1").arg(mapNum));
270 histPath=QDir::convertSeparators (tmpMapDir+"/history");
275 QString MapEditor::saveToDir(const QString &tmpdir, const QString &prefix, bool writeflags, const QPoint &offset, LinkableMapObj *saveSel)
277 // tmpdir temporary directory to which data will be written
278 // prefix mapname, which will be appended to images etc.
279 // writeflags Only write flags for "real" save of map, not undo
280 // offset offset of bbox of whole map in canvas.
281 // Needed for XML export
297 ls="StylePolyParabel";
301 QString s="<?xml version=\"1.0\" encoding=\"utf-8\"?><!DOCTYPE vymmap>\n";
303 if (linkcolorhint==HeadingColor)
304 colhint=attribut("linkColorHint","HeadingColor");
306 QString mapAttr=attribut("version",__VYM_VERSION);
307 if (!saveSel || saveSel==mapCenter)
308 mapAttr+= attribut("author",mapCenter->getAuthor()) +
309 attribut("comment",mapCenter->getComment()) +
310 attribut("date",mapCenter->getDate()) +
311 attribut("backgroundColor", mapCanvas->backgroundColor().name() ) +
312 attribut("linkStyle", ls ) +
313 attribut("linkColor", defLinkColor.name() ) +
314 attribut("defXLinkColor", defXLinkColor.name() ) +
315 attribut("defXLinkWidth", QString().setNum(defXLinkWidth,10) ) +
317 s+=beginElement("vymmap",mapAttr);
320 // Find the used flags while traversing the tree
321 standardFlagsDefault->resetUsedCounter();
323 // Reset the counters before saving
324 FloatImageObj (mapCanvas).resetSaveCounter();
326 // Build xml recursivly
327 if (!saveSel || typeid (*saveSel) == typeid (MapCenterObj))
328 // Save complete map, if saveSel not set
329 s+=mapCenter->saveToDir(tmpdir,prefix,writeflags,offset);
332 if ( typeid(*saveSel) == typeid(BranchObj) )
334 s+=((BranchObj*)(saveSel))->saveToDir(tmpdir,prefix,offset);
335 else if ( typeid(*saveSel) == typeid(FloatImageObj) )
337 s+=((FloatImageObj*)(saveSel))->saveToDir(tmpdir,prefix);
339 else if (selection && typeid(*selection)==typeid(BranchObj))
340 // Save selected branch is saved from mainwindow //FIXME maybe use "subtree" above?
341 // FIXME is this possible at all? BO is already above...
342 s+=((BranchObj*)selection)->saveToDir(tmpdir,prefix,offset);
345 // Save local settings
346 s+=settings.getXMLData (destPath);
349 if (selection && !saveSel )
350 s+=valueElement("select",selection->getSelectString());
353 s+=endElement("vymmap");
356 standardFlagsDefault->saveToDir (tmpdir+"/flags/","",writeflags);
360 void MapEditor::saveStateChangingPart(LinkableMapObj *undoSel, LinkableMapObj* redoSel, const QString &rc, const QString &comment)
362 // save the selected part of the map, Undo will replace part of map
363 QString undoSelection="";
365 undoSelection=undoSel->getSelectString();
367 qWarning ("MapEditor::saveStateChangingPart no undoSel given!");
368 QString redoSelection="";
370 redoSelection=undoSel->getSelectString();
372 qWarning ("MapEditor::saveStateChangingPart no redoSel given!");
375 saveState (PartOfMap,
376 undoSelection, "addMapReplace (\"PATH\")",
382 void MapEditor::saveStateRemovingPart(LinkableMapObj *redoSel, const QString &comment)
386 qWarning ("MapEditor::saveStateRemovingPart no redoSel given!");
389 QString undoSelection=redoSel->getParObj()->getSelectString();
390 QString redoSelection=redoSel->getSelectString();
391 if (typeid(*redoSel) == typeid(BranchObj) )
393 // save the selected branch of the map, Undo will insert part of map
394 saveState (PartOfMap,
395 undoSelection, QString("addMapInsert (\"PATH\",%1)").arg(((BranchObj*)redoSel)->getNum()),
396 redoSelection, "delete ()",
403 void MapEditor::saveState(LinkableMapObj *undoSel, const QString &uc, LinkableMapObj *redoSel, const QString &rc, const QString &comment)
405 // "Normal" savestate: save commands, selections and comment
406 // so just save commands for undo and redo
407 // and use current selection
409 QString redoSelection="";
410 if (redoSel) redoSelection=redoSel->getSelectString();
411 QString undoSelection="";
412 if (undoSel) undoSelection=undoSel->getSelectString();
414 saveState (UndoCommand,
421 void MapEditor::saveState(const QString &undoSel, const QString &uc, const QString &redoSel, const QString &rc, const QString &comment)
423 // "Normal" savestate: save commands, selections and comment
424 // so just save commands for undo and redo
425 // and use current selection
426 saveState (UndoCommand,
434 void MapEditor::saveState(const SaveMode &savemode, const QString &undoSelection, const QString &undoCom, const QString &redoSelection, const QString &redoCom, const QString &comment, LinkableMapObj *saveSel)
438 if (blockSaveState) return;
440 /* TODO remove after testing
442 cout << "ME::saveState() "<<endl;
444 int undosAvail=undoSet.readNumEntry ("/history/undosAvail",0);
445 int redosAvail=undoSet.readNumEntry ("/history/redosAvail",0);
446 int curStep=undoSet.readNumEntry ("/history/curStep",0);
447 // Find out current undo directory
448 if (undosAvail<stepsTotal) undosAvail++;
450 if (curStep>stepsTotal) curStep=1;
452 QString backupXML="";
453 QString bakMapName=QDir::convertSeparators (QString("history-%1").arg(curStep));
454 QString bakMapDir=QDir::convertSeparators (tmpMapDir +"/"+bakMapName);
455 QString bakMapPath=QDir::convertSeparators(bakMapDir+"/map.xml");
457 // Create bakMapDir if not available
460 makeSubDirs (bakMapDir);
462 // Save depending on how much needs to be saved
464 backupXML=saveToDir (bakMapDir,mapName+"-",false, QPoint (),saveSel);
466 QString undoCommand="";
467 if (savemode==UndoCommand)
471 else if (savemode==PartOfMap )
474 undoCommand.replace ("PATH",bakMapPath);
477 if (!backupXML.isEmpty())
478 // Write XML Data to disk
479 saveStringToDisk (QString(bakMapPath),backupXML);
481 // We would have to save all actions in a tree, to keep track of
482 // possible redos after a action. Possible, but we are too lazy: forget about redos.
485 // Write the current state to disk
486 undoSet.setEntry ("/history/undosAvail",QString::number(undosAvail));
487 undoSet.setEntry ("/history/redosAvail",QString::number(redosAvail));
488 undoSet.setEntry ("/history/curStep",QString::number(curStep));
489 undoSet.setEntry (QString("/history/step-%1/undoCommand").arg(curStep),undoCommand);
490 undoSet.setEntry (QString("/history/step-%1/undoSelection").arg(curStep),undoSelection);
491 undoSet.setEntry (QString("/history/step-%1/redoCommand").arg(curStep),redoCom);
492 undoSet.setEntry (QString("/history/step-%1/redoSelection").arg(curStep),redoSelection);
493 undoSet.setEntry (QString("/history/step-%1/comment").arg(curStep),comment);
494 undoSet.setEntry (QString("/history/version"),__VYM_VERSION);
495 undoSet.writeSettings(histPath);
497 /* TODO remove after testing
499 //cout << " into="<< histPath.toStdString()<<endl;
500 cout << " stepsTotal="<<stepsTotal<<
501 ", undosAvail="<<undosAvail<<
502 ", redosAvail="<<redosAvail<<
503 ", curStep="<<curStep<<endl;
504 cout << " ---------------------------"<<endl;
505 cout << " comment="<<comment.toStdString()<<endl;
506 cout << " undoCom="<<undoCommand.toStdString()<<endl;
507 cout << " undoSel="<<undoSelection.toStdString()<<endl;
508 cout << " redoCom="<<redoCom.toStdString()<<endl;
509 cout << " redoSel="<<redoSelection.toStdString()<<endl;
510 if (saveSel) cout << " saveSel="<<saveSel->getSelectString().ascii()<<endl;
511 cout << " ---------------------------"<<endl;
513 historyWindow.update (undoSet);
518 void MapEditor::parseAtom(const QString &atom)
525 // Split string s into command and parameters
526 api.parseInput (atom);
527 QString com=api.command();
530 if (com=="addBranch")
534 api.setError (Aborted,"Nothing selected");
535 } else if ( (typeid(*selection) != typeid(BranchObj) &&
536 typeid(*selection) != typeid(MapCenterObj)) )
538 api.setError (Aborted,"Type of selection is not a branch");
543 if (api.checkParamCount(pl))
545 if (api.paramCount()==0)
546 addNewBranchInt (-2);
550 if (ok ) addNewBranchInt (y);
554 } else if (com=="addBranchBefore")
558 api.setError (Aborted,"Nothing selected");
559 } else if ( (typeid(*selection) != typeid(BranchObj) &&
560 typeid(*selection) != typeid(MapCenterObj)) )
562 api.setError (Aborted,"Type of selection is not a branch");
565 if (api.paramCount()==0)
567 addNewBranchBefore ();
570 } else if (com==QString("addMapReplace"))
574 api.setError (Aborted,"Nothing selected");
575 } else if ( (typeid(*selection) != typeid(BranchObj) &&
576 typeid(*selection) != typeid(MapCenterObj)) )
578 api.setError (Aborted,"Type of selection is not a branch");
579 } else if (api.checkParamCount(1))
581 //s=api.parString (ok,0); // selection
582 t=api.parString (ok,0); // path to map
583 if (QDir::isRelativePath(t)) t=QDir::convertSeparators (tmpMapDir + "/"+t);
584 addMapReplaceInt(selection->getSelectString(),t);
586 } else if (com==QString("addMapInsert"))
590 api.setError (Aborted,"Nothing selected");
591 } else if ( (typeid(*selection) != typeid(BranchObj) &&
592 typeid(*selection) != typeid(MapCenterObj)) )
594 api.setError (Aborted,"Type of selection is not a branch");
597 if (api.checkParamCount(2))
599 t=api.parString (ok,0); // path to map
600 y=api.parInt(ok,1); // position
601 if (QDir::isRelativePath(t)) t=QDir::convertSeparators (tmpMapDir + "/"+t);
602 addMapInsertInt(t,y);
605 } else if (com=="colorItem")
609 api.setError (Aborted,"Nothing selected");
610 } else if ( typeid(*selection) != typeid(BranchObj) &&
611 typeid(*selection) != typeid(MapCenterObj))
613 api.setError (Aborted,"Type of selection is not a branch");
614 } else if (api.checkParamCount(1))
616 QColor c=api.parColor (ok,0);
617 if (ok) colorItem (c);
619 } else if (com=="colorBranch")
623 api.setError (Aborted,"Nothing selected");
624 } else if ( typeid(*selection) != typeid(BranchObj) &&
625 typeid(*selection) != typeid(MapCenterObj))
627 api.setError (Aborted,"Type of selection is not a branch");
628 } else if (api.checkParamCount(1))
630 QColor c=api.parColor (ok,0);
631 if (ok) colorBranch (c);
633 } else if (com=="cut")
637 api.setError (Aborted,"Nothing selected");
638 } else if ( typeid(*selection) != typeid(BranchObj) &&
639 typeid(*selection) != typeid(MapCenterObj) &&
640 typeid(*selection) != typeid(FloatImageObj) )
642 api.setError (Aborted,"Type of selection is not a branch or floatimage");
643 } else if (api.checkParamCount(0))
647 } else if (com=="delete")
651 api.setError (Aborted,"Nothing selected");
652 } else if ( (typeid(*selection) != typeid(BranchObj) &&
653 typeid(*selection) != typeid(MapCenterObj)) )
655 api.setError (Aborted,"Type of selection is not a branch");
656 } else if (api.checkParamCount(0))
660 } else if (com=="deleteKeepChilds")
664 api.setError (Aborted,"Nothing selected");
665 } else if ( (typeid(*selection) != typeid(BranchObj) &&
666 typeid(*selection) != typeid(MapCenterObj)) )
668 api.setError (Aborted,"Type of selection is not a branch");
669 } else if (api.checkParamCount(0))
673 } else if (com=="deleteChilds")
677 api.setError (Aborted,"Nothing selected");
678 } else if ( (typeid(*selection) != typeid(BranchObj) &&
679 typeid(*selection) != typeid(MapCenterObj)) )
681 api.setError (Aborted,"Type of selection is not a branch");
682 } else if (api.checkParamCount(0))
686 } else if (com=="linkBranchToPos")
690 api.setError (Aborted,"Nothing selected");
691 } else if ( (typeid(*selection) != typeid(BranchObj) &&
692 typeid(*selection) != typeid(MapCenterObj)) )
694 api.setError (Aborted,"Type of selection is not a branch");
695 } else if (api.checkParamCount(4))
697 // 0 selectstring of parent
698 // 1 num in parent (for branches)
699 // 2,3 x,y of mainbranch or mapcenter
700 s=api.parString(ok,0);
701 LinkableMapObj *dst=mapCenter->findObjBySelect (s);
704 if (typeid(*dst) == typeid(BranchObj) )
706 // Get number in parent
709 ((BranchObj*)selection)->moveBranchTo ((BranchObj*)(dst),x);
710 } else if (typeid(*dst) == typeid(MapCenterObj) )
712 ((BranchObj*)selection)->moveBranchTo ((BranchObj*)(dst),-1);
713 // Get coordinates of mainbranch
718 if (ok) ((BranchObj*)selection)->move (x,y);
723 } else if (com=="moveBranchUp")
727 api.setError (Aborted,"Nothing selected");
728 } else if ( (typeid(*selection) != typeid(BranchObj) &&
729 typeid(*selection) != typeid(MapCenterObj)) )
731 api.setError (Aborted,"Type of selection is not a branch");
732 } else if (api.checkParamCount(0))
736 } else if (com=="moveBranchDown")
740 api.setError (Aborted,"Nothing selected");
741 } else if ( (typeid(*selection) != typeid(BranchObj) &&
742 typeid(*selection) != typeid(MapCenterObj)) )
744 api.setError (Aborted,"Type of selection is not a branch");
745 } else if (api.checkParamCount(0))
749 } else if (com=="move")
753 api.setError (Aborted,"Nothing selected");
754 } else if ( typeid(*selection) != typeid(BranchObj) &&
755 typeid(*selection) != typeid(MapCenterObj) &&
756 typeid(*selection) != typeid(FloatImageObj) )
758 api.setError (Aborted,"Type of selection is not a branch or floatimage");
759 } else if (api.checkParamCount(2))
768 } else if (com=="moveRel")
772 api.setError (Aborted,"Nothing selected");
773 } else if ( typeid(*selection) != typeid(BranchObj) &&
774 typeid(*selection) != typeid(MapCenterObj) &&
775 typeid(*selection) != typeid(FloatImageObj) )
777 api.setError (Aborted,"Type of selection is not a branch or floatimage");
778 } else if (api.checkParamCount(2))
784 if (ok) moveRel (x,y);
787 } else if (com=="paste")
791 api.setError (Aborted,"Nothing selected");
792 } else if ( typeid(*selection) != typeid(BranchObj) &&
793 typeid(*selection) != typeid(MapCenterObj) )
795 api.setError (Aborted,"Type of selection is not a branch");
796 } else if (api.checkParamCount(0))
800 } else if (com=="select")
802 if (api.checkParamCount(1))
804 s=api.parString(ok,0);
807 } else if (com=="setMapAuthor")
809 if (api.checkParamCount(1))
811 s=api.parString(ok,0);
812 if (ok) setMapAuthor (s);
814 } else if (com=="setMapComment")
816 if (api.checkParamCount(1))
818 s=api.parString(ok,0);
819 if (ok) setMapComment(s);
821 } else if (com=="setMapBackgroundColor")
825 api.setError (Aborted,"Nothing selected");
826 } else if ( (typeid(*selection) != typeid(BranchObj) &&
827 typeid(*selection) != typeid(MapCenterObj)) )
829 api.setError (Aborted,"Type of selection is not a branch");
830 } else if (api.checkParamCount(1))
832 QColor c=api.parColor (ok,0);
833 if (ok) setMapBackgroundColor (c);
835 } else if (com=="setMapDefLinkColor")
839 api.setError (Aborted,"Nothing selected");
840 } else if ( (typeid(*selection) != typeid(BranchObj) &&
841 typeid(*selection) != typeid(MapCenterObj)) )
843 api.setError (Aborted,"Type of selection is not a branch");
844 } else if (api.checkParamCount(1))
846 QColor c=api.parColor (ok,0);
847 if (ok) setMapDefLinkColor (c);
849 } else if (com=="setMapLinkStyle")
851 if (api.checkParamCount(1))
853 s=api.parString (ok,0);
854 if (ok) setMapLinkStyle(s);
856 } else if (com=="setHeading")
860 api.setError (Aborted,"Nothing selected");
861 } else if ( (typeid(*selection) != typeid(BranchObj) &&
862 typeid(*selection) != typeid(MapCenterObj)) )
864 api.setError (Aborted,"Type of selection is not a branch");
865 } else if (api.checkParamCount(1))
867 s=api.parString (ok,0);
871 } else if (com=="setHideExport")
875 api.setError (Aborted,"Nothing selected");
876 } else if ( typeid(*selection) != typeid(BranchObj) &&
877 typeid(*selection) != typeid(FloatImageObj) )
879 api.setError (Aborted,"Type of selection is not a branch or floatimage");
880 } else if (api.checkParamCount(1))
883 if (ok) setHideExport (b);
885 } else if (com=="setURL")
889 api.setError (Aborted,"Nothing selected");
890 } else if ( (typeid(*selection) != typeid(BranchObj) &&
891 typeid(*selection) != typeid(MapCenterObj)) )
893 api.setError (Aborted,"Type of selection is not a branch");
894 } else if (api.checkParamCount(1))
896 s=api.parString (ok,0);
897 if (ok) setURLInt(s);
899 } else if (com=="setVymLink")
903 api.setError (Aborted,"Nothing selected");
904 } else if ( (typeid(*selection) != typeid(BranchObj) &&
905 typeid(*selection) != typeid(MapCenterObj)) )
907 api.setError (Aborted,"Type of selection is not a branch");
908 } else if (api.checkParamCount(1))
910 s=api.parString (ok,0);
911 if (ok) setVymLinkInt(s);
914 else if (com=="setFlag")
918 api.setError (Aborted,"Nothing selected");
919 } else if ( (typeid(*selection) != typeid(BranchObj) &&
920 typeid(*selection) != typeid(MapCenterObj)) )
922 api.setError (Aborted,"Type of selection is not a branch");
923 } else if (api.checkParamCount(1))
925 s=api.parString(ok,0);
928 BranchObj* bo=(BranchObj*)selection;
929 bo->activateStandardFlag(s);
930 bo->updateFlagsToolbar();
934 else if (com=="unsetFlag")
938 api.setError (Aborted,"Nothing selected");
939 } else if ( (typeid(*selection) != typeid(BranchObj) &&
940 typeid(*selection) != typeid(MapCenterObj)) )
942 api.setError (Aborted,"Type of selection is not a branch");
943 } else if (api.checkParamCount(1))
945 s=api.parString(ok,0);
948 BranchObj* bo=(BranchObj*)selection;
949 bo->deactivateStandardFlag(s);
950 bo->updateFlagsToolbar();
955 api.setError (Aborted,"Unknown command");
959 if (api.errorLevel()==NoError)
963 // TODO Error handling
964 qWarning("MapEditor::parseAtom: Error!");
965 qWarning(api.errorMessage());
969 void MapEditor::toggleHistoryWindow()
971 if (historyWindow.isVisible())
972 historyWindow.hide();
974 historyWindow.show();
978 bool MapEditor::isDefault()
983 bool MapEditor::isUnsaved()
988 bool MapEditor::hasChanged()
993 void MapEditor::setChanged()
1001 void MapEditor::closeMap()
1003 // Unselect before disabling the toolbar actions
1004 if (selection) selection->unselect();
1012 void MapEditor::setFilePath(QString fname)
1014 setFilePath (fname,fname);
1017 void MapEditor::setFilePath(QString fname, QString destname)
1019 if (fname.isEmpty() || fname=="")
1026 filePath=fname; // becomes absolute path
1027 fileName=fname; // gets stripped of path
1028 destPath=destname; // needed for vymlinks
1030 // If fname is not an absolute path, complete it
1031 filePath=QDir(fname).absPath();
1032 fileDir=filePath.left (1+filePath.findRev ("/"));
1034 // Set short name, too. Search from behind:
1035 int i=fileName.findRev("/");
1036 if (i>=0) fileName=fileName.remove (0,i+1);
1038 // Forget the .vym (or .xml) for name of map
1039 mapName=fileName.left(fileName.findRev(".",-1,true) );
1041 // Adjust history window
1042 historyWindow.setCaption (__VYM " - " +tr("History for ")+fileName);
1046 QString MapEditor::getFilePath()
1051 QString MapEditor::getFileName()
1056 QString MapEditor::getMapName()
1061 QString MapEditor::getDestPath()
1066 ErrorCode MapEditor::load (QString fname, LoadMode lmode)
1068 ErrorCode err=success;
1072 if (selection) selection->unselect();
1075 mapCenter->setMapEditor(this);
1076 // (map state is set later at end of load...)
1079 if (!selection || (typeid(*selection) != typeid(BranchObj) &&
1080 typeid(*selection) != typeid (MapCenterObj)))
1082 BranchObj *bo=(BranchObj*)selection;
1083 if (lmode==ImportAdd)
1084 saveStateChangingPart(
1087 QString("addMapInsert (%1)").arg(fname),
1088 QString("Add map %1 to %2").arg(fname).arg(getName(bo)));
1090 saveStateChangingPart(
1093 QString("addMapReplace(%1)").arg(fname),
1094 QString("Add map %1 to %2").arg(fname).arg(getName(bo)));
1098 mapBuilderHandler handler;
1099 QFile file( fname );
1101 // I am paranoid: file should exist anyway
1102 // according to check in mainwindow.
1103 if (!file.exists() )
1105 QMessageBox::critical( 0, tr( "Critical Parse Error" ),
1106 tr("Couldn't open map " +fname)+".");
1110 blockReposition=true;
1111 QXmlInputSource source( file);
1112 QXmlSimpleReader reader;
1113 reader.setContentHandler( &handler );
1114 reader.setErrorHandler( &handler );
1115 handler.setMapEditor( this );
1116 handler.setTmpDir (filePath.left(filePath.findRev("/",-1))); // needed to load files with rel. path
1117 handler.setInputFile (file.name());
1118 handler.setLoadMode (lmode);
1119 blockSaveState=true;
1120 bool ok = reader.parse( source );
1121 blockReposition=false;
1122 blockSaveState=false;
1126 mapCenter->reposition();
1136 QMessageBox::critical( 0, tr( "Critical Parse Error" ),
1137 tr( handler.errorProtocol() ) );
1139 // Still return "success": the map maybe at least
1140 // partially read by the parser
1147 int MapEditor::save (const SaveMode &savemode)
1151 // Create mapName and fileDir
1152 makeSubDirs (fileDir);
1156 fname=mapName+".xml";
1158 // use name given by user, even if he chooses .doc
1163 if (savemode==CompleteMap || selection==NULL)
1164 saveFile=saveToDir (fileDir,mapName+"-",true,QPoint(),NULL);
1166 saveFile=saveToDir (fileDir,mapName+"-",true,QPoint(),selection);
1168 if (!saveStringToDisk(fileDir+fname,saveFile))
1181 void MapEditor::setZipped (bool z)
1186 bool MapEditor::saveZipped ()
1191 void MapEditor::print()
1195 printer = new QPrinter;
1196 printer->setColorMode (QPrinter::Color);
1197 printer->setPrinterName (settings.value("/mainwindow/printerName",printer->printerName()).toString());
1200 QRect totalBBox=mapCenter->getTotalBBox();
1202 // Try to set orientation automagically
1203 // Note: Interpretation of generated postscript is amibiguous, if
1204 // there are problems with landscape mode, see
1205 // http://sdb.suse.de/de/sdb/html/jsmeix_print-cups-landscape-81.html
1207 if (totalBBox.width()>totalBBox.height())
1208 // recommend landscape
1209 printer->setOrientation (QPrinter::Landscape);
1211 // recommend portrait
1212 printer->setOrientation (QPrinter::Portrait);
1214 if ( printer->setup(this) )
1215 // returns false, if printing is canceled
1217 QPainter pp(printer);
1219 // Don't print the visualisation of selection
1220 LinkableMapObj *oldselection=NULL;
1223 oldselection=selection;
1224 selection->unselect();
1227 // Handle sizes of map and paper:
1229 // setWindow defines which part of the canvas will be transformed
1230 // setViewport defines area on paper in device coordinates (dpi)
1231 // e.g. (0,50,700,700) is upper part on A4
1232 // see also /usr/lib/qt3/doc/html/coordsys.html
1234 Q3PaintDeviceMetrics metrics (printer);
1236 double paperAspect = (double)metrics.width() / (double)metrics.height();
1237 double mapAspect = (double)totalBBox.width() / (double)totalBBox.height();
1239 QRect mapRect=totalBBox;
1240 Q3CanvasRectangle *frame=NULL;
1241 Q3CanvasText *footerFN=NULL;
1242 Q3CanvasText *footerDate=NULL;
1243 if (printFrame || printFooter)
1248 // Print frame around map
1249 mapRect.setRect (totalBBox.x()-10, totalBBox.y()-10,
1250 totalBBox.width()+20, totalBBox.height()+20);
1251 frame=new Q3CanvasRectangle (mapRect,mapCanvas);
1252 frame->setBrush (QColor(Qt::white));
1253 frame->setPen (QColor(Qt::black));
1257 /* TODO remove after testing
1258 QCanvasLine *l=new QCanvasLine (mapCanvas);
1259 l->setPoints (0,0,mapRect.width(),mapRect.height());
1260 l->setPen (QPen(QColor(black), 1));
1267 // Print footer below map
1269 font.setPointSize(10);
1270 footerFN=new Q3CanvasText (mapCanvas);
1271 footerFN->setText ("VYM - " + fileName);
1272 footerFN->setFont(font);
1273 footerFN->move (mapRect.x(), mapRect.y() + mapRect.height() );
1274 footerFN->setZ(Z_TEXT);
1276 footerDate=new Q3CanvasText (mapCanvas);
1277 footerDate->setText (QDate::currentDate().toString(Qt::TextDate));
1278 footerDate->setFont(font);
1279 footerDate->move (mapRect.x()+mapRect.width()-footerDate->boundingRect().width(), mapRect.y() + mapRect.height() );
1280 footerDate->setZ(Z_TEXT);
1283 pp.setWindow (mapRect.x(), mapRect.y(), mapRect.width(), mapRect.height()+20);
1286 pp.setWindow (mapRect);
1289 if (mapAspect>=paperAspect)
1291 // Fit horizontally to paper width
1292 pp.setViewport(0,0, metrics.width(),(int)(metrics.width()/mapAspect) );
1295 // Fit vertically to paper height
1296 pp.setViewport(0,0,(int)(metrics.height()*mapAspect),metrics.height());
1299 mapCanvas->drawArea(mapRect, &pp); // draw Canvas to printer
1301 // Delete Frame and footer
1305 delete (footerDate);
1307 if (frame) delete (frame);
1309 // Restore selection
1312 selection=oldselection;
1313 selection->select();
1316 // Save settings in vymrc
1317 settings.writeEntry("/mainwindow/printerName",printer->printerName());
1321 QPixmap MapEditor::getPixmap()
1323 QRect mapRect=mapCenter->getTotalBBox();
1324 QPixmap pix (mapRect.size());
1327 // Don't print the visualisation of selection
1328 LinkableMapObj *oldselection=NULL;
1331 oldselection=selection;
1332 selection->unselect();
1335 pp.setWindow (mapRect);
1337 mapCanvas->drawArea(mapRect, &pp); // draw Canvas to painter
1340 // Restore selection
1343 selection=oldselection;
1344 selection->select();
1350 void MapEditor::setHideTmpMode (HideTmpMode mode)
1353 mapCenter->setHideTmp (hidemode);
1354 mapCenter->reposition();
1359 HideTmpMode MapEditor::getHideTmpMode()
1364 void MapEditor::exportImage(QString fn)
1366 setExportMode (true);
1367 QPixmap pix (getPixmap());
1368 pix.save(fn, "PNG");
1369 setExportMode (false);
1372 void MapEditor::setExportMode (bool b)
1374 // should be called before and after exports
1375 // depending on the settings
1376 if (b && settings.value("/export/useHideExport","yes")=="yes")
1377 setHideTmpMode (HideExport);
1379 setHideTmpMode (HideNone);
1382 void MapEditor::exportImage(QString fn, QString format)
1384 setExportMode (true);
1385 QPixmap pix (getPixmap());
1386 pix.save(fn, format);
1387 setExportMode (false);
1390 void MapEditor::exportOOPresentation(const QString &fn, const QString &cf)
1394 ex.setMapCenter(mapCenter);
1395 if (ex.setConfigFile(cf))
1397 setExportMode (true);
1398 ex.exportPresentation();
1399 setExportMode (false);
1405 void MapEditor::exportXML(const QString &dir)
1407 // Hide stuff during export, if settings want this
1408 setExportMode (true);
1410 // Create subdirectories
1413 // write to directory
1414 QString saveFile=saveToDir (dir,mapName+"-",true,mapCenter->getTotalBBox().topLeft() ,NULL);
1417 file.setName ( dir + "/"+mapName+".xml");
1418 if ( !file.open( QIODevice::WriteOnly ) )
1420 // This should neverever happen
1421 QMessageBox::critical (0,tr("Critical Export Error"),tr("MapEditor::exportXML couldn't open %1").arg(file.name()));
1425 // Write it finally, and write in UTF8, no matter what
1426 QTextStream ts( &file );
1427 ts.setEncoding (QTextStream::UnicodeUTF8);
1431 // Now write image, too
1432 exportImage (dir+"/images/"+mapName+".png");
1434 setExportMode (false);
1437 void MapEditor::clear()
1441 selection->unselect();
1448 void MapEditor::copy()
1452 // write to directory
1453 QString clipfile="part";
1454 QString saveFile=saveToDir (fileDir,clipfile+"-",true,QPoint(),selection);
1457 file.setName ( clipboardDir + "/"+clipfile+".xml");
1458 if ( !file.open( QIODevice::WriteOnly ) )
1460 // This should neverever happen
1461 QMessageBox::critical (0,tr("Critical Export Error"),tr("MapEditor::exportXML couldn't open %1").arg(file.name()));
1465 // Write it finally, and write in UTF8, no matter what
1466 QTextStream ts( &file );
1467 ts.setEncoding (QTextStream::UnicodeUTF8);
1471 clipboardEmpty=false;
1476 void MapEditor::redo()
1478 blockSaveState=true;
1480 // Restore variables
1481 int curStep=undoSet.readNumEntry (QString("/history/curStep"));
1482 int undosAvail=undoSet.readNumEntry (QString("/history/undosAvail"));
1483 int redosAvail=undoSet.readNumEntry (QString("/history/redosAvail"));
1484 // Can we undo at all?
1485 if (redosAvail<1) return;
1488 if (undosAvail<stepsTotal) undosAvail++;
1490 if (curStep>stepsTotal) curStep=1;
1491 QString undoCommand= undoSet.readEntry (QString("/history/step-%1/undoCommand").arg(curStep));
1492 QString undoSelection=undoSet.readEntry (QString("/history/step-%1/undoSelection").arg(curStep));
1493 QString redoCommand= undoSet.readEntry (QString("/history/step-%1/redoCommand").arg(curStep));
1494 QString redoSelection=undoSet.readEntry (QString("/history/step-%1/redoSelection").arg(curStep));
1495 QString comment=undoSet.readEntry (QString("/history/step-%1/comment").arg(curStep));
1496 QString version=undoSet.readEntry ("/history/version");
1498 if (!checkVersion(version))
1499 QMessageBox::warning(0,tr("Warning"),
1500 tr("Version %1 of saved undo/redo data\ndoes not match current vym version %2.").arg(version).arg(__VYM_VERSION));
1503 // Find out current undo directory
1504 QString bakMapDir=QDir::convertSeparators (QString(tmpMapDir+"/undo-%1").arg(curStep));
1506 /* TODO remove testing
1508 cout << "ME::redo() begin\n";
1509 cout << " undosAvail="<<undosAvail<<endl;
1510 cout << " redosAvail="<<redosAvail<<endl;
1511 cout << " curStep="<<curStep<<endl;
1512 cout << " ---------------------------"<<endl;
1513 cout << " comment="<<comment.toStdString()<<endl;
1514 cout << " undoCom="<<undoCommand.toStdString()<<endl;
1515 cout << " undoSel="<<undoSelection.toStdString()<<endl;
1516 cout << " redoCom="<<redoCommand.toStdString()<<endl;
1517 cout << " redoSel="<<redoSelection.toStdString()<<endl;
1518 cout << " ---------------------------"<<endl<<endl;
1520 // select object before redo
1521 // FIXME better give up if no selection there...
1522 if (!redoSelection.isEmpty())
1523 select (redoSelection);
1526 parseAtom (redoCommand);
1527 mapCenter->reposition();
1529 blockSaveState=false;
1531 undoSet.setEntry ("/history/undosAvail",QString::number(undosAvail));
1532 undoSet.setEntry ("/history/redosAvail",QString::number(redosAvail));
1533 undoSet.setEntry ("/history/curStep",QString::number(curStep));
1534 undoSet.writeSettings(histPath);
1536 historyWindow.update (undoSet);
1539 /* TODO remove testing
1541 cout << "ME::redo() end\n";
1542 cout << " undosAvail="<<undosAvail<<endl;
1543 cout << " redosAvail="<<redosAvail<<endl;
1544 cout << " curStep="<<curStep<<endl;
1545 cout << " ---------------------------"<<endl<<endl;
1550 bool MapEditor::isRedoAvailable()
1552 if (undoSet.readNumEntry("/history/redosAvail",0)>0)
1558 void MapEditor::undo()
1560 blockSaveState=true;
1562 // Restore variables
1563 int curStep=undoSet.readNumEntry (QString("/history/curStep"));
1564 int undosAvail=undoSet.readNumEntry (QString("/history/undosAvail"));
1565 int redosAvail=undoSet.readNumEntry (QString("/history/redosAvail"));
1567 // Can we undo at all?
1568 if (undosAvail<1) return;
1570 QString undoCommand= undoSet.readEntry (QString("/history/step-%1/undoCommand").arg(curStep));
1571 QString undoSelection=undoSet.readEntry (QString("/history/step-%1/undoSelection").arg(curStep));
1572 QString redoCommand= undoSet.readEntry (QString("/history/step-%1/redoCommand").arg(curStep));
1573 QString redoSelection=undoSet.readEntry (QString("/history/step-%1/redoSelection").arg(curStep));
1574 QString comment=undoSet.readEntry (QString("/history/step-%1/comment").arg(curStep));
1575 QString version=undoSet.readEntry ("/history/version");
1577 if (!checkVersion(version))
1578 QMessageBox::warning(0,tr("Warning"),
1579 tr("Version %1 of saved undo/redo data\ndoes not match current vym version %2.").arg(version).arg(__VYM_VERSION));
1581 // Find out current undo directory
1582 QString bakMapDir=QDir::convertSeparators (QString(tmpMapDir+"/undo-%1").arg(curStep));
1584 // select object before undo
1585 if (!undoSelection.isEmpty())
1586 select (undoSelection);
1590 cout << "ME::undo() begin\n";
1591 cout << " undosAvail="<<undosAvail<<endl;
1592 cout << " redosAvail="<<redosAvail<<endl;
1593 cout << " curStep="<<curStep<<endl;
1594 cout << " ---------------------------"<<endl;
1595 cout << " comment="<<comment.toStdString()<<endl;
1596 cout << " undoCom="<<undoCommand.toStdString()<<endl;
1597 cout << " undoSel="<<undoSelection.toStdString()<<endl;
1598 cout << " redoCom="<<redoCommand.toStdString()<<endl;
1599 cout << " redoSel="<<redoSelection.toStdString()<<endl;
1600 cout << " ---------------------------"<<endl<<endl;
1601 parseAtom (undoCommand);
1602 mapCenter->reposition();
1606 if (curStep<1) curStep=stepsTotal;
1610 blockSaveState=false;
1611 /* TODO remove testing
1613 cout << "ME::undo() end\n";
1614 cout << " undosAvail="<<undosAvail<<endl;
1615 cout << " redosAvail="<<redosAvail<<endl;
1616 cout << " curStep="<<curStep<<endl;
1617 cout << " ---------------------------"<<endl<<endl;
1619 undoSet.setEntry ("/history/undosAvail",QString::number(undosAvail));
1620 undoSet.setEntry ("/history/redosAvail",QString::number(redosAvail));
1621 undoSet.setEntry ("/history/curStep",QString::number(curStep));
1622 undoSet.writeSettings(histPath);
1624 historyWindow.update (undoSet);
1628 bool MapEditor::isUndoAvailable()
1630 if (undoSet.readNumEntry("/history/undosAvail",0)>0)
1636 void MapEditor::gotoStep (int i)
1638 // Restore variables
1639 int undosAvail=undoSet.readNumEntry (QString("/history/undosAvail"));
1640 int redosAvail=undoSet.readNumEntry (QString("/history/redosAvail"));
1642 cout << "ME::goto "<<i<<endl;
1644 if (i<0) i=undosAvail+redosAvail;
1646 // Clicking above current step makes us undo things
1649 for (int j=0; j<undosAvail-i; j++) undo();
1652 // Clicking below current step makes us redo things
1654 for (int j=undosAvail; j<i; j++) redo();
1656 // And ignore clicking the current row ;-)
1659 void MapEditor::addMapReplaceInt(const QString &undoSel, const QString &path)
1661 QString pathDir=path.left(path.findRev("/"));
1667 // We need to parse saved XML data
1668 mapBuilderHandler handler;
1669 QXmlInputSource source( file);
1670 QXmlSimpleReader reader;
1671 reader.setContentHandler( &handler );
1672 reader.setErrorHandler( &handler );
1673 handler.setMapEditor( this );
1674 handler.setTmpDir ( pathDir ); // needed to load files with rel. path
1675 if (undoSel.isEmpty())
1679 handler.setLoadMode (NewMap);
1683 handler.setLoadMode (ImportReplace);
1685 blockReposition=true;
1686 bool ok = reader.parse( source );
1687 blockReposition=false;
1690 // This should never ever happen
1691 QMessageBox::critical( 0, tr( "Critical Parse Error while reading %1").arg(path),
1692 handler.errorProtocol());
1695 QMessageBox::critical( 0, tr( "Critical Error" ), tr("Could not read %1").arg(path));
1698 void MapEditor::addMapInsertInt (const QString &path, int pos)
1700 if (selection && (typeid(*selection) == typeid(BranchObj) ||
1701 typeid(*selection) == typeid(MapCenterObj)))
1703 QString pathDir=path.left(path.findRev("/"));
1709 // We need to parse saved XML data
1710 mapBuilderHandler handler;
1711 QXmlInputSource source( file);
1712 QXmlSimpleReader reader;
1713 reader.setContentHandler( &handler );
1714 reader.setErrorHandler( &handler );
1715 handler.setMapEditor( this );
1716 handler.setTmpDir ( pathDir ); // needed to load files with rel. path
1717 handler.setLoadMode (ImportAdd);
1718 blockReposition=true;
1719 bool ok = reader.parse( source );
1720 blockReposition=false;
1723 // This should never ever happen
1724 QMessageBox::critical( 0, tr( "Critical Parse Error while reading %1").arg(path),
1725 handler.errorProtocol());
1727 if (selection!=mapCenter)
1728 ((BranchObj*)selection)->getLastBranch()->moveBranchTo ((BranchObj*)(selection),pos);
1730 QMessageBox::critical( 0, tr( "Critical Error" ), tr("Could not read %1").arg(path));
1734 void MapEditor::pasteNoSave()
1736 load (clipboardDir+"/part.xml",ImportAdd);
1739 void MapEditor::cutNoSave()
1745 void MapEditor::paste()
1747 if (selection && (typeid(*selection) == typeid(BranchObj) ||
1748 typeid(*selection) == typeid(MapCenterObj)))
1751 saveStateChangingPart(
1755 QString("Paste to %1").arg( getName(selection))
1757 mapCenter->reposition();
1762 void MapEditor::cut()
1764 saveStateChangingPart(
1765 selection->getParObj(),
1768 QString("Cut %1").arg(getName(selection))
1772 mapCenter->reposition();
1776 void MapEditor::move(const int &x, const int &y)
1780 QString ps=qpointToString (selection->getAbsPos());
1781 QString s=selection->getSelectString();
1784 s, "move "+qpointToString (QPoint (x,y)),
1785 QString("Move %1 to %2").arg(getName(selection)).arg(ps));
1786 selection->move(x,y);
1787 mapCenter->reposition();
1793 void MapEditor::moveRel (const int &x, const int &y)
1795 if (selection && (typeid(*selection) == typeid(BranchObj) ||
1796 typeid(*selection) == typeid(MapCenterObj) ||
1797 typeid(*selection) == typeid (FloatImageObj)))
1799 QString ps=qpointToString (selection->getRelPos());
1800 QString s=selection->getSelectString();
1803 s, "moveRel "+qpointToString (QPoint (x,y)),
1804 QString("Move %1 to relativ position %2").arg(getName(selection)).arg(ps));
1805 ((OrnamentedObj*)selection)->move2RelPos (x,y);
1806 mapCenter->reposition();
1811 void MapEditor::moveBranchUp()
1815 if (typeid(*selection) == typeid(BranchObj) )
1817 bo=(BranchObj*)selection;
1818 if (!bo->canMoveBranchUp()) return;
1819 par=(BranchObj*)(bo->getParObj());
1820 selection->unselect();
1821 bo=par->moveBranchUp (bo); // bo will be the one below selection
1822 selection->select();
1823 saveState (selection,"moveBranchDown ()",bo,"moveBranchUp ()",QString("Move up %1").arg(getName(bo)));
1824 mapCenter->reposition();
1825 ensureSelectionVisible();
1829 void MapEditor::moveBranchDown()
1833 if (typeid(*selection) == typeid(BranchObj) )
1835 bo=(BranchObj*)selection;
1836 if (!bo->canMoveBranchDown()) return;
1837 par=(BranchObj*)(bo->getParObj());
1838 selection->unselect();
1839 bo=par->moveBranchDown(bo); // bo will be the one above selection
1840 selection->select();
1841 saveState(selection,"moveBranchUp ()",bo,"moveBranchDown ()",QString("Move down %1").arg(getName(bo)));
1842 mapCenter->reposition();
1843 ensureSelectionVisible();
1847 QString MapEditor::getHeading(bool &ok, QPoint &p)
1850 (typeid(*selection) == typeid(BranchObj) ||
1851 typeid(*selection) == typeid(MapCenterObj) ) )
1854 ensureSelectionVisible();
1855 p = ((BranchObj*)selection)->getAbsPos();
1856 p.setX (p.x() - contentsX());
1857 p.setY (p.y() - contentsY() + ((BranchObj*)selection)->height()/2);
1858 return ((BranchObj*)selection)->getHeading();
1864 void MapEditor::setHeading(const QString &s)
1867 (typeid(*selection) == typeid(BranchObj) ||
1868 typeid(*selection) == typeid(MapCenterObj) ) )
1870 editingBO=(BranchObj*)selection;
1873 "setHeading (\""+editingBO->getHeading()+"\")",
1875 "setHeading (\""+s+"\")",
1876 QString("Set heading of %1 to \"%2\"").arg(getName(editingBO)).arg(s) );
1877 editingBO->setHeading(s );
1879 mapCenter->reposition();
1881 ensureSelectionVisible();
1885 void MapEditor::setURLInt (const QString &s)
1887 // Internal function, no saveState needed
1889 (typeid(*selection) == typeid(BranchObj) ||
1890 typeid(*selection) == typeid(MapCenterObj) ) )
1892 ((BranchObj*)selection)->setURL(s);
1893 mapCenter->reposition();
1895 ensureSelectionVisible();
1899 void MapEditor::setHeadingInt(const QString &s)
1902 (typeid(*selection) == typeid(BranchObj) ||
1903 typeid(*selection) == typeid(MapCenterObj) ) )
1905 ((BranchObj*)selection)->setHeading(s);
1906 mapCenter->reposition();
1908 ensureSelectionVisible();
1912 void MapEditor::setVymLinkInt (const QString &s)
1914 // Internal function, no saveState needed
1916 (typeid(*selection) == typeid(BranchObj) ||
1917 typeid(*selection) == typeid(MapCenterObj) ) )
1919 ((BranchObj*)selection)->setVymLink(s);
1920 mapCenter->reposition();
1922 ensureSelectionVisible();
1926 BranchObj* MapEditor::addNewBranchInt(int num)
1928 // Depending on pos:
1929 // -3 insert in childs of parent above selection
1930 // -2 add branch to selection
1931 // -1 insert in childs of parent below selection
1932 // 0..n insert in childs of parent at pos
1933 BranchObj *newbo=NULL;
1935 (typeid(*selection) == typeid(BranchObj) ||
1936 typeid(*selection) == typeid(MapCenterObj) ) )
1938 BranchObj* bo = (BranchObj*) selection;
1941 // save scroll state. If scrolled, automatically select
1942 // new branch in order to tmp unscroll parent...
1943 return bo->addBranch();
1948 bo=(BranchObj*)bo->getParObj();
1952 bo=(BranchObj*)bo->getParObj();
1955 newbo=bo->insertBranch(num);
1960 BranchObj* MapEditor::addNewBranch(int pos)
1962 // Different meaning than num in addNewBranchInt!
1966 BranchObj *bo = (BranchObj*) selection;
1967 BranchObj *newbo=NULL;
1970 (typeid(*selection) == typeid(BranchObj) ||
1971 typeid(*selection) == typeid(MapCenterObj) ) )
1973 newbo=addNewBranchInt (pos-2);
1978 selection, // FIXME sholdnt newbo be deleted here???
1981 QString ("addBranch (%1)").arg(pos-2),
1982 QString ("Add new branch to %1").arg(getName(bo)));
1984 mapCenter->reposition();
1992 BranchObj* MapEditor::addNewBranchBefore()
1994 BranchObj *newbo=NULL;
1996 (typeid(*selection) == typeid(BranchObj) ) )
1997 // We accept no MapCenterObj here, so we _have_ a parent
1999 BranchObj* bo = (BranchObj*) selection;
2000 QPoint p=bo->getRelPos();
2003 BranchObj *parbo=(BranchObj*)(selection->getParObj());
2005 // add below selection
2006 newbo=parbo->insertBranch(bo->getNum()+1);
2009 newbo->move2RelPos (p);
2011 // Move selection to new branch
2012 ((BranchObj*)selection)->moveBranchTo (newbo,-1);
2014 saveState (newbo, "deleteKeepChilds ()", newbo, "addBranchBefore ()",
2015 QString ("Add branch before %1").arg(getName(bo)));
2017 mapCenter->reposition();
2024 void MapEditor::deleteSelection()
2026 if (selection && typeid(*selection) ==typeid(BranchObj) )
2028 BranchObj* bo=(BranchObj*)selection;
2029 BranchObj* par=(BranchObj*)(bo->getParObj());
2031 saveStateRemovingPart (bo, QString ("Delete %1").arg(getName(bo)));
2033 par->removeBranch(bo);
2035 selection->select();
2036 ensureSelectionVisible();
2037 mapCenter->reposition();
2040 if (selection && typeid(*selection) ==typeid(FloatImageObj) )
2042 FloatImageObj* fio=(FloatImageObj*)selection;
2043 BranchObj* par=(BranchObj*)(fio->getParObj());
2044 saveStateChangingPart(
2048 QString("Delete %1").arg(getName(fio))
2052 par->removeFloatImage(fio);
2054 selection->select();
2055 ensureSelectionVisible();
2056 mapCenter->reposition();
2061 LinkableMapObj* MapEditor::getSelection()
2066 void MapEditor::unselect()
2070 selectionLast=selection;
2071 selection->unselect();
2076 void MapEditor::reselect()
2080 selection=selectionLast;
2081 selection->select();
2086 bool MapEditor::select (const QString &s)
2088 LinkableMapObj *lmo=mapCenter->findObjBySelect(s);
2090 // Finally select the found object
2093 if (selection) unselect();
2095 selection->select();
2097 ensureSelectionVisible();
2103 QString MapEditor::getSelectString()
2105 if (selection) return selection->getSelectString();
2109 void MapEditor::selectInt (LinkableMapObj *lmo)
2111 if (lmo && selection != lmo)
2113 // select the MapObj
2114 if (selection) selection->unselect();
2116 selection->select();
2122 void MapEditor::selectNextBranchInt()
2124 // Increase number of branch
2127 QString s=selection->getSelectString();
2133 part=s.section(",",-1);
2135 num=part.right(part.length() - 3);
2137 s=s.left (s.length() -num.length());
2140 num=QString ("%1").arg(num.toUInt()+1);
2144 // Try to select this one
2145 if (select (s)) return;
2147 // We have no direct successor,
2148 // try to increase the parental number in order to
2149 // find a successor with same depth
2151 int d=selection->getDepth();
2156 while (!found && d>0)
2158 s=s.section (",",0,d-1);
2159 // replace substring of current depth in s with "1"
2160 part=s.section(",",-1);
2162 num=part.right(part.length() - 3);
2166 // increase number of parent
2167 num=QString ("%1").arg(num.toUInt()+1);
2168 s=s.section (",",0,d-2) + ","+ typ+num;
2171 // Special case, look at orientation
2172 if (selection->getOrientation()==OrientRightOfCenter)
2173 num=QString ("%1").arg(num.toUInt()+1);
2175 num=QString ("%1").arg(num.toUInt()-1);
2180 // pad to oldDepth, select the first branch for each depth
2181 for (i=d;i<oldDepth;i++)
2186 if ( ((BranchObj*)selection)->countBranches()>0)
2194 // try to select the freshly built string
2202 void MapEditor::selectPrevBranchInt()
2204 // Decrease number of branch
2207 QString s=selection->getSelectString();
2213 part=s.section(",",-1);
2215 num=part.right(part.length() - 3);
2217 s=s.left (s.length() -num.length());
2220 num=QString ("%1").arg(num.toUInt()-1);
2224 // Try to select this one
2225 if (select (s)) return;
2227 // We have no direct precessor,
2228 // try to decrease the parental number in order to
2229 // find a precessor with same depth
2231 int d=selection->getDepth();
2236 while (!found && d>0)
2238 s=s.section (",",0,d-1);
2239 // replace substring of current depth in s with "1"
2240 part=s.section(",",-1);
2242 num=part.right(part.length() - 3);
2246 // decrease number of parent
2247 num=QString ("%1").arg(num.toUInt()-1);
2248 s=s.section (",",0,d-2) + ","+ typ+num;
2251 // Special case, look at orientation
2252 if (selection->getOrientation()==OrientRightOfCenter)
2253 num=QString ("%1").arg(num.toUInt()-1);
2255 num=QString ("%1").arg(num.toUInt()+1);
2260 // pad to oldDepth, select the last branch for each depth
2261 for (i=d;i<oldDepth;i++)
2265 if ( ((BranchObj*)selection)->countBranches()>0)
2266 s+=",bo:"+ QString ("%1").arg( ((BranchObj*)selection)->countBranches()-1 );
2273 // try to select the freshly built string
2281 void MapEditor::selectUpperBranch()
2285 if (typeid(*selection) == typeid(BranchObj))
2287 if (selection->getOrientation()==OrientRightOfCenter)
2288 selectPrevBranchInt();
2290 if (selection->getDepth()==1)
2291 selectNextBranchInt();
2293 selectPrevBranchInt();
2298 void MapEditor::selectLowerBranch()
2302 if (typeid(*selection) == typeid(BranchObj))
2304 if (selection->getOrientation()==OrientRightOfCenter)
2305 selectNextBranchInt();
2307 if (selection->getDepth()==1)
2308 selectPrevBranchInt();
2310 selectNextBranchInt();
2316 void MapEditor::selectLeftBranch()
2322 if (typeid(*selection) == typeid(MapCenterObj))
2324 par= (BranchObj*) selection;
2325 bo=par->getLastSelectedBranch();
2328 // Workaround for reselecting on left and right side
2329 if (bo->getOrientation()==OrientRightOfCenter)
2331 bo=par->getLastBranch();
2337 selection->select();
2339 ensureSelectionVisible();
2344 par=(BranchObj*)(selection->getParObj());
2345 if (selection->getOrientation()==OrientRightOfCenter)
2347 if (typeid(*selection) == typeid(BranchObj) ||
2348 typeid(*selection) == typeid(FloatImageObj))
2350 selection->unselect();
2352 selection->select();
2354 ensureSelectionVisible();
2358 if (typeid(*selection) == typeid(BranchObj) )
2360 bo=((BranchObj*)selection)->getLastSelectedBranch();
2363 selection->unselect();
2365 selection->select();
2367 ensureSelectionVisible();
2375 void MapEditor::selectRightBranch()
2382 if (typeid(*selection) == typeid(MapCenterObj))
2384 par= (BranchObj*) selection;
2385 bo=par->getLastSelectedBranch();
2388 // Workaround for reselecting on left and right side
2389 if (bo->getOrientation()==OrientLeftOfCenter)
2390 bo=par->getFirstBranch();
2395 selection->select();
2396 ensureSelectionVisible();
2401 par=(BranchObj*)(selection->getParObj());
2402 if (selection->getOrientation()==OrientLeftOfCenter)
2404 if (typeid(*selection) == typeid(BranchObj) ||
2405 typeid(*selection) == typeid(FloatImageObj))
2407 selection->unselect();
2409 selection->select();
2411 ensureSelectionVisible();
2415 if (typeid(*selection) == typeid(BranchObj) )
2417 bo=((BranchObj*)selection)->getLastSelectedBranch();
2420 selection->unselect();
2422 selection->select();
2424 ensureSelectionVisible();
2432 void MapEditor::selectFirstBranch()
2438 if (typeid(*selection) == typeid(BranchObj))
2440 bo1= (BranchObj*) selection;
2441 par=(BranchObj*)(bo1->getParObj());
2442 bo2=par->getFirstBranch();
2446 selection->select();
2447 ensureSelectionVisible();
2454 void MapEditor::selectLastBranch()
2460 if (typeid(*selection) == typeid(BranchObj))
2462 bo1= (BranchObj*) selection;
2463 par=(BranchObj*)(bo1->getParObj());
2464 bo2=par->getLastBranch();
2468 selection->select();
2469 ensureSelectionVisible();
2476 void MapEditor::selectMapBackgroundColor()
2478 QColor col = QColorDialog::getColor( mapCanvas->backgroundColor(), this );
2479 if ( !col.isValid() ) return;
2480 setBackgroundColor( col );
2484 void MapEditor::setMapBackgroundColor(QColor col)
2486 QColor oldcol=mapCanvas->backgroundColor();
2489 QString ("setMapBackgroundColor (%1)").arg(oldcol.name()),
2491 QString ("setMapBackgroundColor (%1)").arg(col.name()),
2492 QString("Set background color of map to %1").arg(col.name()));
2493 mapCanvas->setBackgroundColor (col);
2496 QColor MapEditor::getMapBackgroundColor()
2498 return mapCanvas->backgroundColor();
2501 QColor MapEditor::getCurrentHeadingColor()
2505 if (typeid(*selection) == typeid(BranchObj) ||
2506 typeid(*selection) == typeid(MapCenterObj))
2508 BranchObj *bo=(BranchObj*)selection;
2509 return bo->getColor();
2513 QMessageBox::warning(0,tr("Warning"),tr("Can't get color of heading,\nthere's no branch selected"));
2517 void MapEditor::colorItem(QColor c)
2521 if (typeid(*selection) == typeid(BranchObj) ||
2522 typeid(*selection) == typeid(MapCenterObj))
2524 BranchObj *bo=(BranchObj*)selection;
2527 QString ("colorItem (%1)").arg(bo->getColor().name()),
2529 QString ("colorItem (%1)").arg(c.name()),
2530 QString("Set color of %1 to %2").arg(getName(bo)).arg(c.name())
2532 bo->setColor(c); // color branch
2537 void MapEditor::colorBranch(QColor c)
2541 if (typeid(*selection) == typeid(BranchObj) ||
2542 typeid(*selection) == typeid(MapCenterObj))
2544 BranchObj *bo=(BranchObj*)selection;
2545 saveStateChangingPart(
2548 QString ("colorBranch (%1)").arg(c.name()),
2549 QString ("Set color of %1 and childs to %2").arg(getName(bo)).arg(c.name())
2551 bo->setColorChilds(c); // color links, color childs
2557 void MapEditor::toggleStandardFlag(QString f)
2561 if (typeid(*selection) == typeid(BranchObj) ||
2562 typeid(*selection) == typeid(MapCenterObj))
2564 BranchObj *bo=(BranchObj*)selection;
2566 if (bo->isSetStandardFlag(f))
2578 QString("%1 (\"%2\")").arg(u).arg(f),
2580 QString("%1 (\"%2\")").arg(r).arg(f),
2581 QString("Toggling standard flag \"%1\" of %2").arg(f).arg(getName(bo)));
2582 bo->toggleStandardFlag (f,mainWindow->useFlagGroups());
2588 void MapEditor::setViewCenter()
2590 // transform to CanvasView Coord:
2591 QPoint p=worldMatrix().map(movingCenter);
2592 center ( p.x(), p.y());
2596 BranchObj* MapEditor::findText (QString s, bool cs)
2598 QTextDocument::FindFlags flags=0;
2599 if (cs) flags=QTextDocument::FindCaseSensitively;
2602 { // Nothing found or new find process
2604 // nothing found, start again
2606 itFind=mapCenter->first();
2608 bool searching=true;
2609 bool foundNote=false;
2610 while (searching && !EOFind)
2614 // Searching in Note
2615 if (itFind->getNote().contains(s,cs))
2617 if (selection!=itFind)
2619 if (selection) ((BranchObj*)selection)->unselect();
2621 selection->select();
2623 ensureSelectionVisible();
2625 if (textEditor->findText(s,flags))
2631 // Searching in Heading
2632 if (searching && itFind->getHeading().contains (s,cs) )
2634 if (selection) ((BranchObj*)selection)->unselect();
2636 selection->select();
2638 ensureSelectionVisible();
2644 itFind=itFind->next();
2645 if (!itFind) EOFind=true;
2651 return (BranchObj*)selection;
2656 void MapEditor::findReset()
2657 { // Necessary if text to find changes during a find process
2661 void MapEditor::setURL(const QString &url)
2663 if (selection && (typeid(*selection) == typeid(BranchObj) ||
2664 typeid(*selection) == typeid(MapCenterObj)) )
2666 BranchObj *bo=(BranchObj*)selection;
2667 QString oldurl=bo->getURL();
2671 QString ("setURL (\"%1\")").arg(oldurl),
2673 QString ("setURL (\"%1\")").arg(url),
2674 QString ("set URL of %1 to %2").arg(getName(bo)).arg(url)
2680 void MapEditor::editURL()
2682 if (selection && (typeid(*selection) == typeid(BranchObj) ||
2683 typeid(*selection) == typeid(MapCenterObj)) )
2686 BranchObj *bo=(BranchObj*)selection;
2687 QString text = QInputDialog::getText(
2688 "VYM", tr("Enter URL:"), QLineEdit::Normal,
2689 bo->getURL(), &ok, this );
2691 // user entered something and pressed OK
2696 QString MapEditor::getURL()
2698 if (selection && (typeid(*selection) == typeid(BranchObj) ||
2699 typeid(*selection) == typeid(MapCenterObj)) )
2700 return ((BranchObj*)selection)->getURL();
2705 QStringList MapEditor::getURLs()
2708 if (selection && (typeid(*selection) == typeid(BranchObj) ||
2709 typeid(*selection) == typeid(MapCenterObj)) )
2711 BranchObj *bo=(BranchObj*)selection;
2715 if (!bo->getURL().isEmpty()) urls.append( bo->getURL());
2723 void MapEditor::editHeading2URL()
2725 if (selection && (typeid(*selection) == typeid(BranchObj) ||
2726 typeid(*selection) == typeid(MapCenterObj)) )
2727 setURL (((BranchObj*)selection)->getHeading());
2730 void MapEditor::editBugzilla2URL()
2732 if (selection && (typeid(*selection) == typeid(BranchObj) ||
2733 typeid(*selection) == typeid(MapCenterObj)) )
2735 BranchObj *bo=(BranchObj*)selection;
2736 QString url= "https://bugzilla.novell.com/show_bug.cgi?id="+bo->getHeading();
2741 void MapEditor::editFATE2URL()
2743 if (selection && (typeid(*selection) == typeid(BranchObj) ||
2744 typeid(*selection) == typeid(MapCenterObj)) )
2746 BranchObj *bo=(BranchObj*)selection;
2747 QString url= "http://keeper.suse.de:8080/webfate/match/id?value=ID"+bo->getHeading();
2750 "setURL (\""+bo->getURL()+"\")",
2752 "setURL (\""+url+"\")",
2753 QString("Use heading of %1 as link to FATE").arg(getName(bo))
2760 void MapEditor::editVymLink()
2762 if (selection && (typeid(*selection) == typeid(BranchObj) ||
2763 typeid(*selection) == typeid(MapCenterObj)) )
2765 BranchObj *bo=(BranchObj*)selection;
2766 Q3FileDialog *fd=new Q3FileDialog( this,__VYM " - " +tr("Link to another map"));
2767 fd->addFilter (QString (tr("vym map") + " (*.vym)"));
2768 fd->setCaption(__VYM " - " +tr("Link to another map"));
2769 if (! bo->getVymLink().isEmpty() )
2770 fd->setSelection( bo->getVymLink() );
2774 if ( fd->exec() == QDialog::Accepted )
2778 "setVymLink (\""+bo->getVymLink()+"\")",
2780 "setVymLink (\""+fd->selectedFile()+"\")",
2781 QString("Set vymlink of %1 to %2").arg(getName(bo)).arg(fd->selectedFile())
2783 bo->setVymLink (fd->selectedFile() );
2785 mapCenter->reposition();
2792 void MapEditor::deleteVymLink()
2794 if (selection && (typeid(*selection) == typeid(BranchObj) ||
2795 typeid(*selection) == typeid(MapCenterObj)) )
2797 BranchObj *bo=(BranchObj*)selection;
2800 "setVymLink (\""+bo->getVymLink()+"\")",
2802 "setVymLink (\"\")",
2803 QString("Unset vymlink of %1").arg(getName(bo))
2805 bo->setVymLink ("" );
2807 mapCenter->reposition();
2813 void MapEditor::setHideExport(bool b)
2815 if (selection && (typeid(*selection) == typeid(BranchObj) ||
2816 typeid(*selection)==typeid(FloatImageObj)))
2818 OrnamentedObj *oo=(OrnamentedObj*)selection;
2819 oo->setHideInExport (b);
2820 QString u= b ? "false" : "true";
2821 QString r=!b ? "false" : "true";
2825 QString ("setHideExport (%1)").arg(u),
2827 QString ("setHideExport (%1)").arg(r),
2828 QString ("Set HideExport flag of %1 to %2").arg(getName(oo)).arg (r)
2831 mapCenter->reposition();
2837 void MapEditor::toggleHideExport()
2839 if (selection && (typeid(*selection) == typeid(BranchObj) ||
2840 typeid(*selection)==typeid(FloatImageObj)))
2841 setHideExport ( !((OrnamentedObj*)selection)->hideInExport() );
2844 QString MapEditor::getVymLink()
2846 if (selection && (typeid(*selection) == typeid(BranchObj) ||
2847 typeid(*selection) == typeid(MapCenterObj)) )
2849 return ((BranchObj*)selection)->getVymLink();
2855 QStringList MapEditor::getVymLinks()
2858 if (selection && (typeid(*selection) == typeid(BranchObj) ||
2859 typeid(*selection) == typeid(MapCenterObj)) )
2861 BranchObj *bo=(BranchObj*)selection;
2865 if (!bo->getVymLink().isEmpty()) links.append( bo->getVymLink());
2873 void MapEditor::deleteKeepChilds()
2875 if (selection && (typeid(*selection) == typeid(BranchObj) ))
2877 BranchObj* bo=(BranchObj*)selection;
2878 BranchObj* par=(BranchObj*)(bo->getParObj());
2879 QPoint p=bo->getRelPos();
2880 saveStateChangingPart(
2881 selection->getParObj(),
2883 "deleteKeepChilds ()",
2884 QString("Remove %1 and keep its childs").arg(getName(bo))
2887 QString sel=selection->getSelectString();
2889 par->removeBranchHere(bo);
2890 mapCenter->reposition();
2892 ((BranchObj*)selection)->move2RelPos (p);
2893 mapCenter->reposition();
2898 void MapEditor::deleteChilds()
2900 if (selection && (typeid(*selection) == typeid(BranchObj) ||
2901 typeid(*selection)==typeid(MapCenterObj)))
2903 saveStateChangingPart(
2904 selection->getParObj(),
2907 QString( "Remove childs of branch %1").arg(getName(selection))
2909 ((BranchObj*)selection)->removeChilds();
2910 mapCenter->reposition();
2914 void MapEditor::editMapInfo()
2916 ExtraInfoDialog dia;
2917 dia.setMapName (getFileName() );
2918 dia.setAuthor (mapCenter->getAuthor() );
2919 dia.setComment(mapCenter->getComment() );
2924 Q3CanvasItemList l=canvas()->allItems();
2925 for (Q3CanvasItemList::Iterator it=l.begin(); it!=l.end(); ++it)
2927 stats+=QString ("%1 items on canvas\n").arg (i,6);
2934 bo=mapCenter->first();
2937 if (!bo->getNote().isEmpty() ) n++;
2938 f+= bo->countFloatImages();
2940 xl+=bo->countXLinks();
2943 stats+=QString ("%1 branches\n").arg (b-1,6);
2944 stats+=QString ("%1 xLinks \n").arg (xl,6);
2945 stats+=QString ("%1 notes\n").arg (n,6);
2946 stats+=QString ("%1 images\n").arg (f,6);
2947 dia.setStats (stats);
2949 // Finally show dialog
2950 if (dia.exec() == QDialog::Accepted)
2952 setMapAuthor (dia.getAuthor() );
2953 setMapComment (dia.getComment() );
2957 void MapEditor::updateActions()
2959 mainWindow->updateActions();
2960 // FIXME maybe don't update if blockReposition is set
2963 void MapEditor::updateNoteFlag()
2966 if ( (typeid(*selection) == typeid(BranchObj)) ||
2967 (typeid(*selection) == typeid(MapCenterObj)) )
2968 ((BranchObj*)selection)->updateNoteFlag();
2971 void MapEditor::setMapAuthor (const QString &s)
2975 QString ("setMapAuthor (\"%1\")").arg(mapCenter->getAuthor()),
2977 QString ("setMapAuthor (\"%1\")").arg(s),
2978 QString ("Set author of map to \"%1\"").arg(s)
2980 mapCenter->setAuthor (s);
2983 void MapEditor::setMapComment (const QString &s)
2987 QString ("setMapComment (\"%1\")").arg(mapCenter->getComment()),
2989 QString ("setMapComment (\"%1\")").arg(s),
2990 QString ("Set comment of map")
2992 mapCenter->setComment (s);
2995 void MapEditor::setMapLinkStyle (const QString & s)
2997 saveStateChangingPart (
3000 QString("setMapLinkStyle (\"%1\")").arg(s),
3001 QString("Set map link style (\"%1\")").arg(s)
3005 linkstyle=StyleLine;
3006 else if (s=="StyleParabel")
3007 linkstyle=StyleParabel;
3008 else if (s=="StylePolyLine")
3009 linkstyle=StylePolyLine;
3011 linkstyle=StylePolyParabel;
3014 bo=mapCenter->first();
3018 bo->setLinkStyle(bo->getDefLinkStyle());
3021 mapCenter->reposition();
3024 LinkStyle MapEditor::getMapLinkStyle ()
3029 void MapEditor::setMapDefLinkColor(QColor c)
3035 void MapEditor::setMapLinkColorHintInt()
3037 // called from setMapLinkColorHint(lch) or at end of parse
3039 bo=mapCenter->first();
3047 void MapEditor::setMapLinkColorHint(LinkColorHint lch)
3050 setMapLinkColorHintInt();
3053 void MapEditor::toggleMapLinkColorHint()
3055 if (linkcolorhint==HeadingColor)
3056 linkcolorhint=DefaultColor;
3058 linkcolorhint=HeadingColor;
3060 bo=mapCenter->first();
3068 LinkColorHint MapEditor::getMapLinkColorHint()
3070 return linkcolorhint;
3073 QColor MapEditor::getMapDefLinkColor()
3075 return defLinkColor;
3078 void MapEditor::setMapDefXLinkColor(QColor col)
3083 QColor MapEditor::getMapDefXLinkColor()
3085 return defXLinkColor;
3088 void MapEditor::setMapDefXLinkWidth (int w)
3093 int MapEditor::getMapDefXLinkWidth()
3095 return defXLinkWidth;
3098 void MapEditor::selectMapLinkColor()
3100 QColor col = QColorDialog::getColor( defLinkColor, this );
3101 if ( !col.isValid() ) return;
3104 QString("setMapDefLinkColor (\"%1\")").arg(getMapDefLinkColor().name()),
3106 QString("setMapDefLinkColor (\"%1\")").arg(col.name()),
3107 QString("Set link color to %1").arg(col.name())
3109 setMapDefLinkColor( col );
3113 void MapEditor::toggleScroll()
3115 if (selection && (typeid(*selection) == typeid(BranchObj)) )
3117 BranchObj *bo=((BranchObj*)selection);
3118 if (bo->countBranches()==0) return;
3119 if (bo->getDepth()==0) return;
3121 if (bo->isScrolled())
3133 QString ("%1 ()").arg(u),
3135 QString ("%1 ()").arg(r),
3136 QString ("%1 %2").arg(r).arg(getName(bo))
3144 void MapEditor::unScrollAll()
3147 bo=mapCenter->first();
3150 if (bo->isScrolled()) bo->toggleScroll();
3155 void MapEditor::loadFloatImage ()
3158 (typeid(*selection) == typeid(BranchObj)) ||
3159 (typeid(*selection) == typeid(MapCenterObj)) )
3161 BranchObj *bo=((BranchObj*)selection);
3163 Q3FileDialog *fd=new Q3FileDialog( this);
3164 fd->setMode (Q3FileDialog::ExistingFiles);
3165 fd->addFilter (QString (tr("Images") + " (*.png *.bmp *.xbm *.jpg *.png *.xpm *.gif *.pnm)"));
3166 ImagePreview *p =new ImagePreview (fd);
3167 fd->setContentsPreviewEnabled( TRUE );
3168 fd->setContentsPreview( p, p );
3169 fd->setPreviewMode( Q3FileDialog::Contents );
3170 fd->setCaption(__VYM " - " +tr("Load image"));
3171 fd->setDir (lastImageDir);
3175 if ( fd->exec() == QDialog::Accepted )
3177 // FIXME in QT4 use: lastImageDir=fd->directory();
3178 lastImageDir=QDir (fd->dirPath());
3179 QStringList flist = fd->selectedFiles();
3180 QStringList::Iterator it = flist.begin();
3182 while( it != flist.end() )
3185 bo->addFloatImage();
3186 fio=bo->getLastFloatImage();
3188 // FIXME check if load of fio was successful
3190 (LinkableMapObj*)fio,
3193 QString ("loadFloatImage (%1)").arg(*it),
3194 QString("Add floatimage %1 to %2").arg(*it).arg(getName(selection))
3196 bo->getLastFloatImage()->setOriginalFilename(fn);
3200 mapCenter->reposition();
3209 void MapEditor::saveFloatImage ()
3212 (typeid(*selection) == typeid(FloatImageObj)) )
3214 FloatImageObj *fio=((FloatImageObj*)selection);
3215 QFileDialog *fd=new QFileDialog( this);
3216 fd->setFilters (imageIO.getFilters());
3217 fd->setCaption(__VYM " - " +tr("Save image"));
3218 fd->setFileMode( QFileDialog::AnyFile );
3219 fd->setDirectory (lastImageDir);
3220 // fd->setSelection (fio->getOriginalFilename());
3224 if ( fd->exec() == QDialog::Accepted )
3226 if (QFile (fd->selectedFile()).exists() )
3228 QMessageBox mb( __VYM,
3229 tr("The file %1 exists already.\n"
3230 "Do you want to overwrite it?").arg(fd->selectedFile()),
3231 QMessageBox::Warning,
3232 QMessageBox::Yes | QMessageBox::Default,
3233 QMessageBox::Cancel | QMessageBox::Escape,
3234 QMessageBox::QMessageBox::NoButton );
3236 mb.setButtonText( QMessageBox::Yes, tr("Overwrite") );
3237 mb.setButtonText( QMessageBox::No, tr("Cancel"));
3240 case QMessageBox::Yes:
3243 case QMessageBox::Cancel:
3250 fio->save (fd->selectedFile(),imageIO.getType (fd->selectedFilter() ) );
3256 void MapEditor::setFrame(const FrameType &t)
3259 (typeid(*selection) == typeid(BranchObj)) ||
3260 (typeid(*selection) == typeid(MapCenterObj)) )
3262 selection->setFrameType (t);
3263 mapCenter->reposition();
3264 selection->updateLink();
3268 void MapEditor::setIncludeImagesVer(bool b)
3271 (typeid(*selection) == typeid(BranchObj)) ||
3272 (typeid(*selection) == typeid(MapCenterObj)) )
3273 ((BranchObj*)selection)->setIncludeImagesVer(b);
3274 mapCenter->reposition();
3277 void MapEditor::setIncludeImagesHor(bool b)
3280 (typeid(*selection) == typeid(BranchObj)) ||
3281 (typeid(*selection) == typeid(MapCenterObj)) )
3282 ((BranchObj*)selection)->setIncludeImagesHor(b);
3283 mapCenter->reposition();
3286 void MapEditor::setHideLinkUnselected (bool b)
3289 (typeid(*selection) == typeid(BranchObj)) ||
3290 (typeid(*selection) == typeid(MapCenterObj)) ||
3291 (typeid(*selection) == typeid(FloatImageObj)) )
3292 selection->setHideLinkUnselected(b);
3295 void MapEditor::importDirInt(BranchObj *dst, QDir d)
3298 (typeid(*selection) == typeid(BranchObj)) ||
3299 (typeid(*selection) == typeid(MapCenterObj)) )
3303 // Traverse directories
3304 d.setFilter( QDir::Dirs| QDir::Hidden | QDir::NoSymLinks );
3305 QFileInfoList list = d.entryInfoList();
3308 for (int i = 0; i < list.size(); ++i)
3311 if (fi.fileName() != "." && fi.fileName() != ".." )
3314 bo=dst->getLastBranch();
3315 bo->setHeading (fi.fileName() );
3316 bo->setColor (QColor("blue"));
3318 if ( !d.cd(fi.fileName()) )
3319 QMessageBox::critical (0,tr("Critical Import Error"),tr("Cannot find the directory %1").arg(fi.fileName()));
3322 // Recursively add subdirs
3323 importDirInt (bo,d);
3329 d.setFilter( QDir::Files| QDir::Hidden | QDir::NoSymLinks );
3330 list = d.entryInfoList();
3332 for (int i = 0; i < list.size(); ++i)
3336 bo=dst->getLastBranch();
3337 bo->setHeading (fi.fileName() );
3338 bo->setColor (QColor("black"));
3339 if (fi.fileName().right(4) == ".vym" )
3340 bo->setVymLink (fi.filePath());
3345 void MapEditor::importDir()
3348 (typeid(*selection) == typeid(BranchObj)) ||
3349 (typeid(*selection) == typeid(MapCenterObj)) )
3351 Q3FileDialog *fd=new Q3FileDialog( this,__VYM " - " +tr("Choose directory structure to import"));
3352 fd->setMode (Q3FileDialog::DirectoryOnly);
3353 fd->addFilter (QString (tr("vym map") + " (*.vym)"));
3354 fd->setCaption(__VYM " - " +tr("Choose directory structure to import"));
3358 if ( fd->exec() == QDialog::Accepted )
3360 BranchObj *bo=((BranchObj*)selection);
3361 importDirInt (bo,QDir(fd->selectedFile()) );
3362 mapCenter->reposition();
3369 void MapEditor::followXLink(int i)
3372 (typeid(*selection) == typeid(BranchObj)) ||
3373 (typeid(*selection) == typeid(MapCenterObj)) )
3375 BranchObj *bo=((BranchObj*)selection)->XLinkTargetAt(i);
3378 selection->unselect();
3380 selection->select();
3381 ensureSelectionVisible();
3386 void MapEditor::editXLink(int i)
3389 (typeid(*selection) == typeid(BranchObj)) ||
3390 (typeid(*selection) == typeid(MapCenterObj)) )
3392 XLinkObj *xlo=((BranchObj*)selection)->XLinkAt(i);
3395 EditXLinkDialog dia;
3397 dia.setSelection(selection);
3398 if (dia.exec() == QDialog::Accepted)
3400 if (dia.useSettingsGlobal() )
3402 setMapDefXLinkColor (xlo->getColor() );
3403 setMapDefXLinkWidth (xlo->getWidth() );
3405 if (dia.deleteXLink())
3406 ((BranchObj*)selection)->deleteXLinkAt(i);
3407 //saveStateComplete("Edit xLink"); //FIXME undoCommand
3413 void MapEditor::testFunction()
3415 cout << "MapEditor::testFunction() called\n";
3418 (typeid(*selection) == typeid(BranchObj)) ||
3419 (typeid(*selection) == typeid(MapCenterObj)) )
3421 BranchObj* bo=(BranchObj*)selection;
3422 cout << bo->getHeading().ascii() <<" is scrolled: "<<bo->isScrolled()<<endl;
3427 dia.showCancelButton (true);
3428 dia.setText("This is a longer \nWarning");
3430 dia.setCaption("Warning: Flux problem");
3431 dia.setShowAgainName("/warnings/mapeditor");
3433 if (dia.exec()==QDialog::Accepted)
3434 cout << "accepted!\n";
3436 cout << "canceled!\n";
3439 /* Hide hidden stuff temporary, maybe add this as regular function somewhere
3440 if (hidemode==HideNone)
3442 setHideTmpMode (HideExport);
3443 mapCenter->calcBBoxSizeWithChilds();
3444 QRect totalBBox=mapCenter->getTotalBBox();
3445 QRect mapRect=totalBBox;
3446 QCanvasRectangle *frame=NULL;
3448 cout << " map has =("<<totalBBox.x()<<","<<totalBBox.y()<<","<<totalBBox.width()<<","<<totalBBox.height()<<")\n";
3450 mapRect.setRect (totalBBox.x(), totalBBox.y(),
3451 totalBBox.width(), totalBBox.height());
3452 frame=new QCanvasRectangle (mapRect,mapCanvas);
3453 frame->setBrush (QColor(white));
3454 frame->setPen (QColor(black));
3460 setHideTmpMode (HideNone);
3462 cout <<" hidemode="<<hidemode<<endl;
3466 void MapEditor::ensureSelectionVisible()
3470 LinkableMapObj* lmo= dynamic_cast <LinkableMapObj*> (selection);
3472 if (selection->getOrientation() == OrientLeftOfCenter)
3473 p= worldMatrix().map(QPoint (lmo->x(),lmo->y()));
3475 p= worldMatrix().map(QPoint (lmo->x()+lmo->width(),lmo->y()+lmo->height()));
3476 ensureVisible (p.x(), p.y() );
3481 void MapEditor::updateViewCenter()
3483 // Update movingCenter, so that we can zoom comfortably later
3484 QRect rc = QRect( contentsX(), contentsY(),
3485 visibleWidth(), visibleHeight() );
3486 QRect canvasRect = inverseWorldMatrix().mapRect(rc);
3487 movingCenter.setX((canvasRect.right() + canvasRect.left())/2);
3488 movingCenter.setY((canvasRect.top() + canvasRect.bottom())/2);
3491 void MapEditor::contentsContextMenuEvent ( QContextMenuEvent * e )
3493 // Lineedits are already closed by preceding
3494 // mouseEvent, we don't need to close here.
3496 QPoint p = inverseWorldMatrix().map(e->pos());
3497 LinkableMapObj* lmo=mapCenter->findMapObj(p, NULL);
3500 { // MapObj was found
3501 if (selection != lmo)
3503 // select the MapObj
3504 if (selection) selection->unselect();
3506 selection->select();
3512 if (typeid(*selection)==typeid(BranchObj) ||
3513 typeid(*selection)==typeid(MapCenterObj) )
3515 // Context Menu on branch or mapcenter
3517 branchContextMenu->popup(e->globalPos() );
3519 if (typeid(*selection)==typeid(FloatImageObj))
3521 // Context Menu on floatimage
3523 floatimageContextMenu->popup(e->globalPos() );
3527 { // No MapObj found, we are on the Canvas itself
3528 // Context Menu on Canvas
3530 canvasContextMenu->popup(e->globalPos() );
3535 void MapEditor::keyPressEvent(QKeyEvent* e)
3537 if (e->modifiers() && Qt::ControlModifier)
3539 switch (mainWindow->getModMode())
3542 setCursor (PickColorCursor);
3545 setCursor (CopyCursor);
3548 setCursor (XLinkCursor);
3551 setCursor (Qt::ArrowCursor);
3557 void MapEditor::keyReleaseEvent(QKeyEvent* e)
3559 if (!(e->modifiers() && Qt::ControlModifier))
3560 setCursor (Qt::ArrowCursor);
3563 void MapEditor::contentsMousePressEvent(QMouseEvent* e)
3565 // Ignore right clicks, these will go to context menus
3566 if (e->button() == Qt::RightButton )
3572 QPoint p = inverseWorldMatrix().map(e->pos());
3573 LinkableMapObj* lmo=mapCenter->findMapObj(p, NULL);
3577 //Take care of clickdesystem flags _or_ modifier modes
3579 if (lmo && (typeid(*lmo)==typeid(BranchObj) ||
3580 typeid(*lmo)==typeid(MapCenterObj) ))
3582 QString foname=((BranchObj*)lmo)->getSystemFlagName(p);
3583 if (!foname.isEmpty())
3585 // systemFlag clicked
3589 if (e->state() & Qt::ControlModifier)
3590 mainWindow->editOpenURLTab();
3592 mainWindow->editOpenURL();
3594 else if (foname=="vymLink")
3596 mainWindow->editOpenVymLink();
3597 // tabWidget may change, better return now
3598 // before segfaulting...
3599 } else if (foname=="note")
3600 mainWindow->windowToggleNoteEditor();
3601 else if (foname=="hideInExport")
3606 // No system flag clicked, take care of modmodes
3608 // Special case: CTRL is pressed
3609 if (e->state() & Qt::ControlModifier)
3611 if (mainWindow->getModMode()==ModModeColor)
3614 setCursor (PickColorCursor);
3617 if (mainWindow->getModMode()==ModModeXLink)
3619 BranchObj *bo_begin=NULL;
3621 bo_begin=(BranchObj*)(lmo);
3624 ((typeid(*selection) == typeid(BranchObj)) ||
3625 (typeid(*selection) == typeid(MapCenterObj))) )
3626 bo_begin=(BranchObj*)selection;
3630 linkingObj_src=bo_begin;
3631 tmpXLink=new XLinkObj (mapCanvas);
3632 tmpXLink->setBegin (bo_begin);
3633 tmpXLink->setEnd (p);
3634 tmpXLink->setColor(defXLinkColor);
3635 tmpXLink->setWidth(defXLinkWidth);
3636 tmpXLink->updateXLink();
3637 tmpXLink->setVisibility (true);
3645 // Left Button Move Branches
3646 if (e->button() == Qt::LeftButton )
3648 movingObj_start.setX( p.x() - selection->x() );
3649 movingObj_start.setY( p.y() - selection->y() );
3650 movingObj_orgPos.setX (lmo->x() );
3651 movingObj_orgPos.setY (lmo->y() );
3652 movingObj_orgRelPos=lmo->getRelPos();
3654 // If modMode==copy, then we want to "move" the _new_ object around
3655 // then we need the offset from p to the _old_ selection, because of tmp
3656 if (mainWindow->getModMode()==ModModeCopy &&
3657 e->state() & Qt::ControlModifier)
3659 if (typeid(*selection)==typeid(BranchObj) )
3662 mapCenter->addBranch ((BranchObj*)selection);
3664 selection=mapCenter->getLastBranch();
3665 selection->select();
3666 mapCenter->reposition();
3669 movingObj=selection;
3671 // Middle Button Toggle Scroll
3672 // (On Mac OS X this won't work, but we still have
3673 // a button in the toolbar)
3674 if (e->button() == Qt::MidButton )
3678 { // No MapObj found, we are on the Canvas itself
3679 // Left Button move Pos of CanvasView
3680 if (e->button() == Qt::LeftButton )
3682 movingObj=NULL; // move Content not Obj
3683 movingObj_start=e->globalPos();
3684 movingCont_start=QPoint (contentsX(), contentsY() );
3685 movingVec=QPoint(0,0);
3686 setCursor(HandOpenCursor);
3691 void MapEditor::contentsMouseMoveEvent(QMouseEvent* e)
3693 QPoint p = inverseWorldMatrix().map(e->pos());
3695 // Move the selected MapObj
3696 if ( selection && movingObj)
3698 // To avoid jumping of the CanvasView, only
3699 // ensureSelectionVisible, if not tmp linked
3700 if (!selection->hasParObjTmp())
3701 ensureSelectionVisible ();
3703 // Now move the selection, but add relative position
3704 // (movingObj_start) where selection was chosen with
3705 // mousepointer. (This avoids flickering resp. jumping
3706 // of selection back to absPos)
3708 LinkableMapObj *lmosel;
3709 lmosel = dynamic_cast <LinkableMapObj*> (selection);
3711 // Check if we could link
3712 LinkableMapObj* lmo=mapCenter->findMapObj(p, lmosel);
3715 if (typeid(*selection) == typeid(FloatImageObj))
3717 FloatObj *fo=(FloatObj*)selection;
3718 fo->move (p.x() -movingObj_start.x(), p.y()-movingObj_start.y() );
3722 // Relink float to new mapcenter or branch, if shift is pressed
3723 // Only relink, if selection really has a new parent
3724 if ( (e->modifiers()==Qt::ShiftModifier) && lmo &&
3725 ( (typeid(*lmo)==typeid(BranchObj)) ||
3726 (typeid(*lmo)==typeid(MapCenterObj)) ) &&
3727 ( lmo != fo->getParObj())
3730 if (typeid(*fo) == typeid(FloatImageObj))
3733 //saveStateComplete(QString("Relink %1 to %2").arg(getName(fo)).arg(getName(lmo) ) );
3734 FloatImageObj *fio=(FloatImageObj*)(fo);
3735 ((BranchObj*)(lmo))->addFloatImage (fio);
3737 ((BranchObj*)(fio->getParObj()))->removeFloatImage (fio);
3738 fio=((BranchObj*)(lmo))->getLastFloatImage();
3741 selection=(LinkableMapObj*)(fio);
3742 selection->select();
3743 movingObj=(MapObj*)(fio);
3747 { // selection != a FloatObj
3748 if (lmosel->getDepth()==0)
3751 if (e->buttons()== Qt::LeftButton && e->modifiers()==Qt::ShiftModifier)
3752 mapCenter->moveAll(p.x() -movingObj_start.x(), p.y()-movingObj_start.y() );
3754 mapCenter->move (p.x() -movingObj_start.x(), p.y()-movingObj_start.y() );
3755 mapCenter->updateRelPositions();
3758 if (lmosel->getDepth()==1)
3761 lmosel->move(p.x() -movingObj_start.x(), p.y()-movingObj_start.y() );
3762 lmosel->setRelPos();
3765 // Move ordinary branch
3766 if (lmosel->getOrientation() == OrientLeftOfCenter)
3767 // Add width of bbox here, otherwise alignRelTo will cause jumping around
3768 lmosel->move(p.x() -movingObj_start.x()+lmosel->getBBox().width(),
3769 p.y()-movingObj_start.y() +lmosel->getTopPad() );
3771 lmosel->move(p.x() -movingObj_start.x(), p.y()-movingObj_start.y() -lmosel->getTopPad());
3773 // reposition subbranch
3774 lmosel->reposition();
3776 if (lmo && (lmo!=selection) &&
3777 (typeid(*lmo) == typeid(BranchObj) ||
3778 (typeid(*lmo) == typeid(MapCenterObj) )
3781 if (e->modifiers()==Qt::ControlModifier)
3783 // Special case: CTRL to link below lmo
3784 lmosel->setParObjTmp (lmo,p,+1);
3786 else if (e->modifiers()==Qt::ShiftModifier)
3787 lmosel->setParObjTmp (lmo,p,-1);
3789 lmosel->setParObjTmp (lmo,p,0);
3792 lmosel->unsetParObjTmp();
3796 } // no FloatImageObj
3800 } // selection && moving_obj
3802 // Draw a link from one branch to another
3805 tmpXLink->setEnd (p);
3806 tmpXLink->updateXLink();
3810 if (!movingObj && !pickingColor &&!drawingLink)
3812 QPoint p=e->globalPos();
3813 movingVec.setX(-p.x() + movingObj_start.x() );
3814 movingVec.setY(-p.y() + movingObj_start.y() );
3815 setContentsPos( movingCont_start.x() + movingVec.x(),
3816 movingCont_start.y() + movingVec.y());
3823 void MapEditor::contentsMouseReleaseEvent(QMouseEvent* e)
3825 LinkableMapObj *dst;
3826 // Have we been picking color?
3830 setCursor (Qt::ArrowCursor);
3831 // Check if we are over another branch
3832 dst=mapCenter->findMapObj(inverseWorldMatrix().map(e->pos() ), NULL);
3833 if (dst && selection)
3835 if (e->state() & Qt::ShiftModifier)
3837 ((BranchObj*)selection)->setColor (((BranchObj*)(dst))->getColor());
3838 ((BranchObj*)selection)->setLinkColor ();
3842 ((BranchObj*)selection)->setColorChilds (((BranchObj*)(dst))->getColor());
3843 ((BranchObj*)selection)->setLinkColor ();
3849 // Have we been drawing a link?
3853 // Check if we are over another branch
3854 dst=mapCenter->findMapObj(inverseWorldMatrix().map(e->pos() ), NULL);
3855 if (dst && selection)
3857 tmpXLink->setEnd ( ((BranchObj*)(dst)) );
3858 tmpXLink->updateXLink();
3859 tmpXLink->activate();
3860 //saveStateComplete(QString("Activate xLink from %1 to %2").arg(getName(tmpXLink->getBegin())).arg(getName(tmpXLink->getEnd())) ); //FIXME undoCommand
3869 // Have we been moving something?
3870 if ( selection && movingObj )
3872 if(typeid(*selection)==typeid (FloatImageObj))
3874 // Moved FloatObj. Maybe we need to reposition
3875 FloatImageObj *fo=(FloatImageObj*)selection;
3876 QString pold=qpointToString(movingObj_orgRelPos);
3877 QString pnow=qpointToString(fo->getRelPos());
3883 QString("Move %1 to relativ position %2").arg(getName(selection)).arg(pnow));
3885 // FIXME Why calling parObj here?
3886 selection->getParObj()->requestReposition();
3887 mapCenter->reposition();
3890 // Check if we are over another branch, but ignore
3891 // any found LMOs, which are FloatObjs
3892 dst=mapCenter->findMapObj(inverseWorldMatrix().map(e->pos() ),
3893 ((LinkableMapObj*)selection) );
3895 if (dst && (typeid(*dst)!=typeid(BranchObj) && typeid(*dst)!=typeid(MapCenterObj)))
3898 if (typeid(*selection) == typeid(MapCenterObj) )
3899 { // The MapCenter was moved
3900 cout << "FIXME missing savestate...\n";
3903 if (typeid(*selection) == typeid(BranchObj) )
3904 { // A branch was moved
3906 // save the position in case we link to mapcenter
3907 QPoint savePos=QPoint (selection->x(),selection->y() );
3909 // Reset the temporary drawn link to the original one
3910 ((LinkableMapObj*)selection)->unsetParObjTmp();
3912 // For Redo we may need to save original selection
3913 QString preSelStr=selection->getSelectString();
3918 BranchObj* bsel=(BranchObj*)selection;
3919 BranchObj* bdst=(BranchObj*)dst;
3921 QString preParStr=(bsel->getParObj())->getSelectString();
3922 QString preNum=QString::number (bsel->getNum(),10);
3923 QString preDstParStr;
3925 if (e->state() & Qt::ShiftModifier && dst->getParObj())
3927 preDstParStr=dst->getParObj()->getSelectString();
3928 bsel->moveBranchTo ( (BranchObj*)(bdst->getParObj()), bdst->getNum());
3930 if (e->state() & Qt::ControlModifier && dst->getParObj())
3933 preDstParStr=dst->getParObj()->getSelectString();
3934 bsel->moveBranchTo ( (BranchObj*)(bdst->getParObj()), bdst->getNum()+1);
3937 preDstParStr=dst->getSelectString();
3938 bsel->moveBranchTo (bdst,-1);
3939 if (dst->getDepth()==0) bsel->move (savePos);
3941 QString postSelStr=selection->getSelectString();
3942 QString postNum=QString::number (bsel->getNum(),10);
3944 QString undoCom="linkBranchToPos (\""+
3945 preParStr+ "\"," + preNum +"," +
3946 QString ("%1,%2").arg(movingObj_orgPos.x()).arg(movingObj_orgPos.y())+ ")";
3948 QString redoCom="linkBranchToPos (\""+
3949 preDstParStr + "\"," + postNum + "," +
3950 QString ("%1,%2").arg(savePos.x()).arg(savePos.y())+ ")";
3955 QString("Relink %1 to %2").arg(getName(bsel)).arg(getName(dst)) );
3957 if (selection->getDepth()==1)
3959 // The select string might be different _after_ moving around.
3960 // Therefor reposition and then use string of old selection, too
3961 mapCenter->reposition();
3963 QString ps=qpointToString ( ((BranchObj*)selection)->getRelPos() );
3965 selection->getSelectString(), "moveRel "+qpointToString(movingObj_orgRelPos),
3966 preSelStr, "moveRel "+ps,
3967 QString("Move %1 to relative position %2").arg(getName(selection)).arg(ps));
3970 // Draw the original link, before selection was moved around
3971 mapCenter->reposition();
3973 // Finally resize canvas, if needed
3978 // Just make sure, that actions are still ok,e.g. the move branch up/down buttons...
3981 // maybe we moved View: set old cursor
3982 setCursor (Qt::ArrowCursor);
3986 void MapEditor::contentsMouseDoubleClickEvent(QMouseEvent* e)
3988 if (e->button() == Qt::LeftButton )
3990 QPoint p = inverseWorldMatrix().map(e->pos());
3991 LinkableMapObj *lmo=mapCenter->findMapObj(p, NULL);
3992 if (lmo) { // MapObj was found
3993 // First select the MapObj than edit heading
3994 if (selection) selection->unselect();
3996 selection->select();
3997 mainWindow->editHeading();
4002 void MapEditor::resizeEvent (QResizeEvent* e)
4004 Q3CanvasView::resizeEvent( e );
4008 void MapEditor::contentsDragEnterEvent(QDragEnterEvent *event)
4011 // for (unsigned int i=0;event->format(i);i++) // Debug mime type
4012 // cerr << event->format(i) << endl;
4015 (typeid(*selection) == typeid(BranchObj)) ||
4016 (typeid(*selection) == typeid(MapCenterObj))) {
4018 // If QImageDrag can decode mime type
4019 if (Q3ImageDrag::canDecode(event)) {
4024 // If image are dragged from firefox
4025 if (event->provides("application/x-moz-file-promise-url") &&
4026 event->provides("application/x-moz-nativeimage")) {
4027 event->accept(true);
4031 // If QUriDrag can decode mime type
4032 if (Q3UriDrag::canDecode(event)) {
4037 // If Uri are dragged from firefox
4038 if (event->provides("_NETSCAPE_URL")){
4043 // If QTextDrag can decode mime type
4044 if (Q3TextDrag::canDecode(event)) {
4053 bool isUnicode16(const QByteArray &d)
4055 // TODO: make more precise check for unicode 16.
4056 // Guess unicode16 if any of second bytes are zero
4057 unsigned int length = max(0,d.size()-2)/2;
4058 for (unsigned int i = 0; i<length ; i++)
4059 if (d.at(i*2+1)==0) return true;
4063 void MapEditor::contentsDropEvent(QDropEvent *event)
4066 (typeid(*selection) == typeid(BranchObj)) ||
4067 (typeid(*selection) == typeid(MapCenterObj)))
4072 if (event->provides("image/png"))
4075 if (Q3ImageDrag::decode(event, pix))
4077 addFloatImageInt(pix);
4083 } else if (event->provides("application/x-moz-file-promise-url") &&
4084 event->provides("application/x-moz-nativeimage"))
4086 // Contains url to the img src in unicode16
4087 QByteArray d = event->encodedData("application/x-moz-file-promise-url");
4088 QString url = QString((const QChar*)d.data(),d.size()/2);
4092 } else if (event->provides ("text/uri-list"))
4093 { // Uris provided e.g. by konqueror
4094 Q3UriDrag::decode (event,uris);
4095 } else if (event->provides ("_NETSCAPE_URL"))
4096 { // Uris provided by Mozilla
4097 QStringList l = QStringList::split("\n", event->encodedData("_NETSCAPE_URL"));
4100 } else if (event->provides("text/html")) {
4102 // Handels text mime types
4103 // Look like firefox allways handle text as unicode16 (2 bytes per char.)
4104 QByteArray d = event->encodedData("text/html");
4107 text = QString((const QChar*)d.data(),d.size()/2);
4111 textEditor->setText(text);
4115 } else if (event->provides("text/plain")) {
4116 QByteArray d = event->encodedData("text/plain");
4119 text = QString((const QChar*)d.data(),d.size()/2);
4123 textEditor->setText(text);
4135 for (const char* u=uris.first(); u; u=uris.next())
4137 bo=((BranchObj*)selection)->addBranch();
4140 s=Q3UriDrag::uriToLocalFile(u);
4143 QString file = QDir::convertSeparators(s);
4144 heading = QFileInfo(file).baseName();
4146 if (file.endsWith(".vym", false))
4147 bo->setVymLink(file);
4156 if (!heading.isEmpty())
4157 bo->setHeading(heading);
4167 //FIXME saveState has to be called earlier for each of the drops...
4168 //saveStateComplete("Drop Event"); //TODO undo Command
4169 mapCenter->reposition();
4176 void MapEditor::addFloatImageInt (const QPixmap &img)
4179 (typeid(*selection) == typeid(BranchObj)) ||
4180 (typeid(*selection) == typeid(MapCenterObj)) )
4182 BranchObj *bo=((BranchObj*)selection);
4183 //FIXME XXX saveStateChangingPart(selection,QString("Add floatimage to %1").arg(getName(bo)));
4184 //QString fn=fd->selectedFile();
4185 //lastImageDir=fn.left(fn.findRev ("/"));
4186 FloatImageObj *fio=bo->addFloatImage();
4188 fio->setOriginalFilename("Image added by Drag and Drop");
4189 mapCenter->reposition();
4196 void MapEditor::imageDataFetched(const QByteArray &a, Q3NetworkOperation */*nop*/)
4198 if (!imageBuffer) imageBuffer = new QBuffer();
4199 if (!imageBuffer->isOpen()) {
4200 imageBuffer->open(QIODevice::WriteOnly | QIODevice::Append);
4202 imageBuffer->at(imageBuffer->at()+imageBuffer->writeBlock(a));
4206 void MapEditor::imageDataFinished(Q3NetworkOperation *nop)
4208 if (nop->state()==Q3NetworkProtocol::StDone) {
4209 QPixmap img(imageBuffer->buffer());
4210 addFloatImageInt (img);
4214 imageBuffer->close();
4216 imageBuffer->close();
4223 void MapEditor::fetchImage(const QString &url)
4226 urlOperator->stop();
4227 disconnect(urlOperator);
4231 urlOperator = new Q3UrlOperator(url);
4232 connect(urlOperator, SIGNAL(finished(Q3NetworkOperation *)),
4233 this, SLOT(imageDataFinished(Q3NetworkOperation*)));
4235 connect(urlOperator, SIGNAL(data(const QByteArray &, Q3NetworkOperation *)),
4236 this, SLOT(imageDataFetched(const QByteArray &, Q3NetworkOperation *)));