3 #include <qstatusbar.h>
5 #include <qapplication.h>
7 #include <q3popupmenu.h>
9 #include <q3paintdevicemetrics.h>
11 #include <q3filedialog.h>
14 #include <QColorDialog>
16 #include <qinputdialog.h>
17 #include <q3dragobject.h>
18 #include <q3urloperator.h>
19 #include <q3networkprotocol.h>
22 #include <QResizeEvent>
23 #include <QContextMenuEvent>
26 #include <QMouseEvent>
27 #include <QDragEnterEvent>
28 #include <QTextStream>
30 #include <QActionGroup>
40 #include "editxlinkdialog.h"
42 #include "extrainfodialog.h"
44 #include "linkablemapobj.h"
45 #include "mainwindow.h"
47 #include "texteditor.h"
48 #include "warningdialog.h"
52 extern TextEditor *textEditor;
53 extern int statusbarTime;
54 extern Main *mainWindow;
55 extern QString tmpVymDir;
56 extern QString clipboardDir;
57 extern bool clipboardEmpty;
58 extern FlagRowObj *systemFlagsDefault;
59 extern FlagRowObj *standardFlagsDefault;
61 extern Q3PtrList <QAction> actionListBranches;
63 extern QAction *actionFileSave;
64 extern QAction *actionEditUndo;
65 extern QAction *actionEditRedo;
66 extern QAction *actionEditCopy;
67 extern QAction *actionEditCut;
68 extern QAction *actionEditPaste;
69 extern QAction *actionEditMoveUp;
70 extern QAction *actionEditMoveDown;
71 extern QAction *actionEditToggleScroll;
72 extern QAction *actionEditOpenURL;
73 extern QAction *actionEditOpenURLTab;
74 extern QAction *actionEditURL;
75 extern QAction *actionEditHeading2URL;
76 extern QAction *actionEditBugzilla2URL;
77 extern QAction *actionEditFATE2URL;
78 extern QAction *actionEditOpenVymLink;
79 extern QAction *actionEditVymLink;
80 extern QAction *actionEditDeleteVymLink;
81 extern QAction *actionEditToggleHideExport;
82 extern QAction *actionEditHeading;
83 extern QAction *actionEditDelete;
84 extern QAction *actionEditAddBranch;
85 extern QAction *actionEditAddBranchAbove;
86 extern QAction *actionEditAddBranchBelow;
87 extern QAction *actionEditRemoveBranchHere;
88 extern QAction *actionEditRemoveChilds;
89 extern QAction *actionEditImportAdd;
90 extern QAction *actionEditImportReplace;
91 extern QAction *actionEditSaveBranch;
92 extern QAction *actionEditSelectFirst;
93 extern QAction *actionEditSelectLast;
94 extern QAction *actionEditLoadImage;
96 extern QAction* actionFormatPickColor;
97 extern QAction* actionFormatColorBranch;
98 extern QAction* actionFormatColorSubtree;
99 extern QAction *actionFormatLinkColorHint;
100 extern QAction *actionFormatBackColor;
101 extern QAction *actionFormatLinkColor;
103 extern QActionGroup* actionGroupModModes;
104 extern QAction* actionModModeColor;
105 extern QAction* actionModModeLink;
106 extern QAction* actionModModeCopy;
108 extern QActionGroup *actionGroupFormatFrameTypes;
109 extern QAction *actionFormatFrameNone;
110 extern QAction *actionFormatFrameRectangle;
112 extern QActionGroup *actionGroupFormatLinkStyles;
113 extern QAction *actionFormatIncludeImagesVer;
114 extern QAction *actionFormatIncludeImagesHor;
115 extern QAction *actionFormatHideLinkUnselected;
116 extern QAction *actionFormatLinkStyleLine;
117 extern QAction *actionFormatLinkStyleParabel;
118 extern QAction *actionFormatLinkStylePolyLine;
119 extern QAction *actionFormatLinkStylePolyParabel;
121 extern QAction *actionViewToggleNoteEditor;
123 extern QAction *actionSettingsAutoedit;
124 extern QAction *actionSettingsAutoselectHeading;
125 extern QAction *actionSettingsAutoselectText;
126 extern QAction *actionSettingsUseFlagGroups;
128 extern QMenu* branchContextMenu;
129 extern QMenu* branchAddContextMenu;
130 extern QMenu* branchRemoveContextMenu;
131 extern QMenu* branchLinksContextMenu;
132 extern QMenu* branchXLinksContextMenuEdit;
133 extern QMenu* branchXLinksContextMenuFollow;
134 extern QMenu* floatimageContextMenu;
135 extern QMenu* saveImageFormatMenu;
136 extern QMenu* canvasContextMenu;
137 extern QMenu* lastMapsMenu;
138 extern QMenu* importMenu;
139 extern QMenu* exportMenu;
142 extern Settings settings;
143 extern ImageIO imageIO;
145 extern QString iconPath;
146 extern QDir vymBaseDir;
147 extern QDir lastImageDir;
149 int MapEditor::mapNum=0; // make instance
151 ///////////////////////////////////////////////////////////////////////
152 ///////////////////////////////////////////////////////////////////////
153 MapEditor::MapEditor(
154 QWidget* parent, bool interactive, const char* name, Qt::WFlags f) :
155 Q3CanvasView(parent,name,f), urlOperator(0), imageBuffer(0)
157 //cout << "Constructor ME "<<this<<endl;
160 viewport()->setAcceptDrops(true);
162 mapCanvas = new Q3Canvas(width(),height());
163 mapCanvas->setAdvancePeriod(30);
164 mapCanvas->setBackgroundColor (Qt::white);
166 setCanvas (mapCanvas);
168 // Always show scroll bars (automatic would flicker sometimes)
169 setVScrollBarMode ( Q3ScrollView::AlwaysOn );
170 setHScrollBarMode ( Q3ScrollView::AlwaysOn );
172 mapCenter = new MapCenterObj(mapCanvas);
173 mapCenter->setVisibility (true);
174 mapCenter->setMapEditor (this);
175 mapCenter->setHeading (tr("New Map","Heading of mapcenter in new map"));
176 mapCenter->move(mapCanvas->width()/2-mapCenter->width()/2,mapCanvas->height()/2-mapCenter->height()/2);
180 actColor=Qt::black; setColor (actColor);
181 defLinkColor=QColor (0,0,255);
182 defXLinkColor=QColor (180,180,180);
183 linkcolorhint=DefaultColor;
184 linkstyle=StylePolyParabel;
186 // Create bitmap cursors, platform dependant
187 #if defined(Q_OS_MACX)
188 handOpenCursor=QCursor ( QPixmap(iconPath+"cursorhandopen16.png"),1,1 );
189 pickColorCursor=QCursor ( QPixmap (iconPath+"cursorcolorpicker16.png"), 1,15 );
191 handOpenCursor=QCursor (QPixmap(iconPath+"cursorhandopen.png"),1,1);
192 pickColorCursor=QCursor ( QPixmap(iconPath+"cursorcolorpicker.png"), 5,27 );
204 xelection.setMapCenter (mapCenter);
207 defXLinkColor=QColor (230,230,230);
215 fileName=tr("unnamed");
218 undosTotal=settings.readNumEntry("/mapeditor/undoLevels",50);
220 // Initialize find routine
227 blockReposition=false;
228 blockSaveState=false;
232 isInteractive=interactive;
234 // Create temporary files
237 // Initially set movingCentre
240 // For testing purposes create history window
241 historyWindow = new ShowTextDialog (this);
242 historyWindow->setCaption (fileName);
244 mapCenter->reposition(); // for positioning heading
249 MapEditor::~MapEditor()
251 if (imageBuffer) delete imageBuffer;
257 //cout <<"Destructor MapEditor\n";
260 //settings.writeEntry( "/mapeditor/editmode/autoselect", );
264 QColor MapEditor::color()
269 QColor MapEditor::backgroundColor()
271 return mapCanvas->backgroundColor();
274 MapCenterObj* MapEditor::getMapCenter()
279 Q3Canvas* MapEditor::getCanvas()
284 void MapEditor::adjustCanvasSize()
286 // To adjust the canvas to map, viewport size and position, we have to
287 // do some coordinate magic...
289 // Get rectangle of (scroll-)view.
290 // We want to be in canvas coords, so
291 // we map. Important if view is zoomed...
292 QRect view = inverseWorldMatrix().mapRect( QRect( contentsX(), contentsY(),
293 visibleWidth(), visibleHeight()) );
295 // Now we need the bounding box of view AND map to calc the correct canvas size.
296 // Why? Because if the map itself is moved out of view, the view has to be enlarged
297 // to avoid jumping aroung...
298 QRect map=mapCenter->getTotalBBox();
300 // right edge - left edge
301 int cw= max(map.x() + map.width(), view.x() + view.width()) - min(map.x(), view.x());
302 int ch= max(map.y() + map.height(), view.y() + view.height()) - min(map.y(), view.y());
305 if ( (cw!=mapCanvas->width()) || (ch!=mapCanvas->height()) ||
306 !mapCanvas->onCanvas (map.topLeft()) || !mapCanvas->onCanvas (map.bottomRight())
309 // move the map on canvas (in order to not move it on screen) this is neccessary
310 // a) if topleft corner of canvas is left or above topleft corner of view and also left of
311 // above topleft corner of map. E.g. if map is completly inside view, but it would be possible
312 // to scroll to an empty area of canvas to the left.
313 // b) if topleft corner of map left of or above topleft of canvas
317 if (cw > mapCanvas->width() )
319 if (map.x()<0) dx=-map.x();
321 if (cw < mapCanvas->width() )
322 dx=-min (view.x(),map.x());
323 if (ch > mapCanvas->height() )
325 if (map.y()<0) dy=-map.y();
327 if (ch < mapCanvas->height() )
329 dy=-min (view.y(),map.y());
331 // We really have to resize now. Let's go...
332 mapCanvas->resize (cw,ch);
333 if ( (dx!=0) || (dy!=0) )
335 mapCenter->moveAllBy(dx,dy);
336 mapCenter->reposition();
337 // mapCenter->positionBBox(); // To move float
339 // scroll the view (in order to not move map on screen)
345 bool MapEditor::isRepositionBlocked()
347 return blockReposition;
350 QString MapEditor::getName (LinkableMapObj *lmo)
353 if (!lmo) return QString("Error: NULL has no name!");
355 if ((typeid(*lmo) == typeid(BranchObj) ||
356 typeid(*lmo) == typeid(MapCenterObj)))
359 s=(((BranchObj*)lmo)->getHeading());
360 if (s=="") s="unnamed";
361 return QString("branch (<font color=\"#0000ff\">%1</font>)").arg(s);
363 if ((typeid(*lmo) == typeid(FloatImageObj) ))
364 return QString ("floatimage [<font color=\"#0000ff\">%1</font>]").arg(((FloatImageObj*)lmo)->getOriginalFilename());
365 return QString("Unknown type has no name!");
368 void MapEditor::makeTmpDirs()
370 // Create unique temporary directories
371 tmpMapDir=QDir::convertSeparators (tmpVymDir+QString("/mapeditor-%1").arg(mapNum));
372 histPath=QDir::convertSeparators (tmpMapDir+"/history");
374 d.mkdir (tmpMapDir,true);
377 QString MapEditor::saveToDir(const QString &tmpdir, const QString &prefix, bool writeflags, const QPoint &offset, LinkableMapObj *saveSel)
379 // tmpdir temporary directory to which data will be written
380 // prefix mapname, which will be appended to images etc.
381 // writeflags Only write flags for "real" save of map, not undo
382 // offset offset of bbox of whole map in canvas.
383 // Needed for XML export
399 ls="StylePolyParabel";
403 QString s="<?xml version=\"1.0\" encoding=\"utf-8\"?><!DOCTYPE vymmap>\n";
405 if (linkcolorhint==HeadingColor)
406 colhint=attribut("linkColorHint","HeadingColor");
408 QString mapAttr=attribut("version",__VYM_VERSION);
410 mapAttr+= attribut("author",mapCenter->getAuthor()) +
411 attribut("comment",mapCenter->getComment()) +
412 attribut("date",mapCenter->getDate()) +
413 attribut("backgroundColor", mapCanvas->backgroundColor().name() ) +
414 attribut("linkStyle", ls ) +
415 attribut("linkColor", defLinkColor.name() ) +
416 attribut("defXLinkColor", defXLinkColor.name() ) +
417 attribut("defXLinkWidth", QString().setNum(defXLinkWidth,10) ) +
419 s+=beginElement("vymmap",mapAttr);
422 // Find the used flags while traversing the tree
423 standardFlagsDefault->resetUsedCounter();
425 // Reset the counters before saving
426 FloatImageObj (mapCanvas).resetSaveCounter();
428 // Build xml recursivly
430 // Save complete map, if saveSel not set
431 s+=mapCenter->saveToDir(tmpdir,prefix,writeflags,offset);
434 if ( typeid(*saveSel) == typeid(BranchObj) )
436 s+=((BranchObj*)(saveSel))->saveToDir(tmpdir,prefix,offset);
437 else if ( typeid(*saveSel) == typeid(FloatImageObj) )
439 s+=((FloatImageObj*)(saveSel))->saveToDir(tmpdir,prefix,offset);
441 else if (selection && typeid(*selection)==typeid(BranchObj))
442 // Save selected branch is saved from mainwindow //FIXME maybe use "subtree" above?
443 s+=((BranchObj*)selection)->saveToDir(tmpdir,prefix,offset);
446 // Save local settings
447 s+=settings.getXMLData (destPath);
450 if (selection && !saveSel )
451 s+=valueElement("select",selection->getSelectString());
454 s+=endElement("vymmap");
457 standardFlagsDefault->saveToDir (tmpdir+"/flags/","",writeflags);
461 void MapEditor::saveStateComplete(const QString &comment)
463 // Save complete map, Undo will replace whole map
464 saveState (CompleteMap,
471 void MapEditor::saveStatePart(LinkableMapObj *undoSel, const QString &comment)
473 // save the selected part of the map, Undo will replace part of map
474 QString undoSelection="";
475 if (undoSel) undoSelection=undoSel->getSelectString();
477 saveState (PartOfMap,
484 void MapEditor::saveStateConstSelection(const QString &uc, const QString &rc, const QString &comment)
486 // selection does not change during action,
487 // so just save commands for undo and redo
488 // and use current selection
491 if (selection) sel=selection->getSelectString();
493 saveState (UndoCommand,
500 void MapEditor::saveStateComData(LinkableMapObj *undoSel, const QString &uc, LinkableMapObj *redoSel, const QString &rc, const QString &comment, LinkableMapObj *saveSel)
502 QString redoSelection="";
503 if (redoSel) redoSelection=redoSel->getSelectString();
504 QString undoSelection="";
505 if (undoSel) undoSelection=undoSel->getSelectString();
507 saveState (UndoCommand,
509 redoSelection, "FIXME-redoCom", //FIXME
514 void MapEditor::saveState(LinkableMapObj *undoSel, const QString &uc, LinkableMapObj *redoSel, const QString &rc, const QString &comment)
516 // "Normal" savestate: save commands, selections and comment
517 // so just save commands for undo and redo
518 // and use current selection
520 QString redoSelection="";
521 if (redoSel) redoSelection=redoSel->getSelectString();
522 QString undoSelection="";
523 if (undoSel) undoSelection=undoSel->getSelectString();
525 saveState (UndoCommand,
532 void MapEditor::saveState(const QString &undoSel, const QString &uc, const QString &redoSel, const QString &rc, const QString &comment)
534 // "Normal" savestate: save commands, selections and comment
535 // so just save commands for undo and redo
536 // and use current selection
537 saveState (UndoCommand,
545 void MapEditor::saveState(const SaveMode &savemode, const QString &undoSelection, const QString &undoCom, const QString &redoSelection, const QString &redoCom, const QString &comment, LinkableMapObj *saveSel)
549 if (blockSaveState) return;
551 /* TODO remove after testing
553 cout << "ME::saveState() begin"<<endl;
554 historyWindow->append (comment);
558 int undosAvail=undoSet.readNumEntry ("/history/undosAvail",0);
559 int curStep=undoSet.readNumEntry ("/history/curStep",0);
560 // Find out current undo directory
561 if (undosAvail<undosTotal) undosAvail++;
563 if (curStep>undosTotal) curStep=1;
566 QString bakMapDir=QDir::convertSeparators (QString(tmpMapDir+"/undo-%1").arg(curStep));
567 QString bakMapPath=QDir::convertSeparators(bakMapDir+"/map.xml");
569 // Create bakMapDir if not available
572 makeSubDirs (bakMapDir);
574 // Save depending on how much needs to be saved
578 backupXML=saveToDir (bakMapDir,mapName+"-",false, QPoint (),saveSel);
580 QString undoCommand="";
581 if (savemode==UndoCommand)
585 else if (savemode==PartOfMap )
587 undoCommand="undoPart (\""+ undoSelection+"\",\""+bakMapPath+"\")";
590 undoCommand="undoMap (\""+bakMapPath+"\")";
592 if (!backupXML.isEmpty())
593 // Write XML Data to disk
594 saveStringToDisk (QString(bakMapPath),backupXML);
596 undoSet.setEntry ("/history/undosAvail",QString::number(undosAvail));
597 undoSet.setEntry ("/history/curStep",QString::number(curStep));
598 undoSet.setEntry (QString("/history/step-%1/undoCommand").arg(curStep),undoCommand);
599 undoSet.setEntry (QString("/history/step-%1/undoSelection").arg(curStep),undoSelection);
600 undoSet.setEntry (QString("/history/step-%1/redoCommand").arg(curStep),redoCom);
601 undoSet.setEntry (QString("/history/step-%1/redoSelection").arg(curStep),redoSelection);
602 undoSet.setEntry (QString("/history/step-%1/comment").arg(curStep),comment);
603 undoSet.writeSettings(histPath);
605 /* TODO remove after testing
607 //cout << " into="<< histPath.toStdString()<<endl;
608 cout << " undosTotal="<<undosTotal<<
609 ", undosAvail="<<undosAvail<<
610 ", curStep="<<curStep<<endl;
611 cout << " ---------------------------"<<endl;
612 cout << " comment="<<comment.toStdString()<<endl;
613 cout << " undoCom="<<undoCommand.toStdString()<<endl;
614 cout << " undoSel="<<undoSelection.toStdString()<<endl;
615 cout << " redoCom="<<redoCom.toStdString()<<endl;
616 cout << " redoSel="<<redoSelection.toStdString()<<endl;
617 cout << " ---------------------------"<<endl;
620 void MapEditor::parseAtom(const QString &atom)
627 // Split string s into command and parameters
628 api.parseCommand (atom);
629 QString com=api.command();
632 if (com=="moveBranchUp")
634 else if (com=="moveBranchDown")
636 else if (com=="move")
638 if (api.checkParamCount(2) && selection )
648 else if (com=="moveRel")
650 if (api.checkParamCount(2) && selection )
656 if (ok) moveRel (x,y);
660 else if (com=="delete")
662 if (api.checkParamCount(1) && selection )
664 s=api.parString(ok,0);
665 if (ok &&select (s)) deleteSelection();
668 else if (com=="addBranch")
670 if (api.checkParamCount(1) && selection )
673 if (ok ) addNewBranchInt (y);
676 else if (com=="linkBranchToPos")
678 if (selection && typeid(*selection) == typeid(BranchObj) )
680 if (api.checkParamCount(4))
682 // 0 selectstring of parent
683 // 1 num in parent (for branches)
684 // 2,3 x,y of mainbranch or mapcenter
685 s=api.parString(ok,0);
686 LinkableMapObj *dst=mapCenter->findObjBySelect (s);
689 if (typeid(*dst) == typeid(BranchObj) )
691 // Get number in parent
694 ((BranchObj*)selection)->moveBranchTo ((BranchObj*)(dst),x);
695 } else if (typeid(*dst) == typeid(MapCenterObj) )
697 ((BranchObj*)selection)->moveBranchTo ((BranchObj*)(dst),-1);
698 // Get coordinates of mainbranch
703 if (ok) ((BranchObj*)selection)->move (x,y);
709 } else if (com=="setHeading")
711 if (api.checkParamCount(1))
713 s=api.parString (ok,0);
717 } else if (com=="setURL")
719 if (api.checkParamCount(1))
721 s=api.parString (ok,0);
722 if (ok) setURLInt(s);
724 } else if (com=="setVymLink")
726 if (api.checkParamCount(1))
728 s=api.parString (ok,0);
729 if (ok) setVymLinkInt(s);
732 else if (com=="setFlag")
734 if (selection && typeid(*selection) == typeid(BranchObj) )
736 if (api.checkParamCount(1) )
738 s=api.parString(ok,0);
741 BranchObj* bo=(BranchObj*)selection;
742 bo->activateStandardFlag(s);
743 bo->updateFlagsToolbar();
748 else if (com=="unsetFlag")
750 if (selection && typeid(*selection) == typeid(BranchObj) )
752 if (api.checkParamCount(1) )
754 s=api.parString(ok,0);
757 BranchObj* bo=(BranchObj*)selection;
758 bo->deactivateStandardFlag(s);
759 bo->updateFlagsToolbar();
764 // Internal commands, used for undo etc.
765 else if (com==QString("undoMap"))
767 if (api.checkParamCount(1))
768 undoXML("",api.parString (ok,0));
769 } else if (com==QString("undoPart"))
771 if (api.checkParamCount(2))
773 s=api.parString (ok,0); // undo selection
774 t=api.parString (ok,1); // backup dir
777 } else if (com=="select")
779 if (api.checkParamCount(1))
781 s=api.parString(ok,0);
787 api.setError ("Unknown command in: "+atom);
793 // TODO Error handling
794 qWarning("MapEditor::parseAtom: Error!");
795 qWarning(api.errorDesc());
799 void MapEditor::toggleHistoryWindow()
801 if (historyWindow->isVisible())
802 historyWindow->hide();
804 historyWindow->show();
808 bool MapEditor::isDefault()
813 bool MapEditor::isUnsaved()
818 bool MapEditor::hasChanged()
823 void MapEditor::setChanged()
828 actionEditUndo->setEnabled (true);
829 actionFileSave->setEnabled (true);
833 void MapEditor::closeMap()
835 // Unselect before disabling the toolbar actions
836 if (selection) selection->unselect();
844 void MapEditor::setFilePath(QString fname)
846 setFilePath (fname,fname);
849 void MapEditor::setFilePath(QString fname, QString destname)
851 if (fname.isEmpty() || fname=="")
858 filePath=fname; // becomes absolute path
859 fileName=fname; // gets stripped of path
860 destPath=destname; // needed for vymlinks
862 // If fname is not an absolute path, complete it
863 filePath=QDir(fname).absPath();
864 fileDir=filePath.left (1+filePath.findRev ("/"));
866 // Set short name, too. Search from behind:
867 int i=fileName.findRev("/");
868 if (i>=0) fileName=fileName.remove (0,i+1);
870 // Forget the .vym (or .xml) for name of map
871 mapName=fileName.left(fileName.findRev(".",-1,true) );
873 // Adjust history window
874 historyWindow->setCaption (fileName);
878 QString MapEditor::getFilePath()
883 QString MapEditor::getFileName()
888 QString MapEditor::getMapName()
893 QString MapEditor::getDestPath()
898 ErrorCode MapEditor::load (QString fname, LoadMode lmode)
900 ErrorCode err=success;
904 if (selection) selection->unselect();
907 mapCenter->setMapEditor(this);
908 // (map state is set later at end of load...)
911 saveStatePart(selection,"Load map");
915 mapBuilderHandler handler;
918 // I am paranoid: file should exist anyway
919 // according to check in mainwindow.
922 QMessageBox::critical( 0, tr( "Critical Parse Error" ),
923 tr("Couldn't open map " +fname)+".");
927 blockReposition=true;
928 QXmlInputSource source( file);
929 QXmlSimpleReader reader;
930 reader.setContentHandler( &handler );
931 reader.setErrorHandler( &handler );
932 handler.setMapEditor( this );
933 handler.setTmpDir (filePath.left(filePath.findRev("/",-1))); // needed to load files with rel. path
934 handler.setInputFile (file.name());
935 handler.setLoadMode (lmode);
937 bool ok = reader.parse( source );
938 blockReposition=false;
939 blockSaveState=false;
943 mapCenter->reposition();
953 QMessageBox::critical( 0, tr( "Critical Parse Error" ),
954 tr( handler.errorProtocol() ) );
956 // Still return "success": the map maybe at least
957 // partially read by the parser
964 int MapEditor::save (const SaveMode &savemode)
968 // The SaveMode UndoCommand is not supported here
969 if (savemode==UndoCommand) return 1;
971 // Create mapName and fileDir
972 makeSubDirs (fileDir);
976 fname=mapName+".xml";
978 // use name given by user, even if he chooses .doc
983 if (savemode==CompleteMap || selection==NULL)
984 saveFile=saveToDir (fileDir,mapName+"-",true,QPoint(),NULL);
986 saveFile=saveToDir (fileDir,mapName+"-",true,QPoint(),selection);
988 if (!saveStringToDisk(fileDir+fname,saveFile))
995 actionFileSave->setEnabled(false);
1001 void MapEditor::setZipped (bool z)
1006 bool MapEditor::saveZipped ()
1011 void MapEditor::print()
1015 printer = new QPrinter;
1016 printer->setColorMode (QPrinter::Color);
1017 printer->setPrinterName (settings.value("/mainwindow/printerName",printer->printerName()).toString());
1020 QRect totalBBox=mapCenter->getTotalBBox();
1022 // Try to set orientation automagically
1023 // Note: Interpretation of generated postscript is amibiguous, if
1024 // there are problems with landscape mode, see
1025 // http://sdb.suse.de/de/sdb/html/jsmeix_print-cups-landscape-81.html
1027 if (totalBBox.width()>totalBBox.height())
1028 // recommend landscape
1029 printer->setOrientation (QPrinter::Landscape);
1031 // recommend portrait
1032 printer->setOrientation (QPrinter::Portrait);
1034 if ( printer->setup(this) )
1035 // returns false, if printing is canceled
1037 QPainter pp(printer);
1039 // Don't print the visualisation of selection
1040 LinkableMapObj *oldselection=NULL;
1043 oldselection=selection;
1044 selection->unselect();
1047 // Handle sizes of map and paper:
1049 // setWindow defines which part of the canvas will be transformed
1050 // setViewport defines area on paper in device coordinates (dpi)
1051 // e.g. (0,50,700,700) is upper part on A4
1052 // see also /usr/lib/qt3/doc/html/coordsys.html
1054 Q3PaintDeviceMetrics metrics (printer);
1056 double paperAspect = (double)metrics.width() / (double)metrics.height();
1057 double mapAspect = (double)totalBBox.width() / (double)totalBBox.height();
1059 QRect mapRect=totalBBox;
1060 Q3CanvasRectangle *frame=NULL;
1061 Q3CanvasText *footerFN=NULL;
1062 Q3CanvasText *footerDate=NULL;
1063 if (printFrame || printFooter)
1068 // Print frame around map
1069 mapRect.setRect (totalBBox.x()-10, totalBBox.y()-10,
1070 totalBBox.width()+20, totalBBox.height()+20);
1071 frame=new Q3CanvasRectangle (mapRect,mapCanvas);
1072 frame->setBrush (QColor(Qt::white));
1073 frame->setPen (QColor(Qt::black));
1077 /* TODO remove after testing
1078 QCanvasLine *l=new QCanvasLine (mapCanvas);
1079 l->setPoints (0,0,mapRect.width(),mapRect.height());
1080 l->setPen (QPen(QColor(black), 1));
1087 // Print footer below map
1089 font.setPointSize(10);
1090 footerFN=new Q3CanvasText (mapCanvas);
1091 footerFN->setText ("VYM - " + fileName);
1092 footerFN->setFont(font);
1093 footerFN->move (mapRect.x(), mapRect.y() + mapRect.height() );
1094 footerFN->setZ(Z_TEXT);
1096 footerDate=new Q3CanvasText (mapCanvas);
1097 footerDate->setText (QDate::currentDate().toString(Qt::TextDate));
1098 footerDate->setFont(font);
1099 footerDate->move (mapRect.x()+mapRect.width()-footerDate->boundingRect().width(), mapRect.y() + mapRect.height() );
1100 footerDate->setZ(Z_TEXT);
1103 pp.setWindow (mapRect.x(), mapRect.y(), mapRect.width(), mapRect.height()+20);
1106 pp.setWindow (mapRect);
1109 if (mapAspect>=paperAspect)
1111 // Fit horizontally to paper width
1112 pp.setViewport(0,0, metrics.width(),(int)(metrics.width()/mapAspect) );
1115 // Fit vertically to paper height
1116 pp.setViewport(0,0,(int)(metrics.height()*mapAspect),metrics.height());
1119 mapCanvas->drawArea(mapRect, &pp); // draw Canvas to printer
1121 // Delete Frame and footer
1125 delete (footerDate);
1127 if (frame) delete (frame);
1129 // Restore selection
1132 selection=oldselection;
1133 selection->select();
1136 // Save settings in vymrc
1137 settings.writeEntry("/mainwindow/printerName",printer->printerName());
1141 QPixmap MapEditor::getPixmap()
1143 QRect mapRect=mapCenter->getTotalBBox();
1144 QPixmap pix (mapRect.size());
1147 // Don't print the visualisation of selection
1148 LinkableMapObj *oldselection=NULL;
1151 oldselection=selection;
1152 selection->unselect();
1155 pp.setWindow (mapRect);
1157 mapCanvas->drawArea(mapRect, &pp); // draw Canvas to painter
1160 // Restore selection
1163 selection=oldselection;
1164 selection->select();
1170 void MapEditor::setHideTmpMode (HideTmpMode mode)
1173 mapCenter->setHideTmp (hidemode);
1174 mapCenter->reposition();
1179 HideTmpMode MapEditor::getHideTmpMode()
1184 void MapEditor::exportImage(QString fn)
1186 setExportMode (true);
1187 QPixmap pix (getPixmap());
1188 pix.save(fn, "PNG");
1189 setExportMode (false);
1192 void MapEditor::setExportMode (bool b)
1194 // should be called before and after exports
1195 // depending on the settings
1196 if (b && settings.value("/export/useHideExport","yes")=="yes")
1197 setHideTmpMode (HideExport);
1199 setHideTmpMode (HideNone);
1202 void MapEditor::exportImage(QString fn, QString format)
1204 setExportMode (true);
1205 QPixmap pix (getPixmap());
1206 pix.save(fn, format);
1207 setExportMode (false);
1210 void MapEditor::exportOOPresentation(const QString &fn, const QString &cf)
1214 ex.setMapCenter(mapCenter);
1215 if (ex.setConfigFile(cf))
1217 setExportMode (true);
1218 ex.exportPresentation();
1219 setExportMode (false);
1225 void MapEditor::exportXML(const QString &dir)
1227 // Hide stuff during export, if settings want this
1228 setExportMode (true);
1230 // Create subdirectories
1233 // write to directory
1234 QString saveFile=saveToDir (dir,mapName+"-",true,mapCenter->getTotalBBox().topLeft() ,NULL);
1237 file.setName ( dir + "/"+mapName+".xml");
1238 if ( !file.open( QIODevice::WriteOnly ) )
1240 // This should neverever happen
1241 QMessageBox::critical (0,tr("Critical Export Error"),tr("MapEditor::exportXML couldn't open %1").arg(file.name()));
1245 // Write it finally, and write in UTF8, no matter what
1246 QTextStream ts( &file );
1247 ts.setEncoding (QTextStream::UnicodeUTF8);
1251 // Now write image, too
1252 exportImage (dir+"/images/"+mapName+".png");
1254 setExportMode (false);
1257 void MapEditor::clear()
1261 selection->unselect();
1268 void MapEditor::copy()
1272 // write to directory
1273 QString clipfile="part";
1274 QString saveFile=saveToDir (fileDir,clipfile+"-",true,QPoint(),selection);
1277 file.setName ( clipboardDir + "/"+clipfile+".xml");
1278 if ( !file.open( QIODevice::WriteOnly ) )
1280 // This should neverever happen
1281 QMessageBox::critical (0,tr("Critical Export Error"),tr("MapEditor::exportXML couldn't open %1").arg(file.name()));
1285 // Write it finally, and write in UTF8, no matter what
1286 QTextStream ts( &file );
1287 ts.setEncoding (QTextStream::UnicodeUTF8);
1291 clipboardEmpty=false;
1296 void MapEditor::redo()
1298 blockSaveState=true;
1300 // Restore variables
1301 int curStep=undoSet.readNumEntry (QString("/history/curStep"));
1302 int undosAvail=undoSet.readNumEntry (QString("/history/undosAvail"));
1303 int redosAvail=undoSet.readNumEntry (QString("/history/redosAvail"));
1304 if (redosAvail>0) redosAvail--;
1305 if (undosAvail<undosTotal) undosAvail++;
1307 if (curStep>undosTotal) curStep=1;
1308 QString undoCommand= undoSet.readEntry (QString("/history/step-%1/undoCommand").arg(curStep));
1309 QString undoSelection=undoSet.readEntry (QString("/history/step-%1/undoSelection").arg(curStep));
1310 QString redoCommand= undoSet.readEntry (QString("/history/step-%1/redoCommand").arg(curStep));
1311 QString redoSelection=undoSet.readEntry (QString("/history/step-%1/redoSelection").arg(curStep));
1312 QString comment=undoSet.readEntry (QString("/history/step-%1/comment").arg(curStep));
1314 // Find out current undo directory
1315 QString bakMapDir=QDir::convertSeparators (QString(tmpMapDir+"/undo-%1").arg(curStep));
1317 /* TODO remove testing
1319 cout << "ME::redo() begin\n";
1320 cout << " undosAvail="<<undosAvail<<endl;
1321 cout << " redosAvail="<<redosAvail<<endl;
1322 cout << " curStep="<<curStep<<endl;
1323 cout << " ---------------------------"<<endl;
1324 cout << " comment="<<comment.toStdString()<<endl;
1325 cout << " undoCom="<<undoCommand.toStdString()<<endl;
1326 cout << " undoSel="<<undoSelection.toStdString()<<endl;
1327 cout << " redoCom="<<redoCommand.toStdString()<<endl;
1328 cout << " redoSel="<<redoSelection.toStdString()<<endl;
1329 cout << " ---------------------------"<<endl<<endl;
1331 // select object before redo
1332 // FIXME better give up if no selection there...
1333 if (!redoSelection.isEmpty())
1334 select (redoSelection);
1337 parseAtom (redoCommand);
1338 mapCenter->reposition();
1340 blockSaveState=false;
1342 undoSet.setEntry ("/history/undosAvail",QString::number(undosAvail));
1343 undoSet.setEntry ("/history/redosAvail",QString::number(redosAvail));
1344 undoSet.setEntry ("/history/curStep",QString::number(curStep));
1345 undoSet.writeSettings(histPath);
1349 /* TODO remove testing
1351 cout << "ME::redo() end\n";
1352 cout << " undosAvail="<<undosAvail<<endl;
1353 cout << " redosAvail="<<redosAvail<<endl;
1354 cout << " curStep="<<curStep<<endl;
1355 cout << " ---------------------------"<<endl<<endl;
1360 void MapEditor::undo()
1362 blockSaveState=true;
1364 // Restore variables
1365 int curStep=undoSet.readNumEntry (QString("/history/curStep"));
1366 int undosAvail=undoSet.readNumEntry (QString("/history/undosAvail"));
1367 int redosAvail=undoSet.readNumEntry (QString("/history/redosAvail"));
1368 QString undoCommand= undoSet.readEntry (QString("/history/step-%1/undoCommand").arg(curStep));
1369 QString undoSelection=undoSet.readEntry (QString("/history/step-%1/undoSelection").arg(curStep));
1370 QString redoCommand= undoSet.readEntry (QString("/history/step-%1/redoCommand").arg(curStep));
1371 QString redoSelection=undoSet.readEntry (QString("/history/step-%1/redoSelection").arg(curStep));
1372 QString comment=undoSet.readEntry (QString("/history/step-%1/comment").arg(curStep));
1374 // Find out current undo directory
1375 QString bakMapDir=QDir::convertSeparators (QString(tmpMapDir+"/undo-%1").arg(curStep));
1377 // select object before undo
1378 if (!undoSelection.isEmpty())
1379 select (undoSelection);
1383 cout << "ME::undo() begin\n";
1384 cout << " undosAvail="<<undosAvail<<endl;
1385 cout << " redosAvail="<<redosAvail<<endl;
1386 cout << " curStep="<<curStep<<endl;
1387 cout << " ---------------------------"<<endl;
1388 cout << " comment="<<comment.toStdString()<<endl;
1389 cout << " undoCom="<<undoCommand.toStdString()<<endl;
1390 cout << " undoSel="<<undoSelection.toStdString()<<endl;
1391 cout << " redoCom="<<redoCommand.toStdString()<<endl;
1392 cout << " redoSel="<<redoSelection.toStdString()<<endl;
1393 cout << " ---------------------------"<<endl<<endl;
1394 parseAtom (undoCommand);
1395 mapCenter->reposition();
1399 if (curStep<1) curStep=undosTotal;
1403 blockSaveState=false;
1404 /* TODO remove testing
1406 cout << "ME::undo() end\n";
1407 cout << " undosAvail="<<undosAvail<<endl;
1408 cout << " redosAvail="<<redosAvail<<endl;
1409 cout << " curStep="<<curStep<<endl;
1410 cout << " ---------------------------"<<endl<<endl;
1412 undoSet.setEntry ("/history/undosAvail",QString::number(undosAvail));
1413 undoSet.setEntry ("/history/redosAvail",QString::number(redosAvail));
1414 undoSet.setEntry ("/history/curStep",QString::number(curStep));
1415 undoSet.writeSettings(histPath);
1420 void MapEditor::undoXML(const QString &undoSel, const QString &bakMapPath)
1422 QString bakMapDir=bakMapPath.left(bakMapPath.findRev("/"));
1424 QFile file (bakMapPath);
1428 // We need to parse saved XML data
1429 mapBuilderHandler handler;
1430 QXmlInputSource source( file);
1431 QXmlSimpleReader reader;
1432 reader.setContentHandler( &handler );
1433 reader.setErrorHandler( &handler );
1434 handler.setMapEditor( this );
1435 handler.setTmpDir ( bakMapDir ); // needed to load files with rel. path
1436 if (undoSel.isEmpty())
1440 handler.setLoadMode (NewMap);
1444 handler.setLoadMode (ImportReplace);
1446 blockReposition=true;
1447 bool ok = reader.parse( source );
1448 blockReposition=false;
1451 // This should never ever happen
1452 QMessageBox::critical( 0, tr( "Critical Parse Error by reading backupFile" ),
1453 tr( handler.errorProtocol() )+" in "+bakMapDir );
1457 QMessageBox::critical( 0, tr( "Critical Error" ),
1458 tr("Temporary directory %1 used for undo is gone. \n"
1459 "I will create a new one, but at the moment no undo is available.\n"
1460 "Maybe you want to reload your original data.\n\n"
1461 "Sorry for any inconveniences.").arg(bakMapDir) );
1466 void MapEditor::pasteNoSave()
1468 load (clipboardDir+"/part.xml",ImportAdd);
1471 void MapEditor::cutNoSave()
1477 void MapEditor::paste()
1479 if (selection && (typeid(*selection) == typeid(BranchObj) ||
1480 typeid(*selection) == typeid(MapCenterObj)))
1482 saveStatePart(selection,QString("Paste to %1").arg( getName(selection)));
1484 mapCenter->reposition();
1489 void MapEditor::cut()
1491 saveStatePart(selection->getParObj(),QString("Cut %1").arg(getName(selection)));
1494 mapCenter->reposition();
1498 void MapEditor::move(const int &x, const int &y)
1502 QString ps=qpointToString (selection->getAbsPos());
1503 QString s=selection->getSelectString();
1506 s, "move "+qpointToString (QPoint (x,y)),
1507 QString("Move %1 to %2").arg(getName(selection)).arg(ps));
1508 selection->move(x,y);
1509 mapCenter->reposition();
1515 void MapEditor::moveRel (const int &x, const int &y)
1519 QString ps=qpointToString (selection->getRelPos());
1520 QString s=selection->getSelectString();
1523 s, "moveRel "+qpointToString (QPoint (x,y)),
1524 QString("Move %1 to relativ position %2").arg(getName(selection)).arg(ps));
1525 selection->setRelPos (QPoint(x,y));
1526 mapCenter->reposition();
1531 void MapEditor::moveBranchUp()
1535 if (typeid(*selection) == typeid(BranchObj) )
1537 bo=(BranchObj*)selection;
1538 if (!bo->canMoveBranchUp()) return;
1539 par=(BranchObj*)(bo->getParObj());
1540 selection->unselect();
1541 bo=par->moveBranchUp (bo); // bo will be the one below selection
1542 selection->select();
1543 saveState (selection,"moveBranchDown ()",bo,"moveBranchUp ()",QString("Move up %1").arg(getName(bo)));
1544 mapCenter->reposition();
1545 ensureSelectionVisible();
1549 void MapEditor::moveBranchDown()
1553 if (typeid(*selection) == typeid(BranchObj) )
1555 bo=(BranchObj*)selection;
1556 if (!bo->canMoveBranchDown()) return;
1557 par=(BranchObj*)(bo->getParObj());
1558 selection->unselect();
1559 bo=par->moveBranchDown(bo); // bo will be the one above selection
1560 selection->select();
1561 saveState(selection,"moveBranchUp ()",bo,"moveBranchDown ()",QString("Move down %1").arg(getName(bo)));
1562 mapCenter->reposition();
1563 ensureSelectionVisible();
1567 QString MapEditor::getHeading(bool &ok, QPoint &p)
1570 (typeid(*selection) == typeid(BranchObj) ||
1571 typeid(*selection) == typeid(MapCenterObj) ) )
1574 ensureSelectionVisible();
1575 p = ((BranchObj*)selection)->getAbsPos();
1576 p.setX (p.x() - contentsX());
1577 p.setY (p.y() - contentsY() + ((BranchObj*)selection)->height()/2);
1578 return ((BranchObj*)selection)->getHeading();
1584 void MapEditor::setHeading(const QString &s)
1587 (typeid(*selection) == typeid(BranchObj) ||
1588 typeid(*selection) == typeid(MapCenterObj) ) )
1590 editingBO=(BranchObj*)selection;
1591 saveStateConstSelection(
1592 "setHeading (\""+editingBO->getHeading()+"\")",
1593 "setHeading (\""+s+"\")",
1594 QString("Set heading of %1 to \"%2\"").arg(getName(editingBO)).arg(s) );
1595 editingBO->setHeading(s );
1597 mapCenter->reposition();
1599 ensureSelectionVisible();
1603 void MapEditor::setURLInt (const QString &s)
1605 // Internal function, no saveState needed
1607 (typeid(*selection) == typeid(BranchObj) ||
1608 typeid(*selection) == typeid(MapCenterObj) ) )
1610 ((BranchObj*)selection)->setURL(s);
1611 mapCenter->reposition();
1613 ensureSelectionVisible();
1617 void MapEditor::setHeadingInt(const QString &s)
1620 (typeid(*selection) == typeid(BranchObj) ||
1621 typeid(*selection) == typeid(MapCenterObj) ) )
1623 ((BranchObj*)selection)->setHeading(s);
1624 mapCenter->reposition();
1626 ensureSelectionVisible();
1630 void MapEditor::setVymLinkInt (const QString &s)
1632 // Internal function, no saveState needed
1634 (typeid(*selection) == typeid(BranchObj) ||
1635 typeid(*selection) == typeid(MapCenterObj) ) )
1637 ((BranchObj*)selection)->setVymLink(s);
1638 mapCenter->reposition();
1640 ensureSelectionVisible();
1644 BranchObj* MapEditor::addNewBranchInt(int num)
1646 // Depending on pos:
1647 // -3 insert in childs of parent above selection
1648 // -2 add branch to selection
1649 // -1 insert in childs of parent below selection
1650 // 0..n insert in childs of parent at pos
1651 BranchObj *newbo=NULL;
1653 (typeid(*selection) == typeid(BranchObj) ||
1654 typeid(*selection) == typeid(MapCenterObj) ) )
1656 BranchObj* bo = (BranchObj*) selection;
1659 // save scroll state. If scrolled, automatically select
1660 // new branch in order to tmp unscroll parent...
1661 return bo->addBranch();
1666 bo=(BranchObj*)bo->getParObj();
1670 bo=(BranchObj*)bo->getParObj();
1673 newbo=bo->insertBranch(num);
1678 void MapEditor::addNewBranch(int pos)
1680 // Different meaning than num in addNewBranchInt!
1685 (typeid(*selection) == typeid(BranchObj) ||
1686 typeid(*selection) == typeid(MapCenterObj) ) )
1688 BranchObj *bo = (BranchObj*) selection;
1690 newbo=addNewBranchInt (pos-2);
1694 saveStateConstSelection (
1695 QString ("delete (\"%1\")").arg(newbo->getSelectString()),
1696 QString ("addBranch (%1)").arg(pos-2),
1697 QString ("Add new branch to %1").arg(getName(bo))); //TODO undoCommand
1699 LinkableMapObj *oldselection=selection;
1701 mapCenter->reposition();
1705 if (actionSettingsAutoedit->isOn() ||
1706 actionSettingsAutoselectHeading->isOn() )
1708 selection->unselect();
1710 selection->select();
1711 if (actionSettingsAutoedit->isOn() )
1712 mainWindow->editHeading();
1713 if (!actionSettingsAutoselectHeading->isOn()
1714 )//&& !wasScrolled) //FIXME wasScrolled was moved to addNewBranchInt
1716 selection->unselect();
1717 selection=oldselection;
1718 selection->select();
1726 void MapEditor::addNewBranchHere()
1729 (typeid(*selection) == typeid(BranchObj) ) )
1731 BranchObj* bo1 = (BranchObj*) selection;
1732 saveStatePart(selection, QString("Add new branch here").arg(getName(bo1)));
1734 bool wasScrolled=false;
1735 BranchObj *newbo=NULL;
1736 BranchObj *parbo=(BranchObj*)(selection->getParObj());
1739 // add below selection
1740 newbo=parbo->insertBranch(bo1->getNum()+1);
1743 LinkableMapObj *oldselection=selection;
1744 ((BranchObj*)selection)->moveBranchTo (newbo,-1);
1746 mapCenter->reposition();
1748 if (actionSettingsAutoedit->isOn() ||
1749 actionSettingsAutoselectHeading->isOn() )
1751 selection->unselect();
1753 selection->select();
1754 if (actionSettingsAutoedit->isOn() )
1755 mainWindow->editHeading();
1756 if (!actionSettingsAutoselectHeading->isOn()
1759 selection->unselect();
1760 selection=oldselection;
1761 selection->select();
1767 void MapEditor::deleteSelection()
1769 if (selection && typeid(*selection) ==typeid(BranchObj) )
1771 BranchObj* bo=(BranchObj*)selection;
1772 BranchObj* par=(BranchObj*)(bo->getParObj());
1774 if (selection->getDepth()>1)
1775 // Normal branch, save parent with childs
1776 saveStatePart(par,QString("Delete %1").arg(getName(bo)));
1777 // naveState (UndoCom, par, QString("insertBranchAt (%1)", bo, "", QString ("Delete %1").arg(getName(bo))));
1779 // Mainbranch, save whole map
1780 // TODO Better would be to insert mainbranch again at pos
1781 // But undoCommand is missing right now
1782 saveStateComplete(QString("Delete %1").arg(getName(bo)));
1784 par->removeBranch(bo);
1786 selection->select();
1787 ensureSelectionVisible();
1788 mapCenter->reposition();
1791 if (selection && typeid(*selection) ==typeid(FloatImageObj) )
1793 FloatImageObj* fio=(FloatImageObj*)selection;
1794 BranchObj* par=(BranchObj*)(fio->getParObj());
1795 saveStatePart(par, QString("Delete %1").arg(getName(fio)));
1798 par->removeFloatImage(fio);
1800 selection->select();
1801 ensureSelectionVisible();
1802 mapCenter->reposition();
1807 LinkableMapObj* MapEditor::getSelection()
1812 void MapEditor::unselect()
1816 selectionLast=selection;
1817 selection->unselect();
1822 void MapEditor::reselect()
1826 selection=selectionLast;
1827 selection->select();
1832 bool MapEditor::select (const QString &s)
1834 LinkableMapObj *lmo=mapCenter->findObjBySelect(s);
1836 // Finally select the found object
1839 if (selection) unselect();
1841 selection->select();
1843 ensureSelectionVisible();
1849 QString MapEditor::getSelectString()
1851 if (selection) return selection->getSelectString();
1855 void MapEditor::selectInt (LinkableMapObj *lmo)
1857 if (lmo && selection != lmo)
1859 // select the MapObj
1860 if (selection) selection->unselect();
1862 selection->select();
1868 void MapEditor::selectNextBranchInt()
1870 // Increase number of branch
1873 QString s=selection->getSelectString();
1879 part=s.section(",",-1);
1881 num=part.right(part.length() - 3);
1883 s=s.left (s.length() -num.length());
1886 num=QString ("%1").arg(num.toUInt()+1);
1890 // Try to select this one
1891 if (select (s)) return;
1893 // We have no direct successor,
1894 // try to increase the parental number in order to
1895 // find a successor with same depth
1897 int d=selection->getDepth();
1902 while (!found && d>0)
1904 s=s.section (",",0,d-1);
1905 // replace substring of current depth in s with "1"
1906 part=s.section(",",-1);
1908 num=part.right(part.length() - 3);
1912 // increase number of parent
1913 num=QString ("%1").arg(num.toUInt()+1);
1914 s=s.section (",",0,d-2) + ","+ typ+num;
1917 // Special case, look at orientation
1918 if (selection->getOrientation()==OrientRightOfCenter)
1919 num=QString ("%1").arg(num.toUInt()+1);
1921 num=QString ("%1").arg(num.toUInt()-1);
1926 // pad to oldDepth, select the first branch for each depth
1927 for (i=d;i<oldDepth;i++)
1932 if ( ((BranchObj*)selection)->countBranches()>0)
1940 // try to select the freshly built string
1948 void MapEditor::selectPrevBranchInt()
1950 // Decrease number of branch
1953 QString s=selection->getSelectString();
1959 part=s.section(",",-1);
1961 num=part.right(part.length() - 3);
1963 s=s.left (s.length() -num.length());
1966 num=QString ("%1").arg(num.toUInt()-1);
1970 // Try to select this one
1971 if (select (s)) return;
1973 // We have no direct precessor,
1974 // try to decrease the parental number in order to
1975 // find a precessor with same depth
1977 int d=selection->getDepth();
1982 while (!found && d>0)
1984 s=s.section (",",0,d-1);
1985 // replace substring of current depth in s with "1"
1986 part=s.section(",",-1);
1988 num=part.right(part.length() - 3);
1992 // decrease number of parent
1993 num=QString ("%1").arg(num.toUInt()-1);
1994 s=s.section (",",0,d-2) + ","+ typ+num;
1997 // Special case, look at orientation
1998 if (selection->getOrientation()==OrientRightOfCenter)
1999 num=QString ("%1").arg(num.toUInt()-1);
2001 num=QString ("%1").arg(num.toUInt()+1);
2006 // pad to oldDepth, select the last branch for each depth
2007 for (i=d;i<oldDepth;i++)
2011 if ( ((BranchObj*)selection)->countBranches()>0)
2012 s+=",bo:"+ QString ("%1").arg( ((BranchObj*)selection)->countBranches()-1 );
2019 // try to select the freshly built string
2027 void MapEditor::selectUpperBranch()
2031 if (typeid(*selection) == typeid(BranchObj))
2033 if (selection->getOrientation()==OrientRightOfCenter)
2034 selectPrevBranchInt();
2036 if (selection->getDepth()==1)
2037 selectNextBranchInt();
2039 selectPrevBranchInt();
2044 void MapEditor::selectLowerBranch()
2048 if (typeid(*selection) == typeid(BranchObj))
2050 if (selection->getOrientation()==OrientRightOfCenter)
2051 selectNextBranchInt();
2053 if (selection->getDepth()==1)
2054 selectPrevBranchInt();
2056 selectNextBranchInt();
2062 void MapEditor::selectLeftBranch()
2068 if (typeid(*selection) == typeid(MapCenterObj))
2070 par= (BranchObj*) selection;
2071 bo=par->getLastSelectedBranch();
2074 // Workaround for reselecting on left and right side
2075 if (bo->getOrientation()==OrientRightOfCenter)
2077 bo=par->getLastBranch();
2083 selection->select();
2085 ensureSelectionVisible();
2090 par=(BranchObj*)(selection->getParObj());
2091 if (selection->getOrientation()==OrientRightOfCenter)
2093 if (typeid(*selection) == typeid(BranchObj) ||
2094 typeid(*selection) == typeid(FloatImageObj))
2096 selection->unselect();
2098 selection->select();
2100 ensureSelectionVisible();
2104 if (typeid(*selection) == typeid(BranchObj) )
2106 bo=((BranchObj*)selection)->getLastSelectedBranch();
2109 selection->unselect();
2111 selection->select();
2113 ensureSelectionVisible();
2121 void MapEditor::selectRightBranch()
2128 if (typeid(*selection) == typeid(MapCenterObj))
2130 par= (BranchObj*) selection;
2131 bo=par->getLastSelectedBranch();
2134 // Workaround for reselecting on left and right side
2135 if (bo->getOrientation()==OrientLeftOfCenter)
2136 bo=par->getFirstBranch();
2141 selection->select();
2142 ensureSelectionVisible();
2147 par=(BranchObj*)(selection->getParObj());
2148 if (selection->getOrientation()==OrientLeftOfCenter)
2150 if (typeid(*selection) == typeid(BranchObj) ||
2151 typeid(*selection) == typeid(FloatImageObj))
2153 selection->unselect();
2155 selection->select();
2157 ensureSelectionVisible();
2161 if (typeid(*selection) == typeid(BranchObj) )
2163 bo=((BranchObj*)selection)->getLastSelectedBranch();
2166 selection->unselect();
2168 selection->select();
2170 ensureSelectionVisible();
2178 void MapEditor::selectFirstBranch()
2184 if (typeid(*selection) == typeid(BranchObj))
2186 bo1= (BranchObj*) selection;
2187 par=(BranchObj*)(bo1->getParObj());
2188 bo2=par->getFirstBranch();
2192 selection->select();
2193 ensureSelectionVisible();
2200 void MapEditor::selectLastBranch()
2206 if (typeid(*selection) == typeid(BranchObj))
2208 bo1= (BranchObj*) selection;
2209 par=(BranchObj*)(bo1->getParObj());
2210 bo2=par->getLastBranch();
2214 selection->select();
2215 ensureSelectionVisible();
2222 void MapEditor::setColor(QColor c)
2227 void MapEditor::selectBackgroundColor()
2229 QColor col = QColorDialog::getColor( mapCanvas->backgroundColor(), this );
2230 if ( !col.isValid() ) return;
2231 setBackgroundColor( col );
2233 saveStateComplete(QString("Set background color of map to %1").arg(col.name()));
2236 void MapEditor::setBackgroundColor(QColor c)
2238 mapCanvas->setBackgroundColor (c);
2241 QColor MapEditor::pickColor()
2245 if (typeid(*selection) == typeid(BranchObj) ||
2246 typeid(*selection) == typeid(MapCenterObj))
2248 BranchObj *bo=(BranchObj*)selection;
2249 actColor=bo->getColor();
2255 void MapEditor::colorItem()
2259 if (typeid(*selection) == typeid(BranchObj) ||
2260 typeid(*selection) == typeid(MapCenterObj))
2262 BranchObj *bo=(BranchObj*)selection;
2263 saveStatePart(selection, QString("Set color of %1 to %2").arg(getName(bo)).arg(actColor.name())); //TODO undoCommand
2264 bo->setColor(actColor); // color branch
2269 void MapEditor::colorBranch()
2273 if (typeid(*selection) == typeid(BranchObj) ||
2274 typeid(*selection) == typeid(MapCenterObj))
2276 BranchObj *bo=(BranchObj*)selection;
2277 saveStatePart(selection, QString ("Set color of %1 and childs to %2").arg(getName(bo)).arg(actColor.name())); //TODO undoCommand
2278 bo->setColorChilds(actColor); // color links, color childs
2284 void MapEditor::toggleStandardFlag(QString f)
2288 if (typeid(*selection) == typeid(BranchObj) ||
2289 typeid(*selection) == typeid(MapCenterObj))
2291 BranchObj *bo=(BranchObj*)selection;
2293 if (bo->isSetStandardFlag(f))
2303 saveStateConstSelection(QString("%1 (\"%2\")").arg(u).arg(f),
2304 QString("%1 (\"%2\")").arg(r).arg(f),
2305 QString("Toggling standard flag \"%1\" of %2").arg(f).arg(getName(bo)));
2306 bo->toggleStandardFlag (f,actionSettingsUseFlagGroups->isOn());
2312 void MapEditor::setViewCenter()
2314 // transform to CanvasView Coord:
2315 QPoint p=worldMatrix().map(movingCenter);
2316 center ( p.x(), p.y());
2320 BranchObj* MapEditor::findText (QString s, bool cs)
2322 QTextDocument::FindFlags flags=0;
2323 if (cs) flags=QTextDocument::FindCaseSensitively;
2326 { // Nothing found or new find process
2328 // nothing found, start again
2330 itFind=mapCenter->first();
2332 bool searching=true;
2333 bool foundNote=false;
2334 while (searching && !EOFind)
2338 // Searching in Note
2339 if (itFind->getNote().contains(s,cs))
2341 if (selection!=itFind)
2343 if (selection) ((BranchObj*)selection)->unselect();
2345 selection->select();
2347 ensureSelectionVisible();
2349 if (textEditor->findText(s,flags))
2355 // Searching in Heading
2356 if (searching && itFind->getHeading().contains (s,cs) )
2358 if (selection) ((BranchObj*)selection)->unselect();
2360 selection->select();
2362 ensureSelectionVisible();
2368 itFind=itFind->next();
2369 if (!itFind) EOFind=true;
2375 return (BranchObj*)selection;
2380 void MapEditor::findReset()
2381 { // Necessary if text to find changes during a find process
2386 void MapEditor::editURL()
2388 if (selection && (typeid(*selection) == typeid(BranchObj) ||
2389 typeid(*selection) == typeid(MapCenterObj)) )
2392 BranchObj *bo=(BranchObj*)selection;
2393 QString text = QInputDialog::getText(
2394 "VYM", tr("Enter URL:"), QLineEdit::Normal,
2395 bo->getURL(), &ok, this );
2398 // user entered something and pressed OK
2399 saveStateConstSelection("setURL (\""+bo->getURL()+"\")","setURL (\""+text+"\")", QString("Set URL of %1 to %21").arg(getName(bo)).arg(text));
2406 QString MapEditor::getURL()
2408 if (selection && (typeid(*selection) == typeid(BranchObj) ||
2409 typeid(*selection) == typeid(MapCenterObj)) )
2410 return ((BranchObj*)selection)->getURL();
2415 QStringList MapEditor::getURLs()
2418 if (selection && (typeid(*selection) == typeid(BranchObj) ||
2419 typeid(*selection) == typeid(MapCenterObj)) )
2421 BranchObj *bo=(BranchObj*)selection;
2425 if (!bo->getURL().isEmpty()) urls.append( bo->getURL());
2433 void MapEditor::editHeading2URL()
2435 if (selection && (typeid(*selection) == typeid(BranchObj) ||
2436 typeid(*selection) == typeid(MapCenterObj)) )
2438 BranchObj *bo=(BranchObj*)selection;
2439 saveStateConstSelection("setURL (\""+bo->getURL()+"\")","setURL (\""+bo->getHeading()+"\")",QString("Copy heading of %1 to URL").arg(getName(bo)));
2440 bo->setURL (bo->getHeading());
2445 void MapEditor::editBugzilla2URL()
2447 if (selection && (typeid(*selection) == typeid(BranchObj) ||
2448 typeid(*selection) == typeid(MapCenterObj)) )
2450 BranchObj *bo=(BranchObj*)selection;
2451 QString url= "https://bugzilla.novell.com/show_bug.cgi?id="+bo->getHeading();
2452 saveStateConstSelection("setURL (\""+bo->getURL()+"\")","setURL (\""+url+"\")",QString("Use heading of %1 as link to Novell Bugzilla").arg(getName(bo)));
2458 void MapEditor::editFATE2URL()
2460 if (selection && (typeid(*selection) == typeid(BranchObj) ||
2461 typeid(*selection) == typeid(MapCenterObj)) )
2463 BranchObj *bo=(BranchObj*)selection;
2464 QString url= "http://keeper.suse.de:8080/webfate/match/id?value=ID"+bo->getHeading();
2465 saveStateConstSelection("setURL (\""+bo->getURL()+"\")","setURL (\""+url+"\")",QString("Use heading of %1 as link to FATE").arg(getName(bo)));
2471 void MapEditor::editVymLink()
2473 if (selection && (typeid(*selection) == typeid(BranchObj) ||
2474 typeid(*selection) == typeid(MapCenterObj)) )
2476 BranchObj *bo=(BranchObj*)selection;
2477 Q3FileDialog *fd=new Q3FileDialog( this,__VYM " - " +tr("Link to another map"));
2478 fd->addFilter (QString (tr("vym map") + " (*.vym)"));
2479 fd->setCaption(__VYM " - " +tr("Link to another map"));
2480 if (! bo->getVymLink().isEmpty() )
2481 fd->setSelection( bo->getVymLink() );
2485 if ( fd->exec() == QDialog::Accepted )
2487 saveStateConstSelection("setVymLink (\""+bo->getVymLink()+"\")","setVymLink (\""+fd->selectedFile()+"\")",QString("Set vymlink of %1 to %2").arg(getName(bo)).arg(fd->selectedFile()));
2488 bo->setVymLink (fd->selectedFile() );
2490 mapCenter->reposition();
2497 void MapEditor::deleteVymLink()
2499 if (selection && (typeid(*selection) == typeid(BranchObj) ||
2500 typeid(*selection) == typeid(MapCenterObj)) )
2502 BranchObj *bo=(BranchObj*)selection;
2503 saveStateConstSelection("setVymLink (\""+bo->getVymLink()+"\")","setVymLink (\"\")",QString("Unset vymlink of %1").arg(getName(bo)));
2504 bo->setVymLink ("" );
2506 mapCenter->reposition();
2512 void MapEditor::toggleHideExport()
2514 if (selection && (typeid(*selection) == typeid(BranchObj) ||
2515 typeid(*selection) == typeid(MapCenterObj)) ||
2516 (typeid(*selection)==typeid(FloatImageObj))
2519 OrnamentedObj *oo=(OrnamentedObj*)selection;
2521 if (oo->hideInExport())
2523 oo->setHideInExport(false);
2528 oo->setHideInExport(true);
2531 saveStateComplete(QString ("%1 hide export flag of %2").arg(s).arg(getName(selection))); //TODO undoCommand
2532 actionEditToggleHideExport->setOn (oo->hideInExport());
2534 mapCenter->reposition();
2540 QString MapEditor::getVymLink()
2542 if (selection && (typeid(*selection) == typeid(BranchObj) ||
2543 typeid(*selection) == typeid(MapCenterObj)) )
2545 return ((BranchObj*)selection)->getVymLink();
2551 QStringList MapEditor::getVymLinks()
2554 if (selection && (typeid(*selection) == typeid(BranchObj) ||
2555 typeid(*selection) == typeid(MapCenterObj)) )
2557 BranchObj *bo=(BranchObj*)selection;
2561 if (!bo->getVymLink().isEmpty()) links.append( bo->getVymLink());
2569 void MapEditor::removeBranchKeepChilds()
2571 if (selection && (typeid(*selection) == typeid(BranchObj) ))
2573 BranchObj* bo=(BranchObj*)selection;
2574 BranchObj* par=(BranchObj*)(bo->getParObj());
2575 QString s=QString("Remove %1 and keep its childs").arg(getName(bo));
2576 if (bo->getDepth()==1)
2577 saveStateComplete(s);
2579 saveStatePart(selection->getParObj(),s); // TODO undoCommand
2580 QString sel=selection->getSelectString();
2582 par->removeBranchHere(bo);
2583 mapCenter->reposition();
2588 void MapEditor::removeChilds()
2590 if (selection && (typeid(*selection) == typeid(BranchObj) ))
2592 saveStatePart(selection->getParObj(), QString("Remove childs of branch %1").arg(getName(selection)));
2593 ((BranchObj*)selection)->removeChilds();
2594 mapCenter->reposition();
2598 void MapEditor::editMapInfo()
2600 ExtraInfoDialog dia;
2601 dia.setMapName (getFileName() );
2602 dia.setAuthor (mapCenter->getAuthor() );
2603 dia.setComment(mapCenter->getComment() );
2608 Q3CanvasItemList l=canvas()->allItems();
2609 for (Q3CanvasItemList::Iterator it=l.begin(); it!=l.end(); ++it)
2611 stats+=QString ("%1 items on canvas\n").arg (i,6);
2618 bo=mapCenter->first();
2621 if (!bo->getNote().isEmpty() ) n++;
2622 f+= bo->countFloatImages();
2624 xl+=bo->countXLinks();
2627 stats+=QString ("%1 branches\n").arg (b-1,6);
2628 stats+=QString ("%1 xLinks \n").arg (xl,6);
2629 stats+=QString ("%1 notes\n").arg (n,6);
2630 stats+=QString ("%1 images\n").arg (f,6);
2631 dia.setStats (stats);
2633 // Finally show dialog
2634 if (dia.exec() == QDialog::Accepted)
2636 saveStateComplete("Edit info about map"); //TODO undoCommand
2637 mapCenter->setAuthor (dia.getAuthor() );
2638 mapCenter->setComment (dia.getComment() );
2642 void MapEditor::updateActions()
2645 if (getLinkColorHint()==HeadingColor)
2646 actionFormatLinkColorHint->setOn(true);
2648 actionFormatLinkColorHint->setOn(false);
2653 actionFormatLinkStyleLine->setOn(true);
2656 actionFormatLinkStyleParabel->setOn(true);
2659 actionFormatLinkStylePolyLine->setOn(true);
2661 case StylePolyParabel:
2662 actionFormatLinkStylePolyParabel->setOn(true);
2668 QPixmap pix( 16, 16 );
2669 pix.fill( mapCanvas->backgroundColor() );
2670 actionFormatBackColor->setIconSet( pix );
2671 pix.fill( defLinkColor );
2672 actionFormatLinkColor->setIconSet( pix );
2674 actionFileSave->setEnabled( mapUnsaved );
2675 if (undoSet.readNumEntry("/history/undosAvail",0)>0)
2676 actionEditUndo->setEnabled( true);
2678 actionEditUndo->setEnabled( false);
2680 if (undoSet.readNumEntry("/history/redosAvail",0)>0)
2681 actionEditRedo->setEnabled( true);
2683 actionEditRedo->setEnabled( false);
2687 if ( (typeid(*selection) == typeid(BranchObj)) ||
2688 (typeid(*selection) == typeid(MapCenterObj)) )
2690 BranchObj *bo=(BranchObj*)selection;
2691 // Take care of links
2692 if (bo->countXLinks()==0)
2694 branchXLinksContextMenuEdit->clear();
2695 branchXLinksContextMenuFollow->clear();
2700 branchXLinksContextMenuEdit->clear();
2701 branchXLinksContextMenuFollow->clear();
2702 for (int i=0; i<=bo->countXLinks();i++)
2704 bot=bo->XLinkTargetAt(i);
2707 s=bot->getHeading();
2710 branchXLinksContextMenuFollow->addAction (s);
2711 branchXLinksContextMenuEdit->addAction (s);
2716 standardFlagsDefault->setEnabled (true);
2718 actionEditToggleScroll->setEnabled (true);
2719 if ( bo->isScrolled() )
2720 actionEditToggleScroll->setOn(true);
2722 actionEditToggleScroll->setOn(false);
2724 if ( bo->getURL().isEmpty() )
2726 actionEditOpenURL->setEnabled (false);
2727 actionEditOpenURLTab->setEnabled (false);
2731 actionEditOpenURL->setEnabled (true);
2732 actionEditOpenURLTab->setEnabled (true);
2734 if ( bo->getVymLink().isEmpty() )
2736 actionEditOpenVymLink->setEnabled (false);
2737 actionEditDeleteVymLink->setEnabled (false);
2740 actionEditOpenVymLink->setEnabled (true);
2741 actionEditDeleteVymLink->setEnabled (true);
2744 if (bo->canMoveBranchUp())
2745 actionEditMoveUp->setEnabled (true);
2747 actionEditMoveUp->setEnabled (false);
2748 if (bo->canMoveBranchDown())
2749 actionEditMoveDown->setEnabled (true);
2751 actionEditMoveDown->setEnabled (false);
2754 actionEditToggleHideExport->setEnabled (true);
2755 actionEditToggleHideExport->setOn (bo->hideInExport() );
2757 actionEditCopy->setEnabled (true);
2758 actionEditCut->setEnabled (true);
2759 if (!clipboardEmpty)
2760 actionEditPaste->setEnabled (true);
2762 actionEditPaste->setEnabled (false);
2763 for (a=actionListBranches.first();a;a=actionListBranches.next())
2764 a->setEnabled(true);
2765 actionEditDelete->setEnabled (true);
2766 switch (selection->getFrameType())
2769 actionFormatFrameNone->setOn(true);
2772 actionFormatFrameRectangle->setOn(true);
2777 actionFormatIncludeImagesVer->setOn
2778 ( ((BranchObj*)selection)->getIncludeImagesVer());
2779 actionFormatIncludeImagesHor->setOn
2780 ( ((BranchObj*)selection)->getIncludeImagesHor());
2781 actionFormatHideLinkUnselected->setOn
2782 (selection->getHideLinkUnselected());
2784 if ( (typeid(*selection) == typeid(FloatImageObj)) )
2786 FloatObj *fo=(FloatImageObj*)selection;
2787 //FIXME do this in mainwindow standardFlagsDefault->setEnabled (false);
2789 actionEditOpenURL->setEnabled (false);
2790 actionEditOpenVymLink->setEnabled (false);
2791 actionEditDeleteVymLink->setEnabled (false);
2792 actionEditToggleHideExport->setEnabled (true);
2793 actionEditToggleHideExport->setOn (fo->hideInExport() );
2796 actionEditCopy->setEnabled (true);
2797 actionEditCut->setEnabled (true);
2798 actionEditPaste->setEnabled (false);
2799 for (a=actionListBranches.first();a;a=actionListBranches.next())
2800 a->setEnabled(false);
2801 actionEditDelete->setEnabled (true);
2802 actionFormatHideLinkUnselected->setOn
2803 ( selection->getHideLinkUnselected());
2804 actionEditMoveUp->setEnabled (false);
2805 actionEditMoveDown->setEnabled (false);
2810 //FIXME do this in mainwindow standardFlagsDefault->setEnabled (false);
2812 actionEditCopy->setEnabled (false);
2813 actionEditCut->setEnabled (false);
2814 actionEditPaste->setEnabled (false);
2815 for (a=actionListBranches.first();a;a=actionListBranches.next())
2816 a->setEnabled(false);
2818 actionEditToggleScroll->setEnabled (false);
2819 actionEditOpenURL->setEnabled (false);
2820 actionEditOpenVymLink->setEnabled (false);
2821 actionEditDeleteVymLink->setEnabled (false);
2822 actionEditHeading2URL->setEnabled (false);
2823 actionEditDelete->setEnabled (false);
2824 actionEditMoveUp->setEnabled (false);
2825 actionEditMoveDown->setEnabled (false);
2826 actionEditToggleHideExport->setEnabled (false);
2830 void MapEditor::updateNoteFlag()
2833 if ( (typeid(*selection) == typeid(BranchObj)) ||
2834 (typeid(*selection) == typeid(MapCenterObj)) )
2835 ((BranchObj*)selection)->updateNoteFlag();
2838 void MapEditor::setLinkStyle (LinkStyle ls)
2842 saveStateComplete("Set link style"); // TODO undoCommand
2844 bo=mapCenter->first();
2848 bo->setLinkStyle(bo->getDefLinkStyle());
2851 mapCenter->reposition();
2854 LinkStyle MapEditor::getLinkStyle ()
2859 void MapEditor::setLinkColor(QColor c)
2865 void MapEditor::setLinkColorHint()
2867 // called from setLinkColorHint(lch) or at end of parse
2869 bo=mapCenter->first();
2877 void MapEditor::setLinkColorHint(LinkColorHint lch)
2883 void MapEditor::toggleLinkColorHint()
2885 if (linkcolorhint==HeadingColor)
2886 linkcolorhint=DefaultColor;
2888 linkcolorhint=HeadingColor;
2890 bo=mapCenter->first();
2898 LinkColorHint MapEditor::getLinkColorHint()
2900 return linkcolorhint;
2903 QColor MapEditor::getDefLinkColor()
2905 return defLinkColor;
2908 void MapEditor::setDefXLinkColor(QColor col)
2913 QColor MapEditor::getDefXLinkColor()
2915 return defXLinkColor;
2918 void MapEditor::setDefXLinkWidth (int w)
2923 int MapEditor::getDefXLinkWidth()
2925 return defXLinkWidth;
2928 void MapEditor::selectLinkColor()
2930 QColor col = QColorDialog::getColor( defLinkColor, this );
2931 if ( !col.isValid() ) return;
2932 setLinkColor( col );
2933 saveStateComplete(QString("Set link color to %1").arg(col.name())); //TODO undoCommand
2937 void MapEditor::toggleScroll()
2939 if (selection && (typeid(*selection) == typeid(BranchObj)) )
2941 BranchObj *bo=((BranchObj*)selection);
2942 if (bo->countBranches()==0) return;
2943 if (bo->getDepth()==0) return;
2945 if (bo->isScrolled())
2949 saveStatePart(selection, QString ("%1 %2").arg(s).arg(getName(bo)));
2956 void MapEditor::unScrollAll()
2959 bo=mapCenter->first();
2962 if (bo->isScrolled()) bo->toggleScroll();
2967 void MapEditor::loadFloatImage ()
2970 (typeid(*selection) == typeid(BranchObj)) ||
2971 (typeid(*selection) == typeid(MapCenterObj)) )
2973 BranchObj *bo=((BranchObj*)selection);
2975 Q3FileDialog *fd=new Q3FileDialog( this);
2976 fd->setMode (Q3FileDialog::ExistingFiles);
2977 fd->addFilter (QString (tr("Images") + " (*.png *.bmp *.xbm *.jpg *.png *.xpm *.gif *.pnm)"));
2978 ImagePreview *p =new ImagePreview (fd);
2979 fd->setContentsPreviewEnabled( TRUE );
2980 fd->setContentsPreview( p, p );
2981 fd->setPreviewMode( Q3FileDialog::Contents );
2982 fd->setCaption(__VYM " - " +tr("Load image"));
2983 fd->setDir (lastImageDir);
2987 if ( fd->exec() == QDialog::Accepted )
2989 saveStatePart(selection, QString("Add floatimage to %1").arg(getName(selection)));
2990 // FIXME in QT4 use: lastImageDir=fd->directory();
2991 lastImageDir=QDir (fd->dirPath());
2992 QStringList flist = fd->selectedFiles();
2993 QStringList::Iterator it = flist.begin();
2994 while( it != flist.end() )
2997 bo->addFloatImage();
2998 // TODO check if load was successful
2999 bo->getLastFloatImage()->load(*it);
3000 bo->getLastFloatImage()->setOriginalFilename(fn);
3004 mapCenter->reposition();
3013 void MapEditor::saveFloatImage ()
3016 (typeid(*selection) == typeid(FloatImageObj)) )
3018 FloatImageObj *fio=((FloatImageObj*)selection);
3019 QFileDialog *fd=new QFileDialog( this);
3020 fd->setFilters (imageIO.getFilters());
3021 fd->setCaption(__VYM " - " +tr("Save image"));
3022 fd->setFileMode( QFileDialog::AnyFile );
3023 fd->setDirectory (lastImageDir);
3024 // fd->setSelection (fio->getOriginalFilename());
3028 if ( fd->exec() == QDialog::Accepted )
3030 if (QFile (fd->selectedFile()).exists() )
3032 QMessageBox mb( __VYM,
3033 tr("The file %1 exists already.\n"
3034 "Do you want to overwrite it?").arg(fd->selectedFile()),
3035 QMessageBox::Warning,
3036 QMessageBox::Yes | QMessageBox::Default,
3037 QMessageBox::Cancel | QMessageBox::Escape,
3038 QMessageBox::QMessageBox::NoButton );
3040 mb.setButtonText( QMessageBox::Yes, tr("Overwrite") );
3041 mb.setButtonText( QMessageBox::No, tr("Cancel"));
3044 case QMessageBox::Yes:
3047 case QMessageBox::Cancel:
3053 fio->save (fd->selectedFile(),imageIO.getType (fd->selectedFilter() ) );
3058 void MapEditor::setFrame(const FrameType &t)
3061 (typeid(*selection) == typeid(BranchObj)) ||
3062 (typeid(*selection) == typeid(MapCenterObj)) )
3064 selection->setFrameType (t);
3065 mapCenter->reposition();
3066 selection->updateLink();
3070 void MapEditor::setIncludeImagesVer(bool b)
3073 (typeid(*selection) == typeid(BranchObj)) ||
3074 (typeid(*selection) == typeid(MapCenterObj)) )
3075 ((BranchObj*)selection)->setIncludeImagesVer(b);
3076 mapCenter->reposition();
3079 void MapEditor::setIncludeImagesHor(bool b)
3082 (typeid(*selection) == typeid(BranchObj)) ||
3083 (typeid(*selection) == typeid(MapCenterObj)) )
3084 ((BranchObj*)selection)->setIncludeImagesHor(b);
3085 mapCenter->reposition();
3088 void MapEditor::setHideLinkUnselected (bool b)
3091 (typeid(*selection) == typeid(BranchObj)) ||
3092 (typeid(*selection) == typeid(MapCenterObj)) ||
3093 (typeid(*selection) == typeid(FloatImageObj)) )
3094 selection->setHideLinkUnselected(b);
3097 void MapEditor::importDirInt(BranchObj *dst, QDir d)
3100 (typeid(*selection) == typeid(BranchObj)) ||
3101 (typeid(*selection) == typeid(MapCenterObj)) )
3105 // Traverse directories
3106 d.setFilter( QDir::Dirs| QDir::Hidden | QDir::NoSymLinks );
3107 QFileInfoList list = d.entryInfoList();
3110 for (int i = 0; i < list.size(); ++i)
3113 if (fi.fileName() != "." && fi.fileName() != ".." )
3116 bo=dst->getLastBranch();
3117 bo->setHeading (fi.fileName() );
3118 bo->setColor (QColor("blue"));
3120 if ( !d.cd(fi.fileName()) )
3121 QMessageBox::critical (0,tr("Critical Import Error"),tr("Cannot find the directory %1").arg(fi.fileName()));
3124 // Recursively add subdirs
3125 importDirInt (bo,d);
3131 d.setFilter( QDir::Files| QDir::Hidden | QDir::NoSymLinks );
3132 list = d.entryInfoList();
3134 for (int i = 0; i < list.size(); ++i)
3138 bo=dst->getLastBranch();
3139 bo->setHeading (fi.fileName() );
3140 bo->setColor (QColor("black"));
3141 if (fi.fileName().right(4) == ".vym" )
3142 bo->setVymLink (fi.filePath());
3147 void MapEditor::importDir()
3150 (typeid(*selection) == typeid(BranchObj)) ||
3151 (typeid(*selection) == typeid(MapCenterObj)) )
3153 Q3FileDialog *fd=new Q3FileDialog( this,__VYM " - " +tr("Choose directory structure to import"));
3154 fd->setMode (Q3FileDialog::DirectoryOnly);
3155 fd->addFilter (QString (tr("vym map") + " (*.vym)"));
3156 fd->setCaption(__VYM " - " +tr("Choose directory structure to import"));
3160 if ( fd->exec() == QDialog::Accepted )
3162 BranchObj *bo=((BranchObj*)selection);
3163 importDirInt (bo,QDir(fd->selectedFile()) );
3164 mapCenter->reposition();
3171 void MapEditor::followXLink(int i)
3174 (typeid(*selection) == typeid(BranchObj)) ||
3175 (typeid(*selection) == typeid(MapCenterObj)) )
3177 BranchObj *bo=((BranchObj*)selection)->XLinkTargetAt(i);
3180 selection->unselect();
3182 selection->select();
3183 ensureSelectionVisible();
3188 void MapEditor::editXLink(int i)
3190 qDebug ("ko."); //FIXME Huh?
3192 (typeid(*selection) == typeid(BranchObj)) ||
3193 (typeid(*selection) == typeid(MapCenterObj)) )
3195 XLinkObj *xlo=((BranchObj*)selection)->XLinkAt(i);
3198 EditXLinkDialog dia;
3200 dia.setSelection(selection);
3201 if (dia.exec() == QDialog::Accepted)
3203 if (dia.useSettingsGlobal() )
3205 setDefXLinkColor (xlo->getColor() );
3206 setDefXLinkWidth (xlo->getWidth() );
3208 if (dia.deleteXLink())
3209 ((BranchObj*)selection)->deleteXLinkAt(i);
3210 saveStateComplete("Edit xLink"); //TODO undoCommand
3216 void MapEditor::testFunction()
3218 cout << "MapEditor::testFunction() called\n";
3222 QString text = QInputDialog::getText(
3224 tr("QInputDialog::getText()"),
3225 tr("User name:"), QLineEdit::Normal,
3226 QDir::home().dirName(), &ok, Qt::FramelessWindowHint);
3229 QDialog *d =new QDialog(NULL);
3230 QLineEdit *le=new QLineEdit (d);
3231 // d->setModal (true);
3232 d->setWindowFlags (Qt::FramelessWindowHint);
3234 le->setText ("Foo");
3236 connect (le, SIGNAL (returnPressed()), d, SLOT (accept()));
3238 qWarning( le->text());
3245 dia.setCancelButton (true);
3246 dia.setText("This is a longer \nWarning");
3247 dia.setCaption("Warning: Flux problem");
3248 dia.setShowAgainName("/warnings/mapeditor");
3249 dia.setWindowFlags (Qt::FramelessWindowHint);
3250 if (dia.exec()==QDialog::Accepted)
3251 cout << "accepted!\n";
3253 cout << "canceled!\n";
3257 /* Hide hidden stuff temporary, maybe add this as regular function somewhere
3258 if (hidemode==HideNone)
3260 setHideTmpMode (HideExport);
3261 mapCenter->calcBBoxSizeWithChilds();
3262 QRect totalBBox=mapCenter->getTotalBBox();
3263 QRect mapRect=totalBBox;
3264 QCanvasRectangle *frame=NULL;
3266 cout << " map has =("<<totalBBox.x()<<","<<totalBBox.y()<<","<<totalBBox.width()<<","<<totalBBox.height()<<")\n";
3268 mapRect.setRect (totalBBox.x(), totalBBox.y(),
3269 totalBBox.width(), totalBBox.height());
3270 frame=new QCanvasRectangle (mapRect,mapCanvas);
3271 frame->setBrush (QColor(white));
3272 frame->setPen (QColor(black));
3278 setHideTmpMode (HideNone);
3280 cout <<" hidemode="<<hidemode<<endl;
3284 void MapEditor::ensureSelectionVisible()
3288 LinkableMapObj* lmo= dynamic_cast <LinkableMapObj*> (selection);
3290 if (selection->getOrientation() == OrientLeftOfCenter)
3291 p= worldMatrix().map(QPoint (lmo->x(),lmo->y()));
3293 p= worldMatrix().map(QPoint (lmo->x()+lmo->width(),lmo->y()+lmo->height()));
3294 ensureVisible (p.x(), p.y() );
3299 void MapEditor::updateViewCenter()
3301 // Update movingCenter, so that we can zoom comfortably later
3302 QRect rc = QRect( contentsX(), contentsY(),
3303 visibleWidth(), visibleHeight() );
3304 QRect canvasRect = inverseWorldMatrix().mapRect(rc);
3305 movingCenter.setX((canvasRect.right() + canvasRect.left())/2);
3306 movingCenter.setY((canvasRect.top() + canvasRect.bottom())/2);
3309 void MapEditor::contentsContextMenuEvent ( QContextMenuEvent * e )
3311 // Lineedits are already closed by preceding
3312 // mouseEvent, we don't need to close here.
3314 QPoint p = inverseWorldMatrix().map(e->pos());
3315 LinkableMapObj* lmo=mapCenter->findMapObj(p, NULL);
3318 { // MapObj was found
3319 if (selection != lmo)
3321 // select the MapObj
3322 if (selection) selection->unselect();
3324 selection->select();
3330 if (typeid(*selection)==typeid(BranchObj) ||
3331 typeid(*selection)==typeid(MapCenterObj) )
3333 // Context Menu on branch or mapcenter
3335 branchContextMenu->popup(e->globalPos() );
3337 if (typeid(*selection)==typeid(FloatImageObj))
3339 // Context Menu on floatimage
3341 floatimageContextMenu->popup(e->globalPos() );
3345 { // No MapObj found, we are on the Canvas itself
3346 // Context Menu on Canvas
3348 canvasContextMenu->popup(e->globalPos() );
3353 void MapEditor::contentsMousePressEvent(QMouseEvent* e)
3355 // Ignore right clicks, these will go to context menus
3356 if (e->button() == Qt::RightButton )
3362 QPoint p = inverseWorldMatrix().map(e->pos());
3363 LinkableMapObj* lmo=mapCenter->findMapObj(p, NULL);
3367 //Take care of clickdesystem flags _or_ modifier modes
3369 if (lmo && (typeid(*lmo)==typeid(BranchObj) ||
3370 typeid(*lmo)==typeid(MapCenterObj) ))
3372 QString foname=((BranchObj*)lmo)->getSystemFlagName(p);
3373 if (!foname.isEmpty())
3375 // systemFlag clicked
3379 if (e->state() & Qt::ControlModifier)
3380 mainWindow->editOpenURLTab();
3382 mainWindow->editOpenURL();
3384 else if (foname=="vymLink")
3386 mainWindow->editOpenVymLink();
3387 // tabWidget may change, better return now
3388 // before segfaulting...
3389 } else if (foname=="note")
3390 mainWindow->windowToggleNoteEditor();
3391 else if (foname=="hideInExport")
3396 // No system flag clicked, take care of modmodes
3398 // Special case: CTRL is pressed
3399 if (e->state() & Qt::ControlModifier)
3401 if (actionModModeColor->isOn())
3404 setCursor (pickColorCursor);
3407 if (actionModModeLink->isOn())
3409 BranchObj *bo_begin=NULL;
3411 bo_begin=(BranchObj*)(lmo);
3414 ((typeid(*selection) == typeid(BranchObj)) ||
3415 (typeid(*selection) == typeid(MapCenterObj))) )
3416 bo_begin=(BranchObj*)selection;
3420 linkingObj_src=bo_begin;
3421 tmpXLink=new XLinkObj (mapCanvas);
3422 tmpXLink->setBegin (bo_begin);
3423 tmpXLink->setEnd (p);
3424 tmpXLink->setColor(defXLinkColor);
3425 tmpXLink->setWidth(defXLinkWidth);
3426 tmpXLink->updateXLink();
3427 tmpXLink->setVisibility (true);
3435 // Left Button Move Branches
3436 if (e->button() == Qt::LeftButton )
3438 movingObj_start.setX( p.x() - selection->x() );
3439 movingObj_start.setY( p.y() - selection->y() );
3440 movingObj_orgPos.setX (lmo->x() );
3441 movingObj_orgPos.setY (lmo->y() );
3442 movingObj_orgRelPos=lmo->getRelPos();
3444 // If modMode==copy, then we want to "move" the _new_ object around
3445 // then we need the offset from p to the _old_ selection, because of tmp
3446 if (actionModModeCopy->isOn() &&
3447 e->state() & Qt::ControlModifier)
3449 if (typeid(*selection)==typeid(BranchObj) )
3452 mapCenter->addBranch ((BranchObj*)selection);
3454 selection=mapCenter->getLastBranch();
3455 selection->select();
3456 mapCenter->reposition();
3459 movingObj=selection;
3461 // Middle Button Toggle Scroll
3462 // (On Mac OS X this won't work, but we still have
3463 // a button in the toolbar)
3464 if (e->button() == Qt::MidButton )
3468 { // No MapObj found, we are on the Canvas itself
3469 // Left Button move Pos of CanvasView
3470 if (e->button() == Qt::LeftButton )
3472 movingObj=NULL; // move Content not Obj
3473 movingObj_start=e->globalPos();
3474 movingCont_start=QPoint (contentsX(), contentsY() );
3475 movingVec=QPoint(0,0);
3476 setCursor(handOpenCursor);
3481 void MapEditor::contentsMouseMoveEvent(QMouseEvent* e)
3483 QPoint p = inverseWorldMatrix().map(e->pos());
3485 // Move the selected MapObj
3486 if ( selection && movingObj)
3488 // To avoid jumping of the CanvasView, only
3489 // ensureSelectionVisible, if not tmp linked
3490 if (!selection->hasParObjTmp())
3491 ensureSelectionVisible ();
3493 // Now move the selection, but add relative position
3494 // (movingObj_start) where selection was chosen with
3495 // mousepointer. (This avoids flickering resp. jumping
3496 // of selection back to absPos)
3498 LinkableMapObj *lmosel;
3499 lmosel = dynamic_cast <LinkableMapObj*> (selection);
3501 // Check if we could link
3502 LinkableMapObj* lmo=mapCenter->findMapObj(p, lmosel);
3505 if (typeid(*selection) == typeid(FloatImageObj))
3507 FloatObj *fo=(FloatObj*)selection;
3508 fo->move (p.x() -movingObj_start.x(), p.y()-movingObj_start.y() );
3512 // Relink float to new mapcenter or branch, if shift is pressed
3513 // Only relink, if selection really has a new parent
3514 if ( (e->state() & Qt::ShiftModifier) && lmo &&
3515 ( (typeid(*lmo)==typeid(BranchObj)) ||
3516 (typeid(*lmo)==typeid(MapCenterObj)) ) &&
3517 ( lmo != fo->getParObj())
3520 if (typeid(*fo) == typeid(FloatImageObj))
3523 saveStateComplete(QString("Relink %1 to %2").arg(getName(fo)).arg(getName(lmo) ) );
3524 FloatImageObj *fio=(FloatImageObj*)(fo);
3525 ((BranchObj*)(lmo))->addFloatImage (fio);
3527 ((BranchObj*)(fio->getParObj()))->removeFloatImage (fio);
3528 fio=((BranchObj*)(lmo))->getLastFloatImage();
3531 selection=(LinkableMapObj*)(fio);
3532 selection->select();
3533 movingObj=(MapObj*)(fio);
3536 } else // selection != a FloatObj
3538 if (lmosel->getDepth()==0)
3540 if (e->state() == Qt::LeftButton && e->modifiers()==Qt::ShiftModifier)
3541 // If mapCenter is moved, move all the rest by default, too.
3542 mapCenter->moveAll(p.x() -movingObj_start.x(), p.y()-movingObj_start.y() );
3544 mapCenter->move (p.x() -movingObj_start.x(), p.y()-movingObj_start.y() );
3547 if (lmosel->getDepth()==1)
3549 // depth==1, mainbranch
3550 lmosel->move(p.x() -movingObj_start.x(), p.y()-movingObj_start.y() );
3554 if (lmosel->getOrientation() == OrientLeftOfCenter)
3555 // Add width of bbox here, otherwise alignRelTo will cause jumping around
3556 lmosel->move(p.x() -movingObj_start.x()+lmosel->getBBox().width(),
3557 p.y()-movingObj_start.y() +lmosel->getTopPad() );
3559 lmosel->move(p.x() -movingObj_start.x(), p.y()-movingObj_start.y() -lmosel->getTopPad());
3561 // reposition subbranch
3562 lmosel->reposition();
3563 //ensureSelectionVisible();
3565 if (lmo && (lmo!=selection) &&
3566 (typeid(*lmo) == typeid(BranchObj) ||
3567 (typeid(*lmo) == typeid(MapCenterObj) )
3570 if (e->state() & Qt::ControlModifier)
3572 // Special case: CTRL to link below lmo
3573 lmosel->setParObjTmp (lmo,p,+1);
3575 else if (e->state() & Qt::ShiftModifier)
3576 lmosel->setParObjTmp (lmo,p,-1);
3578 lmosel->setParObjTmp (lmo,p,0);
3581 lmosel->unsetParObjTmp();
3585 } // no FloatImageObj
3589 } // selection && moving_obj
3591 // Draw a link from one branch to another
3594 tmpXLink->setEnd (p);
3595 tmpXLink->updateXLink();
3599 if (!movingObj && !pickingColor &&!drawingLink)
3601 QPoint p=e->globalPos();
3602 movingVec.setX(-p.x() + movingObj_start.x() );
3603 movingVec.setY(-p.y() + movingObj_start.y() );
3604 setContentsPos( movingCont_start.x() + movingVec.x(),
3605 movingCont_start.y() + movingVec.y());
3612 void MapEditor::contentsMouseReleaseEvent(QMouseEvent* e)
3614 LinkableMapObj *dst;
3615 // Have we been picking color?
3619 setCursor (Qt::ArrowCursor);
3620 // Check if we are over another branch
3621 dst=mapCenter->findMapObj(inverseWorldMatrix().map(e->pos() ), NULL);
3622 if (dst && selection)
3624 if (e->state() & Qt::ShiftModifier)
3626 ((BranchObj*)selection)->setColor (((BranchObj*)(dst))->getColor());
3627 ((BranchObj*)selection)->setLinkColor ();
3631 ((BranchObj*)selection)->setColorChilds (((BranchObj*)(dst))->getColor());
3632 ((BranchObj*)selection)->setLinkColor ();
3638 // Have we been drawing a link?
3642 // Check if we are over another branch
3643 dst=mapCenter->findMapObj(inverseWorldMatrix().map(e->pos() ), NULL);
3644 if (dst && selection)
3646 tmpXLink->setEnd ( ((BranchObj*)(dst)) );
3647 tmpXLink->updateXLink();
3648 tmpXLink->activate();
3649 saveStateComplete(QString("Activate xLink from %1 to %2").arg(getName(tmpXLink->getBegin())).arg(getName(tmpXLink->getEnd())) ); //TODO undoCommand
3658 // Have we been moving something?
3659 if ( selection && movingObj )
3661 // Moved FloatObj? Maybe we need to reposition
3662 if(typeid(*selection)==typeid (FloatImageObj))
3664 FloatImageObj *fo=(FloatImageObj*)selection;
3665 QString pold=qpointToString(movingObj_orgRelPos);
3666 QString pnow=qpointToString(fo->getRelPos());
3667 saveStateConstSelection(
3670 QString("Move %1 to relativ position %2").arg(getName(selection)).arg(pnow));
3672 selection->getParObj()->requestReposition();
3673 mapCenter->reposition();
3676 // Check if we are over another branch, but ignore
3677 // any found LMOs, which are FloatObjs
3678 dst=mapCenter->findMapObj(inverseWorldMatrix().map(e->pos() ),
3679 ((LinkableMapObj*)selection) );
3681 if (dst && (typeid(*dst)!=typeid(BranchObj) && typeid(*dst)!=typeid(MapCenterObj)))
3684 // Now check, if we have been moving a branch
3685 if (typeid(*selection) == typeid(BranchObj) )
3687 // save the position in case we link to mapcenter
3688 QPoint savePos=QPoint (selection->x(),selection->y() );
3690 // Reset the temporary drawn link to the original one
3691 ((LinkableMapObj*)selection)->unsetParObjTmp();
3693 // For Redo we may need to save original selection
3694 QString preSelStr=selection->getSelectString();
3699 BranchObj* bsel=(BranchObj*)selection;
3700 BranchObj* bdst=(BranchObj*)dst;
3702 QString preParStr=(bsel->getParObj())->getSelectString();
3703 QString preNum=QString::number (bsel->getNum(),10);
3704 QString preDstParStr;
3706 if (e->state() & Qt::ShiftModifier && dst->getParObj())
3708 preDstParStr=dst->getParObj()->getSelectString();
3709 bsel->moveBranchTo ( (BranchObj*)(bdst->getParObj()), bdst->getNum());
3711 if (e->state() & Qt::ControlModifier && dst->getParObj())
3714 preDstParStr=dst->getParObj()->getSelectString();
3715 bsel->moveBranchTo ( (BranchObj*)(bdst->getParObj()), bdst->getNum()+1);
3718 preDstParStr=dst->getSelectString();
3719 bsel->moveBranchTo (bdst,-1);
3720 if (dst->getDepth()==0) bsel->move (savePos);
3722 QString postSelStr=selection->getSelectString();
3723 QString postNum=QString::number (bsel->getNum(),10);
3725 QString undoCom="linkBranchToPos (\""+
3726 preParStr+ "\"," + preNum +"," +
3727 QString ("%1,%2").arg(movingObj_orgPos.x()).arg(movingObj_orgPos.y())+ ")";
3729 QString redoCom="linkBranchToPos (\""+
3730 preDstParStr + "\"," + postNum + "," +
3731 QString ("%1,%2").arg(savePos.x()).arg(savePos.y())+ ")";
3736 QString("Relink %1 to %2").arg(getName(bsel)).arg(getName(dst)) );
3738 if (selection->getDepth()==1)
3740 // The select string might be different _after_ moving around.
3741 // Therefor reposition and then use string of old selection, too
3742 mapCenter->reposition();
3744 QString ps=qpointToString ( ((BranchObj*)selection)->getRelPos() );
3746 selection->getSelectString(), "moveRel "+qpointToString(movingObj_orgRelPos),
3747 preSelStr, "moveRel "+ps,
3748 QString("Move %1 to relative position %2").arg(getName(selection)).arg(ps));
3751 // Draw the original link, before selection was moved around
3752 mapCenter->reposition();
3754 // Finally resize canvas, if needed
3759 // Just make sure, that actions are still ok,e.g. the move branch up/down buttons...
3762 // maybe we moved View: set old cursor
3763 setCursor (Qt::ArrowCursor);
3767 void MapEditor::contentsMouseDoubleClickEvent(QMouseEvent* e)
3769 if (e->button() == Qt::LeftButton )
3771 QPoint p = inverseWorldMatrix().map(e->pos());
3772 LinkableMapObj *lmo=mapCenter->findMapObj(p, NULL);
3773 if (lmo) { // MapObj was found
3774 // First select the MapObj than edit heading
3775 if (selection) selection->unselect();
3777 selection->select();
3778 mainWindow->editHeading();
3783 void MapEditor::resizeEvent (QResizeEvent* e)
3785 Q3CanvasView::resizeEvent( e );
3789 void MapEditor::contentsDragEnterEvent(QDragEnterEvent *event)
3792 // for (unsigned int i=0;event->format(i);i++) // Debug mime type
3793 // cerr << event->format(i) << endl;
3796 (typeid(*selection) == typeid(BranchObj)) ||
3797 (typeid(*selection) == typeid(MapCenterObj))) {
3799 // If QImageDrag can decode mime type
3800 if (Q3ImageDrag::canDecode(event)) {
3805 // If image are dragged from firefox
3806 if (event->provides("application/x-moz-file-promise-url") &&
3807 event->provides("application/x-moz-nativeimage")) {
3808 event->accept(true);
3812 // If QUriDrag can decode mime type
3813 if (Q3UriDrag::canDecode(event)) {
3818 // If Uri are dragged from firefox
3819 if (event->provides("_NETSCAPE_URL")){
3824 // If QTextDrag can decode mime type
3825 if (Q3TextDrag::canDecode(event)) {
3834 bool isUnicode16(const QByteArray &d)
3836 // TODO: make more precise check for unicode 16.
3837 // Guess unicode16 if any of second bytes are zero
3838 unsigned int length = max(0,d.size()-2)/2;
3839 for (unsigned int i = 0; i<length ; i++)
3840 if (d.at(i*2+1)==0) return true;
3844 void MapEditor::contentsDropEvent(QDropEvent *event)
3847 (typeid(*selection) == typeid(BranchObj)) ||
3848 (typeid(*selection) == typeid(MapCenterObj)))
3853 if (event->provides("image/png"))
3856 if (Q3ImageDrag::decode(event, pix))
3864 } else if (event->provides("application/x-moz-file-promise-url") &&
3865 event->provides("application/x-moz-nativeimage"))
3867 // Contains url to the img src in unicode16
3868 QByteArray d = event->encodedData("application/x-moz-file-promise-url");
3869 QString url = QString((const QChar*)d.data(),d.size()/2);
3873 } else if (event->provides ("text/uri-list"))
3874 { // Uris provided e.g. by konqueror
3875 Q3UriDrag::decode (event,uris);
3876 } else if (event->provides ("_NETSCAPE_URL"))
3877 { // Uris provided by Mozilla
3878 QStringList l = QStringList::split("\n", event->encodedData("_NETSCAPE_URL"));
3881 } else if (event->provides("text/html")) {
3883 // Handels text mime types
3884 // Look like firefox allways handle text as unicode16 (2 bytes per char.)
3885 QByteArray d = event->encodedData("text/html");
3888 text = QString((const QChar*)d.data(),d.size()/2);
3892 textEditor->setText(text);
3896 } else if (event->provides("text/plain")) {
3897 QByteArray d = event->encodedData("text/plain");
3900 text = QString((const QChar*)d.data(),d.size()/2);
3904 textEditor->setText(text);
3916 for (const char* u=uris.first(); u; u=uris.next())
3918 bo=((BranchObj*)selection)->addBranch();
3921 s=Q3UriDrag::uriToLocalFile(u);
3924 QString file = QDir::convertSeparators(s);
3925 heading = QFileInfo(file).baseName();
3927 if (file.endsWith(".vym", false))
3928 bo->setVymLink(file);
3937 if (!heading.isEmpty())
3938 bo->setHeading(heading);
3948 //FIXME saveState has to be called earlier for each of the drops...
3949 saveStateComplete("Drop Event"); //TODO undo Command
3950 mapCenter->reposition();
3957 void MapEditor::addFloatImage(const QPixmap &img)
3960 (typeid(*selection) == typeid(BranchObj)) ||
3961 (typeid(*selection) == typeid(MapCenterObj)) )
3963 BranchObj *bo=((BranchObj*)selection);
3964 saveStatePart(selection,QString("Add floatimage to %1").arg(getName(bo)));
3965 //QString fn=fd->selectedFile();
3966 //lastImageDir=fn.left(fn.findRev ("/"));
3967 bo->addFloatImage();
3968 // FIXME check if load was successful
3969 bo->getLastFloatImage()->load(img);
3970 //bo->getLastFloatImage()->setOriginalFilename(fn);
3971 mapCenter->reposition();
3978 void MapEditor::imageDataFetched(const QByteArray &a, Q3NetworkOperation */*nop*/)
3980 if (!imageBuffer) imageBuffer = new QBuffer();
3981 if (!imageBuffer->isOpen()) {
3982 imageBuffer->open(QIODevice::WriteOnly | QIODevice::Append);
3984 imageBuffer->at(imageBuffer->at()+imageBuffer->writeBlock(a));
3988 void MapEditor::imageDataFinished(Q3NetworkOperation *nop)
3990 if (nop->state()==Q3NetworkProtocol::StDone) {
3991 QPixmap img(imageBuffer->buffer());
3996 imageBuffer->close();
3998 imageBuffer->close();
4005 void MapEditor::fetchImage(const QString &url)
4008 urlOperator->stop();
4009 disconnect(urlOperator);
4013 urlOperator = new Q3UrlOperator(url);
4014 connect(urlOperator, SIGNAL(finished(Q3NetworkOperation *)),
4015 this, SLOT(imageDataFinished(Q3NetworkOperation*)));
4017 connect(urlOperator, SIGNAL(data(const QByteArray &, Q3NetworkOperation *)),
4018 this, SLOT(imageDataFetched(const QByteArray &, Q3NetworkOperation *)));