1 #include <QApplication>
6 #include "editxlinkdialog.h"
8 #include "exportxhtmldialog.h"
10 #include "geometry.h" // for addBBox
11 #include "mainwindow.h"
12 #include "mapcenterobj.h"
15 #include "selection.h"
18 #include "warningdialog.h"
19 #include "xml-freemind.h"
25 extern Main *mainWindow;
26 extern Settings settings;
27 extern QString tmpVymDir;
29 extern TextEditor *textEditor;
32 extern QString clipboardDir;
33 extern QString clipboardFile;
34 extern bool clipboardEmpty;
36 extern ImageIO imageIO;
38 extern QString vymName;
39 extern QString vymVersion;
40 extern QDir vymBaseDir;
42 extern QDir lastImageDir;
43 extern QDir lastFileDir;
45 extern FlagRowObj *standardFlagsDefault;
47 extern Settings settings;
51 int VymModel::mapNum=0; // make instance
55 // cout << "Const VymModel\n";
62 // cout << "Destr VymModel\n";
63 autosaveTimer->stop();
64 fileChangedTimer->stop();
68 void VymModel::clear()
70 cout << "VymModel::clear rows="<<rowCount(index(rootItem))<<endl;
74 while (!mapCenters.isEmpty()) // FIXME VM needs to be in treemodel only...
75 delete mapCenters.takeFirst();
77 QModelIndex ri=index(rootItem);
78 removeRows (0, rowCount(ri),ri);
81 void VymModel::init ()
83 // We should have at least one map center to start with
84 // addMapCenter(); FIXME VM create this in MapEditor as long as model is part of that
99 stepsTotal=settings.readNumEntry("/history/stepsTotal",100);
100 undoSet.setEntry ("/history/stepsTotal",QString::number(stepsTotal));
101 mainWindow->updateHistory (undoSet);
104 makeTmpDirectories();
109 fileName=tr("unnamed");
111 blockReposition=false;
112 blockSaveState=false;
114 autosaveTimer=new QTimer (this);
115 connect(autosaveTimer, SIGNAL(timeout()), this, SLOT(autosave()));
117 fileChangedTimer=new QTimer (this);
118 fileChangedTimer->start(3000);
119 connect(fileChangedTimer, SIGNAL(timeout()), this, SLOT(fileChanged()));
123 selection.setModel (this);
124 selection.unselect();
131 animationUse=settings.readBoolEntry("/animation/use",false);
132 animationTicks=settings.readNumEntry("/animation/ticks",10);
133 animationInterval=settings.readNumEntry("/animation/interval",50);
135 animationTimer=new QTimer (this);
136 connect(animationTimer, SIGNAL(timeout()), this, SLOT(animate()));
139 defLinkColor=QColor (0,0,255);
140 defXLinkColor=QColor (180,180,180);
141 linkcolorhint=LinkableMapObj::DefaultColor;
142 linkstyle=LinkableMapObj::PolyParabel;
144 defXLinkColor=QColor (230,230,230);
154 // addMapCenter(); FIXME VM create this in MapEditor until BO and MCO are independent of scene
158 void VymModel::makeTmpDirectories()
160 // Create unique temporary directories
161 tmpMapDir = tmpVymDir+QString("/model-%1").arg(mapNum);
162 histPath = tmpMapDir+"/history";
168 MapEditor* VymModel::getMapEditor() // FIXME VM better return favourite editor here
173 bool VymModel::isRepositionBlocked()
175 return blockReposition;
178 void VymModel::updateActions() // FIXME maybe don't update if blockReposition is set
180 // Tell mainwindow to update states of actions
181 mainWindow->updateActions();
186 QString VymModel::saveToDir(const QString &tmpdir, const QString &prefix, bool writeflags, const QPointF &offset, LinkableMapObj *saveSel)
188 // tmpdir temporary directory to which data will be written
189 // prefix mapname, which will be appended to images etc.
190 // writeflags Only write flags for "real" save of map, not undo
191 // offset offset of bbox of whole map in scene.
192 // Needed for XML export
201 case LinkableMapObj::Line:
204 case LinkableMapObj::Parabel:
207 case LinkableMapObj::PolyLine:
211 ls="StylePolyParabel";
215 QString s="<?xml version=\"1.0\" encoding=\"utf-8\"?><!DOCTYPE vymmap>\n";
217 if (linkcolorhint==LinkableMapObj::HeadingColor)
218 colhint=xml.attribut("linkColorHint","HeadingColor");
220 QString mapAttr=xml.attribut("version",vymVersion);
222 mapAttr+= xml.attribut("author",author) +
223 xml.attribut("comment",comment) +
224 xml.attribut("date",getDate()) +
225 xml.attribut("backgroundColor", mapScene->backgroundBrush().color().name() ) +
226 xml.attribut("selectionColor", selection.getColor().name() ) +
227 xml.attribut("linkStyle", ls ) +
228 xml.attribut("linkColor", defLinkColor.name() ) +
229 xml.attribut("defXLinkColor", defXLinkColor.name() ) +
230 xml.attribut("defXLinkWidth", QString().setNum(defXLinkWidth,10) ) +
232 s+=xml.beginElement("vymmap",mapAttr);
235 // Find the used flags while traversing the tree
236 standardFlagsDefault->resetUsedCounter();
238 // Reset the counters before saving
239 // TODO constr. of FIO creates lots of objects, better do this in some other way...
240 FloatImageObj (mapScene).resetSaveCounter();
242 // Build xml recursivly
243 if (!saveSel || typeid (*saveSel) == typeid (MapCenterObj))
244 // Save complete map, if saveSel not set
245 s+=saveToDir(tmpdir,prefix,writeflags,offset);
248 if ( typeid(*saveSel) == typeid(BranchObj) )
250 s+=((BranchObj*)(saveSel))->saveToDir(tmpdir,prefix,offset);
251 else if ( typeid(*saveSel) == typeid(FloatImageObj) )
253 s+=((FloatImageObj*)(saveSel))->saveToDir(tmpdir,prefix);
256 // Save local settings
257 s+=settings.getDataXML (destPath);
260 if (!selection.isEmpty() && !saveSel )
261 s+=xml.valueElement("select",selection.getSelectString());
264 s+=xml.endElement("vymmap");
267 standardFlagsDefault->saveToDir (tmpdir+"/flags/","",writeflags);
271 void VymModel::setFilePath(QString fpath, QString destname)
273 if (fpath.isEmpty() || fpath=="")
280 filePath=fpath; // becomes absolute path
281 fileName=fpath; // gets stripped of path
282 destPath=destname; // needed for vymlinks and during load to reset fileChangedTime
284 // If fpath is not an absolute path, complete it
285 filePath=QDir(fpath).absPath();
286 fileDir=filePath.left (1+filePath.findRev ("/"));
288 // Set short name, too. Search from behind:
289 int i=fileName.findRev("/");
290 if (i>=0) fileName=fileName.remove (0,i+1);
292 // Forget the .vym (or .xml) for name of map
293 mapName=fileName.left(fileName.findRev(".",-1,true) );
297 void VymModel::setFilePath(QString fpath)
299 setFilePath (fpath,fpath);
302 QString VymModel::getFilePath()
307 QString VymModel::getFileName()
312 QString VymModel::getMapName()
317 QString VymModel::getDestPath()
322 ErrorCode VymModel::load (QString fname, const LoadMode &lmode, const FileType &ftype)
324 ErrorCode err=success;
326 parseBaseHandler *handler;
330 case VymMap: handler=new parseVYMHandler; break;
331 case FreemindMap : handler=new parseFreemindHandler; break;
333 QMessageBox::critical( 0, tr( "Critical Parse Error" ),
334 "Unknown FileType in VymModel::load()");
340 // FIXME VM not needed??? model->setMapEditor(this);
341 // (map state is set later at end of load...)
344 BranchObj *bo=selection.getBranch();
345 if (!bo) return aborted;
346 if (lmode==ImportAdd)
347 saveStateChangingPart(
350 QString("addMapInsert (%1)").arg(fname),
351 QString("Add map %1 to %2").arg(fname).arg(getObjectName(bo)));
353 saveStateChangingPart(
356 QString("addMapReplace(%1)").arg(fname),
357 QString("Add map %1 to %2").arg(fname).arg(getObjectName(bo)));
361 // Create temporary directory for packing
363 QString tmpZipDir=makeTmpDir (ok,"vym-pack");
366 QMessageBox::critical( 0, tr( "Critical Load Error" ),
367 tr("Couldn't create temporary directory before load\n"));
372 err=unzipDir (tmpZipDir,fname);
382 // Look for mapname.xml
383 xmlfile= fname.left(fname.findRev(".",-1,true));
384 xmlfile=xmlfile.section( '/', -1 );
385 QFile mfile( tmpZipDir + "/" + xmlfile + ".xml");
386 if (!mfile.exists() )
388 // mapname.xml does not exist, well,
389 // maybe someone renamed the mapname.vym file...
390 // Try to find any .xml in the toplevel
391 // directory of the .vym file
392 QStringList flist=QDir (tmpZipDir).entryList("*.xml");
393 if (flist.count()==1)
395 // Only one entry, take this one
396 xmlfile=tmpZipDir + "/"+flist.first();
399 for ( QStringList::Iterator it = flist.begin(); it != flist.end(); ++it )
400 *it=tmpZipDir + "/" + *it;
401 // TODO Multiple entries, load all (but only the first one into this ME)
402 //mainWindow->fileLoadFromTmp (flist);
403 //returnCode=1; // Silently forget this attempt to load
404 qWarning ("MainWindow::load (fn) multimap found...");
407 if (flist.isEmpty() )
409 QMessageBox::critical( 0, tr( "Critical Load Error" ),
410 tr("Couldn't find a map (*.xml) in .vym archive.\n"));
413 } //file doesn't exist
415 xmlfile=mfile.name();
418 QFile file( xmlfile);
420 // I am paranoid: file should exist anyway
421 // according to check in mainwindow.
424 QMessageBox::critical( 0, tr( "Critical Parse Error" ),
425 tr(QString("Couldn't open map %1").arg(file.name())));
429 bool blockSaveStateOrg=blockSaveState;
430 blockReposition=true;
432 QXmlInputSource source( file);
433 QXmlSimpleReader reader;
434 reader.setContentHandler( handler );
435 reader.setErrorHandler( handler );
436 handler->setModel ( this);
439 // We need to set the tmpDir in order to load files with rel. path
444 tmpdir=fname.left(fname.findRev("/",-1));
445 handler->setTmpDir (tmpdir);
446 handler->setInputFile (file.name());
447 handler->setLoadMode (lmode);
448 bool ok = reader.parse( source );
449 blockReposition=false;
450 blockSaveState=blockSaveStateOrg;
454 reposition(); // FIXME VM reposition the view instead...
461 autosaveTimer->stop();
464 // Reset timestamp to check for later updates of file
465 fileChangedTime=QFileInfo (destPath).lastModified();
468 QMessageBox::critical( 0, tr( "Critical Parse Error" ),
469 tr( handler->errorProtocol() ) );
471 // Still return "success": the map maybe at least
472 // partially read by the parser
477 removeDir (QDir(tmpZipDir));
483 ErrorCode VymModel::save (const SaveMode &savemode)
487 QString safeFilePath;
489 ErrorCode err=success;
493 mapFileName=mapName+".xml";
495 // use name given by user, even if he chooses .doc
496 mapFileName=fileName;
498 // Look, if we should zip the data:
501 QMessageBox mb( vymName,
502 tr("The map %1\ndid not use the compressed "
503 "vym file format.\nWriting it uncompressed will also write images \n"
504 "and flags and thus may overwrite files in the "
505 "given directory\n\nDo you want to write the map").arg(filePath),
506 QMessageBox::Warning,
507 QMessageBox::Yes | QMessageBox::Default,
509 QMessageBox::Cancel | QMessageBox::Escape);
510 mb.setButtonText( QMessageBox::Yes, tr("compressed (vym default)") );
511 mb.setButtonText( QMessageBox::No, tr("uncompressed") );
512 mb.setButtonText( QMessageBox::Cancel, tr("Cancel"));
515 case QMessageBox::Yes:
516 // save compressed (default file format)
519 case QMessageBox::No:
523 case QMessageBox::Cancel:
530 // First backup existing file, we
531 // don't want to add to old zip archives
535 if ( settings.value ("/mapeditor/writeBackupFile").toBool())
537 QString backupFileName(destPath + "~");
538 QFile backupFile(backupFileName);
539 if (backupFile.exists() && !backupFile.remove())
541 QMessageBox::warning(0, tr("Save Error"),
542 tr("%1\ncould not be removed before saving").arg(backupFileName));
544 else if (!f.rename(backupFileName))
546 QMessageBox::warning(0, tr("Save Error"),
547 tr("%1\ncould not be renamed before saving").arg(destPath));
554 // Create temporary directory for packing
556 tmpZipDir=makeTmpDir (ok,"vym-zip");
559 QMessageBox::critical( 0, tr( "Critical Load Error" ),
560 tr("Couldn't create temporary directory before save\n"));
564 safeFilePath=filePath;
565 setFilePath (tmpZipDir+"/"+ mapName+ ".xml", safeFilePath);
568 // Create mapName and fileDir
569 makeSubDirs (fileDir);
572 if (savemode==CompleteMap || selection.isEmpty())
575 saveFile=saveToDir (fileDir,mapName+"-",true,QPointF(),NULL);
578 autosaveTimer->stop();
583 if (selection.type()==Selection::FloatImage)
586 saveFile=saveToDir (fileDir,mapName+"-",true,QPointF(),selection.getBranch());
587 // TODO take care of multiselections
590 if (!saveStringToDisk(fileDir+mapFileName,saveFile))
593 qWarning ("ME::saveStringToDisk failed!");
599 if (err==success) err=zipDir (tmpZipDir,destPath);
602 removeDir (QDir(tmpZipDir));
604 // Restore original filepath outside of tmp zip dir
605 setFilePath (safeFilePath);
609 fileChangedTime=QFileInfo (destPath).lastModified();
613 void VymModel::addMapReplaceInt(const QString &undoSel, const QString &path)
615 QString pathDir=path.left(path.findRev("/"));
621 // We need to parse saved XML data
622 parseVYMHandler handler;
623 QXmlInputSource source( file);
624 QXmlSimpleReader reader;
625 reader.setContentHandler( &handler );
626 reader.setErrorHandler( &handler );
627 handler.setModel ( this);
628 handler.setTmpDir ( pathDir ); // needed to load files with rel. path
629 if (undoSel.isEmpty())
633 handler.setLoadMode (NewMap);
637 handler.setLoadMode (ImportReplace);
639 blockReposition=true;
640 bool ok = reader.parse( source );
641 blockReposition=false;
644 // This should never ever happen
645 QMessageBox::critical( 0, tr( "Critical Parse Error while reading %1").arg(path),
646 handler.errorProtocol());
649 QMessageBox::critical( 0, tr( "Critical Error" ), tr("Could not read %1").arg(path));
652 void VymModel::addMapInsertInt (const QString &path, int pos)
654 BranchObj *sel=selection.getBranch();
657 QString pathDir=path.left(path.findRev("/"));
663 // We need to parse saved XML data
664 parseVYMHandler handler;
665 QXmlInputSource source( file);
666 QXmlSimpleReader reader;
667 reader.setContentHandler( &handler );
668 reader.setErrorHandler( &handler );
669 handler.setModel (this);
670 handler.setTmpDir ( pathDir ); // needed to load files with rel. path
671 handler.setLoadMode (ImportAdd);
672 blockReposition=true;
673 bool ok = reader.parse( source );
674 blockReposition=false;
677 // This should never ever happen
678 QMessageBox::critical( 0, tr( "Critical Parse Error while reading %1").arg(path),
679 handler.errorProtocol());
681 if (sel->getDepth()>0)
682 sel->getLastBranch()->linkTo (sel,pos);
684 QMessageBox::critical( 0, tr( "Critical Error" ), tr("Could not read %1").arg(path));
688 FloatImageObj* VymModel::loadFloatImageInt (QString fn)
690 BranchObj *bo=selection.getBranch();
695 fio=bo->getLastFloatImage();
698 // FIXME VM needed? scene()->update();
704 void VymModel::loadFloatImage ()
706 BranchObj *bo=selection.getBranch();
710 Q3FileDialog *fd=new Q3FileDialog( NULL);
711 fd->setMode (Q3FileDialog::ExistingFiles);
712 fd->addFilter (QString (tr("Images") + " (*.png *.bmp *.xbm *.jpg *.png *.xpm *.gif *.pnm)"));
713 ImagePreview *p =new ImagePreview (fd);
714 fd->setContentsPreviewEnabled( TRUE );
715 fd->setContentsPreview( p, p );
716 fd->setPreviewMode( Q3FileDialog::Contents );
717 fd->setCaption(vymName+" - " +tr("Load image"));
718 fd->setDir (lastImageDir);
721 if ( fd->exec() == QDialog::Accepted )
723 // TODO loadFIO in QT4 use: lastImageDir=fd->directory();
724 lastImageDir=QDir (fd->dirPath());
727 for (int j=0; j<fd->selectedFiles().count(); j++)
729 s=fd->selectedFiles().at(j);
730 fio=loadFloatImageInt (s);
733 (LinkableMapObj*)fio,
736 QString ("loadImage (%1)").arg(s ),
737 QString("Add image %1 to %2").arg(s).arg(getObjectName(bo))
740 // TODO loadFIO error handling
741 qWarning ("Failed to load "+s);
749 void VymModel::saveFloatImageInt (FloatImageObj *fio, const QString &type, const QString &fn)
754 void VymModel::saveFloatImage ()
756 FloatImageObj *fio=selection.getFloatImage();
759 QFileDialog *fd=new QFileDialog( NULL);
760 fd->setFilters (imageIO.getFilters());
761 fd->setCaption(vymName+" - " +tr("Save image"));
762 fd->setFileMode( QFileDialog::AnyFile );
763 fd->setDirectory (lastImageDir);
764 // fd->setSelection (fio->getOriginalFilename());
768 if ( fd->exec() == QDialog::Accepted && fd->selectedFiles().count()==1)
770 fn=fd->selectedFiles().at(0);
771 if (QFile (fn).exists() )
773 QMessageBox mb( vymName,
774 tr("The file %1 exists already.\n"
775 "Do you want to overwrite it?").arg(fn),
776 QMessageBox::Warning,
777 QMessageBox::Yes | QMessageBox::Default,
778 QMessageBox::Cancel | QMessageBox::Escape,
779 QMessageBox::NoButton );
781 mb.setButtonText( QMessageBox::Yes, tr("Overwrite") );
782 mb.setButtonText( QMessageBox::No, tr("Cancel"));
785 case QMessageBox::Yes:
788 case QMessageBox::Cancel:
795 saveFloatImageInt (fio,fd->selectedFilter(),fn );
802 void VymModel::importDirInt(BranchObj *dst, QDir d)
804 BranchObj *bo=selection.getBranch();
807 // Traverse directories
808 d.setFilter( QDir::Dirs| QDir::Hidden | QDir::NoSymLinks );
809 QFileInfoList list = d.entryInfoList();
812 for (int i = 0; i < list.size(); ++i)
815 if (fi.fileName() != "." && fi.fileName() != ".." )
818 bo=dst->getLastBranch();
819 bo->setHeading (fi.fileName() );
820 bo->setColor (QColor("blue"));
822 if ( !d.cd(fi.fileName()) )
823 QMessageBox::critical (0,tr("Critical Import Error"),tr("Cannot find the directory %1").arg(fi.fileName()));
826 // Recursively add subdirs
833 d.setFilter( QDir::Files| QDir::Hidden | QDir::NoSymLinks );
834 list = d.entryInfoList();
836 for (int i = 0; i < list.size(); ++i)
840 bo=dst->getLastBranch();
841 bo->setHeading (fi.fileName() );
842 bo->setColor (QColor("black"));
843 if (fi.fileName().right(4) == ".vym" )
844 bo->setVymLink (fi.filePath());
849 void VymModel::importDirInt (const QString &s)
851 BranchObj *bo=selection.getBranch();
854 saveStateChangingPart (bo,bo,QString ("importDir (\"%1\")").arg(s),QString("Import directory structure from %1").arg(s));
861 void VymModel::importDir()
863 BranchObj *bo=selection.getBranch();
867 filters <<"VYM map (*.vym)";
868 QFileDialog *fd=new QFileDialog( NULL,vymName+ " - " +tr("Choose directory structure to import"));
869 fd->setMode (QFileDialog::DirectoryOnly);
870 fd->setFilters (filters);
871 fd->setCaption(vymName+" - " +tr("Choose directory structure to import"));
875 if ( fd->exec() == QDialog::Accepted )
877 importDirInt (fd->selectedFile() );
879 //FIXME VM needed? scene()->update();
885 void VymModel::autosave()
887 QDateTime now=QDateTime().currentDateTime();
889 // Disable autosave, while we have gone back in history
890 int redosAvail=undoSet.readNumEntry (QString("/history/redosAvail"));
891 if (redosAvail>0) return;
893 // Also disable autosave for new map without filename
894 if (filePath.isEmpty()) return;
897 if (mapUnsaved &&mapChanged && settings.value ("/autosave/use",true).toBool() )
899 if (QFileInfo(filePath).lastModified()<=fileChangedTime)
900 mainWindow->fileSave (this);
903 cout <<" ME::autosave rejected, file on disk is newer than last save.\n";
908 void VymModel::fileChanged()
910 // Check if file on disk has changed meanwhile
911 if (!filePath.isEmpty())
913 QDateTime tmod=QFileInfo (filePath).lastModified();
914 if (tmod>fileChangedTime)
916 // FIXME VM switch to current mapeditor and finish lineedits...
917 QMessageBox mb( vymName,
918 tr("The file of the map on disk has changed:\n\n"
919 " %1\n\nDo you want to reload that map with the new file?").arg(filePath),
920 QMessageBox::Question,
922 QMessageBox::Cancel | QMessageBox::Default,
923 QMessageBox::NoButton );
925 mb.setButtonText( QMessageBox::Yes, tr("Reload"));
926 mb.setButtonText( QMessageBox::No, tr("Ignore"));
929 case QMessageBox::Yes:
931 load (filePath,NewMap,fileType);
932 case QMessageBox::Cancel:
933 fileChangedTime=tmod; // allow autosave to overwrite newer file!
939 bool VymModel::isDefault()
944 void VymModel::makeDefault()
950 bool VymModel::hasChanged()
955 void VymModel::setChanged()
958 autosaveTimer->start(settings.value("/autosave/ms/",300000).toInt());
966 QString VymModel::getObjectName (const LinkableMapObj *lmo)
969 if (!lmo) return QString("Error: NULL has no name!");
971 if ((typeid(*lmo) == typeid(BranchObj) ||
972 typeid(*lmo) == typeid(MapCenterObj)))
975 s=(((BranchObj*)lmo)->getHeading());
976 if (s=="") s="unnamed";
977 return QString("branch (%1)").arg(s);
979 if ((typeid(*lmo) == typeid(FloatImageObj) ))
980 return QString ("floatimage [%1]").arg(((FloatImageObj*)lmo)->getOriginalFilename());
981 return QString("Unknown type has no name!");
984 void VymModel::redo()
986 // Can we undo at all?
987 if (redosAvail<1) return;
989 bool blockSaveStateOrg=blockSaveState;
994 if (undosAvail<stepsTotal) undosAvail++;
996 if (curStep>stepsTotal) curStep=1;
997 QString undoCommand= undoSet.readEntry (QString("/history/step-%1/undoCommand").arg(curStep));
998 QString undoSelection=undoSet.readEntry (QString("/history/step-%1/undoSelection").arg(curStep));
999 QString redoCommand= undoSet.readEntry (QString("/history/step-%1/redoCommand").arg(curStep));
1000 QString redoSelection=undoSet.readEntry (QString("/history/step-%1/redoSelection").arg(curStep));
1001 QString comment=undoSet.readEntry (QString("/history/step-%1/comment").arg(curStep));
1002 QString version=undoSet.readEntry ("/history/version");
1004 /* TODO Maybe check for version, if we save the history
1005 if (!checkVersion(version))
1006 QMessageBox::warning(0,tr("Warning"),
1007 tr("Version %1 of saved undo/redo data\ndoes not match current vym version %2.").arg(version).arg(vymVersion));
1010 // Find out current undo directory
1011 QString bakMapDir(QString(tmpMapDir+"/undo-%1").arg(curStep));
1015 cout << "VymModel::redo() begin\n";
1016 cout << " undosAvail="<<undosAvail<<endl;
1017 cout << " redosAvail="<<redosAvail<<endl;
1018 cout << " curStep="<<curStep<<endl;
1019 cout << " ---------------------------"<<endl;
1020 cout << " comment="<<comment.toStdString()<<endl;
1021 cout << " undoCom="<<undoCommand.toStdString()<<endl;
1022 cout << " undoSel="<<undoSelection.toStdString()<<endl;
1023 cout << " redoCom="<<redoCommand.toStdString()<<endl;
1024 cout << " redoSel="<<redoSelection.toStdString()<<endl;
1025 cout << " ---------------------------"<<endl<<endl;
1028 // select object before redo
1029 if (!redoSelection.isEmpty())
1030 select (redoSelection);
1033 parseAtom (redoCommand);
1036 blockSaveState=blockSaveStateOrg;
1038 undoSet.setEntry ("/history/undosAvail",QString::number(undosAvail));
1039 undoSet.setEntry ("/history/redosAvail",QString::number(redosAvail));
1040 undoSet.setEntry ("/history/curStep",QString::number(curStep));
1041 undoSet.writeSettings(histPath);
1043 mainWindow->updateHistory (undoSet);
1046 /* TODO remove testing
1047 cout << "ME::redo() end\n";
1048 cout << " undosAvail="<<undosAvail<<endl;
1049 cout << " redosAvail="<<redosAvail<<endl;
1050 cout << " curStep="<<curStep<<endl;
1051 cout << " ---------------------------"<<endl<<endl;
1057 bool VymModel::isRedoAvailable()
1059 if (undoSet.readNumEntry("/history/redosAvail",0)>0)
1065 void VymModel::undo()
1067 // Can we undo at all?
1068 if (undosAvail<1) return;
1070 mainWindow->statusMessage (tr("Autosave disabled during undo."));
1072 bool blockSaveStateOrg=blockSaveState;
1073 blockSaveState=true;
1075 QString undoCommand= undoSet.readEntry (QString("/history/step-%1/undoCommand").arg(curStep));
1076 QString undoSelection=undoSet.readEntry (QString("/history/step-%1/undoSelection").arg(curStep));
1077 QString redoCommand= undoSet.readEntry (QString("/history/step-%1/redoCommand").arg(curStep));
1078 QString redoSelection=undoSet.readEntry (QString("/history/step-%1/redoSelection").arg(curStep));
1079 QString comment=undoSet.readEntry (QString("/history/step-%1/comment").arg(curStep));
1080 QString version=undoSet.readEntry ("/history/version");
1082 /* TODO Maybe check for version, if we save the history
1083 if (!checkVersion(version))
1084 QMessageBox::warning(0,tr("Warning"),
1085 tr("Version %1 of saved undo/redo data\ndoes not match current vym version %2.").arg(version).arg(vymVersion));
1088 // Find out current undo directory
1089 QString bakMapDir(QString(tmpMapDir+"/undo-%1").arg(curStep));
1091 // select object before undo
1092 if (!undoSelection.isEmpty())
1093 select (undoSelection);
1097 cout << "VymModel::undo() begin\n";
1098 cout << " undosAvail="<<undosAvail<<endl;
1099 cout << " redosAvail="<<redosAvail<<endl;
1100 cout << " curStep="<<curStep<<endl;
1101 cout << " ---------------------------"<<endl;
1102 cout << " comment="<<comment.toStdString()<<endl;
1103 cout << " undoCom="<<undoCommand.toStdString()<<endl;
1104 cout << " undoSel="<<undoSelection.toStdString()<<endl;
1105 cout << " redoCom="<<redoCommand.toStdString()<<endl;
1106 cout << " redoSel="<<redoSelection.toStdString()<<endl;
1107 cout << " ---------------------------"<<endl<<endl;
1109 parseAtom (undoCommand);
1114 if (curStep<1) curStep=stepsTotal;
1118 blockSaveState=blockSaveStateOrg;
1119 /* TODO remove testing
1120 cout << "VymModel::undo() end\n";
1121 cout << " undosAvail="<<undosAvail<<endl;
1122 cout << " redosAvail="<<redosAvail<<endl;
1123 cout << " curStep="<<curStep<<endl;
1124 cout << " ---------------------------"<<endl<<endl;
1127 undoSet.setEntry ("/history/undosAvail",QString::number(undosAvail));
1128 undoSet.setEntry ("/history/redosAvail",QString::number(redosAvail));
1129 undoSet.setEntry ("/history/curStep",QString::number(curStep));
1130 undoSet.writeSettings(histPath);
1132 mainWindow->updateHistory (undoSet);
1135 ensureSelectionVisible();
1138 bool VymModel::isUndoAvailable()
1140 if (undoSet.readNumEntry("/history/undosAvail",0)>0)
1146 void VymModel::gotoHistoryStep (int i)
1148 // Restore variables
1149 int undosAvail=undoSet.readNumEntry (QString("/history/undosAvail"));
1150 int redosAvail=undoSet.readNumEntry (QString("/history/redosAvail"));
1152 if (i<0) i=undosAvail+redosAvail;
1154 // Clicking above current step makes us undo things
1157 for (int j=0; j<undosAvail-i; j++) undo();
1160 // Clicking below current step makes us redo things
1162 for (int j=undosAvail; j<i; j++)
1164 if (debug) cout << "VymModel::gotoHistoryStep redo "<<j<<"/"<<undosAvail<<" i="<<i<<endl;
1168 // And ignore clicking the current row ;-)
1172 QString VymModel::getHistoryPath()
1174 QString histName(QString("history-%1").arg(curStep));
1175 return (tmpMapDir+"/"+histName);
1178 void VymModel::saveState(const SaveMode &savemode, const QString &undoSelection, const QString &undoCom, const QString &redoSelection, const QString &redoCom, const QString &comment, LinkableMapObj *saveSel)
1180 sendData(redoCom); //FIXME testing
1185 if (blockSaveState) return;
1187 if (debug) cout << "ME::saveState() for "<<qPrintable (mapName)<<endl;
1189 // Find out current undo directory
1190 if (undosAvail<stepsTotal) undosAvail++;
1192 if (curStep>stepsTotal) curStep=1;
1194 QString backupXML="";
1195 QString histDir=getHistoryPath();
1196 QString bakMapPath=histDir+"/map.xml";
1198 // Create histDir if not available
1201 makeSubDirs (histDir);
1203 // Save depending on how much needs to be saved
1205 backupXML=saveToDir (histDir,mapName+"-",false, QPointF (),saveSel);
1207 QString undoCommand="";
1208 if (savemode==UndoCommand)
1210 undoCommand=undoCom;
1212 else if (savemode==PartOfMap )
1214 undoCommand=undoCom;
1215 undoCommand.replace ("PATH",bakMapPath);
1218 if (!backupXML.isEmpty())
1219 // Write XML Data to disk
1220 saveStringToDisk (bakMapPath,backupXML);
1222 // We would have to save all actions in a tree, to keep track of
1223 // possible redos after a action. Possible, but we are too lazy: forget about redos.
1226 // Write the current state to disk
1227 undoSet.setEntry ("/history/undosAvail",QString::number(undosAvail));
1228 undoSet.setEntry ("/history/redosAvail",QString::number(redosAvail));
1229 undoSet.setEntry ("/history/curStep",QString::number(curStep));
1230 undoSet.setEntry (QString("/history/step-%1/undoCommand").arg(curStep),undoCommand);
1231 undoSet.setEntry (QString("/history/step-%1/undoSelection").arg(curStep),undoSelection);
1232 undoSet.setEntry (QString("/history/step-%1/redoCommand").arg(curStep),redoCom);
1233 undoSet.setEntry (QString("/history/step-%1/redoSelection").arg(curStep),redoSelection);
1234 undoSet.setEntry (QString("/history/step-%1/comment").arg(curStep),comment);
1235 undoSet.setEntry (QString("/history/version"),vymVersion);
1236 undoSet.writeSettings(histPath);
1240 // TODO remove after testing
1241 //cout << " into="<< histPath.toStdString()<<endl;
1242 cout << " stepsTotal="<<stepsTotal<<
1243 ", undosAvail="<<undosAvail<<
1244 ", redosAvail="<<redosAvail<<
1245 ", curStep="<<curStep<<endl;
1246 cout << " ---------------------------"<<endl;
1247 cout << " comment="<<comment.toStdString()<<endl;
1248 cout << " undoCom="<<undoCommand.toStdString()<<endl;
1249 cout << " undoSel="<<undoSelection.toStdString()<<endl;
1250 cout << " redoCom="<<redoCom.toStdString()<<endl;
1251 cout << " redoSel="<<redoSelection.toStdString()<<endl;
1252 if (saveSel) cout << " saveSel="<<qPrintable (getSelectString(saveSel))<<endl;
1253 cout << " ---------------------------"<<endl;
1256 mainWindow->updateHistory (undoSet);
1262 void VymModel::saveStateChangingPart(LinkableMapObj *undoSel, LinkableMapObj* redoSel, const QString &rc, const QString &comment)
1264 // save the selected part of the map, Undo will replace part of map
1265 QString undoSelection="";
1267 undoSelection=getSelectString(undoSel);
1269 qWarning ("VymModel::saveStateChangingPart no undoSel given!");
1270 QString redoSelection="";
1272 redoSelection=getSelectString(undoSel);
1274 qWarning ("VymModel::saveStateChangingPart no redoSel given!");
1277 saveState (PartOfMap,
1278 undoSelection, "addMapReplace (\"PATH\")",
1284 void VymModel::saveStateRemovingPart(LinkableMapObj *redoSel, const QString &comment)
1288 qWarning ("VymModel::saveStateRemovingPart no redoSel given!");
1291 QString undoSelection=getSelectString (redoSel->getParObj());
1292 QString redoSelection=getSelectString(redoSel);
1293 if (typeid(*redoSel) == typeid(BranchObj) )
1295 // save the selected branch of the map, Undo will insert part of map
1296 saveState (PartOfMap,
1297 undoSelection, QString("addMapInsert (\"PATH\",%1)").arg(((BranchObj*)redoSel)->getNum()),
1298 redoSelection, "delete ()",
1305 void VymModel::saveState(LinkableMapObj *undoSel, const QString &uc, LinkableMapObj *redoSel, const QString &rc, const QString &comment)
1307 // "Normal" savestate: save commands, selections and comment
1308 // so just save commands for undo and redo
1309 // and use current selection
1311 QString redoSelection="";
1312 if (redoSel) redoSelection=getSelectString(redoSel);
1313 QString undoSelection="";
1314 if (undoSel) undoSelection=getSelectString(undoSel);
1316 saveState (UndoCommand,
1323 void VymModel::saveState(const QString &undoSel, const QString &uc, const QString &redoSel, const QString &rc, const QString &comment)
1325 // "Normal" savestate: save commands, selections and comment
1326 // so just save commands for undo and redo
1327 // and use current selection
1328 saveState (UndoCommand,
1335 void VymModel::saveState(const QString &uc, const QString &rc, const QString &comment)
1337 // "Normal" savestate applied to model (no selection needed):
1338 // save commands and comment
1339 saveState (UndoCommand,
1347 QGraphicsScene* VymModel::getScene ()
1352 BranchObj* VymModel::first()
1354 if (mapCenters.count()>0)
1355 return mapCenters.first();
1360 BranchObj* VymModel::next(BranchObj *bo_start)
1363 BranchObj *bo=bo_start;
1366 // Try to find next branch in current MapCenter
1368 if (rbo) return rbo;
1370 // Try to find MapCenter of bo
1371 while (bo->getDepth()>0) bo=(BranchObj*)bo->getParObj();
1373 // Try to find next MapCenter
1374 int i=mapCenters.indexOf ((MapCenterObj*)bo);
1375 if (i+2 > mapCenters.count() || i<0) return NULL;
1376 if (mapCenters.at(i+1)!=bo_start)
1377 return mapCenters.at(i+1);
1382 LinkableMapObj* VymModel::findMapObj(QPointF p, LinkableMapObj *excludeLMO)
1384 LinkableMapObj *lmo;
1386 for (int i=0;i<mapCenters.count(); i++)
1388 lmo=mapCenters.at(i)->findMapObj (p,excludeLMO);
1389 if (lmo) return lmo;
1394 LinkableMapObj* VymModel::findObjBySelect(const QString &s)
1396 LinkableMapObj *lmo;
1402 part=s.section(",",0,0);
1404 num=part.right(part.length() - 3);
1405 if (typ=="mc" && num.toInt()>=0 && num.toInt() <mapCenters.count() )
1406 return mapCenters.at(num.toInt() );
1409 for (int i=0; i<mapCenters.count(); i++)
1411 lmo=mapCenters.at(i)->findObjBySelect(s);
1412 if (lmo) return lmo;
1417 LinkableMapObj* VymModel::findID (const QString &s)
1419 LinkableMapObj *lmo;
1420 for (int i=0; i<mapCenters.count(); i++)
1422 lmo=mapCenters.at(i)->findID (s);
1423 if (lmo) return lmo;
1428 QString VymModel::saveToDir (const QString &tmpdir,const QString &prefix, int verbose, const QPointF &offset)
1432 for (int i=0; i<mapCenters.count(); i++)
1433 s+=mapCenters.at(i)->saveToDir (tmpdir,prefix,verbose,offset);
1437 //////////////////////////////////////////////
1439 //////////////////////////////////////////////
1440 void VymModel::setVersion (const QString &s)
1445 void VymModel::setAuthor (const QString &s)
1448 QString ("setMapAuthor (\"%1\")").arg(author),
1449 QString ("setMapAuthor (\"%1\")").arg(s),
1450 QString ("Set author of map to \"%1\"").arg(s)
1456 QString VymModel::getAuthor()
1461 void VymModel::setComment (const QString &s)
1464 QString ("setMapComment (\"%1\")").arg(comment),
1465 QString ("setMapComment (\"%1\")").arg(s),
1466 QString ("Set comment of map")
1472 QString VymModel::getComment ()
1477 QString VymModel::getDate ()
1479 return QDate::currentDate().toString ("yyyy-MM-dd");
1482 void VymModel::setHeading(const QString &s)
1484 BranchObj *sel=selection.getBranch();
1489 "setHeading (\""+sel->getHeading()+"\")",
1491 "setHeading (\""+s+"\")",
1492 QString("Set heading of %1 to \"%2\"").arg(getObjectName(sel)).arg(s) );
1493 sel->setHeading(s );
1494 TreeItem *ti=selection.getBranchItem();
1498 //FIXME VM ix is wrong ModelIndex below, ix2 is (hopefully) correct:
1499 QModelIndex ix=index( ti->row(), ti->column(), index (0,0,QModelIndex()) );
1500 //FIXME VM testing only cout <<"VM::setHeading s="<<s.toStdString()<<" ti="<<ti<<" r,c=("<<ti->row()<<","<<ti->column()<<")"<<endl;
1501 QModelIndex ix2=index (ti);
1502 emit (dataChanged ( ix2,ix2));
1506 cout << "Warning: VM::setHeading ti==NULL\n";
1509 //cout <<" (r,c)=("<<ix2.row()<<","<<ix2.column()<<")"<<endl;
1513 ensureSelectionVisible();
1517 void VymModel::setHeadingInt(const QString &s)
1519 BranchObj *bo=selection.getBranch();
1525 ensureSelectionVisible();
1529 BranchObj* VymModel::findText (QString s, bool cs)
1531 QTextDocument::FindFlags flags=0;
1532 if (cs) flags=QTextDocument::FindCaseSensitively;
1535 { // Nothing found or new find process
1537 // nothing found, start again
1541 bool searching=true;
1542 bool foundNote=false;
1543 while (searching && !EOFind)
1547 // Searching in Note
1548 if (itFind->getNote().contains(s,cs))
1550 if (selection.single()!=itFind)
1552 selection.select(itFind);
1553 ensureSelectionVisible();
1555 if (textEditor->findText(s,flags))
1561 // Searching in Heading
1562 if (searching && itFind->getHeading().contains (s,cs) )
1564 selection.select(itFind);
1565 ensureSelectionVisible();
1571 itFind=next(itFind);
1572 if (!itFind) EOFind=true;
1574 //cout <<"still searching... "<<qPrintable( itFind->getHeading())<<endl;
1577 return selection.getBranch();
1582 void VymModel::findReset()
1583 { // Necessary if text to find changes during a find process
1590 void VymModel::setScene (QGraphicsScene *s)
1593 init(); // Here we have a mapScene set,
1594 // which is (still) needed to create MapCenters
1597 void VymModel::setURL(const QString &url)
1599 BranchObj *bo=selection.getBranch();
1602 QString oldurl=bo->getURL();
1606 QString ("setURL (\"%1\")").arg(oldurl),
1608 QString ("setURL (\"%1\")").arg(url),
1609 QString ("set URL of %1 to %2").arg(getObjectName(bo)).arg(url)
1614 ensureSelectionVisible();
1618 QString VymModel::getURL()
1620 BranchObj *bo=selection.getBranch();
1622 return bo->getURL();
1627 QStringList VymModel::getURLs()
1630 BranchObj *bo=selection.getBranch();
1636 if (!bo->getURL().isEmpty()) urls.append( bo->getURL());
1643 void VymModel::linkFloatImageTo(const QString &dstString)
1645 FloatImageObj *fio=selection.getFloatImage();
1648 BranchObj *dst=(BranchObj*)findObjBySelect(dstString);
1649 if (dst && (typeid(*dst)==typeid (BranchObj) ||
1650 typeid(*dst)==typeid (MapCenterObj)))
1652 LinkableMapObj *dstPar=dst->getParObj();
1653 QString parString=getSelectString(dstPar);
1654 QString fioPreSelectString=getSelectString(fio);
1655 QString fioPreParentSelectString=getSelectString (fio->getParObj());
1656 ((BranchObj*)dst)->addFloatImage (fio);
1657 selection.unselect();
1658 ((BranchObj*)(fio->getParObj()))->removeFloatImage (fio);
1659 fio=((BranchObj*)dst)->getLastFloatImage();
1662 selection.select(fio);
1664 getSelectString(fio),
1665 QString("linkTo (\"%1\")").arg(fioPreParentSelectString),
1667 QString ("linkTo (\"%1\")").arg(dstString),
1668 QString ("Link floatimage to %1").arg(getObjectName(dst)));
1674 void VymModel::setFrameType(const FrameObj::FrameType &t)
1676 BranchObj *bo=selection.getBranch();
1679 QString s=bo->getFrameTypeName();
1680 bo->setFrameType (t);
1681 saveState (bo, QString("setFrameType (\"%1\")").arg(s),
1682 bo, QString ("setFrameType (\"%1\")").arg(bo->getFrameTypeName()),QString ("set type of frame to %1").arg(s));
1688 void VymModel::setFrameType(const QString &s)
1690 BranchObj *bo=selection.getBranch();
1693 saveState (bo, QString("setFrameType (\"%1\")").arg(bo->getFrameTypeName()),
1694 bo, QString ("setFrameType (\"%1\")").arg(s),QString ("set type of frame to %1").arg(s));
1695 bo->setFrameType (s);
1701 void VymModel::setFramePenColor(const QColor &c)
1703 BranchObj *bo=selection.getBranch();
1706 saveState (bo, QString("setFramePenColor (\"%1\")").arg(bo->getFramePenColor().name() ),
1707 bo, QString ("setFramePenColor (\"%1\")").arg(c.name() ),QString ("set pen color of frame to %1").arg(c.name() ));
1708 bo->setFramePenColor (c);
1712 void VymModel::setFrameBrushColor(const QColor &c)
1714 BranchObj *bo=selection.getBranch();
1717 saveState (bo, QString("setFrameBrushColor (\"%1\")").arg(bo->getFrameBrushColor().name() ),
1718 bo, QString ("setFrameBrushColor (\"%1\")").arg(c.name() ),QString ("set brush color of frame to %1").arg(c.name() ));
1719 bo->setFrameBrushColor (c);
1723 void VymModel::setFramePadding (const int &i)
1725 BranchObj *bo=selection.getBranch();
1728 saveState (bo, QString("setFramePadding (\"%1\")").arg(bo->getFramePadding() ),
1729 bo, QString ("setFramePadding (\"%1\")").arg(i),QString ("set brush color of frame to %1").arg(i));
1730 bo->setFramePadding (i);
1736 void VymModel::setFrameBorderWidth(const int &i)
1738 BranchObj *bo=selection.getBranch();
1741 saveState (bo, QString("setFrameBorderWidth (\"%1\")").arg(bo->getFrameBorderWidth() ),
1742 bo, QString ("setFrameBorderWidth (\"%1\")").arg(i),QString ("set border width of frame to %1").arg(i));
1743 bo->setFrameBorderWidth (i);
1749 void VymModel::setIncludeImagesVer(bool b)
1751 BranchObj *bo=selection.getBranch();
1754 QString u= b ? "false" : "true";
1755 QString r=!b ? "false" : "true";
1759 QString("setIncludeImagesVertically (%1)").arg(u),
1761 QString("setIncludeImagesVertically (%1)").arg(r),
1762 QString("Include images vertically in %1").arg(getObjectName(bo))
1764 bo->setIncludeImagesVer(b);
1769 void VymModel::setIncludeImagesHor(bool b)
1771 BranchObj *bo=selection.getBranch();
1774 QString u= b ? "false" : "true";
1775 QString r=!b ? "false" : "true";
1779 QString("setIncludeImagesHorizontally (%1)").arg(u),
1781 QString("setIncludeImagesHorizontally (%1)").arg(r),
1782 QString("Include images horizontally in %1").arg(getObjectName(bo))
1784 bo->setIncludeImagesHor(b);
1789 void VymModel::setHideLinkUnselected (bool b)
1791 LinkableMapObj *sel=selection.single();
1793 (selection.type() == Selection::Branch ||
1794 selection.type() == Selection::MapCenter ||
1795 selection.type() == Selection::FloatImage ))
1797 QString u= b ? "false" : "true";
1798 QString r=!b ? "false" : "true";
1802 QString("setHideLinkUnselected (%1)").arg(u),
1804 QString("setHideLinkUnselected (%1)").arg(r),
1805 QString("Hide link of %1 if unselected").arg(getObjectName(sel))
1807 sel->setHideLinkUnselected(b);
1811 void VymModel::setHideExport(bool b)
1813 BranchObj *bo=selection.getBranch();
1816 bo->setHideInExport (b);
1817 QString u= b ? "false" : "true";
1818 QString r=!b ? "false" : "true";
1822 QString ("setHideExport (%1)").arg(u),
1824 QString ("setHideExport (%1)").arg(r),
1825 QString ("Set HideExport flag of %1 to %2").arg(getObjectName(bo)).arg (r)
1830 // FIXME VM needed? scene()->update();
1834 void VymModel::toggleHideExport()
1836 BranchObj *bo=selection.getBranch();
1838 setHideExport ( !bo->hideInExport() );
1842 void VymModel::copy()
1844 LinkableMapObj *sel=selection.single();
1847 if (redosAvail == 0)
1850 QString s=getSelectString(sel);
1851 saveState (PartOfMap, s, "nop ()", s, "copy ()","Copy selection to clipboard",sel );
1852 curClipboard=curStep;
1855 // Copy also to global clipboard, because we are at last step in history
1856 QString bakMapName(QString("history-%1").arg(curStep));
1857 QString bakMapDir(tmpMapDir +"/"+bakMapName);
1858 copyDir (bakMapDir,clipboardDir );
1860 clipboardEmpty=false;
1866 void VymModel::pasteNoSave(const int &n)
1868 bool old=blockSaveState;
1869 blockSaveState=true;
1870 bool zippedOrg=zipped;
1871 if (redosAvail > 0 || n!=0)
1873 // Use the "historical" buffer
1874 QString bakMapName(QString("history-%1").arg(n));
1875 QString bakMapDir(tmpMapDir +"/"+bakMapName);
1876 load (bakMapDir+"/"+clipboardFile,ImportAdd, VymMap);
1878 // Use the global buffer
1879 load (clipboardDir+"/"+clipboardFile,ImportAdd, VymMap);
1884 void VymModel::paste()
1886 BranchObj *sel=selection.getBranch();
1889 saveStateChangingPart(
1892 QString ("paste (%1)").arg(curClipboard),
1893 QString("Paste to %1").arg( getObjectName(sel))
1900 void VymModel::cut()
1902 LinkableMapObj *sel=selection.single();
1903 if ( sel && (selection.type() == Selection::Branch ||
1904 selection.type()==Selection::MapCenter ||
1905 selection.type()==Selection::FloatImage))
1907 /* No savestate! savestate is called in cutNoSave
1908 saveStateChangingPart(
1912 QString("Cut %1").arg(getObjectName(sel ))
1921 void VymModel::moveBranchUp()
1923 BranchObj* bo=selection.getBranch();
1927 if (!bo->canMoveBranchUp()) return;
1928 par=(BranchObj*)(bo->getParObj());
1929 BranchObj *obo=par->moveBranchUp (bo); // bo will be the one below selection
1930 saveState (getSelectString(bo),"moveBranchDown ()",getSelectString(obo),"moveBranchUp ()",QString("Move up %1").arg(getObjectName(bo)));
1932 //FIXME VM needed? scene()->update();
1934 ensureSelectionVisible();
1938 void VymModel::moveBranchDown()
1940 BranchObj* bo=selection.getBranch();
1944 if (!bo->canMoveBranchDown()) return;
1945 par=(BranchObj*)(bo->getParObj());
1946 BranchObj *obo=par->moveBranchDown(bo); // bo will be the one above selection
1947 saveState(getSelectString(bo),"moveBranchUp ()",getSelectString(obo),"moveBranchDown ()",QString("Move down %1").arg(getObjectName(bo)));
1949 //FIXME VM needed? scene()->update();
1951 ensureSelectionVisible();
1955 void VymModel::sortChildren()
1957 BranchObj* bo=selection.getBranch();
1960 if(bo->countBranches()>1)
1962 saveStateChangingPart(bo,bo, "sortChildren ()",QString("Sort children of %1").arg(getObjectName(bo)));
1965 ensureSelectionVisible();
1970 void VymModel::createMapCenter()
1972 MapCenterObj *mco=addMapCenter (QPointF (0,0) );
1973 selection.select (mco);
1976 void VymModel::createBranch()
1978 BranchObj *bo=selection.getBranch();
1981 BranchObj *newbo=addNewBranchInt (-2); // FIXME VM Old model, merge with below
1984 QList<QVariant> cData;
1985 cData << "VM:createBranch" << "undef"<<"undef";
1986 TreeItem *parti=bo->getTreeItem();
1987 TreeItem *ti=new TreeItem (cData,parti);
1989 ti->setType (TreeItem::Branch);
1990 parti->appendChild (ti);
1994 newbo->setTreeItem (ti);
1995 selection.select (newbo); // FIXME VM really needed here?
2000 MapCenterObj* VymModel::addMapCenter ()
2002 MapCenterObj *mco=addMapCenter (contextPos);
2003 selection.select (mco);
2005 ensureSelectionVisible();
2010 QString ("addMapCenter (%1,%2)").arg (contextPos.x()).arg(contextPos.y()),
2011 QString ("Adding MapCenter to (%1,%2)").arg (contextPos.x()).arg(contextPos.y())
2016 MapCenterObj* VymModel::addMapCenter(QPointF absPos)
2018 MapCenterObj *mapCenter = new MapCenterObj(mapScene,this);
2019 mapCenter->setMapEditor(mapEditor); //FIXME VM needed to get defLinkStyle, mapLinkColorHint ... for later added objects
2020 mapCenter->move (absPos);
2021 mapCenter->setVisibility (true);
2022 mapCenter->setHeading (QApplication::translate("Heading of mapcenter in new map", "New map"));
2023 mapCenters.append(mapCenter);
2026 QList<QVariant> cData;
2027 cData << "VM:addMapCenter" << "undef"<<"undef";
2028 TreeItem *ti=new TreeItem (cData,rootItem);
2029 ti->setLMO (mapCenter);
2030 ti->setType (TreeItem::MapCenter);
2031 mapCenter->setTreeItem (ti);
2032 rootItem->appendChild (ti);
2037 MapCenterObj* VymModel::removeMapCenter(MapCenterObj* mco)
2039 int i=mapCenters.indexOf (mco);
2042 mapCenters.removeAt (i);
2044 if (i>0) return mapCenters.at(i-1); // Return previous MCO
2049 MapCenterObj* VymModel::getLastMapCenter()
2051 if (mapCenters.size()>0)
2052 return mapCenters.last();
2059 BranchObj* VymModel::addNewBranchInt(int num)
2061 // Depending on pos:
2062 // -3 insert in children of parent above selection
2063 // -2 add branch to selection
2064 // -1 insert in children of parent below selection
2065 // 0..n insert in children of parent at pos
2066 BranchObj *newbo=NULL;
2067 BranchObj *bo=selection.getBranch();
2072 // save scroll state. If scrolled, automatically select
2073 // new branch in order to tmp unscroll parent...
2074 newbo=bo->addBranch();
2079 bo=(BranchObj*)bo->getParObj();
2080 if (bo) newbo=bo->insertBranch(num);
2084 bo=(BranchObj*)bo->getParObj();
2085 if (bo) newbo=bo->insertBranch(num);
2087 if (!newbo) return NULL;
2092 BranchObj* VymModel::addNewBranch(int pos)
2094 // Different meaning than num in addNewBranchInt!
2098 BranchObj *bo = selection.getBranch();
2099 BranchObj *newbo=NULL;
2103 // FIXME VM do we still need this in model? setCursor (Qt::ArrowCursor);
2105 newbo=addNewBranchInt (pos-2);
2113 QString ("addBranch (%1)").arg(pos),
2114 QString ("Add new branch to %1").arg(getObjectName(bo)));
2118 latestSelectionString=getSelectString(newbo);
2119 // In Network mode, the client needs to know where the new branch is,
2120 // so we have to pass on this information via saveState.
2121 // TODO: Get rid of this positioning workaround
2122 QString ps=qpointfToString (newbo->getAbsPos());
2123 sendData ("selectLatestAdded ()");
2124 sendData (QString("move %1").arg(ps));
2132 BranchObj* VymModel::addNewBranchBefore()
2134 BranchObj *newbo=NULL;
2135 BranchObj *bo = selection.getBranch();
2136 if (bo && selection.type()==Selection::Branch)
2137 // We accept no MapCenterObj here, so we _have_ a parent
2139 QPointF p=bo->getRelPos();
2142 BranchObj *parbo=(BranchObj*)(bo->getParObj());
2144 // add below selection
2145 newbo=parbo->insertBranch(bo->getNum()+1);
2148 newbo->move2RelPos (p);
2150 // Move selection to new branch
2151 bo->linkTo (newbo,-1);
2153 saveState (newbo, "deleteKeepChildren ()", newbo, "addBranchBefore ()",
2154 QString ("Add branch before %1").arg(getObjectName(bo)));
2160 latestSelectionString=selection.getSelectString();
2164 void VymModel::deleteSelection()
2166 BranchObj *bo = selection.getBranch();
2167 if (bo && selection.type()==Selection::MapCenter)
2169 // BranchObj* par=(BranchObj*)(bo->getParObj());
2170 selection.unselect();
2171 /* FIXME VM Note: does saveStateRemovingPart work for MCO? (No parent!)
2172 saveStateRemovingPart (bo, QString ("Delete %1").arg(getObjectName(bo)));
2174 bo=removeMapCenter ((MapCenterObj*)bo);
2177 selection.select (bo);
2178 ensureSelectionVisible();
2184 if (bo && selection.type()==Selection::Branch)
2186 //FIXME need to check if any animObj is part of Branch, remove from animated obj list then
2191 BranchObj* par=(BranchObj*)bo->getParObj();
2192 selection.unselect();
2193 saveStateRemovingPart (bo, QString ("Delete %1").arg(getObjectName(bo)));
2194 par->removeBranch(bo);
2195 selection.select (par);
2196 ensureSelectionVisible();
2201 FloatImageObj *fio=selection.getFloatImage();
2204 BranchObj* par=(BranchObj*)fio->getParObj();
2205 saveStateChangingPart(
2209 QString("Delete %1").arg(getObjectName(fio))
2211 selection.unselect();
2212 par->removeFloatImage(fio);
2213 selection.select (par);
2216 ensureSelectionVisible();
2221 void VymModel::deleteKeepChildren()
2223 BranchObj *bo=selection.getBranch();
2227 par=(BranchObj*)(bo->getParObj());
2229 // Don't use this on mapcenter
2232 // Check if we have childs at all to keep
2233 if (bo->countBranches()==0)
2239 QPointF p=bo->getRelPos();
2240 saveStateChangingPart(
2243 "deleteKeepChildren ()",
2244 QString("Remove %1 and keep its children").arg(getObjectName(bo))
2247 QString sel=getSelectString(bo);
2249 par->removeBranchHere(bo);
2252 selection.getBranch()->move2RelPos (p);
2257 void VymModel::deleteChildren()
2259 BranchObj *bo=selection.getBranch();
2262 saveStateChangingPart(
2265 "deleteChildren ()",
2266 QString( "Remove children of branch %1").arg(getObjectName(bo))
2268 bo->removeChildren();
2274 bool VymModel::scrollBranch(BranchObj *bo)
2278 if (bo->isScrolled()) return false;
2279 if (bo->countBranches()==0) return false;
2280 if (bo->getDepth()==0) return false;
2286 QString ("%1 ()").arg(u),
2288 QString ("%1 ()").arg(r),
2289 QString ("%1 %2").arg(r).arg(getObjectName(bo))
2293 // FIXME VM needed? scene()->update();
2299 bool VymModel::unscrollBranch(BranchObj *bo)
2303 if (!bo->isScrolled()) return false;
2304 if (bo->countBranches()==0) return false;
2305 if (bo->getDepth()==0) return false;
2311 QString ("%1 ()").arg(u),
2313 QString ("%1 ()").arg(r),
2314 QString ("%1 %2").arg(r).arg(getObjectName(bo))
2318 // FIXME VM needed? scene()->update();
2324 void VymModel::toggleScroll()
2326 BranchObj *bo=selection.getBranch();
2327 if (selection.type()==Selection::Branch )
2329 if (bo->isScrolled())
2330 unscrollBranch (bo);
2336 void VymModel::unscrollChildren()
2338 BranchObj *bo=selection.getBranch();
2344 if (bo->isScrolled()) unscrollBranch (bo);
2349 void VymModel::addFloatImage (const QPixmap &img)
2351 BranchObj *bo=selection.getBranch();
2354 FloatImageObj *fio=bo->addFloatImage();
2356 fio->setOriginalFilename("No original filename (image added by dropevent)");
2357 QString s=getSelectString(bo);
2358 saveState (PartOfMap, s, "nop ()", s, "copy ()","Copy dropped image to clipboard",fio );
2359 saveState (fio,"delete ()", bo,QString("paste(%1)").arg(curStep),"Pasting dropped image");
2361 // FIXME VM needed? scene()->update();
2366 void VymModel::colorBranch (QColor c)
2368 BranchObj *bo=selection.getBranch();
2373 QString ("colorBranch (\"%1\")").arg(bo->getColor().name()),
2375 QString ("colorBranch (\"%1\")").arg(c.name()),
2376 QString("Set color of %1 to %2").arg(getObjectName(bo)).arg(c.name())
2378 bo->setColor(c); // color branch
2382 void VymModel::colorSubtree (QColor c)
2384 BranchObj *bo=selection.getBranch();
2387 saveStateChangingPart(
2390 QString ("colorSubtree (\"%1\")").arg(c.name()),
2391 QString ("Set color of %1 and children to %2").arg(getObjectName(bo)).arg(c.name())
2393 bo->setColorSubtree (c); // color links, color children
2397 QColor VymModel::getCurrentHeadingColor()
2399 BranchObj *bo=selection.getBranch();
2400 if (bo) return bo->getColor();
2402 QMessageBox::warning(0,"Warning","Can't get color of heading,\nthere's no branch selected");
2408 void VymModel::editURL()
2410 BranchObj *bo=selection.getBranch();
2414 QString text = QInputDialog::getText(
2415 "VYM", tr("Enter URL:"), QLineEdit::Normal,
2416 bo->getURL(), &ok, NULL);
2418 // user entered something and pressed OK
2423 void VymModel::editLocalURL()
2425 BranchObj *bo=selection.getBranch();
2428 QStringList filters;
2429 filters <<"All files (*)";
2430 filters << tr("Text","Filedialog") + " (*.txt)";
2431 filters << tr("Spreadsheet","Filedialog") + " (*.odp,*.sxc)";
2432 filters << tr("Textdocument","Filedialog") +" (*.odw,*.sxw)";
2433 filters << tr("Images","Filedialog") + " (*.png *.bmp *.xbm *.jpg *.png *.xpm *.gif *.pnm)";
2434 QFileDialog *fd=new QFileDialog( NULL,vymName+" - " +tr("Set URL to a local file"));
2435 fd->setFilters (filters);
2436 fd->setCaption(vymName+" - " +tr("Set URL to a local file"));
2437 fd->setDirectory (lastFileDir);
2438 if (! bo->getVymLink().isEmpty() )
2439 fd->selectFile( bo->getURL() );
2442 if ( fd->exec() == QDialog::Accepted )
2444 lastFileDir=QDir (fd->directory().path());
2445 setURL (fd->selectedFile() );
2451 void VymModel::editHeading2URL()
2453 BranchObj *bo=selection.getBranch();
2455 setURL (bo->getHeading());
2458 void VymModel::editBugzilla2URL()
2460 BranchObj *bo=selection.getBranch();
2463 QString url= "https://bugzilla.novell.com/show_bug.cgi?id="+bo->getHeading();
2468 void VymModel::editFATE2URL()
2470 BranchObj *bo=selection.getBranch();
2473 QString url= "http://keeper.suse.de:8080/webfate/match/id?value=ID"+bo->getHeading();
2476 "setURL (\""+bo->getURL()+"\")",
2478 "setURL (\""+url+"\")",
2479 QString("Use heading of %1 as link to FATE").arg(getObjectName(bo))
2486 void VymModel::editVymLink()
2488 BranchObj *bo=selection.getBranch();
2491 QStringList filters;
2492 filters <<"VYM map (*.vym)";
2493 QFileDialog *fd=new QFileDialog( NULL,vymName+" - " +tr("Link to another map"));
2494 fd->setFilters (filters);
2495 fd->setCaption(vymName+" - " +tr("Link to another map"));
2496 fd->setDirectory (lastFileDir);
2497 if (! bo->getVymLink().isEmpty() )
2498 fd->selectFile( bo->getVymLink() );
2502 if ( fd->exec() == QDialog::Accepted )
2504 lastFileDir=QDir (fd->directory().path());
2507 "setVymLink (\""+bo->getVymLink()+"\")",
2509 "setVymLink (\""+fd->selectedFile()+"\")",
2510 QString("Set vymlink of %1 to %2").arg(getObjectName(bo)).arg(fd->selectedFile())
2512 setVymLink (fd->selectedFile() ); // FIXME ok?
2517 void VymModel::setVymLink (const QString &s)
2519 // Internal function, no saveState needed
2520 BranchObj *bo=selection.getBranch();
2527 ensureSelectionVisible();
2531 void VymModel::deleteVymLink()
2533 BranchObj *bo=selection.getBranch();
2538 "setVymLink (\""+bo->getVymLink()+"\")",
2540 "setVymLink (\"\")",
2541 QString("Unset vymlink of %1").arg(getObjectName(bo))
2543 bo->setVymLink ("" );
2546 // FIXME VM needed? scene()->update();
2550 QString VymModel::getVymLink()
2552 BranchObj *bo=selection.getBranch();
2554 return bo->getVymLink();
2560 QStringList VymModel::getVymLinks()
2563 BranchObj *bo=selection.getBranch();
2569 if (!bo->getVymLink().isEmpty()) links.append( bo->getVymLink());
2577 void VymModel::followXLink(int i)
2579 BranchObj *bo=selection.getBranch();
2582 bo=bo->XLinkTargetAt(i);
2585 selection.select(bo);
2586 ensureSelectionVisible();
2591 void VymModel::editXLink(int i) // FIXME VM missing saveState
2593 BranchObj *bo=selection.getBranch();
2596 XLinkObj *xlo=bo->XLinkAt(i);
2599 EditXLinkDialog dia;
2601 dia.setSelection(bo);
2602 if (dia.exec() == QDialog::Accepted)
2604 if (dia.useSettingsGlobal() )
2606 setMapDefXLinkColor (xlo->getColor() );
2607 setMapDefXLinkWidth (xlo->getWidth() );
2609 if (dia.deleteXLink())
2610 bo->deleteXLinkAt(i);
2620 //////////////////////////////////////////////
2622 //////////////////////////////////////////////
2624 void VymModel::parseAtom(const QString &atom)
2626 BranchObj *selb=selection.getBranch();
2632 // Split string s into command and parameters
2633 parser.parseAtom (atom);
2634 QString com=parser.getCommand();
2636 // External commands
2637 /////////////////////////////////////////////////////////////////////
2638 if (com=="addBranch")
2640 if (selection.isEmpty())
2642 parser.setError (Aborted,"Nothing selected");
2645 parser.setError (Aborted,"Type of selection is not a branch");
2650 if (parser.checkParCount(pl))
2652 if (parser.parCount()==0)
2656 n=parser.parInt (ok,0);
2657 if (ok ) addNewBranch (n);
2661 /////////////////////////////////////////////////////////////////////
2662 } else if (com=="addBranchBefore")
2664 if (selection.isEmpty())
2666 parser.setError (Aborted,"Nothing selected");
2669 parser.setError (Aborted,"Type of selection is not a branch");
2672 if (parser.parCount()==0)
2674 addNewBranchBefore ();
2677 /////////////////////////////////////////////////////////////////////
2678 } else if (com==QString("addMapCenter"))
2680 if (parser.checkParCount(2))
2682 x=parser.parDouble (ok,0);
2685 y=parser.parDouble (ok,1);
2686 if (ok) addMapCenter (QPointF(x,y));
2689 /////////////////////////////////////////////////////////////////////
2690 } else if (com==QString("addMapReplace"))
2692 if (selection.isEmpty())
2694 parser.setError (Aborted,"Nothing selected");
2697 parser.setError (Aborted,"Type of selection is not a branch");
2698 } else if (parser.checkParCount(1))
2700 //s=parser.parString (ok,0); // selection
2701 t=parser.parString (ok,0); // path to map
2702 if (QDir::isRelativePath(t)) t=(tmpMapDir + "/"+t);
2703 addMapReplaceInt(getSelectString(selb),t);
2705 /////////////////////////////////////////////////////////////////////
2706 } else if (com==QString("addMapInsert"))
2708 if (selection.isEmpty())
2710 parser.setError (Aborted,"Nothing selected");
2713 parser.setError (Aborted,"Type of selection is not a branch");
2716 if (parser.checkParCount(2))
2718 t=parser.parString (ok,0); // path to map
2719 n=parser.parInt(ok,1); // position
2720 if (QDir::isRelativePath(t)) t=(tmpMapDir + "/"+t);
2721 addMapInsertInt(t,n);
2724 /////////////////////////////////////////////////////////////////////
2725 } else if (com=="clearFlags")
2727 if (selection.isEmpty() )
2729 parser.setError (Aborted,"Nothing selected");
2732 parser.setError (Aborted,"Type of selection is not a branch");
2733 } else if (parser.checkParCount(0))
2735 selb->clearStandardFlags();
2736 selb->updateFlagsToolbar();
2738 /////////////////////////////////////////////////////////////////////
2739 } else if (com=="colorBranch")
2741 if (selection.isEmpty())
2743 parser.setError (Aborted,"Nothing selected");
2746 parser.setError (Aborted,"Type of selection is not a branch");
2747 } else if (parser.checkParCount(1))
2749 QColor c=parser.parColor (ok,0);
2750 if (ok) colorBranch (c);
2752 /////////////////////////////////////////////////////////////////////
2753 } else if (com=="colorSubtree")
2755 if (selection.isEmpty())
2757 parser.setError (Aborted,"Nothing selected");
2760 parser.setError (Aborted,"Type of selection is not a branch");
2761 } else if (parser.checkParCount(1))
2763 QColor c=parser.parColor (ok,0);
2764 if (ok) colorSubtree (c);
2766 /////////////////////////////////////////////////////////////////////
2767 } else if (com=="copy")
2769 if (selection.isEmpty())
2771 parser.setError (Aborted,"Nothing selected");
2774 parser.setError (Aborted,"Type of selection is not a branch");
2775 } else if (parser.checkParCount(0))
2777 //FIXME missing action for copy
2779 /////////////////////////////////////////////////////////////////////
2780 } else if (com=="cut")
2782 if (selection.isEmpty())
2784 parser.setError (Aborted,"Nothing selected");
2785 } else if ( selection.type()!=Selection::Branch &&
2786 selection.type()!=Selection::MapCenter &&
2787 selection.type()!=Selection::FloatImage )
2789 parser.setError (Aborted,"Type of selection is not a branch or floatimage");
2790 } else if (parser.checkParCount(0))
2794 /////////////////////////////////////////////////////////////////////
2795 } else if (com=="delete")
2797 if (selection.isEmpty())
2799 parser.setError (Aborted,"Nothing selected");
2801 /*else if (selection.type() != Selection::Branch && selection.type() != Selection::FloatImage )
2803 parser.setError (Aborted,"Type of selection is wrong.");
2806 else if (parser.checkParCount(0))
2810 /////////////////////////////////////////////////////////////////////
2811 } else if (com=="deleteKeepChildren")
2813 if (selection.isEmpty())
2815 parser.setError (Aborted,"Nothing selected");
2818 parser.setError (Aborted,"Type of selection is not a branch");
2819 } else if (parser.checkParCount(0))
2821 deleteKeepChildren();
2823 /////////////////////////////////////////////////////////////////////
2824 } else if (com=="deleteChildren")
2826 if (selection.isEmpty())
2828 parser.setError (Aborted,"Nothing selected");
2831 parser.setError (Aborted,"Type of selection is not a branch");
2832 } else if (parser.checkParCount(0))
2836 /////////////////////////////////////////////////////////////////////
2837 } else if (com=="exportASCII")
2841 if (parser.parCount()>=1)
2842 // Hey, we even have a filename
2843 fname=parser.parString(ok,0);
2846 parser.setError (Aborted,"Could not read filename");
2849 exportASCII (fname,false);
2851 /////////////////////////////////////////////////////////////////////
2852 } else if (com=="exportImage")
2856 if (parser.parCount()>=2)
2857 // Hey, we even have a filename
2858 fname=parser.parString(ok,0);
2861 parser.setError (Aborted,"Could not read filename");
2864 QString format="PNG";
2865 if (parser.parCount()>=2)
2867 format=parser.parString(ok,1);
2869 exportImage (fname,false,format);
2871 /////////////////////////////////////////////////////////////////////
2872 } else if (com=="exportXHTML")
2876 if (parser.parCount()>=2)
2877 // Hey, we even have a filename
2878 fname=parser.parString(ok,1);
2881 parser.setError (Aborted,"Could not read filename");
2884 exportXHTML (fname,false);
2886 /////////////////////////////////////////////////////////////////////
2887 } else if (com=="exportXML")
2891 if (parser.parCount()>=2)
2892 // Hey, we even have a filename
2893 fname=parser.parString(ok,1);
2896 parser.setError (Aborted,"Could not read filename");
2899 exportXML (fname,false);
2901 /////////////////////////////////////////////////////////////////////
2902 } else if (com=="importDir")
2904 if (selection.isEmpty())
2906 parser.setError (Aborted,"Nothing selected");
2909 parser.setError (Aborted,"Type of selection is not a branch");
2910 } else if (parser.checkParCount(1))
2912 s=parser.parString(ok,0);
2913 if (ok) importDirInt(s);
2915 /////////////////////////////////////////////////////////////////////
2916 } else if (com=="linkTo")
2918 if (selection.isEmpty())
2920 parser.setError (Aborted,"Nothing selected");
2923 if (parser.checkParCount(4))
2925 // 0 selectstring of parent
2926 // 1 num in parent (for branches)
2927 // 2,3 x,y of mainbranch or mapcenter
2928 s=parser.parString(ok,0);
2929 LinkableMapObj *dst=findObjBySelect (s);
2932 if (typeid(*dst) == typeid(BranchObj) )
2934 // Get number in parent
2935 n=parser.parInt (ok,1);
2938 selb->linkTo ((BranchObj*)(dst),n);
2941 } else if (typeid(*dst) == typeid(MapCenterObj) )
2943 selb->linkTo ((BranchObj*)(dst),-1);
2944 // Get coordinates of mainbranch
2945 x=parser.parDouble(ok,2);
2948 y=parser.parDouble(ok,3);
2958 } else if ( selection.type() == Selection::FloatImage)
2960 if (parser.checkParCount(1))
2962 // 0 selectstring of parent
2963 s=parser.parString(ok,0);
2964 LinkableMapObj *dst=findObjBySelect (s);
2967 if (typeid(*dst) == typeid(BranchObj) ||
2968 typeid(*dst) == typeid(MapCenterObj))
2969 linkFloatImageTo (getSelectString(dst));
2971 parser.setError (Aborted,"Destination is not a branch");
2974 parser.setError (Aborted,"Type of selection is not a floatimage or branch");
2975 /////////////////////////////////////////////////////////////////////
2976 } else if (com=="loadImage")
2978 if (selection.isEmpty())
2980 parser.setError (Aborted,"Nothing selected");
2983 parser.setError (Aborted,"Type of selection is not a branch");
2984 } else if (parser.checkParCount(1))
2986 s=parser.parString(ok,0);
2987 if (ok) loadFloatImageInt (s);
2989 /////////////////////////////////////////////////////////////////////
2990 } else if (com=="moveBranchUp")
2992 if (selection.isEmpty() )
2994 parser.setError (Aborted,"Nothing selected");
2997 parser.setError (Aborted,"Type of selection is not a branch");
2998 } else if (parser.checkParCount(0))
3002 /////////////////////////////////////////////////////////////////////
3003 } else if (com=="moveBranchDown")
3005 if (selection.isEmpty() )
3007 parser.setError (Aborted,"Nothing selected");
3010 parser.setError (Aborted,"Type of selection is not a branch");
3011 } else if (parser.checkParCount(0))
3015 /////////////////////////////////////////////////////////////////////
3016 } else if (com=="move")
3018 if (selection.isEmpty() )
3020 parser.setError (Aborted,"Nothing selected");
3021 } else if ( selection.type()!=Selection::Branch &&
3022 selection.type()!=Selection::MapCenter &&
3023 selection.type()!=Selection::FloatImage )
3025 parser.setError (Aborted,"Type of selection is not a branch or floatimage");
3026 } else if (parser.checkParCount(2))
3028 x=parser.parDouble (ok,0);
3031 y=parser.parDouble (ok,1);
3035 /////////////////////////////////////////////////////////////////////
3036 } else if (com=="moveRel")
3038 if (selection.isEmpty() )
3040 parser.setError (Aborted,"Nothing selected");
3041 } else if ( selection.type()!=Selection::Branch &&
3042 selection.type()!=Selection::MapCenter &&
3043 selection.type()!=Selection::FloatImage )
3045 parser.setError (Aborted,"Type of selection is not a branch or floatimage");
3046 } else if (parser.checkParCount(2))
3048 x=parser.parDouble (ok,0);
3051 y=parser.parDouble (ok,1);
3052 if (ok) moveRel (x,y);
3055 /////////////////////////////////////////////////////////////////////
3056 } else if (com=="nop")
3058 /////////////////////////////////////////////////////////////////////
3059 } else if (com=="paste")
3061 if (selection.isEmpty() )
3063 parser.setError (Aborted,"Nothing selected");
3066 parser.setError (Aborted,"Type of selection is not a branch");
3067 } else if (parser.checkParCount(1))
3069 n=parser.parInt (ok,0);
3070 if (ok) pasteNoSave(n);
3072 /////////////////////////////////////////////////////////////////////
3073 } else if (com=="qa")
3075 if (selection.isEmpty() )
3077 parser.setError (Aborted,"Nothing selected");
3080 parser.setError (Aborted,"Type of selection is not a branch");
3081 } else if (parser.checkParCount(4))
3084 c=parser.parString (ok,0);
3087 parser.setError (Aborted,"No comment given");
3090 s=parser.parString (ok,1);
3093 parser.setError (Aborted,"First parameter is not a string");
3096 t=parser.parString (ok,2);
3099 parser.setError (Aborted,"Condition is not a string");
3102 u=parser.parString (ok,3);
3105 parser.setError (Aborted,"Third parameter is not a string");
3110 parser.setError (Aborted,"Unknown type: "+s);
3115 parser.setError (Aborted,"Unknown operator: "+t);
3120 parser.setError (Aborted,"Type of selection is not a branch");
3123 if (selb->getHeading() == u)
3125 cout << "PASSED: " << qPrintable (c) << endl;
3128 cout << "FAILED: " << qPrintable (c) << endl;
3138 /////////////////////////////////////////////////////////////////////
3139 } else if (com=="saveImage")
3141 FloatImageObj *fio=selection.getFloatImage();
3144 parser.setError (Aborted,"Type of selection is not an image");
3145 } else if (parser.checkParCount(2))
3147 s=parser.parString(ok,0);
3150 t=parser.parString(ok,1);
3151 if (ok) saveFloatImageInt (fio,t,s);
3154 /////////////////////////////////////////////////////////////////////
3155 } else if (com=="scroll")
3157 if (selection.isEmpty() )
3159 parser.setError (Aborted,"Nothing selected");
3162 parser.setError (Aborted,"Type of selection is not a branch");
3163 } else if (parser.checkParCount(0))
3165 if (!scrollBranch (selb))
3166 parser.setError (Aborted,"Could not scroll branch");
3168 /////////////////////////////////////////////////////////////////////
3169 } else if (com=="select")
3171 if (parser.checkParCount(1))
3173 s=parser.parString(ok,0);
3176 /////////////////////////////////////////////////////////////////////
3177 } else if (com=="selectLastBranch")
3179 if (selection.isEmpty() )
3181 parser.setError (Aborted,"Nothing selected");
3184 parser.setError (Aborted,"Type of selection is not a branch");
3185 } else if (parser.checkParCount(0))
3187 BranchObj *bo=selb->getLastBranch();
3189 parser.setError (Aborted,"Could not select last branch");
3193 /////////////////////////////////////////////////////////////////////
3194 } else if (com=="selectLastImage")
3196 if (selection.isEmpty() )
3198 parser.setError (Aborted,"Nothing selected");
3201 parser.setError (Aborted,"Type of selection is not a branch");
3202 } else if (parser.checkParCount(0))
3204 FloatImageObj *fio=selb->getLastFloatImage();
3206 parser.setError (Aborted,"Could not select last image");
3210 /////////////////////////////////////////////////////////////////////
3211 } else if (com=="selectLatestAdded")
3213 if (latestSelectionString.isEmpty() )
3215 parser.setError (Aborted,"No latest added object");
3218 if (!select (latestSelectionString))
3219 parser.setError (Aborted,"Could not select latest added object "+latestSelectionString);
3221 /////////////////////////////////////////////////////////////////////
3222 } else if (com=="setFrameType")
3224 if ( selection.type()!=Selection::Branch && selection.type()!= Selection::MapCenter && selection.type()!=Selection::FloatImage)
3226 parser.setError (Aborted,"Type of selection does not allow setting frame type");
3228 else if (parser.checkParCount(1))
3230 s=parser.parString(ok,0);
3231 if (ok) setFrameType (s);
3233 /////////////////////////////////////////////////////////////////////
3234 } else if (com=="setFramePenColor")
3236 if ( selection.type()!=Selection::Branch && selection.type()!= Selection::MapCenter && selection.type()!=Selection::FloatImage)
3238 parser.setError (Aborted,"Type of selection does not allow setting of pen color");
3240 else if (parser.checkParCount(1))
3242 QColor c=parser.parColor(ok,0);
3243 if (ok) setFramePenColor (c);
3245 /////////////////////////////////////////////////////////////////////
3246 } else if (com=="setFrameBrushColor")
3248 if ( selection.type()!=Selection::Branch && selection.type()!= Selection::MapCenter && selection.type()!=Selection::FloatImage)
3250 parser.setError (Aborted,"Type of selection does not allow setting brush color");
3252 else if (parser.checkParCount(1))
3254 QColor c=parser.parColor(ok,0);
3255 if (ok) setFrameBrushColor (c);
3257 /////////////////////////////////////////////////////////////////////
3258 } else if (com=="setFramePadding")
3260 if ( selection.type()!=Selection::Branch && selection.type()!= Selection::MapCenter && selection.type()!=Selection::FloatImage)
3262 parser.setError (Aborted,"Type of selection does not allow setting frame padding");
3264 else if (parser.checkParCount(1))
3266 n=parser.parInt(ok,0);
3267 if (ok) setFramePadding(n);
3269 /////////////////////////////////////////////////////////////////////
3270 } else if (com=="setFrameBorderWidth")
3272 if ( selection.type()!=Selection::Branch && selection.type()!= Selection::MapCenter && selection.type()!=Selection::FloatImage)
3274 parser.setError (Aborted,"Type of selection does not allow setting frame border width");
3276 else if (parser.checkParCount(1))
3278 n=parser.parInt(ok,0);
3279 if (ok) setFrameBorderWidth (n);
3281 /////////////////////////////////////////////////////////////////////
3282 } else if (com=="setMapAuthor")
3284 if (parser.checkParCount(1))
3286 s=parser.parString(ok,0);
3287 if (ok) setAuthor (s);
3289 /////////////////////////////////////////////////////////////////////
3290 } else if (com=="setMapComment")
3292 if (parser.checkParCount(1))
3294 s=parser.parString(ok,0);
3295 if (ok) setComment(s);
3297 /////////////////////////////////////////////////////////////////////
3298 } else if (com=="setMapBackgroundColor")
3300 if (selection.isEmpty() )
3302 parser.setError (Aborted,"Nothing selected");
3303 } else if (! selection.getBranch() )
3305 parser.setError (Aborted,"Type of selection is not a branch");
3306 } else if (parser.checkParCount(1))
3308 QColor c=parser.parColor (ok,0);
3309 if (ok) setMapBackgroundColor (c);
3311 /////////////////////////////////////////////////////////////////////
3312 } else if (com=="setMapDefLinkColor")
3314 if (selection.isEmpty() )
3316 parser.setError (Aborted,"Nothing selected");
3319 parser.setError (Aborted,"Type of selection is not a branch");
3320 } else if (parser.checkParCount(1))
3322 QColor c=parser.parColor (ok,0);
3323 if (ok) setMapDefLinkColor (c);
3325 /////////////////////////////////////////////////////////////////////
3326 } else if (com=="setMapLinkStyle")
3328 if (parser.checkParCount(1))
3330 s=parser.parString (ok,0);
3331 if (ok) setMapLinkStyle(s);
3333 /////////////////////////////////////////////////////////////////////
3334 } else if (com=="setHeading")
3336 if (selection.isEmpty() )
3338 parser.setError (Aborted,"Nothing selected");
3341 parser.setError (Aborted,"Type of selection is not a branch");
3342 } else if (parser.checkParCount(1))
3344 s=parser.parString (ok,0);
3348 /////////////////////////////////////////////////////////////////////
3349 } else if (com=="setHideExport")
3351 if (selection.isEmpty() )
3353 parser.setError (Aborted,"Nothing selected");
3354 } else if (selection.type()!=Selection::Branch && selection.type() != Selection::MapCenter &&selection.type()!=Selection::FloatImage)
3356 parser.setError (Aborted,"Type of selection is not a branch or floatimage");
3357 } else if (parser.checkParCount(1))
3359 b=parser.parBool(ok,0);
3360 if (ok) setHideExport (b);
3362 /////////////////////////////////////////////////////////////////////
3363 } else if (com=="setIncludeImagesHorizontally")
3365 if (selection.isEmpty() )
3367 parser.setError (Aborted,"Nothing selected");
3370 parser.setError (Aborted,"Type of selection is not a branch");
3371 } else if (parser.checkParCount(1))
3373 b=parser.parBool(ok,0);
3374 if (ok) setIncludeImagesHor(b);
3376 /////////////////////////////////////////////////////////////////////
3377 } else if (com=="setIncludeImagesVertically")
3379 if (selection.isEmpty() )
3381 parser.setError (Aborted,"Nothing selected");
3384 parser.setError (Aborted,"Type of selection is not a branch");
3385 } else if (parser.checkParCount(1))
3387 b=parser.parBool(ok,0);
3388 if (ok) setIncludeImagesVer(b);
3390 /////////////////////////////////////////////////////////////////////
3391 } else if (com=="setHideLinkUnselected")
3393 if (selection.isEmpty() )
3395 parser.setError (Aborted,"Nothing selected");
3396 } else if ( selection.type()!=Selection::Branch && selection.type()!= Selection::MapCenter && selection.type()!=Selection::FloatImage)
3398 parser.setError (Aborted,"Type of selection does not allow hiding the link");
3399 } else if (parser.checkParCount(1))
3401 b=parser.parBool(ok,0);
3402 if (ok) setHideLinkUnselected(b);
3404 /////////////////////////////////////////////////////////////////////
3405 } else if (com=="setSelectionColor")
3407 if (parser.checkParCount(1))
3409 QColor c=parser.parColor (ok,0);
3410 if (ok) setSelectionColorInt (c);
3412 /////////////////////////////////////////////////////////////////////
3413 } else if (com=="setURL")
3415 if (selection.isEmpty() )
3417 parser.setError (Aborted,"Nothing selected");
3420 parser.setError (Aborted,"Type of selection is not a branch");
3421 } else if (parser.checkParCount(1))
3423 s=parser.parString (ok,0);
3426 /////////////////////////////////////////////////////////////////////
3427 } else if (com=="setVymLink")
3429 if (selection.isEmpty() )
3431 parser.setError (Aborted,"Nothing selected");
3434 parser.setError (Aborted,"Type of selection is not a branch");
3435 } else if (parser.checkParCount(1))
3437 s=parser.parString (ok,0);
3438 if (ok) setVymLink(s);
3441 /////////////////////////////////////////////////////////////////////
3442 else if (com=="setFlag")
3444 if (selection.isEmpty() )
3446 parser.setError (Aborted,"Nothing selected");
3449 parser.setError (Aborted,"Type of selection is not a branch");
3450 } else if (parser.checkParCount(1))
3452 s=parser.parString(ok,0);
3455 selb->activateStandardFlag(s);
3456 selb->updateFlagsToolbar();
3459 /////////////////////////////////////////////////////////////////////
3460 } else if (com=="setFrameType")
3462 if (selection.isEmpty() )
3464 parser.setError (Aborted,"Nothing selected");
3467 parser.setError (Aborted,"Type of selection is not a branch");
3468 } else if (parser.checkParCount(1))
3470 s=parser.parString(ok,0);
3474 /////////////////////////////////////////////////////////////////////
3475 } else if (com=="sortChildren")
3477 if (selection.isEmpty() )
3479 parser.setError (Aborted,"Nothing selected");
3482 parser.setError (Aborted,"Type of selection is not a branch");
3483 } else if (parser.checkParCount(0))
3487 /////////////////////////////////////////////////////////////////////
3488 } else if (com=="toggleFlag")
3490 if (selection.isEmpty() )
3492 parser.setError (Aborted,"Nothing selected");
3495 parser.setError (Aborted,"Type of selection is not a branch");
3496 } else if (parser.checkParCount(1))
3498 s=parser.parString(ok,0);
3501 selb->toggleStandardFlag(s);
3502 selb->updateFlagsToolbar();
3505 /////////////////////////////////////////////////////////////////////
3506 } else if (com=="unscroll")
3508 if (selection.isEmpty() )
3510 parser.setError (Aborted,"Nothing selected");
3513 parser.setError (Aborted,"Type of selection is not a branch");
3514 } else if (parser.checkParCount(0))
3516 if (!unscrollBranch (selb))
3517 parser.setError (Aborted,"Could not unscroll branch");
3519 /////////////////////////////////////////////////////////////////////
3520 } else if (com=="unscrollChildren")
3522 if (selection.isEmpty() )
3524 parser.setError (Aborted,"Nothing selected");
3527 parser.setError (Aborted,"Type of selection is not a branch");
3528 } else if (parser.checkParCount(0))
3530 unscrollChildren ();
3532 /////////////////////////////////////////////////////////////////////
3533 } else if (com=="unsetFlag")
3535 if (selection.isEmpty() )
3537 parser.setError (Aborted,"Nothing selected");
3540 parser.setError (Aborted,"Type of selection is not a branch");
3541 } else if (parser.checkParCount(1))
3543 s=parser.parString(ok,0);
3546 selb->deactivateStandardFlag(s);
3547 selb->updateFlagsToolbar();
3551 parser.setError (Aborted,"Unknown command");
3554 if (parser.errorLevel()==NoError)
3556 // setChanged(); FIXME should not be called e.g. for export?!
3561 // TODO Error handling
3562 qWarning("VymModel::parseAtom: Error!");
3563 qWarning(parser.errorMessage());
3567 void VymModel::runScript (QString script)
3569 parser.setScript (script);
3571 while (parser.next() )
3572 parseAtom(parser.getAtom());
3575 void VymModel::setExportMode (bool b)
3577 // should be called before and after exports
3578 // depending on the settings
3579 if (b && settings.value("/export/useHideExport","true")=="true")
3580 setHideTmpMode (HideExport);
3582 setHideTmpMode (HideNone);
3585 void VymModel::exportImage(QString fname, bool askName, QString format)
3589 fname=getMapName()+".png";
3596 QFileDialog *fd=new QFileDialog (NULL);
3597 fd->setCaption (tr("Export map as image"));
3598 fd->setDirectory (lastImageDir);
3599 fd->setFileMode(QFileDialog::AnyFile);
3600 fd->setFilters (imageIO.getFilters() );
3603 fl=fd->selectedFiles();
3605 format=imageIO.getType(fd->selectedFilter());
3609 setExportMode (true);
3610 QPixmap pix (getPixmap());
3611 pix.save(fname, format);
3612 setExportMode (false);
3616 void VymModel::exportXML(QString dir, bool askForName)
3620 dir=browseDirectory(NULL,tr("Export XML to directory"));
3621 if (dir =="" && !reallyWriteDirectory(dir) )
3625 // Hide stuff during export, if settings want this
3626 setExportMode (true);
3628 // Create subdirectories
3631 // write to directory
3632 QString saveFile=saveToDir (dir,mapName+"-",true,getTotalBBox().topLeft() ,NULL);
3635 file.setName ( dir + "/"+mapName+".xml");
3636 if ( !file.open( QIODevice::WriteOnly ) )
3638 // This should neverever happen
3639 QMessageBox::critical (0,tr("Critical Export Error"),tr("VymModel::exportXML couldn't open %1").arg(file.name()));
3643 // Write it finally, and write in UTF8, no matter what
3644 QTextStream ts( &file );
3645 ts.setEncoding (QTextStream::UnicodeUTF8);
3649 // Now write image, too
3650 exportImage (dir+"/images/"+mapName+".png",false,"PNG");
3652 setExportMode (false);
3655 void VymModel::exportASCII(QString fname,bool askName)
3660 ex.setFile (mapName+".txt");
3666 //ex.addFilter ("TXT (*.txt)");
3667 ex.setDir(lastImageDir);
3668 //ex.setCaption(vymName+ " -" +tr("Export as ASCII")+" "+tr("(still experimental)"));
3673 setExportMode(true);
3675 setExportMode(false);
3679 void VymModel::exportXHTML (const QString &dir, bool askForName)
3681 ExportXHTMLDialog dia(NULL);
3682 dia.setFilePath (filePath );
3683 dia.setMapName (mapName );
3685 if (dir!="") dia.setDir (dir);
3691 if (dia.exec()!=QDialog::Accepted)
3695 QDir d (dia.getDir());
3696 // Check, if warnings should be used before overwriting
3697 // the output directory
3698 if (d.exists() && d.count()>0)
3701 warn.showCancelButton (true);
3702 warn.setText(QString(
3703 "The directory %1 is not empty.\n"
3704 "Do you risk to overwrite some of its contents?").arg(d.path() ));
3705 warn.setCaption("Warning: Directory not empty");
3706 warn.setShowAgainName("mainwindow/overwrite-dir-xhtml");
3708 if (warn.exec()!=QDialog::Accepted) ok=false;
3715 exportXML (dia.getDir(),false );
3716 dia.doExport(mapName );
3717 //if (dia.hasChanged()) setChanged();
3721 void VymModel::exportOOPresentation(const QString &fn, const QString &cf)
3726 if (ex.setConfigFile(cf))
3728 setExportMode (true);
3729 ex.exportPresentation();
3730 setExportMode (false);
3737 //////////////////////////////////////////////
3739 //////////////////////////////////////////////
3741 void VymModel::registerEditor(QWidget *me)
3743 mapEditor=(MapEditor*)me;
3744 for (int i=0; i<mapCenters.count(); i++)
3745 mapCenters.at(i)->setMapEditor(mapEditor);
3748 void VymModel::unregisterEditor(QWidget *)
3753 void VymModel::setContextPos(QPointF p)
3758 void VymModel::unsetContextPos()
3760 contextPos=QPointF();
3763 void VymModel::updateNoteFlag()
3766 BranchObj *bo=selection.getBranch();
3769 bo->updateNoteFlag();
3770 mainWindow->updateActions();
3774 void VymModel::updateRelPositions()
3776 for (int i=0; i<mapCenters.count(); i++)
3777 mapCenters.at(i)->updateRelPositions();
3780 void VymModel::reposition()
3782 for (int i=0;i<mapCenters.count(); i++)
3783 mapCenters.at(i)->reposition(); // for positioning heading
3786 QPolygonF VymModel::shape(BranchObj *bo)
3788 // Creating (arbitrary) shapes
3791 QRectF rb=bo->getBBox();
3792 if (bo->getDepth()==0)
3794 // Just take BBox of this mapCenter
3795 p<<rb.topLeft()<<rb.topRight()<<rb.bottomRight()<<rb.bottomLeft();
3799 // Take union of BBox and TotalBBox
3801 QRectF ra=bo->getTotalBBox();
3802 if (bo->getOrientation()==LinkableMapObj::LeftOfCenter)
3805 <<QPointF (rb.topLeft().x(), ra.topLeft().y() )
3808 <<QPointF (rb.bottomLeft().x(), ra.bottomLeft().y() ) ;
3810 p <<ra.bottomRight()
3812 <<QPointF (rb.topRight().x(), ra.topRight().y() )
3815 <<QPointF (rb.bottomRight().x(), ra.bottomRight().y() ) ;
3820 void VymModel::moveAway(LinkableMapObj *lmo)
3824 // Move all branches and MapCenters away from lmo
3825 // to avoid collisions
3830 BranchObj *boA=(BranchObj*)lmo;
3832 for (int i=0; i<mapCenters.count(); i++)
3834 boB=mapCenters.at(i);
3837 PolygonCollisionResult r = PolygonCollision(pA, pB, QPoint(0,0));
3840 <<" ("<<qPrintable(boA->getHeading() )<<")"
3841 <<" with ("<< qPrintable (boB->getHeading() )
3844 <<" minT="<<r.minTranslation<<endl<<endl;
3848 QPixmap VymModel::getPixmap()
3850 QRectF mapRect=getTotalBBox();
3851 QPixmap pix((int)mapRect.width()+2,(int)mapRect.height()+1);
3854 pp.setRenderHints(mapEditor->renderHints());
3856 // Don't print the visualisation of selection
3857 selection.unselect();
3859 mapScene->render ( &pp,
3860 QRectF(0,0,mapRect.width()+2,mapRect.height()+2),
3861 QRectF(mapRect.x(),mapRect.y(),mapRect.width(),mapRect.height() ));
3863 // Restore selection
3864 selection.reselect();
3870 void VymModel::setMapLinkStyle (const QString & s)
3875 case LinkableMapObj::Line :
3878 case LinkableMapObj::Parabel:
3879 snow="StyleParabel";
3881 case LinkableMapObj::PolyLine:
3882 snow="StylePolyLine";
3884 case LinkableMapObj::PolyParabel:
3885 snow="StylePolyParabel";
3888 snow="UndefinedStyle";
3893 QString("setMapLinkStyle (\"%1\")").arg(s),
3894 QString("setMapLinkStyle (\"%1\")").arg(snow),
3895 QString("Set map link style (\"%1\")").arg(s)
3899 linkstyle=LinkableMapObj::Line;
3900 else if (s=="StyleParabel")
3901 linkstyle=LinkableMapObj::Parabel;
3902 else if (s=="StylePolyLine")
3903 linkstyle=LinkableMapObj::PolyLine;
3904 else if (s=="StylePolyParabel")
3905 linkstyle=LinkableMapObj::PolyParabel;
3907 linkstyle=LinkableMapObj::UndefinedStyle;
3914 bo->setLinkStyle(bo->getDefLinkStyle());
3920 LinkableMapObj::Style VymModel::getMapLinkStyle ()
3925 void VymModel::setMapDefLinkColor(QColor col)
3927 if ( !col.isValid() ) return;
3929 QString("setMapDefLinkColor (\"%1\")").arg(getMapDefLinkColor().name()),
3930 QString("setMapDefLinkColor (\"%1\")").arg(col.name()),
3931 QString("Set map link color to %1").arg(col.name())
3945 void VymModel::setMapLinkColorHintInt()
3947 // called from setMapLinkColorHint(lch) or at end of parse
3957 void VymModel::setMapLinkColorHint(LinkableMapObj::ColorHint lch)
3960 setMapLinkColorHintInt();
3963 void VymModel::toggleMapLinkColorHint()
3965 if (linkcolorhint==LinkableMapObj::HeadingColor)
3966 linkcolorhint=LinkableMapObj::DefaultColor;
3968 linkcolorhint=LinkableMapObj::HeadingColor;
3978 void VymModel::selectMapBackgroundImage ()
3980 Q3FileDialog *fd=new Q3FileDialog( NULL);
3981 fd->setMode (Q3FileDialog::ExistingFile);
3982 fd->addFilter (QString (tr("Images") + " (*.png *.bmp *.xbm *.jpg *.png *.xpm *.gif *.pnm)"));
3983 ImagePreview *p =new ImagePreview (fd);
3984 fd->setContentsPreviewEnabled( TRUE );
3985 fd->setContentsPreview( p, p );
3986 fd->setPreviewMode( Q3FileDialog::Contents );
3987 fd->setCaption(vymName+" - " +tr("Load background image"));
3988 fd->setDir (lastImageDir);
3991 if ( fd->exec() == QDialog::Accepted )
3993 // TODO selectMapBackgroundImg in QT4 use: lastImageDir=fd->directory();
3994 lastImageDir=QDir (fd->dirPath());
3995 setMapBackgroundImage (fd->selectedFile());
3999 void VymModel::setMapBackgroundImage (const QString &fn) //FIXME missing savestate
4001 QColor oldcol=mapScene->backgroundBrush().color();
4005 QString ("setMapBackgroundImage (%1)").arg(oldcol.name()),
4007 QString ("setMapBackgroundImage (%1)").arg(col.name()),
4008 QString("Set background color of map to %1").arg(col.name()));
4011 brush.setTextureImage (QPixmap (fn));
4012 mapScene->setBackgroundBrush(brush);
4015 void VymModel::selectMapBackgroundColor()
4017 QColor col = QColorDialog::getColor( mapScene->backgroundBrush().color(), NULL);
4018 if ( !col.isValid() ) return;
4019 setMapBackgroundColor( col );
4023 void VymModel::setMapBackgroundColor(QColor col)
4025 QColor oldcol=mapScene->backgroundBrush().color();
4027 QString ("setMapBackgroundColor (\"%1\")").arg(oldcol.name()),
4028 QString ("setMapBackgroundColor (\"%1\")").arg(col.name()),
4029 QString("Set background color of map to %1").arg(col.name()));
4030 mapScene->setBackgroundBrush(col);
4033 QColor VymModel::getMapBackgroundColor()
4035 return mapScene->backgroundBrush().color();
4039 LinkableMapObj::ColorHint VymModel::getMapLinkColorHint()
4041 return linkcolorhint;
4044 QColor VymModel::getMapDefLinkColor()
4046 return defLinkColor;
4049 void VymModel::setMapDefXLinkColor(QColor col)
4054 QColor VymModel::getMapDefXLinkColor()
4056 return defXLinkColor;
4059 void VymModel::setMapDefXLinkWidth (int w)
4064 int VymModel::getMapDefXLinkWidth()
4066 return defXLinkWidth;
4069 void VymModel::move(const double &x, const double &y)
4071 LinkableMapObj *sel=selection.single();
4074 QPointF ap(sel->getAbsPos());
4078 QString ps=qpointfToString(ap);
4079 QString s=selection.getSelectString();
4082 s, "move "+qpointfToString(to),
4083 QString("Move %1 to %2").arg(getObjectName(sel)).arg(ps));
4091 void VymModel::moveRel (const double &x, const double &y)
4093 LinkableMapObj *sel=selection.single();
4096 QPointF rp(sel->getRelPos());
4100 QString ps=qpointfToString (sel->getRelPos());
4101 QString s=getSelectString(sel);
4104 s, "moveRel "+qpointfToString(to),
4105 QString("Move %1 to relative position %2").arg(getObjectName(sel)).arg(ps));
4106 ((OrnamentedObj*)sel)->move2RelPos (x,y);
4115 void VymModel::animate()
4117 animationTimer->stop();
4120 while (i<animObjList.size() )
4122 bo=(BranchObj*)animObjList.at(i);
4127 animObjList.removeAt(i);
4134 mapEditor->updateSelection();
4136 if (!animObjList.isEmpty()) animationTimer->start();
4140 void VymModel::startAnimation(BranchObj *bo, const QPointF &start, const QPointF &dest)
4142 if (bo && bo->getDepth()>0)
4145 ap.setStart (start);
4147 ap.setTicks (animationTicks);
4148 ap.setAnimated (true);
4149 bo->setAnimation (ap);
4150 animObjList.append( bo );
4151 animationTimer->setSingleShot (true);
4152 animationTimer->start(animationInterval);
4156 void VymModel::stopAnimation (MapObj *mo)
4158 int i=animObjList.indexOf(mo);
4160 animObjList.removeAt (i);
4163 void VymModel::sendSelection()
4165 if (netstate!=Server) return;
4166 sendData (QString("select (\"%1\")").arg(selection.getSelectString()) );
4169 void VymModel::newServer()
4173 tcpServer = new QTcpServer(this);
4174 if (!tcpServer->listen(QHostAddress::Any,port)) {
4175 QMessageBox::critical(NULL, "vym server",
4176 QString("Unable to start the server: %1.").arg(tcpServer->errorString()));
4177 //FIXME needed? we are no widget any longer... close();
4180 connect(tcpServer, SIGNAL(newConnection()), this, SLOT(newClient()));
4182 cout<<"Server is running on port "<<tcpServer->serverPort()<<endl;
4185 void VymModel::connectToServer()
4188 server="salam.suse.de";
4190 clientSocket = new QTcpSocket (this);
4191 clientSocket->abort();
4192 clientSocket->connectToHost(server ,port);
4193 connect(clientSocket, SIGNAL(readyRead()), this, SLOT(readData()));
4194 connect(clientSocket, SIGNAL(error(QAbstractSocket::SocketError)),
4195 this, SLOT(displayNetworkError(QAbstractSocket::SocketError)));
4197 cout<<"connected to "<<qPrintable (server)<<" port "<<port<<endl;
4202 void VymModel::newClient()
4204 QTcpSocket *newClient = tcpServer->nextPendingConnection();
4205 connect(newClient, SIGNAL(disconnected()),
4206 newClient, SLOT(deleteLater()));
4208 cout <<"ME::newClient at "<<qPrintable( newClient->peerAddress().toString() )<<endl;
4210 clientList.append (newClient);
4214 void VymModel::sendData(const QString &s)
4216 if (clientList.size()==0) return;
4218 // Create bytearray to send
4220 QDataStream out(&block, QIODevice::WriteOnly);
4221 out.setVersion(QDataStream::Qt_4_0);
4223 // Reserve some space for blocksize
4226 // Write sendCounter
4227 out << sendCounter++;
4232 // Go back and write blocksize so far
4233 out.device()->seek(0);
4234 quint16 bs=(quint16)(block.size() - 2*sizeof(quint16));
4238 cout << "ME::sendData bs="<<bs<<" counter="<<sendCounter<<" s="<<qPrintable(s)<<endl;
4240 for (int i=0; i<clientList.size(); ++i)
4242 //cout << "Sending \""<<qPrintable (s)<<"\" to "<<qPrintable (clientList.at(i)->peerAddress().toString())<<endl;
4243 clientList.at(i)->write (block);
4247 void VymModel::readData ()
4249 while (clientSocket->bytesAvailable() >=(int)sizeof(quint16) )
4252 cout <<"readData bytesAvail="<<clientSocket->bytesAvailable();
4256 QDataStream in(clientSocket);
4257 in.setVersion(QDataStream::Qt_4_0);
4265 cout << " t="<<qPrintable (t)<<endl;
4271 void VymModel::displayNetworkError(QAbstractSocket::SocketError socketError)
4273 switch (socketError) {
4274 case QAbstractSocket::RemoteHostClosedError:
4276 case QAbstractSocket::HostNotFoundError:
4277 QMessageBox::information(NULL, vymName +" Network client",
4278 "The host was not found. Please check the "
4279 "host name and port settings.");
4281 case QAbstractSocket::ConnectionRefusedError:
4282 QMessageBox::information(NULL, vymName + " Network client",
4283 "The connection was refused by the peer. "
4284 "Make sure the fortune server is running, "
4285 "and check that the host name and port "
4286 "settings are correct.");
4289 QMessageBox::information(NULL, vymName + " Network client",
4290 QString("The following error occurred: %1.")
4291 .arg(clientSocket->errorString()));
4298 void VymModel::selectMapSelectionColor()
4300 QColor col = QColorDialog::getColor( defLinkColor, NULL);
4301 setSelectionColor (col);
4304 void VymModel::setSelectionColorInt (QColor col)
4306 if ( !col.isValid() ) return;
4308 QString("setSelectionColor (%1)").arg(selection.getColor().name()),
4309 QString("setSelectionColor (%1)").arg(col.name()),
4310 QString("Set color of selection box to %1").arg(col.name())
4313 selection.setColor (col);
4316 void VymModel::updateSelection()
4321 void VymModel::setSelectionColor(QColor col)
4323 if ( !col.isValid() ) return;
4325 QString("setSelectionColor (%1)").arg(selection.getColor().name()),
4326 QString("setSelectionColor (%1)").arg(col.name()),
4327 QString("Set color of selection box to %1").arg(col.name())
4329 setSelectionColorInt (col);
4332 QColor VymModel::getSelectionColor()
4334 return selection.getColor();
4337 void VymModel::setHideTmpMode (HideTmpMode mode)
4340 for (int i=0;i<mapCenters.count(); i++)
4341 mapCenters.at(i)->setHideTmp (mode);
4343 // FIXME needed? scene()->update();
4347 QRectF VymModel::getTotalBBox()
4350 for (int i=0;i<mapCenters.count(); i++)
4351 r=addBBox (mapCenters.at(i)->getTotalBBox(), r);
4355 //////////////////////////////////////////////
4356 // Selection related
4357 //////////////////////////////////////////////
4359 void VymModel::setSelectionModel (QItemSelectionModel *sm)
4364 void VymModel::setSelectionBlocked (bool b)
4369 selection.unblock();
4372 bool VymModel::isSelectionBlocked()
4374 return selection.isBlocked();
4377 bool VymModel::select ()
4379 QModelIndex index=selModel->selectedIndexes().first(); // TODO no multiselections yet
4381 TreeItem *item = static_cast<TreeItem*>(index.internalPointer());
4382 return select (item->getLMO() );
4385 bool VymModel::select (const QString &s)
4387 if (selection.select(s))
4390 ensureSelectionVisible();
4398 bool VymModel::select (LinkableMapObj *lmo)
4400 if (selection.select(lmo))
4403 ensureSelectionVisible();
4410 void VymModel::unselect()
4412 selection.unselect();
4415 void VymModel::reselect()
4417 selection.reselect();
4420 void VymModel::ensureSelectionVisible()
4422 LinkableMapObj *lmo=selection.single();
4423 if (lmo &&mapEditor) mapEditor->ensureVisible (lmo->getBBox() );
4427 void VymModel::selectInt (LinkableMapObj *lmo)
4429 if (selection.select(lmo))
4437 void VymModel::selectNextBranchInt()
4439 // Increase number of branch
4440 LinkableMapObj *sel=selection.single();
4443 QString s=selection.getSelectString();
4449 part=s.section(",",-1);
4451 num=part.right(part.length() - 3);
4453 s=s.left (s.length() -num.length());
4456 num=QString ("%1").arg(num.toUInt()+1);
4460 // Try to select this one
4461 if (select (s)) return;
4463 // We have no direct successor,
4464 // try to increase the parental number in order to
4465 // find a successor with same depth
4467 int d=selection.single()->getDepth();
4472 while (!found && d>0)
4474 s=s.section (",",0,d-1);
4475 // replace substring of current depth in s with "1"
4476 part=s.section(",",-1);
4478 num=part.right(part.length() - 3);
4482 // increase number of parent
4483 num=QString ("%1").arg(num.toUInt()+1);
4484 s=s.section (",",0,d-2) + ","+ typ+num;
4487 // Special case, look at orientation
4488 if (selection.single()->getOrientation()==LinkableMapObj::RightOfCenter)
4489 num=QString ("%1").arg(num.toUInt()+1);
4491 num=QString ("%1").arg(num.toUInt()-1);
4496 // pad to oldDepth, select the first branch for each depth
4497 for (i=d;i<oldDepth;i++)
4502 if ( selection.getBranch()->countBranches()>0)
4510 // try to select the freshly built string
4518 void VymModel::selectPrevBranchInt()
4520 // Decrease number of branch
4521 BranchObj *bo=selection.getBranch();
4524 QString s=selection.getSelectString();
4530 part=s.section(",",-1);
4532 num=part.right(part.length() - 3);
4534 s=s.left (s.length() -num.length());
4536 int n=num.toInt()-1;
4539 num=QString ("%1").arg(n);
4542 // Try to select this one
4543 if (n>=0 && select (s)) return;
4545 // We have no direct precessor,
4546 // try to decrease the parental number in order to
4547 // find a precessor with same depth
4549 int d=selection.single()->getDepth();
4554 while (!found && d>0)
4556 s=s.section (",",0,d-1);
4557 // replace substring of current depth in s with "1"
4558 part=s.section(",",-1);
4560 num=part.right(part.length() - 3);
4564 // decrease number of parent
4565 num=QString ("%1").arg(num.toInt()-1);
4566 s=s.section (",",0,d-2) + ","+ typ+num;
4569 // Special case, look at orientation
4570 if (selection.single()->getOrientation()==LinkableMapObj::RightOfCenter)
4571 num=QString ("%1").arg(num.toInt()-1);
4573 num=QString ("%1").arg(num.toInt()+1);
4578 // pad to oldDepth, select the last branch for each depth
4579 for (i=d;i<oldDepth;i++)
4583 if ( selection.getBranch()->countBranches()>0)
4584 s+=",bo:"+ QString ("%1").arg( selection.getBranch()->countBranches()-1 );
4591 // try to select the freshly built string
4599 void VymModel::selectUpperBranch()
4601 if (selection.isBlocked() ) return;
4603 BranchObj *bo=selection.getBranch();
4604 if (bo && selection.type()==Selection::Branch)
4606 if (bo->getOrientation()==LinkableMapObj::RightOfCenter)
4607 selectPrevBranchInt();
4609 if (bo->getDepth()==1)
4610 selectNextBranchInt();
4612 selectPrevBranchInt();
4616 void VymModel::selectLowerBranch()
4618 if (selection.isBlocked() ) return;
4620 BranchObj *bo=selection.getBranch();
4621 if (bo && selection.type()==Selection::Branch)
4623 if (bo->getOrientation()==LinkableMapObj::RightOfCenter)
4624 selectNextBranchInt();
4626 if (bo->getDepth()==1)
4627 selectPrevBranchInt();
4629 selectNextBranchInt();
4634 void VymModel::selectLeftBranch()
4636 if (selection.isBlocked() ) return;
4640 LinkableMapObj *sel=selection.single();
4643 if (selection.type()== Selection::MapCenter)
4645 par=selection.getBranch();
4646 bo=par->getLastSelectedBranch();
4649 // Workaround for reselecting on left and right side
4650 if (bo->getOrientation()==LinkableMapObj::RightOfCenter)
4651 bo=par->getLastBranch();
4654 bo=par->getLastBranch();
4655 selection.select(bo);
4657 ensureSelectionVisible();
4663 par=(BranchObj*)(sel->getParObj());
4664 if (sel->getOrientation()==LinkableMapObj::RightOfCenter)
4666 if (selection.type() == Selection::Branch ||
4667 selection.type() == Selection::FloatImage)
4669 selection.select(par);
4671 ensureSelectionVisible();
4676 if (selection.type() == Selection::Branch )
4678 bo=selection.getBranch()->getLastSelectedBranch();
4681 selection.select(bo);
4683 ensureSelectionVisible();
4692 void VymModel::selectRightBranch()
4694 if (selection.isBlocked() ) return;
4698 LinkableMapObj *sel=selection.single();
4701 if (selection.type()==Selection::MapCenter)
4703 par=selection.getBranch();
4704 bo=par->getLastSelectedBranch();
4707 // Workaround for reselecting on left and right side
4708 if (bo->getOrientation()==LinkableMapObj::LeftOfCenter)
4709 bo=par->getFirstBranch();
4712 selection.select(bo);
4714 ensureSelectionVisible();
4720 par=(BranchObj*)(selection.single()->getParObj());
4721 if (selection.single()->getOrientation()==LinkableMapObj::LeftOfCenter)
4723 if (selection.type() == Selection::Branch ||
4724 selection.type() == Selection::FloatImage)
4726 selection.select(par);
4728 ensureSelectionVisible();
4733 if (selection.type() == Selection::Branch)
4735 bo=selection.getBranch()->getLastSelectedBranch();
4738 selection.select(bo);
4740 ensureSelectionVisible();
4749 void VymModel::selectFirstBranch()
4751 BranchObj *bo1=selection.getBranch();
4756 par=(BranchObj*)(bo1->getParObj());
4758 bo2=par->getFirstBranch();
4760 selection.select(bo2);
4762 ensureSelectionVisible();
4768 void VymModel::selectLastBranch()
4770 BranchObj *bo1=selection.getBranch();
4775 par=(BranchObj*)(bo1->getParObj());
4777 bo2=par->getLastBranch();
4780 selection.select(bo2);
4782 ensureSelectionVisible();
4788 void VymModel::selectParent()
4790 LinkableMapObj *lmo=selection.first();
4794 par=(BranchObj*)(lmo->getParObj());
4796 selection.select(par);
4798 ensureSelectionVisible();
4803 Selection::Type VymModel::selectionType()
4805 return selection.type();
4808 LinkableMapObj* VymModel::getSelection()
4810 return selection.single();
4812 BranchObj* VymModel::getSelectedBranch()
4814 return selection.getBranch();
4817 FloatImageObj* VymModel::getSelectedFloatImage()
4819 return selection.getFloatImage();
4822 QString VymModel::getSelectString ()
4824 return selection.getSelectString();
4827 QString VymModel::getSelectString (LinkableMapObj *lmo)
4831 if (typeid(*lmo)==typeid(BranchObj) ||
4832 typeid(*lmo)==typeid(MapCenterObj) )
4834 LinkableMapObj *par=lmo->getParObj();
4837 if (lmo->getDepth() ==1)
4838 // Mainbranch, return
4839 s= "bo:" + QString("%1").arg(((BranchObj*)lmo)->getNum());
4841 // Branch, call myself recursively
4842 s= getSelectString(par) + ",bo:" + QString("%1").arg(((BranchObj*)lmo)->getNum());
4846 int i=mapCenters.indexOf ((MapCenterObj*)lmo);
4847 if (i>=0) s=QString("mc:%1").arg(i);