historywindow moved to mainwindow. Started to get rid of Q3PtrList finally
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* canvasContextMenu;
46 extern Settings settings;
47 extern ImageIO imageIO;
49 extern QString iconPath;
50 extern QDir vymBaseDir;
51 extern QDir lastImageDir;
53 int MapEditor::mapNum=0; // make instance
55 ///////////////////////////////////////////////////////////////////////
56 ///////////////////////////////////////////////////////////////////////
58 QWidget* parent, const char* name, Qt::WFlags f) :
59 Q3CanvasView(parent,name,f), urlOperator(0), imageBuffer(0)
61 //cout << "Constructor ME "<<this<<endl;
64 viewport()->setAcceptDrops(true);
66 mapCanvas = new Q3Canvas(width(),height());
67 mapCanvas->setAdvancePeriod(30);
68 mapCanvas->setBackgroundColor (Qt::white);
70 setCanvas (mapCanvas);
72 // Always show scroll bars (automatic would flicker sometimes)
73 setVScrollBarMode ( Q3ScrollView::AlwaysOn );
74 setHScrollBarMode ( Q3ScrollView::AlwaysOn );
76 mapCenter = new MapCenterObj(mapCanvas);
77 mapCenter->setVisibility (true);
78 mapCenter->setMapEditor (this);
79 mapCenter->setHeading (tr("New Map","Heading of mapcenter in new map"));
80 mapCenter->move(mapCanvas->width()/2-mapCenter->width()/2,mapCanvas->height()/2-mapCenter->height()/2);
84 defLinkColor=QColor (0,0,255);
85 defXLinkColor=QColor (180,180,180);
86 linkcolorhint=DefaultColor;
87 linkstyle=StylePolyParabel;
89 // Create bitmap cursors, platform dependant
90 // FIXME should now work also on Mac...
91 //#if defined(Q_OS_MACX)
92 // HandOpenCursor=QCursor ( QPixmap(iconPath+"cursorhandopen16.png"),1,1 );
93 // PickColorCursor=QCursor ( QPixmap (iconPath+"cursorcolorpicker16.png"), 1,15 );
95 HandOpenCursor=QCursor (QPixmap(iconPath+"cursorhandopen.png"),1,1);
96 PickColorCursor=QCursor ( QPixmap(iconPath+"cursorcolorpicker.png"), 5,27 );
97 CopyCursor=QCursor ( QPixmap(iconPath+"cursorcopy.png"), 5,5 );
98 XLinkCursor=QCursor ( QPixmap(iconPath+"cursorxlink.png"), 5,27 );
101 setFocusPolicy (Qt::StrongFocus);
112 xelection.setMapCenter (mapCenter);
115 defXLinkColor=QColor (230,230,230);
123 fileName=tr("unnamed");
126 stepsTotal=settings.readNumEntry("/mapeditor/stepsTotal",100);
127 undoSet.setEntry ("/history/stepsTotal",QString::number(stepsTotal));
129 // Initialize find routine
136 blockReposition=false;
137 blockSaveState=false;
141 // Create temporary files
144 // Initially set movingCentre
147 mapCenter->reposition(); // for positioning heading
149 // Initialize history window;
150 historyWindow.setME(this);
151 historyWindow.setStepsTotal(stepsTotal);
152 historyWindow.update (undoSet);
155 MapEditor::~MapEditor()
157 if (imageBuffer) delete imageBuffer;
163 //cout <<"Destructor MapEditor\n";
166 MapCenterObj* MapEditor::getMapCenter()
171 Q3Canvas* MapEditor::getCanvas()
176 void MapEditor::adjustCanvasSize()
178 // To adjust the canvas to map, viewport size and position, we have to
179 // do some coordinate magic...
181 // Get rectangle of (scroll-)view.
182 // We want to be in canvas coords, so
183 // we map. Important if view is zoomed...
184 QRect view = inverseWorldMatrix().mapRect( QRect( contentsX(), contentsY(),
185 visibleWidth(), visibleHeight()) );
187 // Now we need the bounding box of view AND map to calc the correct canvas size.
188 // Why? Because if the map itself is moved out of view, the view has to be enlarged
189 // to avoid jumping aroung...
190 QRect map=mapCenter->getTotalBBox();
192 // right edge - left edge
193 int cw= max(map.x() + map.width(), view.x() + view.width()) - min(map.x(), view.x());
194 int ch= max(map.y() + map.height(), view.y() + view.height()) - min(map.y(), view.y());
197 if ( (cw!=mapCanvas->width()) || (ch!=mapCanvas->height()) ||
198 !mapCanvas->onCanvas (map.topLeft()) || !mapCanvas->onCanvas (map.bottomRight())
201 // move the map on canvas (in order to not move it on screen) this is neccessary
202 // a) if topleft corner of canvas is left or above topleft corner of view and also left of
203 // above topleft corner of map. E.g. if map is completly inside view, but it would be possible
204 // to scroll to an empty area of canvas to the left.
205 // b) if topleft corner of map left of or above topleft of canvas
209 if (cw > mapCanvas->width() )
211 if (map.x()<0) dx=-map.x();
213 if (cw < mapCanvas->width() )
214 dx=-min (view.x(),map.x());
215 if (ch > mapCanvas->height() )
217 if (map.y()<0) dy=-map.y();
219 if (ch < mapCanvas->height() )
221 dy=-min (view.y(),map.y());
223 // We really have to resize now. Let's go...
224 mapCanvas->resize (cw,ch);
225 if ( (dx!=0) || (dy!=0) )
227 mapCenter->moveAllBy(dx,dy);
228 mapCenter->reposition();
229 // mapCenter->positionBBox(); // To move float
231 // scroll the view (in order to not move map on screen)
237 bool MapEditor::isRepositionBlocked()
239 return blockReposition;
242 QString MapEditor::getName (LinkableMapObj *lmo)
245 if (!lmo) return QString("Error: NULL has no name!");
247 if ((typeid(*lmo) == typeid(BranchObj) ||
248 typeid(*lmo) == typeid(MapCenterObj)))
251 s=(((BranchObj*)lmo)->getHeading());
252 if (s=="") s="unnamed";
253 return QString("branch (%1)").arg(s);
254 //return QString("branch (<font color=\"#0000ff\">%1</font>)").arg(s);
256 if ((typeid(*lmo) == typeid(FloatImageObj) ))
257 return QString ("floatimage [%1]").arg(((FloatImageObj*)lmo)->getOriginalFilename());
258 //return QString ("floatimage [<font color=\"#0000ff\">%1</font>]").arg(((FloatImageObj*)lmo)->getOriginalFilename());
259 return QString("Unknown type has no name!");
262 void MapEditor::makeTmpDirs()
264 // Create unique temporary directories
265 tmpMapDir=QDir::convertSeparators (tmpVymDir+QString("/mapeditor-%1").arg(mapNum));
266 histPath=QDir::convertSeparators (tmpMapDir+"/history");
271 QString MapEditor::saveToDir(const QString &tmpdir, const QString &prefix, bool writeflags, const QPoint &offset, LinkableMapObj *saveSel)
273 // tmpdir temporary directory to which data will be written
274 // prefix mapname, which will be appended to images etc.
275 // writeflags Only write flags for "real" save of map, not undo
276 // offset offset of bbox of whole map in canvas.
277 // Needed for XML export
293 ls="StylePolyParabel";
297 QString s="<?xml version=\"1.0\" encoding=\"utf-8\"?><!DOCTYPE vymmap>\n";
299 if (linkcolorhint==HeadingColor)
300 colhint=attribut("linkColorHint","HeadingColor");
302 QString mapAttr=attribut("version",__VYM_VERSION);
303 if (!saveSel || saveSel==mapCenter)
304 mapAttr+= attribut("author",mapCenter->getAuthor()) +
305 attribut("comment",mapCenter->getComment()) +
306 attribut("date",mapCenter->getDate()) +
307 attribut("backgroundColor", mapCanvas->backgroundColor().name() ) +
308 attribut("linkStyle", ls ) +
309 attribut("linkColor", defLinkColor.name() ) +
310 attribut("defXLinkColor", defXLinkColor.name() ) +
311 attribut("defXLinkWidth", QString().setNum(defXLinkWidth,10) ) +
313 s+=beginElement("vymmap",mapAttr);
316 // Find the used flags while traversing the tree
317 standardFlagsDefault->resetUsedCounter();
319 // Reset the counters before saving
320 FloatImageObj (mapCanvas).resetSaveCounter();
322 // Build xml recursivly
323 if (!saveSel || typeid (*saveSel) == typeid (MapCenterObj))
324 // Save complete map, if saveSel not set
325 s+=mapCenter->saveToDir(tmpdir,prefix,writeflags,offset);
328 if ( typeid(*saveSel) == typeid(BranchObj) )
330 s+=((BranchObj*)(saveSel))->saveToDir(tmpdir,prefix,offset);
331 else if ( typeid(*saveSel) == typeid(FloatImageObj) )
333 s+=((FloatImageObj*)(saveSel))->saveToDir(tmpdir,prefix);
335 else if (selection && typeid(*selection)==typeid(BranchObj))
336 // Save selected branch is saved from mainwindow //FIXME maybe use "subtree" above?
337 // FIXME is this possible at all? BO is already above...
338 s+=((BranchObj*)selection)->saveToDir(tmpdir,prefix,offset);
341 // Save local settings
342 s+=settings.getXMLData (destPath);
345 if (selection && !saveSel )
346 s+=valueElement("select",selection->getSelectString());
349 s+=endElement("vymmap");
352 standardFlagsDefault->saveToDir (tmpdir+"/flags/","",writeflags);
356 void MapEditor::saveStateChangingPart(LinkableMapObj *undoSel, LinkableMapObj* redoSel, const QString &rc, const QString &comment)
358 // save the selected part of the map, Undo will replace part of map
359 QString undoSelection="";
361 undoSelection=undoSel->getSelectString();
363 qWarning ("MapEditor::saveStateChangingPart no undoSel given!");
364 QString redoSelection="";
366 redoSelection=undoSel->getSelectString();
368 qWarning ("MapEditor::saveStateChangingPart no redoSel given!");
371 saveState (PartOfMap,
372 undoSelection, "addMapReplace (\"PATH\")",
378 void MapEditor::saveStateRemovingPart(LinkableMapObj *redoSel, const QString &comment)
382 qWarning ("MapEditor::saveStateRemovingPart no redoSel given!");
385 QString undoSelection=redoSel->getParObj()->getSelectString();
386 QString redoSelection=redoSel->getSelectString();
387 if (typeid(*redoSel) == typeid(BranchObj) )
389 // save the selected branch of the map, Undo will insert part of map
390 saveState (PartOfMap,
391 undoSelection, QString("addMapInsert (\"PATH\",%1)").arg(((BranchObj*)redoSel)->getNum()),
392 redoSelection, "delete ()",
399 void MapEditor::saveState(LinkableMapObj *undoSel, const QString &uc, LinkableMapObj *redoSel, const QString &rc, const QString &comment)
401 // "Normal" savestate: save commands, selections and comment
402 // so just save commands for undo and redo
403 // and use current selection
405 QString redoSelection="";
406 if (redoSel) redoSelection=redoSel->getSelectString();
407 QString undoSelection="";
408 if (undoSel) undoSelection=undoSel->getSelectString();
410 saveState (UndoCommand,
417 void MapEditor::saveState(const QString &undoSel, const QString &uc, const QString &redoSel, const QString &rc, const QString &comment)
419 // "Normal" savestate: save commands, selections and comment
420 // so just save commands for undo and redo
421 // and use current selection
422 saveState (UndoCommand,
430 void MapEditor::saveState(const SaveMode &savemode, const QString &undoSelection, const QString &undoCom, const QString &redoSelection, const QString &redoCom, const QString &comment, LinkableMapObj *saveSel)
434 if (blockSaveState) return;
436 /* TODO remove after testing
438 cout << "ME::saveState() "<<endl;
440 int undosAvail=undoSet.readNumEntry ("/history/undosAvail",0);
441 int redosAvail=undoSet.readNumEntry ("/history/redosAvail",0);
442 int curStep=undoSet.readNumEntry ("/history/curStep",0);
443 // Find out current undo directory
444 if (undosAvail<stepsTotal) undosAvail++;
446 if (curStep>stepsTotal) curStep=1;
448 QString backupXML="";
449 QString bakMapName=QDir::convertSeparators (QString("history-%1").arg(curStep));
450 QString bakMapDir=QDir::convertSeparators (tmpMapDir +"/"+bakMapName);
451 QString bakMapPath=QDir::convertSeparators(bakMapDir+"/map.xml");
453 // Create bakMapDir if not available
456 makeSubDirs (bakMapDir);
458 // Save depending on how much needs to be saved
460 backupXML=saveToDir (bakMapDir,mapName+"-",false, QPoint (),saveSel);
462 QString undoCommand="";
463 if (savemode==UndoCommand)
467 else if (savemode==PartOfMap )
470 undoCommand.replace ("PATH",bakMapPath);
473 if (!backupXML.isEmpty())
474 // Write XML Data to disk
475 saveStringToDisk (QString(bakMapPath),backupXML);
477 // We would have to save all actions in a tree, to keep track of
478 // possible redos after a action. Possible, but we are too lazy: forget about redos.
481 // Write the current state to disk
482 undoSet.setEntry ("/history/undosAvail",QString::number(undosAvail));
483 undoSet.setEntry ("/history/redosAvail",QString::number(redosAvail));
484 undoSet.setEntry ("/history/curStep",QString::number(curStep));
485 undoSet.setEntry (QString("/history/step-%1/undoCommand").arg(curStep),undoCommand);
486 undoSet.setEntry (QString("/history/step-%1/undoSelection").arg(curStep),undoSelection);
487 undoSet.setEntry (QString("/history/step-%1/redoCommand").arg(curStep),redoCom);
488 undoSet.setEntry (QString("/history/step-%1/redoSelection").arg(curStep),redoSelection);
489 undoSet.setEntry (QString("/history/step-%1/comment").arg(curStep),comment);
490 undoSet.setEntry (QString("/history/version"),__VYM_VERSION);
491 undoSet.writeSettings(histPath);
493 /* TODO remove after testing
495 //cout << " into="<< histPath.toStdString()<<endl;
496 cout << " stepsTotal="<<stepsTotal<<
497 ", undosAvail="<<undosAvail<<
498 ", redosAvail="<<redosAvail<<
499 ", curStep="<<curStep<<endl;
500 cout << " ---------------------------"<<endl;
501 cout << " comment="<<comment.toStdString()<<endl;
502 cout << " undoCom="<<undoCommand.toStdString()<<endl;
503 cout << " undoSel="<<undoSelection.toStdString()<<endl;
504 cout << " redoCom="<<redoCom.toStdString()<<endl;
505 cout << " redoSel="<<redoSelection.toStdString()<<endl;
506 if (saveSel) cout << " saveSel="<<saveSel->getSelectString().ascii()<<endl;
507 cout << " ---------------------------"<<endl;
509 historyWindow.update (undoSet);
514 void MapEditor::parseAtom(const QString &atom)
521 // Split string s into command and parameters
522 api.parseInput (atom);
523 QString com=api.command();
526 if (com=="addBranch")
530 api.setError (Aborted,"Nothing selected");
531 } else if ( (typeid(*selection) != typeid(BranchObj) &&
532 typeid(*selection) != typeid(MapCenterObj)) )
534 api.setError (Aborted,"Type of selection is not a branch");
539 if (api.checkParamCount(pl))
541 if (api.paramCount()==0)
542 addNewBranchInt (-2);
546 if (ok ) addNewBranchInt (y);
550 } else if (com=="addBranchBefore")
554 api.setError (Aborted,"Nothing selected");
555 } else if ( (typeid(*selection) != typeid(BranchObj) &&
556 typeid(*selection) != typeid(MapCenterObj)) )
558 api.setError (Aborted,"Type of selection is not a branch");
561 if (api.paramCount()==0)
563 addNewBranchBefore ();
566 } else if (com==QString("addMapReplace"))
570 api.setError (Aborted,"Nothing selected");
571 } else if ( (typeid(*selection) != typeid(BranchObj) &&
572 typeid(*selection) != typeid(MapCenterObj)) )
574 api.setError (Aborted,"Type of selection is not a branch");
575 } else if (api.checkParamCount(1))
577 //s=api.parString (ok,0); // selection
578 t=api.parString (ok,0); // path to map
579 if (QDir::isRelativePath(t)) t=QDir::convertSeparators (tmpMapDir + "/"+t);
580 addMapReplaceInt(selection->getSelectString(),t);
582 } else if (com==QString("addMapInsert"))
586 api.setError (Aborted,"Nothing selected");
587 } else if ( (typeid(*selection) != typeid(BranchObj) &&
588 typeid(*selection) != typeid(MapCenterObj)) )
590 api.setError (Aborted,"Type of selection is not a branch");
593 if (api.checkParamCount(2))
595 t=api.parString (ok,0); // path to map
596 y=api.parInt(ok,1); // position
597 if (QDir::isRelativePath(t)) t=QDir::convertSeparators (tmpMapDir + "/"+t);
598 addMapInsertInt(t,y);
601 } else if (com=="colorItem")
605 api.setError (Aborted,"Nothing selected");
606 } else if ( typeid(*selection) != typeid(BranchObj) &&
607 typeid(*selection) != typeid(MapCenterObj))
609 api.setError (Aborted,"Type of selection is not a branch");
610 } else if (api.checkParamCount(1))
612 QColor c=api.parColor (ok,0);
613 if (ok) colorItem (c);
615 } else if (com=="colorBranch")
619 api.setError (Aborted,"Nothing selected");
620 } else if ( typeid(*selection) != typeid(BranchObj) &&
621 typeid(*selection) != typeid(MapCenterObj))
623 api.setError (Aborted,"Type of selection is not a branch");
624 } else if (api.checkParamCount(1))
626 QColor c=api.parColor (ok,0);
627 if (ok) colorBranch (c);
629 } else if (com=="cut")
633 api.setError (Aborted,"Nothing selected");
634 } else if ( typeid(*selection) != typeid(BranchObj) &&
635 typeid(*selection) != typeid(MapCenterObj) &&
636 typeid(*selection) != typeid(FloatImageObj) )
638 api.setError (Aborted,"Type of selection is not a branch or floatimage");
639 } else if (api.checkParamCount(0))
643 } else if (com=="delete")
647 api.setError (Aborted,"Nothing selected");
648 } else if ( (typeid(*selection) != typeid(BranchObj) &&
649 typeid(*selection) != typeid(MapCenterObj)) )
651 api.setError (Aborted,"Type of selection is not a branch");
652 } else if (api.checkParamCount(0))
656 } else if (com=="deleteKeepChilds")
660 api.setError (Aborted,"Nothing selected");
661 } else if ( (typeid(*selection) != typeid(BranchObj) &&
662 typeid(*selection) != typeid(MapCenterObj)) )
664 api.setError (Aborted,"Type of selection is not a branch");
665 } else if (api.checkParamCount(0))
669 } else if (com=="deleteChilds")
673 api.setError (Aborted,"Nothing selected");
674 } else if ( (typeid(*selection) != typeid(BranchObj) &&
675 typeid(*selection) != typeid(MapCenterObj)) )
677 api.setError (Aborted,"Type of selection is not a branch");
678 } else if (api.checkParamCount(0))
682 } else if (com=="linkBranchToPos")
686 api.setError (Aborted,"Nothing selected");
687 } else if ( (typeid(*selection) != typeid(BranchObj) &&
688 typeid(*selection) != typeid(MapCenterObj)) )
690 api.setError (Aborted,"Type of selection is not a branch");
691 } else if (api.checkParamCount(4))
693 // 0 selectstring of parent
694 // 1 num in parent (for branches)
695 // 2,3 x,y of mainbranch or mapcenter
696 s=api.parString(ok,0);
697 LinkableMapObj *dst=mapCenter->findObjBySelect (s);
700 if (typeid(*dst) == typeid(BranchObj) )
702 // Get number in parent
705 ((BranchObj*)selection)->moveBranchTo ((BranchObj*)(dst),x);
706 } else if (typeid(*dst) == typeid(MapCenterObj) )
708 ((BranchObj*)selection)->moveBranchTo ((BranchObj*)(dst),-1);
709 // Get coordinates of mainbranch
714 if (ok) ((BranchObj*)selection)->move (x,y);
719 } else if (com=="moveBranchUp")
723 api.setError (Aborted,"Nothing selected");
724 } else if ( (typeid(*selection) != typeid(BranchObj) &&
725 typeid(*selection) != typeid(MapCenterObj)) )
727 api.setError (Aborted,"Type of selection is not a branch");
728 } else if (api.checkParamCount(0))
732 } else if (com=="moveBranchDown")
736 api.setError (Aborted,"Nothing selected");
737 } else if ( (typeid(*selection) != typeid(BranchObj) &&
738 typeid(*selection) != typeid(MapCenterObj)) )
740 api.setError (Aborted,"Type of selection is not a branch");
741 } else if (api.checkParamCount(0))
745 } else if (com=="move")
749 api.setError (Aborted,"Nothing selected");
750 } else if ( typeid(*selection) != typeid(BranchObj) &&
751 typeid(*selection) != typeid(MapCenterObj) &&
752 typeid(*selection) != typeid(FloatImageObj) )
754 api.setError (Aborted,"Type of selection is not a branch or floatimage");
755 } else if (api.checkParamCount(2))
764 } else if (com=="moveRel")
768 api.setError (Aborted,"Nothing selected");
769 } else if ( typeid(*selection) != typeid(BranchObj) &&
770 typeid(*selection) != typeid(MapCenterObj) &&
771 typeid(*selection) != typeid(FloatImageObj) )
773 api.setError (Aborted,"Type of selection is not a branch or floatimage");
774 } else if (api.checkParamCount(2))
780 if (ok) moveRel (x,y);
783 } else if (com=="paste")
787 api.setError (Aborted,"Nothing selected");
788 } else if ( typeid(*selection) != typeid(BranchObj) &&
789 typeid(*selection) != typeid(MapCenterObj) )
791 api.setError (Aborted,"Type of selection is not a branch");
792 } else if (api.checkParamCount(0))
796 } else if (com=="select")
798 if (api.checkParamCount(1))
800 s=api.parString(ok,0);
803 } else if (com=="setMapAuthor")
805 if (api.checkParamCount(1))
807 s=api.parString(ok,0);
808 if (ok) setMapAuthor (s);
810 } else if (com=="setMapComment")
812 if (api.checkParamCount(1))
814 s=api.parString(ok,0);
815 if (ok) setMapComment(s);
817 } else if (com=="setMapBackgroundColor")
821 api.setError (Aborted,"Nothing selected");
822 } else if ( (typeid(*selection) != typeid(BranchObj) &&
823 typeid(*selection) != typeid(MapCenterObj)) )
825 api.setError (Aborted,"Type of selection is not a branch");
826 } else if (api.checkParamCount(1))
828 QColor c=api.parColor (ok,0);
829 if (ok) setMapBackgroundColor (c);
831 } else if (com=="setMapDefLinkColor")
835 api.setError (Aborted,"Nothing selected");
836 } else if ( (typeid(*selection) != typeid(BranchObj) &&
837 typeid(*selection) != typeid(MapCenterObj)) )
839 api.setError (Aborted,"Type of selection is not a branch");
840 } else if (api.checkParamCount(1))
842 QColor c=api.parColor (ok,0);
843 if (ok) setMapDefLinkColor (c);
845 } else if (com=="setMapLinkStyle")
847 if (api.checkParamCount(1))
849 s=api.parString (ok,0);
850 if (ok) setMapLinkStyle(s);
852 } else if (com=="setHeading")
856 api.setError (Aborted,"Nothing selected");
857 } else if ( (typeid(*selection) != typeid(BranchObj) &&
858 typeid(*selection) != typeid(MapCenterObj)) )
860 api.setError (Aborted,"Type of selection is not a branch");
861 } else if (api.checkParamCount(1))
863 s=api.parString (ok,0);
867 } else if (com=="setHideExport")
871 api.setError (Aborted,"Nothing selected");
872 } else if ( typeid(*selection) != typeid(BranchObj) &&
873 typeid(*selection) != typeid(FloatImageObj) )
875 api.setError (Aborted,"Type of selection is not a branch or floatimage");
876 } else if (api.checkParamCount(1))
879 if (ok) setHideExport (b);
881 } else if (com=="setURL")
885 api.setError (Aborted,"Nothing selected");
886 } else if ( (typeid(*selection) != typeid(BranchObj) &&
887 typeid(*selection) != typeid(MapCenterObj)) )
889 api.setError (Aborted,"Type of selection is not a branch");
890 } else if (api.checkParamCount(1))
892 s=api.parString (ok,0);
893 if (ok) setURLInt(s);
895 } else if (com=="setVymLink")
899 api.setError (Aborted,"Nothing selected");
900 } else if ( (typeid(*selection) != typeid(BranchObj) &&
901 typeid(*selection) != typeid(MapCenterObj)) )
903 api.setError (Aborted,"Type of selection is not a branch");
904 } else if (api.checkParamCount(1))
906 s=api.parString (ok,0);
907 if (ok) setVymLinkInt(s);
910 else if (com=="setFlag")
914 api.setError (Aborted,"Nothing selected");
915 } else if ( (typeid(*selection) != typeid(BranchObj) &&
916 typeid(*selection) != typeid(MapCenterObj)) )
918 api.setError (Aborted,"Type of selection is not a branch");
919 } else if (api.checkParamCount(1))
921 s=api.parString(ok,0);
924 BranchObj* bo=(BranchObj*)selection;
925 bo->activateStandardFlag(s);
926 bo->updateFlagsToolbar();
930 else if (com=="unsetFlag")
934 api.setError (Aborted,"Nothing selected");
935 } else if ( (typeid(*selection) != typeid(BranchObj) &&
936 typeid(*selection) != typeid(MapCenterObj)) )
938 api.setError (Aborted,"Type of selection is not a branch");
939 } else if (api.checkParamCount(1))
941 s=api.parString(ok,0);
944 BranchObj* bo=(BranchObj*)selection;
945 bo->deactivateStandardFlag(s);
946 bo->updateFlagsToolbar();
951 api.setError (Aborted,"Unknown command");
955 if (api.errorLevel()==NoError)
959 // TODO Error handling
960 qWarning("MapEditor::parseAtom: Error!");
961 qWarning(api.errorMessage());
965 void MapEditor::toggleHistoryWindow()
967 if (historyWindow.isVisible())
968 historyWindow.hide();
970 historyWindow.show();
974 bool MapEditor::isDefault()
979 bool MapEditor::isUnsaved()
984 bool MapEditor::hasChanged()
989 void MapEditor::setChanged()
997 void MapEditor::closeMap()
999 // Unselect before disabling the toolbar actions
1000 if (selection) selection->unselect();
1008 void MapEditor::setFilePath(QString fname)
1010 setFilePath (fname,fname);
1013 void MapEditor::setFilePath(QString fname, QString destname)
1015 if (fname.isEmpty() || fname=="")
1022 filePath=fname; // becomes absolute path
1023 fileName=fname; // gets stripped of path
1024 destPath=destname; // needed for vymlinks
1026 // If fname is not an absolute path, complete it
1027 filePath=QDir(fname).absPath();
1028 fileDir=filePath.left (1+filePath.findRev ("/"));
1030 // Set short name, too. Search from behind:
1031 int i=fileName.findRev("/");
1032 if (i>=0) fileName=fileName.remove (0,i+1);
1034 // Forget the .vym (or .xml) for name of map
1035 mapName=fileName.left(fileName.findRev(".",-1,true) );
1037 // Adjust history window
1038 historyWindow.setCaption (__VYM " - " +tr("History for ")+fileName);
1042 QString MapEditor::getFilePath()
1047 QString MapEditor::getFileName()
1052 QString MapEditor::getMapName()
1057 QString MapEditor::getDestPath()
1062 ErrorCode MapEditor::load (QString fname, LoadMode lmode)
1064 ErrorCode err=success;
1068 if (selection) selection->unselect();
1071 mapCenter->setMapEditor(this);
1072 // (map state is set later at end of load...)
1075 if (!selection || (typeid(*selection) != typeid(BranchObj) &&
1076 typeid(*selection) != typeid (MapCenterObj)))
1078 BranchObj *bo=(BranchObj*)selection;
1079 if (lmode==ImportAdd)
1080 saveStateChangingPart(
1083 QString("addMapInsert (%1)").arg(fname),
1084 QString("Add map %1 to %2").arg(fname).arg(getName(bo)));
1086 saveStateChangingPart(
1089 QString("addMapReplace(%1)").arg(fname),
1090 QString("Add map %1 to %2").arg(fname).arg(getName(bo)));
1094 mapBuilderHandler handler;
1095 QFile file( fname );
1097 // I am paranoid: file should exist anyway
1098 // according to check in mainwindow.
1099 if (!file.exists() )
1101 QMessageBox::critical( 0, tr( "Critical Parse Error" ),
1102 tr("Couldn't open map " +fname)+".");
1106 blockReposition=true;
1107 QXmlInputSource source( file);
1108 QXmlSimpleReader reader;
1109 reader.setContentHandler( &handler );
1110 reader.setErrorHandler( &handler );
1111 handler.setMapEditor( this );
1112 handler.setTmpDir (filePath.left(filePath.findRev("/",-1))); // needed to load files with rel. path
1113 handler.setInputFile (file.name());
1114 handler.setLoadMode (lmode);
1115 blockSaveState=true;
1116 bool ok = reader.parse( source );
1117 blockReposition=false;
1118 blockSaveState=false;
1122 mapCenter->reposition();
1132 QMessageBox::critical( 0, tr( "Critical Parse Error" ),
1133 tr( handler.errorProtocol() ) );
1135 // Still return "success": the map maybe at least
1136 // partially read by the parser
1143 int MapEditor::save (const SaveMode &savemode)
1147 // Create mapName and fileDir
1148 makeSubDirs (fileDir);
1152 fname=mapName+".xml";
1154 // use name given by user, even if he chooses .doc
1159 if (savemode==CompleteMap || selection==NULL)
1160 saveFile=saveToDir (fileDir,mapName+"-",true,QPoint(),NULL);
1162 saveFile=saveToDir (fileDir,mapName+"-",true,QPoint(),selection);
1164 if (!saveStringToDisk(fileDir+fname,saveFile))
1177 void MapEditor::setZipped (bool z)
1182 bool MapEditor::saveZipped ()
1187 void MapEditor::print()
1191 printer = new QPrinter;
1192 printer->setColorMode (QPrinter::Color);
1193 printer->setPrinterName (settings.value("/mainwindow/printerName",printer->printerName()).toString());
1196 QRect totalBBox=mapCenter->getTotalBBox();
1198 // Try to set orientation automagically
1199 // Note: Interpretation of generated postscript is amibiguous, if
1200 // there are problems with landscape mode, see
1201 // http://sdb.suse.de/de/sdb/html/jsmeix_print-cups-landscape-81.html
1203 if (totalBBox.width()>totalBBox.height())
1204 // recommend landscape
1205 printer->setOrientation (QPrinter::Landscape);
1207 // recommend portrait
1208 printer->setOrientation (QPrinter::Portrait);
1210 if ( printer->setup(this) )
1211 // returns false, if printing is canceled
1213 QPainter pp(printer);
1215 // Don't print the visualisation of selection
1216 LinkableMapObj *oldselection=NULL;
1219 oldselection=selection;
1220 selection->unselect();
1223 // Handle sizes of map and paper:
1225 // setWindow defines which part of the canvas will be transformed
1226 // setViewport defines area on paper in device coordinates (dpi)
1227 // e.g. (0,50,700,700) is upper part on A4
1228 // see also /usr/lib/qt3/doc/html/coordsys.html
1230 Q3PaintDeviceMetrics metrics (printer);
1232 double paperAspect = (double)metrics.width() / (double)metrics.height();
1233 double mapAspect = (double)totalBBox.width() / (double)totalBBox.height();
1235 QRect mapRect=totalBBox;
1236 Q3CanvasRectangle *frame=NULL;
1237 Q3CanvasText *footerFN=NULL;
1238 Q3CanvasText *footerDate=NULL;
1239 if (printFrame || printFooter)
1244 // Print frame around map
1245 mapRect.setRect (totalBBox.x()-10, totalBBox.y()-10,
1246 totalBBox.width()+20, totalBBox.height()+20);
1247 frame=new Q3CanvasRectangle (mapRect,mapCanvas);
1248 frame->setBrush (QColor(Qt::white));
1249 frame->setPen (QColor(Qt::black));
1253 /* TODO remove after testing
1254 QCanvasLine *l=new QCanvasLine (mapCanvas);
1255 l->setPoints (0,0,mapRect.width(),mapRect.height());
1256 l->setPen (QPen(QColor(black), 1));
1263 // Print footer below map
1265 font.setPointSize(10);
1266 footerFN=new Q3CanvasText (mapCanvas);
1267 footerFN->setText ("VYM - " + fileName);
1268 footerFN->setFont(font);
1269 footerFN->move (mapRect.x(), mapRect.y() + mapRect.height() );
1270 footerFN->setZ(Z_TEXT);
1272 footerDate=new Q3CanvasText (mapCanvas);
1273 footerDate->setText (QDate::currentDate().toString(Qt::TextDate));
1274 footerDate->setFont(font);
1275 footerDate->move (mapRect.x()+mapRect.width()-footerDate->boundingRect().width(), mapRect.y() + mapRect.height() );
1276 footerDate->setZ(Z_TEXT);
1279 pp.setWindow (mapRect.x(), mapRect.y(), mapRect.width(), mapRect.height()+20);
1282 pp.setWindow (mapRect);
1285 if (mapAspect>=paperAspect)
1287 // Fit horizontally to paper width
1288 pp.setViewport(0,0, metrics.width(),(int)(metrics.width()/mapAspect) );
1291 // Fit vertically to paper height
1292 pp.setViewport(0,0,(int)(metrics.height()*mapAspect),metrics.height());
1295 mapCanvas->drawArea(mapRect, &pp); // draw Canvas to printer
1297 // Delete Frame and footer
1301 delete (footerDate);
1303 if (frame) delete (frame);
1305 // Restore selection
1308 selection=oldselection;
1309 selection->select();
1312 // Save settings in vymrc
1313 settings.writeEntry("/mainwindow/printerName",printer->printerName());
1317 QPixmap MapEditor::getPixmap()
1319 QRect mapRect=mapCenter->getTotalBBox();
1320 QPixmap pix (mapRect.size());
1323 // Don't print the visualisation of selection
1324 LinkableMapObj *oldselection=NULL;
1327 oldselection=selection;
1328 selection->unselect();
1331 pp.setWindow (mapRect);
1333 mapCanvas->drawArea(mapRect, &pp); // draw Canvas to painter
1336 // Restore selection
1339 selection=oldselection;
1340 selection->select();
1346 void MapEditor::setHideTmpMode (HideTmpMode mode)
1349 mapCenter->setHideTmp (hidemode);
1350 mapCenter->reposition();
1355 HideTmpMode MapEditor::getHideTmpMode()
1360 void MapEditor::exportImage(QString fn)
1362 setExportMode (true);
1363 QPixmap pix (getPixmap());
1364 pix.save(fn, "PNG");
1365 setExportMode (false);
1368 void MapEditor::setExportMode (bool b)
1370 // should be called before and after exports
1371 // depending on the settings
1372 if (b && settings.value("/export/useHideExport","yes")=="yes")
1373 setHideTmpMode (HideExport);
1375 setHideTmpMode (HideNone);
1378 void MapEditor::exportImage(QString fn, QString format)
1380 setExportMode (true);
1381 QPixmap pix (getPixmap());
1382 pix.save(fn, format);
1383 setExportMode (false);
1386 void MapEditor::exportOOPresentation(const QString &fn, const QString &cf)
1390 ex.setMapCenter(mapCenter);
1391 if (ex.setConfigFile(cf))
1393 setExportMode (true);
1394 ex.exportPresentation();
1395 setExportMode (false);
1401 void MapEditor::exportXML(const QString &dir)
1403 // Hide stuff during export, if settings want this
1404 setExportMode (true);
1406 // Create subdirectories
1409 // write to directory
1410 QString saveFile=saveToDir (dir,mapName+"-",true,mapCenter->getTotalBBox().topLeft() ,NULL);
1413 file.setName ( dir + "/"+mapName+".xml");
1414 if ( !file.open( QIODevice::WriteOnly ) )
1416 // This should neverever happen
1417 QMessageBox::critical (0,tr("Critical Export Error"),tr("MapEditor::exportXML couldn't open %1").arg(file.name()));
1421 // Write it finally, and write in UTF8, no matter what
1422 QTextStream ts( &file );
1423 ts.setEncoding (QTextStream::UnicodeUTF8);
1427 // Now write image, too
1428 exportImage (dir+"/images/"+mapName+".png");
1430 setExportMode (false);
1433 void MapEditor::clear()
1437 selection->unselect();
1444 void MapEditor::copy()
1448 // write to directory
1449 QString clipfile="part";
1450 QString saveFile=saveToDir (fileDir,clipfile+"-",true,QPoint(),selection);
1453 file.setName ( clipboardDir + "/"+clipfile+".xml");
1454 if ( !file.open( QIODevice::WriteOnly ) )
1456 // This should neverever happen
1457 QMessageBox::critical (0,tr("Critical Export Error"),tr("MapEditor::exportXML couldn't open %1").arg(file.name()));
1461 // Write it finally, and write in UTF8, no matter what
1462 QTextStream ts( &file );
1463 ts.setEncoding (QTextStream::UnicodeUTF8);
1467 clipboardEmpty=false;
1472 void MapEditor::redo()
1474 blockSaveState=true;
1476 // Restore variables
1477 int curStep=undoSet.readNumEntry (QString("/history/curStep"));
1478 int undosAvail=undoSet.readNumEntry (QString("/history/undosAvail"));
1479 int redosAvail=undoSet.readNumEntry (QString("/history/redosAvail"));
1480 // Can we undo at all?
1481 if (redosAvail<1) return;
1484 if (undosAvail<stepsTotal) undosAvail++;
1486 if (curStep>stepsTotal) curStep=1;
1487 QString undoCommand= undoSet.readEntry (QString("/history/step-%1/undoCommand").arg(curStep));
1488 QString undoSelection=undoSet.readEntry (QString("/history/step-%1/undoSelection").arg(curStep));
1489 QString redoCommand= undoSet.readEntry (QString("/history/step-%1/redoCommand").arg(curStep));
1490 QString redoSelection=undoSet.readEntry (QString("/history/step-%1/redoSelection").arg(curStep));
1491 QString comment=undoSet.readEntry (QString("/history/step-%1/comment").arg(curStep));
1492 QString version=undoSet.readEntry ("/history/version");
1494 if (!checkVersion(version))
1495 QMessageBox::warning(0,tr("Warning"),
1496 tr("Version %1 of saved undo/redo data\ndoes not match current vym version %2.").arg(version).arg(__VYM_VERSION));
1499 // Find out current undo directory
1500 QString bakMapDir=QDir::convertSeparators (QString(tmpMapDir+"/undo-%1").arg(curStep));
1502 /* TODO remove testing
1504 cout << "ME::redo() begin\n";
1505 cout << " undosAvail="<<undosAvail<<endl;
1506 cout << " redosAvail="<<redosAvail<<endl;
1507 cout << " curStep="<<curStep<<endl;
1508 cout << " ---------------------------"<<endl;
1509 cout << " comment="<<comment.toStdString()<<endl;
1510 cout << " undoCom="<<undoCommand.toStdString()<<endl;
1511 cout << " undoSel="<<undoSelection.toStdString()<<endl;
1512 cout << " redoCom="<<redoCommand.toStdString()<<endl;
1513 cout << " redoSel="<<redoSelection.toStdString()<<endl;
1514 cout << " ---------------------------"<<endl<<endl;
1516 // select object before redo
1517 // FIXME better give up if no selection there...
1518 if (!redoSelection.isEmpty())
1519 select (redoSelection);
1522 parseAtom (redoCommand);
1523 mapCenter->reposition();
1525 blockSaveState=false;
1527 undoSet.setEntry ("/history/undosAvail",QString::number(undosAvail));
1528 undoSet.setEntry ("/history/redosAvail",QString::number(redosAvail));
1529 undoSet.setEntry ("/history/curStep",QString::number(curStep));
1530 undoSet.writeSettings(histPath);
1532 historyWindow.update (undoSet);
1535 /* TODO remove testing
1537 cout << "ME::redo() end\n";
1538 cout << " undosAvail="<<undosAvail<<endl;
1539 cout << " redosAvail="<<redosAvail<<endl;
1540 cout << " curStep="<<curStep<<endl;
1541 cout << " ---------------------------"<<endl<<endl;
1546 bool MapEditor::isRedoAvailable()
1548 if (undoSet.readNumEntry("/history/redosAvail",0)>0)
1554 void MapEditor::undo()
1556 blockSaveState=true;
1558 // Restore variables
1559 int curStep=undoSet.readNumEntry (QString("/history/curStep"));
1560 int undosAvail=undoSet.readNumEntry (QString("/history/undosAvail"));
1561 int redosAvail=undoSet.readNumEntry (QString("/history/redosAvail"));
1563 // Can we undo at all?
1564 if (undosAvail<1) return;
1566 QString undoCommand= undoSet.readEntry (QString("/history/step-%1/undoCommand").arg(curStep));
1567 QString undoSelection=undoSet.readEntry (QString("/history/step-%1/undoSelection").arg(curStep));
1568 QString redoCommand= undoSet.readEntry (QString("/history/step-%1/redoCommand").arg(curStep));
1569 QString redoSelection=undoSet.readEntry (QString("/history/step-%1/redoSelection").arg(curStep));
1570 QString comment=undoSet.readEntry (QString("/history/step-%1/comment").arg(curStep));
1571 QString version=undoSet.readEntry ("/history/version");
1573 if (!checkVersion(version))
1574 QMessageBox::warning(0,tr("Warning"),
1575 tr("Version %1 of saved undo/redo data\ndoes not match current vym version %2.").arg(version).arg(__VYM_VERSION));
1577 // Find out current undo directory
1578 QString bakMapDir=QDir::convertSeparators (QString(tmpMapDir+"/undo-%1").arg(curStep));
1580 // select object before undo
1581 if (!undoSelection.isEmpty())
1582 select (undoSelection);
1586 cout << "ME::undo() begin\n";
1587 cout << " undosAvail="<<undosAvail<<endl;
1588 cout << " redosAvail="<<redosAvail<<endl;
1589 cout << " curStep="<<curStep<<endl;
1590 cout << " ---------------------------"<<endl;
1591 cout << " comment="<<comment.toStdString()<<endl;
1592 cout << " undoCom="<<undoCommand.toStdString()<<endl;
1593 cout << " undoSel="<<undoSelection.toStdString()<<endl;
1594 cout << " redoCom="<<redoCommand.toStdString()<<endl;
1595 cout << " redoSel="<<redoSelection.toStdString()<<endl;
1596 cout << " ---------------------------"<<endl<<endl;
1597 parseAtom (undoCommand);
1598 mapCenter->reposition();
1602 if (curStep<1) curStep=stepsTotal;
1606 blockSaveState=false;
1607 /* TODO remove testing
1609 cout << "ME::undo() end\n";
1610 cout << " undosAvail="<<undosAvail<<endl;
1611 cout << " redosAvail="<<redosAvail<<endl;
1612 cout << " curStep="<<curStep<<endl;
1613 cout << " ---------------------------"<<endl<<endl;
1615 undoSet.setEntry ("/history/undosAvail",QString::number(undosAvail));
1616 undoSet.setEntry ("/history/redosAvail",QString::number(redosAvail));
1617 undoSet.setEntry ("/history/curStep",QString::number(curStep));
1618 undoSet.writeSettings(histPath);
1620 historyWindow.update (undoSet);
1624 bool MapEditor::isUndoAvailable()
1626 if (undoSet.readNumEntry("/history/undosAvail",0)>0)
1632 void MapEditor::gotoStep (int i)
1634 // Restore variables
1635 int undosAvail=undoSet.readNumEntry (QString("/history/undosAvail"));
1636 int redosAvail=undoSet.readNumEntry (QString("/history/redosAvail"));
1638 cout << "ME::goto "<<i<<endl;
1640 if (i<0) i=undosAvail+redosAvail;
1642 // Clicking above current step makes us undo things
1645 for (int j=0; j<undosAvail-i; j++) undo();
1648 // Clicking below current step makes us redo things
1650 for (int j=undosAvail; j<i; j++) redo();
1652 // And ignore clicking the current row ;-)
1655 void MapEditor::addMapReplaceInt(const QString &undoSel, const QString &path)
1657 QString pathDir=path.left(path.findRev("/"));
1663 // We need to parse saved XML data
1664 mapBuilderHandler handler;
1665 QXmlInputSource source( file);
1666 QXmlSimpleReader reader;
1667 reader.setContentHandler( &handler );
1668 reader.setErrorHandler( &handler );
1669 handler.setMapEditor( this );
1670 handler.setTmpDir ( pathDir ); // needed to load files with rel. path
1671 if (undoSel.isEmpty())
1675 handler.setLoadMode (NewMap);
1679 handler.setLoadMode (ImportReplace);
1681 blockReposition=true;
1682 bool ok = reader.parse( source );
1683 blockReposition=false;
1686 // This should never ever happen
1687 QMessageBox::critical( 0, tr( "Critical Parse Error while reading %1").arg(path),
1688 handler.errorProtocol());
1691 QMessageBox::critical( 0, tr( "Critical Error" ), tr("Could not read %1").arg(path));
1694 void MapEditor::addMapInsertInt (const QString &path, int pos)
1696 if (selection && (typeid(*selection) == typeid(BranchObj) ||
1697 typeid(*selection) == typeid(MapCenterObj)))
1699 QString pathDir=path.left(path.findRev("/"));
1705 // We need to parse saved XML data
1706 mapBuilderHandler handler;
1707 QXmlInputSource source( file);
1708 QXmlSimpleReader reader;
1709 reader.setContentHandler( &handler );
1710 reader.setErrorHandler( &handler );
1711 handler.setMapEditor( this );
1712 handler.setTmpDir ( pathDir ); // needed to load files with rel. path
1713 handler.setLoadMode (ImportAdd);
1714 blockReposition=true;
1715 bool ok = reader.parse( source );
1716 blockReposition=false;
1719 // This should never ever happen
1720 QMessageBox::critical( 0, tr( "Critical Parse Error while reading %1").arg(path),
1721 handler.errorProtocol());
1723 if (selection!=mapCenter)
1724 ((BranchObj*)selection)->getLastBranch()->moveBranchTo ((BranchObj*)(selection),pos);
1726 QMessageBox::critical( 0, tr( "Critical Error" ), tr("Could not read %1").arg(path));
1730 void MapEditor::pasteNoSave()
1732 load (clipboardDir+"/part.xml",ImportAdd);
1735 void MapEditor::cutNoSave()
1741 void MapEditor::paste()
1743 if (selection && (typeid(*selection) == typeid(BranchObj) ||
1744 typeid(*selection) == typeid(MapCenterObj)))
1747 saveStateChangingPart(
1751 QString("Paste to %1").arg( getName(selection))
1753 mapCenter->reposition();
1758 void MapEditor::cut()
1760 saveStateChangingPart(
1761 selection->getParObj(),
1764 QString("Cut %1").arg(getName(selection))
1768 mapCenter->reposition();
1772 void MapEditor::move(const int &x, const int &y)
1776 QString ps=qpointToString (selection->getAbsPos());
1777 QString s=selection->getSelectString();
1780 s, "move "+qpointToString (QPoint (x,y)),
1781 QString("Move %1 to %2").arg(getName(selection)).arg(ps));
1782 selection->move(x,y);
1783 mapCenter->reposition();
1789 void MapEditor::moveRel (const int &x, const int &y)
1791 if (selection && (typeid(*selection) == typeid(BranchObj) ||
1792 typeid(*selection) == typeid(MapCenterObj) ||
1793 typeid(*selection) == typeid (FloatImageObj)))
1795 QString ps=qpointToString (selection->getRelPos());
1796 QString s=selection->getSelectString();
1799 s, "moveRel "+qpointToString (QPoint (x,y)),
1800 QString("Move %1 to relativ position %2").arg(getName(selection)).arg(ps));
1801 ((OrnamentedObj*)selection)->move2RelPos (x,y);
1802 mapCenter->reposition();
1807 void MapEditor::moveBranchUp()
1811 if (typeid(*selection) == typeid(BranchObj) )
1813 bo=(BranchObj*)selection;
1814 if (!bo->canMoveBranchUp()) return;
1815 par=(BranchObj*)(bo->getParObj());
1816 selection->unselect();
1817 bo=par->moveBranchUp (bo); // bo will be the one below selection
1818 selection->select();
1819 saveState (selection,"moveBranchDown ()",bo,"moveBranchUp ()",QString("Move up %1").arg(getName(bo)));
1820 mapCenter->reposition();
1821 ensureSelectionVisible();
1825 void MapEditor::moveBranchDown()
1829 if (typeid(*selection) == typeid(BranchObj) )
1831 bo=(BranchObj*)selection;
1832 if (!bo->canMoveBranchDown()) return;
1833 par=(BranchObj*)(bo->getParObj());
1834 selection->unselect();
1835 bo=par->moveBranchDown(bo); // bo will be the one above selection
1836 selection->select();
1837 saveState(selection,"moveBranchUp ()",bo,"moveBranchDown ()",QString("Move down %1").arg(getName(bo)));
1838 mapCenter->reposition();
1839 ensureSelectionVisible();
1843 QString MapEditor::getHeading(bool &ok, QPoint &p)
1846 (typeid(*selection) == typeid(BranchObj) ||
1847 typeid(*selection) == typeid(MapCenterObj) ) )
1850 ensureSelectionVisible();
1851 p = ((BranchObj*)selection)->getAbsPos();
1852 p.setX (p.x() - contentsX());
1853 p.setY (p.y() - contentsY() + ((BranchObj*)selection)->height()/2);
1854 return ((BranchObj*)selection)->getHeading();
1860 void MapEditor::setHeading(const QString &s)
1863 (typeid(*selection) == typeid(BranchObj) ||
1864 typeid(*selection) == typeid(MapCenterObj) ) )
1866 editingBO=(BranchObj*)selection;
1869 "setHeading (\""+editingBO->getHeading()+"\")",
1871 "setHeading (\""+s+"\")",
1872 QString("Set heading of %1 to \"%2\"").arg(getName(editingBO)).arg(s) );
1873 editingBO->setHeading(s );
1875 mapCenter->reposition();
1877 ensureSelectionVisible();
1881 void MapEditor::setURLInt (const QString &s)
1883 // Internal function, no saveState needed
1885 (typeid(*selection) == typeid(BranchObj) ||
1886 typeid(*selection) == typeid(MapCenterObj) ) )
1888 ((BranchObj*)selection)->setURL(s);
1889 mapCenter->reposition();
1891 ensureSelectionVisible();
1895 void MapEditor::setHeadingInt(const QString &s)
1898 (typeid(*selection) == typeid(BranchObj) ||
1899 typeid(*selection) == typeid(MapCenterObj) ) )
1901 ((BranchObj*)selection)->setHeading(s);
1902 mapCenter->reposition();
1904 ensureSelectionVisible();
1908 void MapEditor::setVymLinkInt (const QString &s)
1910 // Internal function, no saveState needed
1912 (typeid(*selection) == typeid(BranchObj) ||
1913 typeid(*selection) == typeid(MapCenterObj) ) )
1915 ((BranchObj*)selection)->setVymLink(s);
1916 mapCenter->reposition();
1918 ensureSelectionVisible();
1922 BranchObj* MapEditor::addNewBranchInt(int num)
1924 // Depending on pos:
1925 // -3 insert in childs of parent above selection
1926 // -2 add branch to selection
1927 // -1 insert in childs of parent below selection
1928 // 0..n insert in childs of parent at pos
1929 BranchObj *newbo=NULL;
1931 (typeid(*selection) == typeid(BranchObj) ||
1932 typeid(*selection) == typeid(MapCenterObj) ) )
1934 BranchObj* bo = (BranchObj*) selection;
1937 // save scroll state. If scrolled, automatically select
1938 // new branch in order to tmp unscroll parent...
1939 return bo->addBranch();
1944 bo=(BranchObj*)bo->getParObj();
1948 bo=(BranchObj*)bo->getParObj();
1951 newbo=bo->insertBranch(num);
1956 BranchObj* MapEditor::addNewBranch(int pos)
1958 // Different meaning than num in addNewBranchInt!
1962 BranchObj *bo = (BranchObj*) selection;
1963 BranchObj *newbo=NULL;
1966 (typeid(*selection) == typeid(BranchObj) ||
1967 typeid(*selection) == typeid(MapCenterObj) ) )
1969 newbo=addNewBranchInt (pos-2);
1974 selection, // FIXME sholdnt newbo be deleted here???
1977 QString ("addBranch (%1)").arg(pos-2),
1978 QString ("Add new branch to %1").arg(getName(bo)));
1980 mapCenter->reposition();
1988 BranchObj* MapEditor::addNewBranchBefore()
1990 BranchObj *newbo=NULL;
1992 (typeid(*selection) == typeid(BranchObj) ) )
1993 // We accept no MapCenterObj here, so we _have_ a parent
1995 BranchObj* bo = (BranchObj*) selection;
1996 QPoint p=bo->getRelPos();
1999 BranchObj *parbo=(BranchObj*)(selection->getParObj());
2001 // add below selection
2002 newbo=parbo->insertBranch(bo->getNum()+1);
2005 newbo->move2RelPos (p);
2007 // Move selection to new branch
2008 ((BranchObj*)selection)->moveBranchTo (newbo,-1);
2010 saveState (newbo, "deleteKeepChilds ()", newbo, "addBranchBefore ()",
2011 QString ("Add branch before %1").arg(getName(bo)));
2013 mapCenter->reposition();
2020 void MapEditor::deleteSelection()
2022 if (selection && typeid(*selection) ==typeid(BranchObj) )
2024 BranchObj* bo=(BranchObj*)selection;
2025 BranchObj* par=(BranchObj*)(bo->getParObj());
2027 saveStateRemovingPart (bo, QString ("Delete %1").arg(getName(bo)));
2029 par->removeBranch(bo);
2031 selection->select();
2032 ensureSelectionVisible();
2033 mapCenter->reposition();
2036 if (selection && typeid(*selection) ==typeid(FloatImageObj) )
2038 FloatImageObj* fio=(FloatImageObj*)selection;
2039 BranchObj* par=(BranchObj*)(fio->getParObj());
2040 saveStateChangingPart(
2044 QString("Delete %1").arg(getName(fio))
2048 par->removeFloatImage(fio);
2050 selection->select();
2051 ensureSelectionVisible();
2052 mapCenter->reposition();
2057 LinkableMapObj* MapEditor::getSelection()
2062 void MapEditor::unselect()
2066 selectionLast=selection;
2067 selection->unselect();
2072 void MapEditor::reselect()
2076 selection=selectionLast;
2077 selection->select();
2082 bool MapEditor::select (const QString &s)
2084 LinkableMapObj *lmo=mapCenter->findObjBySelect(s);
2086 // Finally select the found object
2089 if (selection) unselect();
2091 selection->select();
2093 ensureSelectionVisible();
2099 QString MapEditor::getSelectString()
2101 if (selection) return selection->getSelectString();
2105 void MapEditor::selectInt (LinkableMapObj *lmo)
2107 if (lmo && selection != lmo)
2109 // select the MapObj
2110 if (selection) selection->unselect();
2112 selection->select();
2118 void MapEditor::selectNextBranchInt()
2120 // Increase number of branch
2123 QString s=selection->getSelectString();
2129 part=s.section(",",-1);
2131 num=part.right(part.length() - 3);
2133 s=s.left (s.length() -num.length());
2136 num=QString ("%1").arg(num.toUInt()+1);
2140 // Try to select this one
2141 if (select (s)) return;
2143 // We have no direct successor,
2144 // try to increase the parental number in order to
2145 // find a successor with same depth
2147 int d=selection->getDepth();
2152 while (!found && d>0)
2154 s=s.section (",",0,d-1);
2155 // replace substring of current depth in s with "1"
2156 part=s.section(",",-1);
2158 num=part.right(part.length() - 3);
2162 // increase number of parent
2163 num=QString ("%1").arg(num.toUInt()+1);
2164 s=s.section (",",0,d-2) + ","+ typ+num;
2167 // Special case, look at orientation
2168 if (selection->getOrientation()==OrientRightOfCenter)
2169 num=QString ("%1").arg(num.toUInt()+1);
2171 num=QString ("%1").arg(num.toUInt()-1);
2176 // pad to oldDepth, select the first branch for each depth
2177 for (i=d;i<oldDepth;i++)
2182 if ( ((BranchObj*)selection)->countBranches()>0)
2190 // try to select the freshly built string
2198 void MapEditor::selectPrevBranchInt()
2200 // Decrease number of branch
2203 QString s=selection->getSelectString();
2209 part=s.section(",",-1);
2211 num=part.right(part.length() - 3);
2213 s=s.left (s.length() -num.length());
2216 num=QString ("%1").arg(num.toUInt()-1);
2220 // Try to select this one
2221 if (select (s)) return;
2223 // We have no direct precessor,
2224 // try to decrease the parental number in order to
2225 // find a precessor with same depth
2227 int d=selection->getDepth();
2232 while (!found && d>0)
2234 s=s.section (",",0,d-1);
2235 // replace substring of current depth in s with "1"
2236 part=s.section(",",-1);
2238 num=part.right(part.length() - 3);
2242 // decrease number of parent
2243 num=QString ("%1").arg(num.toUInt()-1);
2244 s=s.section (",",0,d-2) + ","+ typ+num;
2247 // Special case, look at orientation
2248 if (selection->getOrientation()==OrientRightOfCenter)
2249 num=QString ("%1").arg(num.toUInt()-1);
2251 num=QString ("%1").arg(num.toUInt()+1);
2256 // pad to oldDepth, select the last branch for each depth
2257 for (i=d;i<oldDepth;i++)
2261 if ( ((BranchObj*)selection)->countBranches()>0)
2262 s+=",bo:"+ QString ("%1").arg( ((BranchObj*)selection)->countBranches()-1 );
2269 // try to select the freshly built string
2277 void MapEditor::selectUpperBranch()
2281 if (typeid(*selection) == typeid(BranchObj))
2283 if (selection->getOrientation()==OrientRightOfCenter)
2284 selectPrevBranchInt();
2286 if (selection->getDepth()==1)
2287 selectNextBranchInt();
2289 selectPrevBranchInt();
2294 void MapEditor::selectLowerBranch()
2298 if (typeid(*selection) == typeid(BranchObj))
2300 if (selection->getOrientation()==OrientRightOfCenter)
2301 selectNextBranchInt();
2303 if (selection->getDepth()==1)
2304 selectPrevBranchInt();
2306 selectNextBranchInt();
2312 void MapEditor::selectLeftBranch()
2318 if (typeid(*selection) == typeid(MapCenterObj))
2320 par= (BranchObj*) selection;
2321 bo=par->getLastSelectedBranch();
2324 // Workaround for reselecting on left and right side
2325 if (bo->getOrientation()==OrientRightOfCenter)
2327 bo=par->getLastBranch();
2333 selection->select();
2335 ensureSelectionVisible();
2340 par=(BranchObj*)(selection->getParObj());
2341 if (selection->getOrientation()==OrientRightOfCenter)
2343 if (typeid(*selection) == typeid(BranchObj) ||
2344 typeid(*selection) == typeid(FloatImageObj))
2346 selection->unselect();
2348 selection->select();
2350 ensureSelectionVisible();
2354 if (typeid(*selection) == typeid(BranchObj) )
2356 bo=((BranchObj*)selection)->getLastSelectedBranch();
2359 selection->unselect();
2361 selection->select();
2363 ensureSelectionVisible();
2371 void MapEditor::selectRightBranch()
2378 if (typeid(*selection) == typeid(MapCenterObj))
2380 par= (BranchObj*) selection;
2381 bo=par->getLastSelectedBranch();
2384 // Workaround for reselecting on left and right side
2385 if (bo->getOrientation()==OrientLeftOfCenter)
2386 bo=par->getFirstBranch();
2391 selection->select();
2392 ensureSelectionVisible();
2397 par=(BranchObj*)(selection->getParObj());
2398 if (selection->getOrientation()==OrientLeftOfCenter)
2400 if (typeid(*selection) == typeid(BranchObj) ||
2401 typeid(*selection) == typeid(FloatImageObj))
2403 selection->unselect();
2405 selection->select();
2407 ensureSelectionVisible();
2411 if (typeid(*selection) == typeid(BranchObj) )
2413 bo=((BranchObj*)selection)->getLastSelectedBranch();
2416 selection->unselect();
2418 selection->select();
2420 ensureSelectionVisible();
2428 void MapEditor::selectFirstBranch()
2434 if (typeid(*selection) == typeid(BranchObj))
2436 bo1= (BranchObj*) selection;
2437 par=(BranchObj*)(bo1->getParObj());
2438 bo2=par->getFirstBranch();
2442 selection->select();
2443 ensureSelectionVisible();
2450 void MapEditor::selectLastBranch()
2456 if (typeid(*selection) == typeid(BranchObj))
2458 bo1= (BranchObj*) selection;
2459 par=(BranchObj*)(bo1->getParObj());
2460 bo2=par->getLastBranch();
2464 selection->select();
2465 ensureSelectionVisible();
2472 void MapEditor::selectMapBackgroundColor()
2474 QColor col = QColorDialog::getColor( mapCanvas->backgroundColor(), this );
2475 if ( !col.isValid() ) return;
2476 setBackgroundColor( col );
2480 void MapEditor::setMapBackgroundColor(QColor col)
2482 QColor oldcol=mapCanvas->backgroundColor();
2485 QString ("setMapBackgroundColor (%1)").arg(oldcol.name()),
2487 QString ("setMapBackgroundColor (%1)").arg(col.name()),
2488 QString("Set background color of map to %1").arg(col.name()));
2489 mapCanvas->setBackgroundColor (col);
2492 QColor MapEditor::getMapBackgroundColor()
2494 return mapCanvas->backgroundColor();
2497 QColor MapEditor::getCurrentHeadingColor()
2501 if (typeid(*selection) == typeid(BranchObj) ||
2502 typeid(*selection) == typeid(MapCenterObj))
2504 BranchObj *bo=(BranchObj*)selection;
2505 return bo->getColor();
2509 QMessageBox::warning(0,tr("Warning"),tr("Can't get color of heading,\nthere's no branch selected"));
2513 void MapEditor::colorItem(QColor c)
2517 if (typeid(*selection) == typeid(BranchObj) ||
2518 typeid(*selection) == typeid(MapCenterObj))
2520 BranchObj *bo=(BranchObj*)selection;
2523 QString ("colorItem (%1)").arg(bo->getColor().name()),
2525 QString ("colorItem (%1)").arg(c.name()),
2526 QString("Set color of %1 to %2").arg(getName(bo)).arg(c.name())
2528 bo->setColor(c); // color branch
2533 void MapEditor::colorBranch(QColor c)
2537 if (typeid(*selection) == typeid(BranchObj) ||
2538 typeid(*selection) == typeid(MapCenterObj))
2540 BranchObj *bo=(BranchObj*)selection;
2541 saveStateChangingPart(
2544 QString ("colorBranch (%1)").arg(c.name()),
2545 QString ("Set color of %1 and childs to %2").arg(getName(bo)).arg(c.name())
2547 bo->setColorChilds(c); // color links, color childs
2553 void MapEditor::toggleStandardFlag(QString f)
2557 if (typeid(*selection) == typeid(BranchObj) ||
2558 typeid(*selection) == typeid(MapCenterObj))
2560 BranchObj *bo=(BranchObj*)selection;
2562 if (bo->isSetStandardFlag(f))
2574 QString("%1 (\"%2\")").arg(u).arg(f),
2576 QString("%1 (\"%2\")").arg(r).arg(f),
2577 QString("Toggling standard flag \"%1\" of %2").arg(f).arg(getName(bo)));
2578 bo->toggleStandardFlag (f,mainWindow->useFlagGroups());
2584 void MapEditor::setViewCenter()
2586 // transform to CanvasView Coord:
2587 QPoint p=worldMatrix().map(movingCenter);
2588 center ( p.x(), p.y());
2592 BranchObj* MapEditor::findText (QString s, bool cs)
2594 QTextDocument::FindFlags flags=0;
2595 if (cs) flags=QTextDocument::FindCaseSensitively;
2598 { // Nothing found or new find process
2600 // nothing found, start again
2602 itFind=mapCenter->first();
2604 bool searching=true;
2605 bool foundNote=false;
2606 while (searching && !EOFind)
2610 // Searching in Note
2611 if (itFind->getNote().contains(s,cs))
2613 if (selection!=itFind)
2615 if (selection) ((BranchObj*)selection)->unselect();
2617 selection->select();
2619 ensureSelectionVisible();
2621 if (textEditor->findText(s,flags))
2627 // Searching in Heading
2628 if (searching && itFind->getHeading().contains (s,cs) )
2630 if (selection) ((BranchObj*)selection)->unselect();
2632 selection->select();
2634 ensureSelectionVisible();
2640 itFind=itFind->next();
2641 if (!itFind) EOFind=true;
2647 return (BranchObj*)selection;
2652 void MapEditor::findReset()
2653 { // Necessary if text to find changes during a find process
2657 void MapEditor::setURL(const QString &url)
2659 if (selection && (typeid(*selection) == typeid(BranchObj) ||
2660 typeid(*selection) == typeid(MapCenterObj)) )
2662 BranchObj *bo=(BranchObj*)selection;
2663 QString oldurl=bo->getURL();
2667 QString ("setURL (\"%1\")").arg(oldurl),
2669 QString ("setURL (\"%1\")").arg(url),
2670 QString ("set URL of %1 to %2").arg(getName(bo)).arg(url)
2676 void MapEditor::editURL()
2678 if (selection && (typeid(*selection) == typeid(BranchObj) ||
2679 typeid(*selection) == typeid(MapCenterObj)) )
2682 BranchObj *bo=(BranchObj*)selection;
2683 QString text = QInputDialog::getText(
2684 "VYM", tr("Enter URL:"), QLineEdit::Normal,
2685 bo->getURL(), &ok, this );
2687 // user entered something and pressed OK
2692 QString MapEditor::getURL()
2694 if (selection && (typeid(*selection) == typeid(BranchObj) ||
2695 typeid(*selection) == typeid(MapCenterObj)) )
2696 return ((BranchObj*)selection)->getURL();
2701 QStringList MapEditor::getURLs()
2704 if (selection && (typeid(*selection) == typeid(BranchObj) ||
2705 typeid(*selection) == typeid(MapCenterObj)) )
2707 BranchObj *bo=(BranchObj*)selection;
2711 if (!bo->getURL().isEmpty()) urls.append( bo->getURL());
2719 void MapEditor::editHeading2URL()
2721 if (selection && (typeid(*selection) == typeid(BranchObj) ||
2722 typeid(*selection) == typeid(MapCenterObj)) )
2723 setURL (((BranchObj*)selection)->getHeading());
2726 void MapEditor::editBugzilla2URL()
2728 if (selection && (typeid(*selection) == typeid(BranchObj) ||
2729 typeid(*selection) == typeid(MapCenterObj)) )
2731 BranchObj *bo=(BranchObj*)selection;
2732 QString url= "https://bugzilla.novell.com/show_bug.cgi?id="+bo->getHeading();
2737 void MapEditor::editFATE2URL()
2739 if (selection && (typeid(*selection) == typeid(BranchObj) ||
2740 typeid(*selection) == typeid(MapCenterObj)) )
2742 BranchObj *bo=(BranchObj*)selection;
2743 QString url= "http://keeper.suse.de:8080/webfate/match/id?value=ID"+bo->getHeading();
2746 "setURL (\""+bo->getURL()+"\")",
2748 "setURL (\""+url+"\")",
2749 QString("Use heading of %1 as link to FATE").arg(getName(bo))
2756 void MapEditor::editVymLink()
2758 if (selection && (typeid(*selection) == typeid(BranchObj) ||
2759 typeid(*selection) == typeid(MapCenterObj)) )
2761 BranchObj *bo=(BranchObj*)selection;
2762 Q3FileDialog *fd=new Q3FileDialog( this,__VYM " - " +tr("Link to another map"));
2763 fd->addFilter (QString (tr("vym map") + " (*.vym)"));
2764 fd->setCaption(__VYM " - " +tr("Link to another map"));
2765 if (! bo->getVymLink().isEmpty() )
2766 fd->setSelection( bo->getVymLink() );
2770 if ( fd->exec() == QDialog::Accepted )
2774 "setVymLink (\""+bo->getVymLink()+"\")",
2776 "setVymLink (\""+fd->selectedFile()+"\")",
2777 QString("Set vymlink of %1 to %2").arg(getName(bo)).arg(fd->selectedFile())
2779 bo->setVymLink (fd->selectedFile() );
2781 mapCenter->reposition();
2788 void MapEditor::deleteVymLink()
2790 if (selection && (typeid(*selection) == typeid(BranchObj) ||
2791 typeid(*selection) == typeid(MapCenterObj)) )
2793 BranchObj *bo=(BranchObj*)selection;
2796 "setVymLink (\""+bo->getVymLink()+"\")",
2798 "setVymLink (\"\")",
2799 QString("Unset vymlink of %1").arg(getName(bo))
2801 bo->setVymLink ("" );
2803 mapCenter->reposition();
2809 void MapEditor::setHideExport(bool b)
2811 if (selection && (typeid(*selection) == typeid(BranchObj) ||
2812 typeid(*selection)==typeid(FloatImageObj)))
2814 OrnamentedObj *oo=(OrnamentedObj*)selection;
2815 oo->setHideInExport (b);
2816 QString u= b ? "false" : "true";
2817 QString r=!b ? "false" : "true";
2821 QString ("setHideExport (%1)").arg(u),
2823 QString ("setHideExport (%1)").arg(r),
2824 QString ("Set HideExport flag of %1 to %2").arg(getName(oo)).arg (r)
2827 mapCenter->reposition();
2833 void MapEditor::toggleHideExport()
2835 if (selection && (typeid(*selection) == typeid(BranchObj) ||
2836 typeid(*selection)==typeid(FloatImageObj)))
2837 setHideExport ( !((OrnamentedObj*)selection)->hideInExport() );
2840 QString MapEditor::getVymLink()
2842 if (selection && (typeid(*selection) == typeid(BranchObj) ||
2843 typeid(*selection) == typeid(MapCenterObj)) )
2845 return ((BranchObj*)selection)->getVymLink();
2851 QStringList MapEditor::getVymLinks()
2854 if (selection && (typeid(*selection) == typeid(BranchObj) ||
2855 typeid(*selection) == typeid(MapCenterObj)) )
2857 BranchObj *bo=(BranchObj*)selection;
2861 if (!bo->getVymLink().isEmpty()) links.append( bo->getVymLink());
2869 void MapEditor::deleteKeepChilds()
2871 if (selection && (typeid(*selection) == typeid(BranchObj) ))
2873 BranchObj* bo=(BranchObj*)selection;
2874 BranchObj* par=(BranchObj*)(bo->getParObj());
2875 QPoint p=bo->getRelPos();
2876 saveStateChangingPart(
2877 selection->getParObj(),
2879 "deleteKeepChilds ()",
2880 QString("Remove %1 and keep its childs").arg(getName(bo))
2883 QString sel=selection->getSelectString();
2885 par->removeBranchHere(bo);
2886 mapCenter->reposition();
2888 ((BranchObj*)selection)->move2RelPos (p);
2889 mapCenter->reposition();
2894 void MapEditor::deleteChilds()
2896 if (selection && (typeid(*selection) == typeid(BranchObj) ||
2897 typeid(*selection)==typeid(MapCenterObj)))
2899 saveStateChangingPart(
2900 selection->getParObj(),
2903 QString( "Remove childs of branch %1").arg(getName(selection))
2905 ((BranchObj*)selection)->removeChilds();
2906 mapCenter->reposition();
2910 void MapEditor::editMapInfo()
2912 ExtraInfoDialog dia;
2913 dia.setMapName (getFileName() );
2914 dia.setAuthor (mapCenter->getAuthor() );
2915 dia.setComment(mapCenter->getComment() );
2920 Q3CanvasItemList l=canvas()->allItems();
2921 for (Q3CanvasItemList::Iterator it=l.begin(); it!=l.end(); ++it)
2923 stats+=QString ("%1 items on canvas\n").arg (i,6);
2930 bo=mapCenter->first();
2933 if (!bo->getNote().isEmpty() ) n++;
2934 f+= bo->countFloatImages();
2936 xl+=bo->countXLinks();
2939 stats+=QString ("%1 branches\n").arg (b-1,6);
2940 stats+=QString ("%1 xLinks \n").arg (xl,6);
2941 stats+=QString ("%1 notes\n").arg (n,6);
2942 stats+=QString ("%1 images\n").arg (f,6);
2943 dia.setStats (stats);
2945 // Finally show dialog
2946 if (dia.exec() == QDialog::Accepted)
2948 setMapAuthor (dia.getAuthor() );
2949 setMapComment (dia.getComment() );
2953 void MapEditor::updateActions()
2955 mainWindow->updateActions();
2956 // FIXME maybe don't update if blockReposition is set
2959 void MapEditor::updateNoteFlag()
2962 if ( (typeid(*selection) == typeid(BranchObj)) ||
2963 (typeid(*selection) == typeid(MapCenterObj)) )
2964 ((BranchObj*)selection)->updateNoteFlag();
2967 void MapEditor::setMapAuthor (const QString &s)
2971 QString ("setMapAuthor (\"%1\")").arg(mapCenter->getAuthor()),
2973 QString ("setMapAuthor (\"%1\")").arg(s),
2974 QString ("Set author of map to \"%1\"").arg(s)
2976 mapCenter->setAuthor (s);
2979 void MapEditor::setMapComment (const QString &s)
2983 QString ("setMapComment (\"%1\")").arg(mapCenter->getComment()),
2985 QString ("setMapComment (\"%1\")").arg(s),
2986 QString ("Set comment of map")
2988 mapCenter->setComment (s);
2991 void MapEditor::setMapLinkStyle (const QString & s)
2993 saveStateChangingPart (
2996 QString("setMapLinkStyle (\"%1\")").arg(s),
2997 QString("Set map link style (\"%1\")").arg(s)
3001 linkstyle=StyleLine;
3002 else if (s=="StyleParabel")
3003 linkstyle=StyleParabel;
3004 else if (s=="StylePolyLine")
3005 linkstyle=StylePolyLine;
3007 linkstyle=StylePolyParabel;
3010 bo=mapCenter->first();
3014 bo->setLinkStyle(bo->getDefLinkStyle());
3017 mapCenter->reposition();
3020 LinkStyle MapEditor::getMapLinkStyle ()
3025 void MapEditor::setMapDefLinkColor(QColor c)
3031 void MapEditor::setMapLinkColorHintInt()
3033 // called from setMapLinkColorHint(lch) or at end of parse
3035 bo=mapCenter->first();
3043 void MapEditor::setMapLinkColorHint(LinkColorHint lch)
3046 setMapLinkColorHintInt();
3049 void MapEditor::toggleMapLinkColorHint()
3051 if (linkcolorhint==HeadingColor)
3052 linkcolorhint=DefaultColor;
3054 linkcolorhint=HeadingColor;
3056 bo=mapCenter->first();
3064 LinkColorHint MapEditor::getMapLinkColorHint()
3066 return linkcolorhint;
3069 QColor MapEditor::getMapDefLinkColor()
3071 return defLinkColor;
3074 void MapEditor::setMapDefXLinkColor(QColor col)
3079 QColor MapEditor::getMapDefXLinkColor()
3081 return defXLinkColor;
3084 void MapEditor::setMapDefXLinkWidth (int w)
3089 int MapEditor::getMapDefXLinkWidth()
3091 return defXLinkWidth;
3094 void MapEditor::selectMapLinkColor()
3096 QColor col = QColorDialog::getColor( defLinkColor, this );
3097 if ( !col.isValid() ) return;
3100 QString("setMapDefLinkColor (\"%1\")").arg(getMapDefLinkColor().name()),
3102 QString("setMapDefLinkColor (\"%1\")").arg(col.name()),
3103 QString("Set link color to %1").arg(col.name())
3105 setMapDefLinkColor( col );
3109 void MapEditor::toggleScroll()
3111 if (selection && (typeid(*selection) == typeid(BranchObj)) )
3113 BranchObj *bo=((BranchObj*)selection);
3114 if (bo->countBranches()==0) return;
3115 if (bo->getDepth()==0) return;
3117 if (bo->isScrolled())
3129 QString ("%1 ()").arg(u),
3131 QString ("%1 ()").arg(r),
3132 QString ("%1 %2").arg(r).arg(getName(bo))
3140 void MapEditor::unScrollAll()
3143 bo=mapCenter->first();
3146 if (bo->isScrolled()) bo->toggleScroll();
3151 void MapEditor::loadFloatImage ()
3154 (typeid(*selection) == typeid(BranchObj)) ||
3155 (typeid(*selection) == typeid(MapCenterObj)) )
3157 BranchObj *bo=((BranchObj*)selection);
3159 Q3FileDialog *fd=new Q3FileDialog( this);
3160 fd->setMode (Q3FileDialog::ExistingFiles);
3161 fd->addFilter (QString (tr("Images") + " (*.png *.bmp *.xbm *.jpg *.png *.xpm *.gif *.pnm)"));
3162 ImagePreview *p =new ImagePreview (fd);
3163 fd->setContentsPreviewEnabled( TRUE );
3164 fd->setContentsPreview( p, p );
3165 fd->setPreviewMode( Q3FileDialog::Contents );
3166 fd->setCaption(__VYM " - " +tr("Load image"));
3167 fd->setDir (lastImageDir);
3171 if ( fd->exec() == QDialog::Accepted )
3173 // FIXME in QT4 use: lastImageDir=fd->directory();
3174 lastImageDir=QDir (fd->dirPath());
3175 QStringList flist = fd->selectedFiles();
3176 QStringList::Iterator it = flist.begin();
3178 while( it != flist.end() )
3181 bo->addFloatImage();
3182 fio=bo->getLastFloatImage();
3184 // FIXME check if load of fio was successful
3186 (LinkableMapObj*)fio,
3189 QString ("loadFloatImage (%1)").arg(*it),
3190 QString("Add floatimage %1 to %2").arg(*it).arg(getName(selection))
3192 bo->getLastFloatImage()->setOriginalFilename(fn);
3196 mapCenter->reposition();
3205 void MapEditor::saveFloatImage ()
3208 (typeid(*selection) == typeid(FloatImageObj)) )
3210 FloatImageObj *fio=((FloatImageObj*)selection);
3211 QFileDialog *fd=new QFileDialog( this);
3212 fd->setFilters (imageIO.getFilters());
3213 fd->setCaption(__VYM " - " +tr("Save image"));
3214 fd->setFileMode( QFileDialog::AnyFile );
3215 fd->setDirectory (lastImageDir);
3216 // fd->setSelection (fio->getOriginalFilename());
3220 if ( fd->exec() == QDialog::Accepted )
3222 if (QFile (fd->selectedFile()).exists() )
3224 QMessageBox mb( __VYM,
3225 tr("The file %1 exists already.\n"
3226 "Do you want to overwrite it?").arg(fd->selectedFile()),
3227 QMessageBox::Warning,
3228 QMessageBox::Yes | QMessageBox::Default,
3229 QMessageBox::Cancel | QMessageBox::Escape,
3230 QMessageBox::QMessageBox::NoButton );
3232 mb.setButtonText( QMessageBox::Yes, tr("Overwrite") );
3233 mb.setButtonText( QMessageBox::No, tr("Cancel"));
3236 case QMessageBox::Yes:
3239 case QMessageBox::Cancel:
3246 fio->save (fd->selectedFile(),imageIO.getType (fd->selectedFilter() ) );
3252 void MapEditor::setFrame(const FrameType &t)
3255 (typeid(*selection) == typeid(BranchObj)) ||
3256 (typeid(*selection) == typeid(MapCenterObj)) )
3258 selection->setFrameType (t);
3259 mapCenter->reposition();
3260 selection->updateLink();
3264 void MapEditor::setIncludeImagesVer(bool b)
3267 (typeid(*selection) == typeid(BranchObj)) ||
3268 (typeid(*selection) == typeid(MapCenterObj)) )
3269 ((BranchObj*)selection)->setIncludeImagesVer(b);
3270 mapCenter->reposition();
3273 void MapEditor::setIncludeImagesHor(bool b)
3276 (typeid(*selection) == typeid(BranchObj)) ||
3277 (typeid(*selection) == typeid(MapCenterObj)) )
3278 ((BranchObj*)selection)->setIncludeImagesHor(b);
3279 mapCenter->reposition();
3282 void MapEditor::setHideLinkUnselected (bool b)
3285 (typeid(*selection) == typeid(BranchObj)) ||
3286 (typeid(*selection) == typeid(MapCenterObj)) ||
3287 (typeid(*selection) == typeid(FloatImageObj)) )
3288 selection->setHideLinkUnselected(b);
3291 void MapEditor::importDirInt(BranchObj *dst, QDir d)
3294 (typeid(*selection) == typeid(BranchObj)) ||
3295 (typeid(*selection) == typeid(MapCenterObj)) )
3299 // Traverse directories
3300 d.setFilter( QDir::Dirs| QDir::Hidden | QDir::NoSymLinks );
3301 QFileInfoList list = d.entryInfoList();
3304 for (int i = 0; i < list.size(); ++i)
3307 if (fi.fileName() != "." && fi.fileName() != ".." )
3310 bo=dst->getLastBranch();
3311 bo->setHeading (fi.fileName() );
3312 bo->setColor (QColor("blue"));
3314 if ( !d.cd(fi.fileName()) )
3315 QMessageBox::critical (0,tr("Critical Import Error"),tr("Cannot find the directory %1").arg(fi.fileName()));
3318 // Recursively add subdirs
3319 importDirInt (bo,d);
3325 d.setFilter( QDir::Files| QDir::Hidden | QDir::NoSymLinks );
3326 list = d.entryInfoList();
3328 for (int i = 0; i < list.size(); ++i)
3332 bo=dst->getLastBranch();
3333 bo->setHeading (fi.fileName() );
3334 bo->setColor (QColor("black"));
3335 if (fi.fileName().right(4) == ".vym" )
3336 bo->setVymLink (fi.filePath());
3341 void MapEditor::importDir()
3344 (typeid(*selection) == typeid(BranchObj)) ||
3345 (typeid(*selection) == typeid(MapCenterObj)) )
3347 Q3FileDialog *fd=new Q3FileDialog( this,__VYM " - " +tr("Choose directory structure to import"));
3348 fd->setMode (Q3FileDialog::DirectoryOnly);
3349 fd->addFilter (QString (tr("vym map") + " (*.vym)"));
3350 fd->setCaption(__VYM " - " +tr("Choose directory structure to import"));
3354 if ( fd->exec() == QDialog::Accepted )
3356 BranchObj *bo=((BranchObj*)selection);
3357 importDirInt (bo,QDir(fd->selectedFile()) );
3358 mapCenter->reposition();
3365 void MapEditor::followXLink(int i)
3368 (typeid(*selection) == typeid(BranchObj)) ||
3369 (typeid(*selection) == typeid(MapCenterObj)) )
3371 BranchObj *bo=((BranchObj*)selection)->XLinkTargetAt(i);
3374 selection->unselect();
3376 selection->select();
3377 ensureSelectionVisible();
3382 void MapEditor::editXLink(int i)
3385 (typeid(*selection) == typeid(BranchObj)) ||
3386 (typeid(*selection) == typeid(MapCenterObj)) )
3388 XLinkObj *xlo=((BranchObj*)selection)->XLinkAt(i);
3391 EditXLinkDialog dia;
3393 dia.setSelection(selection);
3394 if (dia.exec() == QDialog::Accepted)
3396 if (dia.useSettingsGlobal() )
3398 setMapDefXLinkColor (xlo->getColor() );
3399 setMapDefXLinkWidth (xlo->getWidth() );
3401 if (dia.deleteXLink())
3402 ((BranchObj*)selection)->deleteXLinkAt(i);
3403 //saveStateComplete("Edit xLink"); //FIXME undoCommand
3409 void MapEditor::testFunction()
3411 cout << "MapEditor::testFunction() called\n";
3414 (typeid(*selection) == typeid(BranchObj)) ||
3415 (typeid(*selection) == typeid(MapCenterObj)) )
3417 BranchObj* bo=(BranchObj*)selection;
3418 cout << bo->getHeading().ascii() <<" is scrolled: "<<bo->isScrolled()<<endl;
3423 dia.showCancelButton (true);
3424 dia.setText("This is a longer \nWarning");
3426 dia.setCaption("Warning: Flux problem");
3427 dia.setShowAgainName("/warnings/mapeditor");
3429 if (dia.exec()==QDialog::Accepted)
3430 cout << "accepted!\n";
3432 cout << "canceled!\n";
3435 /* Hide hidden stuff temporary, maybe add this as regular function somewhere
3436 if (hidemode==HideNone)
3438 setHideTmpMode (HideExport);
3439 mapCenter->calcBBoxSizeWithChilds();
3440 QRect totalBBox=mapCenter->getTotalBBox();
3441 QRect mapRect=totalBBox;
3442 QCanvasRectangle *frame=NULL;
3444 cout << " map has =("<<totalBBox.x()<<","<<totalBBox.y()<<","<<totalBBox.width()<<","<<totalBBox.height()<<")\n";
3446 mapRect.setRect (totalBBox.x(), totalBBox.y(),
3447 totalBBox.width(), totalBBox.height());
3448 frame=new QCanvasRectangle (mapRect,mapCanvas);
3449 frame->setBrush (QColor(white));
3450 frame->setPen (QColor(black));
3456 setHideTmpMode (HideNone);
3458 cout <<" hidemode="<<hidemode<<endl;
3462 void MapEditor::ensureSelectionVisible()
3466 LinkableMapObj* lmo= dynamic_cast <LinkableMapObj*> (selection);
3468 if (selection->getOrientation() == OrientLeftOfCenter)
3469 p= worldMatrix().map(QPoint (lmo->x(),lmo->y()));
3471 p= worldMatrix().map(QPoint (lmo->x()+lmo->width(),lmo->y()+lmo->height()));
3472 ensureVisible (p.x(), p.y() );
3477 void MapEditor::updateViewCenter()
3479 // Update movingCenter, so that we can zoom comfortably later
3480 QRect rc = QRect( contentsX(), contentsY(),
3481 visibleWidth(), visibleHeight() );
3482 QRect canvasRect = inverseWorldMatrix().mapRect(rc);
3483 movingCenter.setX((canvasRect.right() + canvasRect.left())/2);
3484 movingCenter.setY((canvasRect.top() + canvasRect.bottom())/2);
3487 void MapEditor::contentsContextMenuEvent ( QContextMenuEvent * e )
3489 // Lineedits are already closed by preceding
3490 // mouseEvent, we don't need to close here.
3492 QPoint p = inverseWorldMatrix().map(e->pos());
3493 LinkableMapObj* lmo=mapCenter->findMapObj(p, NULL);
3496 { // MapObj was found
3497 if (selection != lmo)
3499 // select the MapObj
3500 if (selection) selection->unselect();
3502 selection->select();
3508 if (typeid(*selection)==typeid(BranchObj) ||
3509 typeid(*selection)==typeid(MapCenterObj) )
3511 // Context Menu on branch or mapcenter
3513 branchContextMenu->popup(e->globalPos() );
3515 if (typeid(*selection)==typeid(FloatImageObj))
3517 // Context Menu on floatimage
3519 floatimageContextMenu->popup(e->globalPos() );
3523 { // No MapObj found, we are on the Canvas itself
3524 // Context Menu on Canvas
3526 canvasContextMenu->popup(e->globalPos() );
3531 void MapEditor::keyPressEvent(QKeyEvent* e)
3533 if (e->modifiers() && Qt::ControlModifier)
3535 switch (mainWindow->getModMode())
3538 setCursor (PickColorCursor);
3541 setCursor (CopyCursor);
3544 setCursor (XLinkCursor);
3547 setCursor (Qt::ArrowCursor);
3553 void MapEditor::keyReleaseEvent(QKeyEvent* e)
3555 if (!(e->modifiers() && Qt::ControlModifier))
3556 setCursor (Qt::ArrowCursor);
3559 void MapEditor::contentsMousePressEvent(QMouseEvent* e)
3561 // Ignore right clicks, these will go to context menus
3562 if (e->button() == Qt::RightButton )
3568 QPoint p = inverseWorldMatrix().map(e->pos());
3569 LinkableMapObj* lmo=mapCenter->findMapObj(p, NULL);
3573 //Take care of clickdesystem flags _or_ modifier modes
3575 if (lmo && (typeid(*lmo)==typeid(BranchObj) ||
3576 typeid(*lmo)==typeid(MapCenterObj) ))
3578 QString foname=((BranchObj*)lmo)->getSystemFlagName(p);
3579 if (!foname.isEmpty())
3581 // systemFlag clicked
3585 if (e->state() & Qt::ControlModifier)
3586 mainWindow->editOpenURLTab();
3588 mainWindow->editOpenURL();
3590 else if (foname=="vymLink")
3592 mainWindow->editOpenVymLink();
3593 // tabWidget may change, better return now
3594 // before segfaulting...
3595 } else if (foname=="note")
3596 mainWindow->windowToggleNoteEditor();
3597 else if (foname=="hideInExport")
3602 // No system flag clicked, take care of modmodes
3604 // Special case: CTRL is pressed
3605 if (e->state() & Qt::ControlModifier)
3607 if (mainWindow->getModMode()==ModModeColor)
3610 setCursor (PickColorCursor);
3613 if (mainWindow->getModMode()==ModModeXLink)
3615 BranchObj *bo_begin=NULL;
3617 bo_begin=(BranchObj*)(lmo);
3620 ((typeid(*selection) == typeid(BranchObj)) ||
3621 (typeid(*selection) == typeid(MapCenterObj))) )
3622 bo_begin=(BranchObj*)selection;
3626 linkingObj_src=bo_begin;
3627 tmpXLink=new XLinkObj (mapCanvas);
3628 tmpXLink->setBegin (bo_begin);
3629 tmpXLink->setEnd (p);
3630 tmpXLink->setColor(defXLinkColor);
3631 tmpXLink->setWidth(defXLinkWidth);
3632 tmpXLink->updateXLink();
3633 tmpXLink->setVisibility (true);
3641 // Left Button Move Branches
3642 if (e->button() == Qt::LeftButton )
3644 movingObj_start.setX( p.x() - selection->x() );
3645 movingObj_start.setY( p.y() - selection->y() );
3646 movingObj_orgPos.setX (lmo->x() );
3647 movingObj_orgPos.setY (lmo->y() );
3648 movingObj_orgRelPos=lmo->getRelPos();
3650 // If modMode==copy, then we want to "move" the _new_ object around
3651 // then we need the offset from p to the _old_ selection, because of tmp
3652 if (mainWindow->getModMode()==ModModeCopy &&
3653 e->state() & Qt::ControlModifier)
3655 if (typeid(*selection)==typeid(BranchObj) )
3658 mapCenter->addBranch ((BranchObj*)selection);
3660 selection=mapCenter->getLastBranch();
3661 selection->select();
3662 mapCenter->reposition();
3665 movingObj=selection;
3667 // Middle Button Toggle Scroll
3668 // (On Mac OS X this won't work, but we still have
3669 // a button in the toolbar)
3670 if (e->button() == Qt::MidButton )
3674 { // No MapObj found, we are on the Canvas itself
3675 // Left Button move Pos of CanvasView
3676 if (e->button() == Qt::LeftButton )
3678 movingObj=NULL; // move Content not Obj
3679 movingObj_start=e->globalPos();
3680 movingCont_start=QPoint (contentsX(), contentsY() );
3681 movingVec=QPoint(0,0);
3682 setCursor(HandOpenCursor);
3687 void MapEditor::contentsMouseMoveEvent(QMouseEvent* e)
3689 QPoint p = inverseWorldMatrix().map(e->pos());
3691 // Move the selected MapObj
3692 if ( selection && movingObj)
3694 // To avoid jumping of the CanvasView, only
3695 // ensureSelectionVisible, if not tmp linked
3696 if (!selection->hasParObjTmp())
3697 ensureSelectionVisible ();
3699 // Now move the selection, but add relative position
3700 // (movingObj_start) where selection was chosen with
3701 // mousepointer. (This avoids flickering resp. jumping
3702 // of selection back to absPos)
3704 LinkableMapObj *lmosel;
3705 lmosel = dynamic_cast <LinkableMapObj*> (selection);
3707 // Check if we could link
3708 LinkableMapObj* lmo=mapCenter->findMapObj(p, lmosel);
3711 if (typeid(*selection) == typeid(FloatImageObj))
3713 FloatObj *fo=(FloatObj*)selection;
3714 fo->move (p.x() -movingObj_start.x(), p.y()-movingObj_start.y() );
3718 // Relink float to new mapcenter or branch, if shift is pressed
3719 // Only relink, if selection really has a new parent
3720 if ( (e->modifiers()==Qt::ShiftModifier) && lmo &&
3721 ( (typeid(*lmo)==typeid(BranchObj)) ||
3722 (typeid(*lmo)==typeid(MapCenterObj)) ) &&
3723 ( lmo != fo->getParObj())
3726 if (typeid(*fo) == typeid(FloatImageObj))
3729 //saveStateComplete(QString("Relink %1 to %2").arg(getName(fo)).arg(getName(lmo) ) );
3730 FloatImageObj *fio=(FloatImageObj*)(fo);
3731 ((BranchObj*)(lmo))->addFloatImage (fio);
3733 ((BranchObj*)(fio->getParObj()))->removeFloatImage (fio);
3734 fio=((BranchObj*)(lmo))->getLastFloatImage();
3737 selection=(LinkableMapObj*)(fio);
3738 selection->select();
3739 movingObj=(MapObj*)(fio);
3743 { // selection != a FloatObj
3744 if (lmosel->getDepth()==0)
3747 if (e->buttons()== Qt::LeftButton && e->modifiers()==Qt::ShiftModifier)
3748 mapCenter->moveAll(p.x() -movingObj_start.x(), p.y()-movingObj_start.y() );
3750 mapCenter->move (p.x() -movingObj_start.x(), p.y()-movingObj_start.y() );
3751 mapCenter->updateRelPositions();
3754 if (lmosel->getDepth()==1)
3757 lmosel->move(p.x() -movingObj_start.x(), p.y()-movingObj_start.y() );
3758 lmosel->setRelPos();
3761 // Move ordinary branch
3762 if (lmosel->getOrientation() == OrientLeftOfCenter)
3763 // Add width of bbox here, otherwise alignRelTo will cause jumping around
3764 lmosel->move(p.x() -movingObj_start.x()+lmosel->getBBox().width(),
3765 p.y()-movingObj_start.y() +lmosel->getTopPad() );
3767 lmosel->move(p.x() -movingObj_start.x(), p.y()-movingObj_start.y() -lmosel->getTopPad());
3769 // reposition subbranch
3770 lmosel->reposition();
3772 if (lmo && (lmo!=selection) &&
3773 (typeid(*lmo) == typeid(BranchObj) ||
3774 (typeid(*lmo) == typeid(MapCenterObj) )
3777 if (e->modifiers()==Qt::ControlModifier)
3779 // Special case: CTRL to link below lmo
3780 lmosel->setParObjTmp (lmo,p,+1);
3782 else if (e->modifiers()==Qt::ShiftModifier)
3783 lmosel->setParObjTmp (lmo,p,-1);
3785 lmosel->setParObjTmp (lmo,p,0);
3788 lmosel->unsetParObjTmp();
3792 } // no FloatImageObj
3796 } // selection && moving_obj
3798 // Draw a link from one branch to another
3801 tmpXLink->setEnd (p);
3802 tmpXLink->updateXLink();
3806 if (!movingObj && !pickingColor &&!drawingLink)
3808 QPoint p=e->globalPos();
3809 movingVec.setX(-p.x() + movingObj_start.x() );
3810 movingVec.setY(-p.y() + movingObj_start.y() );
3811 setContentsPos( movingCont_start.x() + movingVec.x(),
3812 movingCont_start.y() + movingVec.y());
3819 void MapEditor::contentsMouseReleaseEvent(QMouseEvent* e)
3821 LinkableMapObj *dst;
3822 // Have we been picking color?
3826 setCursor (Qt::ArrowCursor);
3827 // Check if we are over another branch
3828 dst=mapCenter->findMapObj(inverseWorldMatrix().map(e->pos() ), NULL);
3829 if (dst && selection)
3831 if (e->state() & Qt::ShiftModifier)
3833 ((BranchObj*)selection)->setColor (((BranchObj*)(dst))->getColor());
3834 ((BranchObj*)selection)->setLinkColor ();
3838 ((BranchObj*)selection)->setColorChilds (((BranchObj*)(dst))->getColor());
3839 ((BranchObj*)selection)->setLinkColor ();
3845 // Have we been drawing a link?
3849 // Check if we are over another branch
3850 dst=mapCenter->findMapObj(inverseWorldMatrix().map(e->pos() ), NULL);
3851 if (dst && selection)
3853 tmpXLink->setEnd ( ((BranchObj*)(dst)) );
3854 tmpXLink->updateXLink();
3855 tmpXLink->activate();
3856 //saveStateComplete(QString("Activate xLink from %1 to %2").arg(getName(tmpXLink->getBegin())).arg(getName(tmpXLink->getEnd())) ); //FIXME undoCommand
3865 // Have we been moving something?
3866 if ( selection && movingObj )
3868 if(typeid(*selection)==typeid (FloatImageObj))
3870 // Moved FloatObj. Maybe we need to reposition
3871 FloatImageObj *fo=(FloatImageObj*)selection;
3872 QString pold=qpointToString(movingObj_orgRelPos);
3873 QString pnow=qpointToString(fo->getRelPos());
3879 QString("Move %1 to relativ position %2").arg(getName(selection)).arg(pnow));
3881 // FIXME Why calling parObj here?
3882 selection->getParObj()->requestReposition();
3883 mapCenter->reposition();
3886 // Check if we are over another branch, but ignore
3887 // any found LMOs, which are FloatObjs
3888 dst=mapCenter->findMapObj(inverseWorldMatrix().map(e->pos() ),
3889 ((LinkableMapObj*)selection) );
3891 if (dst && (typeid(*dst)!=typeid(BranchObj) && typeid(*dst)!=typeid(MapCenterObj)))
3894 if (typeid(*selection) == typeid(MapCenterObj) )
3895 { // The MapCenter was moved
3896 cout << "FIXME missing savestate...\n";
3899 if (typeid(*selection) == typeid(BranchObj) )
3900 { // A branch was moved
3902 // save the position in case we link to mapcenter
3903 QPoint savePos=QPoint (selection->x(),selection->y() );
3905 // Reset the temporary drawn link to the original one
3906 ((LinkableMapObj*)selection)->unsetParObjTmp();
3908 // For Redo we may need to save original selection
3909 QString preSelStr=selection->getSelectString();
3914 BranchObj* bsel=(BranchObj*)selection;
3915 BranchObj* bdst=(BranchObj*)dst;
3917 QString preParStr=(bsel->getParObj())->getSelectString();
3918 QString preNum=QString::number (bsel->getNum(),10);
3919 QString preDstParStr;
3921 if (e->state() & Qt::ShiftModifier && dst->getParObj())
3923 preDstParStr=dst->getParObj()->getSelectString();
3924 bsel->moveBranchTo ( (BranchObj*)(bdst->getParObj()), bdst->getNum());
3926 if (e->state() & Qt::ControlModifier && dst->getParObj())
3929 preDstParStr=dst->getParObj()->getSelectString();
3930 bsel->moveBranchTo ( (BranchObj*)(bdst->getParObj()), bdst->getNum()+1);
3933 preDstParStr=dst->getSelectString();
3934 bsel->moveBranchTo (bdst,-1);
3935 if (dst->getDepth()==0) bsel->move (savePos);
3937 QString postSelStr=selection->getSelectString();
3938 QString postNum=QString::number (bsel->getNum(),10);
3940 QString undoCom="linkBranchToPos (\""+
3941 preParStr+ "\"," + preNum +"," +
3942 QString ("%1,%2").arg(movingObj_orgPos.x()).arg(movingObj_orgPos.y())+ ")";
3944 QString redoCom="linkBranchToPos (\""+
3945 preDstParStr + "\"," + postNum + "," +
3946 QString ("%1,%2").arg(savePos.x()).arg(savePos.y())+ ")";
3951 QString("Relink %1 to %2").arg(getName(bsel)).arg(getName(dst)) );
3953 if (selection->getDepth()==1)
3955 // The select string might be different _after_ moving around.
3956 // Therefor reposition and then use string of old selection, too
3957 mapCenter->reposition();
3959 QString ps=qpointToString ( ((BranchObj*)selection)->getRelPos() );
3961 selection->getSelectString(), "moveRel "+qpointToString(movingObj_orgRelPos),
3962 preSelStr, "moveRel "+ps,
3963 QString("Move %1 to relative position %2").arg(getName(selection)).arg(ps));
3966 // Draw the original link, before selection was moved around
3967 mapCenter->reposition();
3969 // Finally resize canvas, if needed
3974 // Just make sure, that actions are still ok,e.g. the move branch up/down buttons...
3977 // maybe we moved View: set old cursor
3978 setCursor (Qt::ArrowCursor);
3982 void MapEditor::contentsMouseDoubleClickEvent(QMouseEvent* e)
3984 if (e->button() == Qt::LeftButton )
3986 QPoint p = inverseWorldMatrix().map(e->pos());
3987 LinkableMapObj *lmo=mapCenter->findMapObj(p, NULL);
3988 if (lmo) { // MapObj was found
3989 // First select the MapObj than edit heading
3990 if (selection) selection->unselect();
3992 selection->select();
3993 mainWindow->editHeading();
3998 void MapEditor::resizeEvent (QResizeEvent* e)
4000 Q3CanvasView::resizeEvent( e );
4004 void MapEditor::contentsDragEnterEvent(QDragEnterEvent *event)
4007 // for (unsigned int i=0;event->format(i);i++) // Debug mime type
4008 // cerr << event->format(i) << endl;
4011 (typeid(*selection) == typeid(BranchObj)) ||
4012 (typeid(*selection) == typeid(MapCenterObj))) {
4014 // If QImageDrag can decode mime type
4015 if (Q3ImageDrag::canDecode(event)) {
4020 // If image are dragged from firefox
4021 if (event->provides("application/x-moz-file-promise-url") &&
4022 event->provides("application/x-moz-nativeimage")) {
4023 event->accept(true);
4027 // If QUriDrag can decode mime type
4028 if (Q3UriDrag::canDecode(event)) {
4033 // If Uri are dragged from firefox
4034 if (event->provides("_NETSCAPE_URL")){
4039 // If QTextDrag can decode mime type
4040 if (Q3TextDrag::canDecode(event)) {
4049 bool isUnicode16(const QByteArray &d)
4051 // TODO: make more precise check for unicode 16.
4052 // Guess unicode16 if any of second bytes are zero
4053 unsigned int length = max(0,d.size()-2)/2;
4054 for (unsigned int i = 0; i<length ; i++)
4055 if (d.at(i*2+1)==0) return true;
4059 void MapEditor::contentsDropEvent(QDropEvent *event)
4062 (typeid(*selection) == typeid(BranchObj)) ||
4063 (typeid(*selection) == typeid(MapCenterObj)))
4068 if (event->provides("image/png"))
4071 if (Q3ImageDrag::decode(event, pix))
4073 addFloatImageInt(pix);
4079 } else if (event->provides("application/x-moz-file-promise-url") &&
4080 event->provides("application/x-moz-nativeimage"))
4082 // Contains url to the img src in unicode16
4083 QByteArray d = event->encodedData("application/x-moz-file-promise-url");
4084 QString url = QString((const QChar*)d.data(),d.size()/2);
4088 } else if (event->provides ("text/uri-list"))
4089 { // Uris provided e.g. by konqueror
4090 Q3UriDrag::decode (event,uris);
4091 } else if (event->provides ("_NETSCAPE_URL"))
4092 { // Uris provided by Mozilla
4093 QStringList l = QStringList::split("\n", event->encodedData("_NETSCAPE_URL"));
4096 } else if (event->provides("text/html")) {
4098 // Handels text mime types
4099 // Look like firefox allways handle text as unicode16 (2 bytes per char.)
4100 QByteArray d = event->encodedData("text/html");
4103 text = QString((const QChar*)d.data(),d.size()/2);
4107 textEditor->setText(text);
4111 } else if (event->provides("text/plain")) {
4112 QByteArray d = event->encodedData("text/plain");
4115 text = QString((const QChar*)d.data(),d.size()/2);
4119 textEditor->setText(text);
4131 for (const char* u=uris.first(); u; u=uris.next())
4133 bo=((BranchObj*)selection)->addBranch();
4136 s=Q3UriDrag::uriToLocalFile(u);
4139 QString file = QDir::convertSeparators(s);
4140 heading = QFileInfo(file).baseName();
4142 if (file.endsWith(".vym", false))
4143 bo->setVymLink(file);
4152 if (!heading.isEmpty())
4153 bo->setHeading(heading);
4163 //FIXME saveState has to be called earlier for each of the drops...
4164 //saveStateComplete("Drop Event"); //TODO undo Command
4165 mapCenter->reposition();
4172 void MapEditor::addFloatImageInt (const QPixmap &img)
4175 (typeid(*selection) == typeid(BranchObj)) ||
4176 (typeid(*selection) == typeid(MapCenterObj)) )
4178 BranchObj *bo=((BranchObj*)selection);
4179 //FIXME XXX saveStateChangingPart(selection,QString("Add floatimage to %1").arg(getName(bo)));
4180 //QString fn=fd->selectedFile();
4181 //lastImageDir=fn.left(fn.findRev ("/"));
4182 FloatImageObj *fio=bo->addFloatImage();
4184 fio->setOriginalFilename("Image added by Drag and Drop");
4185 mapCenter->reposition();
4192 void MapEditor::imageDataFetched(const QByteArray &a, Q3NetworkOperation */*nop*/)
4194 if (!imageBuffer) imageBuffer = new QBuffer();
4195 if (!imageBuffer->isOpen()) {
4196 imageBuffer->open(QIODevice::WriteOnly | QIODevice::Append);
4198 imageBuffer->at(imageBuffer->at()+imageBuffer->writeBlock(a));
4202 void MapEditor::imageDataFinished(Q3NetworkOperation *nop)
4204 if (nop->state()==Q3NetworkProtocol::StDone) {
4205 QPixmap img(imageBuffer->buffer());
4206 addFloatImageInt (img);
4210 imageBuffer->close();
4212 imageBuffer->close();
4219 void MapEditor::fetchImage(const QString &url)
4222 urlOperator->stop();
4223 disconnect(urlOperator);
4227 urlOperator = new Q3UrlOperator(url);
4228 connect(urlOperator, SIGNAL(finished(Q3NetworkOperation *)),
4229 this, SLOT(imageDataFinished(Q3NetworkOperation*)));
4231 connect(urlOperator, SIGNAL(data(const QByteArray &, Q3NetworkOperation *)),
4232 this, SLOT(imageDataFetched(const QByteArray &, Q3NetworkOperation *)));