1 #include <QApplication>
6 #include "attributeitem.h"
8 #include "branchitem.h"
9 #include "editxlinkdialog.h"
11 #include "exportxhtmldialog.h"
13 #include "geometry.h" // for addBBox
14 #include "mainwindow.h"
18 #include "warningdialog.h"
19 #include "xlinkitem.h"
20 #include "xml-freemind.h"
26 extern Main *mainWindow;
27 extern QDBusConnection dbusConnection;
29 extern Settings settings;
30 extern QString tmpVymDir;
32 extern TextEditor *textEditor;
33 extern FlagRow *standardFlagsMaster;
35 extern QString clipboardDir;
36 extern QString clipboardFile;
37 extern bool clipboardEmpty;
39 extern ImageIO imageIO;
41 extern QString vymName;
42 extern QString vymVersion;
43 extern QDir vymBaseDir;
45 extern QDir lastImageDir;
46 extern QDir lastFileDir;
48 extern Settings settings;
52 int VymModel::mapNum=0; // make instance
56 // cout << "Const VymModel\n";
58 rootItem->setModel (this);
64 cout << "Destr VymModel\n";
65 autosaveTimer->stop();
66 fileChangedTimer->stop();
70 void VymModel::clear()
72 selModel->clearSelection();
74 //QModelIndex ri=index(rootItem);
75 //removeRows (0, rowCount(ri),ri); // FIXME-3 here should be at least a beginRemoveRows...
78 void VymModel::init ()
83 // Also no scene yet (should not be needed anyway) FIXME-3 VM
96 stepsTotal=settings.readNumEntry("/history/stepsTotal",100);
97 undoSet.setEntry ("/history/stepsTotal",QString::number(stepsTotal));
98 mainWindow->updateHistory (undoSet);
101 makeTmpDirectories();
106 fileName=tr("unnamed");
108 blockReposition=false;
109 blockSaveState=false;
111 autosaveTimer=new QTimer (this);
112 connect(autosaveTimer, SIGNAL(timeout()), this, SLOT(autosave()));
114 fileChangedTimer=new QTimer (this);
115 fileChangedTimer->start(3000);
116 connect(fileChangedTimer, SIGNAL(timeout()), this, SLOT(fileChanged()));
121 selectionBlocked=false;
128 // animations // FIXME-3 switch to new animation system
129 animationUse=settings.readBoolEntry("/animation/use",false); // FIXME-3 add options to control _what_ is animated
130 animationTicks=settings.readNumEntry("/animation/ticks",10);
131 animationInterval=settings.readNumEntry("/animation/interval",50);
133 animationTimer=new QTimer (this);
134 connect(animationTimer, SIGNAL(timeout()), this, SLOT(animate()));
137 defLinkColor=QColor (0,0,255);
138 defXLinkColor=QColor (180,180,180);
139 linkcolorhint=LinkableMapObj::DefaultColor;
140 linkstyle=LinkableMapObj::PolyParabel;
142 defXLinkColor=QColor (230,230,230);
144 hidemode=TreeItem::HideNone;
150 // addMapCenter(); FIXME-2 VM create this in MapEditor until BO and MCO are independent of scene
153 adaptorModel=new AdaptorModel(this); // Created and not deleted as documented in Qt
154 //adaptor->setModel (this);
155 //connection.registerObject("/Car", car);
156 dbusConnection.registerService("org.insilmaril.VymModel");
157 dbusConnection.sessionBus().registerObject ("/Object1",this);
160 void VymModel::makeTmpDirectories()
162 // Create unique temporary directories
163 tmpMapDir = tmpVymDir+QString("/model-%1").arg(mapNum);
164 histPath = tmpMapDir+"/history";
170 MapEditor* VymModel::getMapEditor() // FIXME-3 VM better return favourite editor here
175 bool VymModel::isRepositionBlocked()
177 return blockReposition;
180 void VymModel::updateActions() // FIXME-2 maybe don't update if blockReposition is set
182 //cout << "VM::updateActions \n";
183 // Tell mainwindow to update states of actions
184 mainWindow->updateActions();
189 QString VymModel::saveToDir(const QString &tmpdir, const QString &prefix, bool writeflags, const QPointF &offset, TreeItem *saveSel)
191 // tmpdir temporary directory to which data will be written
192 // prefix mapname, which will be appended to images etc.
193 // writeflags Only write flags for "real" save of map, not undo
194 // offset offset of bbox of whole map in scene.
195 // Needed for XML export
204 case LinkableMapObj::Line:
207 case LinkableMapObj::Parabel:
210 case LinkableMapObj::PolyLine:
214 ls="StylePolyParabel";
218 QString s="<?xml version=\"1.0\" encoding=\"utf-8\"?><!DOCTYPE vymmap>\n";
220 if (linkcolorhint==LinkableMapObj::HeadingColor)
221 colhint=xml.attribut("linkColorHint","HeadingColor");
223 QString mapAttr=xml.attribut("version",vymVersion);
225 mapAttr+= xml.attribut("author",author) +
226 xml.attribut("comment",comment) +
227 xml.attribut("date",getDate()) +
228 xml.attribut("branchCount", QString().number(branchCount())) +
229 xml.attribut("backgroundColor", mapScene->backgroundBrush().color().name() ) +
230 xml.attribut("selectionColor", mapEditor->getSelectionColor().name() ) +
231 xml.attribut("linkStyle", ls ) +
232 xml.attribut("linkColor", defLinkColor.name() ) +
233 xml.attribut("defXLinkColor", defXLinkColor.name() ) +
234 xml.attribut("defXLinkWidth", QString().setNum(defXLinkWidth,10) ) +
236 s+=xml.beginElement("vymmap",mapAttr);
239 // Find the used flags while traversing the tree // FIXME-3 this can be done local to vymmodel maybe...
240 standardFlagsMaster->resetUsedCounter();
242 // Build xml recursivly
244 // Save all mapcenters as complete map, if saveSel not set
245 s+=saveTreeToDir(tmpdir,prefix,writeflags,offset);
248 switch (saveSel->getType())
250 case TreeItem::Branch:
252 s+=((BranchItem*)saveSel)->saveToDir(tmpdir,prefix,offset);
254 case TreeItem::MapCenter:
256 s+=((BranchItem*)saveSel)->saveToDir(tmpdir,prefix,offset);
258 case TreeItem::Image:
260 s+=((ImageItem*)saveSel)->saveToDir(tmpdir,prefix);
263 // other types shouldn't be safed directly...
268 // Save local settings
269 s+=settings.getDataXML (destPath);
272 if (getSelectedItem() && !saveSel )
273 s+=xml.valueElement("select",getSelectString());
276 s+=xml.endElement("vymmap");
278 //cout << s.toStdString() << endl;
280 if (writeflags) standardFlagsMaster->saveToDir (tmpdir+"/flags/","",writeflags);
284 QString VymModel::saveTreeToDir (const QString &tmpdir,const QString &prefix, int verbose, const QPointF &offset) // FIXME-4 verbose not needed (used to write icons)
288 for (int i=0; i<rootItem->branchCount(); i++)
289 s+=rootItem->getBranchNum(i)->saveToDir (tmpdir,prefix,offset);
293 void VymModel::setFilePath(QString fpath, QString destname)
295 if (fpath.isEmpty() || fpath=="")
302 filePath=fpath; // becomes absolute path
303 fileName=fpath; // gets stripped of path
304 destPath=destname; // needed for vymlinks and during load to reset fileChangedTime
306 // If fpath is not an absolute path, complete it
307 filePath=QDir(fpath).absPath();
308 fileDir=filePath.left (1+filePath.findRev ("/"));
310 // Set short name, too. Search from behind:
311 int i=fileName.findRev("/");
312 if (i>=0) fileName=fileName.remove (0,i+1);
314 // Forget the .vym (or .xml) for name of map
315 mapName=fileName.left(fileName.findRev(".",-1,true) );
319 void VymModel::setFilePath(QString fpath)
321 setFilePath (fpath,fpath);
324 QString VymModel::getFilePath()
329 QString VymModel::getFileName()
334 QString VymModel::getMapName()
339 QString VymModel::getDestPath()
344 ErrorCode VymModel::load (QString fname, const LoadMode &lmode, const FileType &ftype)
346 ErrorCode err=success;
348 parseBaseHandler *handler;
352 case VymMap: handler=new parseVYMHandler; break;
353 case FreemindMap : handler=new parseFreemindHandler; break;
355 QMessageBox::critical( 0, tr( "Critical Parse Error" ),
356 "Unknown FileType in VymModel::load()");
360 bool zipped_org=zipped;
364 selModel->clearSelection();
365 // FIXME-2 VM not needed??? model->setMapEditor(this);
366 // (map state is set later at end of load...)
369 BranchItem *bi=getSelectedBranch();
370 if (!bi) return aborted;
371 if (lmode==ImportAdd)
372 saveStateChangingPart(
375 QString("addMapInsert (%1)").arg(fname),
376 QString("Add map %1 to %2").arg(fname).arg(getObjectName(bi)));
378 saveStateChangingPart(
381 QString("addMapReplace(%1)").arg(fname),
382 QString("Add map %1 to %2").arg(fname).arg(getObjectName(bi)));
386 // Create temporary directory for packing
388 QString tmpZipDir=makeTmpDir (ok,"vym-pack");
391 QMessageBox::critical( 0, tr( "Critical Load Error" ),
392 tr("Couldn't create temporary directory before load\n"));
397 err=unzipDir (tmpZipDir,fname);
407 // Look for mapname.xml
408 xmlfile= fname.left(fname.findRev(".",-1,true));
409 xmlfile=xmlfile.section( '/', -1 );
410 QFile mfile( tmpZipDir + "/" + xmlfile + ".xml");
411 if (!mfile.exists() )
413 // mapname.xml does not exist, well,
414 // maybe someone renamed the mapname.vym file...
415 // Try to find any .xml in the toplevel
416 // directory of the .vym file
417 QStringList flist=QDir (tmpZipDir).entryList("*.xml");
418 if (flist.count()==1)
420 // Only one entry, take this one
421 xmlfile=tmpZipDir + "/"+flist.first();
424 for ( QStringList::Iterator it = flist.begin(); it != flist.end(); ++it )
425 *it=tmpZipDir + "/" + *it;
426 // TODO Multiple entries, load all (but only the first one into this ME)
427 //mainWindow->fileLoadFromTmp (flist);
428 //returnCode=1; // Silently forget this attempt to load
429 qWarning ("MainWindow::load (fn) multimap found...");
432 if (flist.isEmpty() )
434 QMessageBox::critical( 0, tr( "Critical Load Error" ),
435 tr("Couldn't find a map (*.xml) in .vym archive.\n"));
438 } //file doesn't exist
440 xmlfile=mfile.name();
443 QFile file( xmlfile);
445 // I am paranoid: file should exist anyway
446 // according to check in mainwindow.
449 QMessageBox::critical( 0, tr( "Critical Parse Error" ),
450 tr(QString("Couldn't open map %1").arg(file.name())));
454 bool blockSaveStateOrg=blockSaveState;
455 blockReposition=true;
457 mapEditor->setViewportUpdateMode (QGraphicsView::NoViewportUpdate);
458 QXmlInputSource source( file);
459 QXmlSimpleReader reader;
460 reader.setContentHandler( handler );
461 reader.setErrorHandler( handler );
462 handler->setModel ( this);
465 // We need to set the tmpDir in order to load files with rel. path
470 tmpdir=fname.left(fname.findRev("/",-1));
471 handler->setTmpDir (tmpdir);
472 handler->setInputFile (file.name());
473 handler->setLoadMode (lmode);
474 bool ok = reader.parse( source );
475 blockReposition=false;
476 blockSaveState=blockSaveStateOrg;
477 mapEditor->setViewportUpdateMode (QGraphicsView::MinimalViewportUpdate);
481 reposition(); // FIXME-2 VM reposition the view instead...
482 emitSelectionChanged();
488 autosaveTimer->stop();
491 // Reset timestamp to check for later updates of file
492 fileChangedTime=QFileInfo (destPath).lastModified();
495 QMessageBox::critical( 0, tr( "Critical Parse Error" ),
496 tr( handler->errorProtocol() ) );
498 // Still return "success": the map maybe at least
499 // partially read by the parser
504 removeDir (QDir(tmpZipDir));
506 // Restore original zip state
513 ErrorCode VymModel::save (const SaveMode &savemode)
517 QString safeFilePath;
519 ErrorCode err=success;
523 mapFileName=mapName+".xml";
525 // use name given by user, even if he chooses .doc
526 mapFileName=fileName;
528 // Look, if we should zip the data:
531 QMessageBox mb( vymName,
532 tr("The map %1\ndid not use the compressed "
533 "vym file format.\nWriting it uncompressed will also write images \n"
534 "and flags and thus may overwrite files in the "
535 "given directory\n\nDo you want to write the map").arg(filePath),
536 QMessageBox::Warning,
537 QMessageBox::Yes | QMessageBox::Default,
539 QMessageBox::Cancel | QMessageBox::Escape);
540 mb.setButtonText( QMessageBox::Yes, tr("compressed (vym default)") );
541 mb.setButtonText( QMessageBox::No, tr("uncompressed") );
542 mb.setButtonText( QMessageBox::Cancel, tr("Cancel"));
545 case QMessageBox::Yes:
546 // save compressed (default file format)
549 case QMessageBox::No:
553 case QMessageBox::Cancel:
560 // First backup existing file, we
561 // don't want to add to old zip archives
565 if ( settings.value ("/mapeditor/writeBackupFile").toBool())
567 QString backupFileName(destPath + "~");
568 QFile backupFile(backupFileName);
569 if (backupFile.exists() && !backupFile.remove())
571 QMessageBox::warning(0, tr("Save Error"),
572 tr("%1\ncould not be removed before saving").arg(backupFileName));
574 else if (!f.rename(backupFileName))
576 QMessageBox::warning(0, tr("Save Error"),
577 tr("%1\ncould not be renamed before saving").arg(destPath));
584 // Create temporary directory for packing
586 tmpZipDir=makeTmpDir (ok,"vym-zip");
589 QMessageBox::critical( 0, tr( "Critical Load Error" ),
590 tr("Couldn't create temporary directory before save\n"));
594 safeFilePath=filePath;
595 setFilePath (tmpZipDir+"/"+ mapName+ ".xml", safeFilePath);
598 // Create mapName and fileDir
599 makeSubDirs (fileDir);
602 if (savemode==CompleteMap || selModel->selection().isEmpty())
605 saveFile=saveToDir (fileDir,mapName+"-",true,QPointF(),NULL);
608 autosaveTimer->stop();
613 if (selectionType()==TreeItem::Image)
616 saveFile=saveToDir (fileDir,mapName+"-",true,QPointF(),getSelectedBranch());
617 // TODO take care of multiselections
620 if (!saveStringToDisk(fileDir+mapFileName,saveFile))
623 qWarning ("ME::saveStringToDisk failed!");
629 if (err==success) err=zipDir (tmpZipDir,destPath);
632 removeDir (QDir(tmpZipDir));
634 // Restore original filepath outside of tmp zip dir
635 setFilePath (safeFilePath);
639 fileChangedTime=QFileInfo (destPath).lastModified();
643 void VymModel::addMapReplaceInt(const QString &undoSel, const QString &path) // FIXME-1 test e.g. with undo color subtree
645 QString pathDir=path.left(path.findRev("/"));
651 // We need to parse saved XML data
652 parseVYMHandler handler;
653 QXmlInputSource source( file);
654 QXmlSimpleReader reader;
655 reader.setContentHandler( &handler );
656 reader.setErrorHandler( &handler );
657 handler.setModel ( this);
658 handler.setTmpDir ( pathDir ); // needed to load files with rel. path
659 if (undoSel.isEmpty())
663 handler.setLoadMode (NewMap);
667 handler.setLoadMode (ImportReplace);
669 blockReposition=true;
670 bool ok = reader.parse( source );
671 blockReposition=false;
674 // This should never ever happen
675 QMessageBox::critical( 0, tr( "Critical Parse Error while reading %1").arg(path),
676 handler.errorProtocol());
679 QMessageBox::critical( 0, tr( "Critical Error" ), tr("Could not read %1").arg(path));
682 bool VymModel::addMapInsertInt (const QString &path)
684 QString pathDir=path.left(path.findRev("/"));
690 // We need to parse saved XML data
691 parseVYMHandler handler;
692 QXmlInputSource source( file);
693 QXmlSimpleReader reader;
694 reader.setContentHandler( &handler );
695 reader.setErrorHandler( &handler );
696 handler.setModel (this);
697 handler.setTmpDir ( pathDir ); // needed to load files with rel. path
698 handler.setLoadMode (ImportAdd);
699 blockReposition=true;
700 bool ok = reader.parse( source );
701 blockReposition=false;
702 if ( ok ) return true;
704 // This should never ever happen
705 QMessageBox::critical( 0, tr( "Critical Parse Error while reading %1").arg(path),
706 handler.errorProtocol());
709 QMessageBox::critical( 0, tr( "Critical Error" ), tr("Could not read %1").arg(path));
713 bool VymModel::addMapInsertInt (const QString &path, int pos)
715 BranchItem *selbi=getSelectedBranch();
718 if (addMapInsertInt (path))
720 if (selbi->depth()>0)
721 relinkBranch (selbi->getLastBranch(), selbi,pos);
725 QMessageBox::critical( 0, tr( "Critical Error" ), tr("Could not read %1").arg(path));
729 qWarning ("ME::addMapInsertInt nothing selected");
733 ImageItem* VymModel::loadFloatImageInt (BranchItem *dst,QString fn)
735 ImageItem *ii=createImage(dst);
745 void VymModel::loadFloatImage ()
747 BranchItem *selbi=getSelectedBranch();
751 Q3FileDialog *fd=new Q3FileDialog( NULL); // FIXME-4 get rid of Q3FileDialog
752 fd->setMode (Q3FileDialog::ExistingFiles);
753 fd->addFilter (QString (tr("Images") + " (*.png *.bmp *.xbm *.jpg *.png *.xpm *.gif *.pnm)"));
754 ImagePreview *p =new ImagePreview (fd);
755 fd->setContentsPreviewEnabled( TRUE );
756 fd->setContentsPreview( p, p );
757 fd->setPreviewMode( Q3FileDialog::Contents );
758 fd->setCaption(vymName+" - " +tr("Load image"));
759 fd->setDir (lastImageDir);
762 if ( fd->exec() == QDialog::Accepted )
764 // TODO loadFIO in QT4 use: lastImageDir=fd->directory();
765 lastImageDir=QDir (fd->dirPath());
768 for (int j=0; j<fd->selectedFiles().count(); j++)
770 s=fd->selectedFiles().at(j);
771 ii=loadFloatImageInt (selbi,s);
772 //FIXME-3 check savestate for loadImage
778 QString ("loadImage (%1)").arg(s ),
779 QString("Add image %1 to %2").arg(s).arg(getObjectName(selbi))
782 // TODO loadFIO error handling
783 qWarning ("Failed to load "+s);
791 void VymModel::saveFloatImageInt (ImageItem *ii, const QString &type, const QString &fn)
796 void VymModel::saveFloatImage ()
798 ImageItem *ii=getSelectedImage();
801 QFileDialog *fd=new QFileDialog( NULL);
802 fd->setFilters (imageIO.getFilters());
803 fd->setCaption(vymName+" - " +tr("Save image"));
804 fd->setFileMode( QFileDialog::AnyFile );
805 fd->setDirectory (lastImageDir);
806 // fd->setSelection (fio->getOriginalFilename());
810 if ( fd->exec() == QDialog::Accepted && fd->selectedFiles().count()==1)
812 fn=fd->selectedFiles().at(0);
813 if (QFile (fn).exists() )
815 QMessageBox mb( vymName,
816 tr("The file %1 exists already.\n"
817 "Do you want to overwrite it?").arg(fn),
818 QMessageBox::Warning,
819 QMessageBox::Yes | QMessageBox::Default,
820 QMessageBox::Cancel | QMessageBox::Escape,
821 QMessageBox::NoButton );
823 mb.setButtonText( QMessageBox::Yes, tr("Overwrite") );
824 mb.setButtonText( QMessageBox::No, tr("Cancel"));
827 case QMessageBox::Yes:
830 case QMessageBox::Cancel:
837 saveFloatImageInt (ii,fd->selectedFilter(),fn );
844 void VymModel::importDirInt(BranchItem *dst, QDir d)
846 BranchItem *selbi=getSelectedBranch();
850 // Traverse directories
851 d.setFilter( QDir::Dirs| QDir::Hidden | QDir::NoSymLinks );
852 QFileInfoList list = d.entryInfoList();
855 for (int i = 0; i < list.size(); ++i)
858 if (fi.fileName() != "." && fi.fileName() != ".." )
860 bi=addNewBranchInt(dst,-2);
861 bi->setHeading (fi.fileName() ); // FIXME-3 check this
862 bi->setHeadingColor (QColor("blue"));
864 if ( !d.cd(fi.fileName()) )
865 QMessageBox::critical (0,tr("Critical Import Error"),tr("Cannot find the directory %1").arg(fi.fileName()));
868 // Recursively add subdirs
875 d.setFilter( QDir::Files| QDir::Hidden | QDir::NoSymLinks );
876 list = d.entryInfoList();
878 for (int i = 0; i < list.size(); ++i)
881 bi=addNewBranchInt (dst,-2);
882 bi->setHeading (fi.fileName() );
883 bi->setHeadingColor (QColor("black"));
884 if (fi.fileName().right(4) == ".vym" )
885 bi->setVymLink (fi.filePath());
890 void VymModel::importDirInt (const QString &s)
892 BranchItem *selbi=getSelectedBranch();
895 saveStateChangingPart (selbi,selbi,QString ("importDir (\"%1\")").arg(s),QString("Import directory structure from %1").arg(s));
898 importDirInt (selbi,d);
902 void VymModel::importDir() //FIXME-3 check me... (not tested yet)
904 BranchItem *selbi=getSelectedBranch();
908 filters <<"VYM map (*.vym)";
909 QFileDialog *fd=new QFileDialog( NULL,vymName+ " - " +tr("Choose directory structure to import"));
910 fd->setMode (QFileDialog::DirectoryOnly);
911 fd->setFilters (filters);
912 fd->setCaption(vymName+" - " +tr("Choose directory structure to import"));
916 if ( fd->exec() == QDialog::Accepted )
918 importDirInt (fd->selectedFile() );
920 //FIXME-3 VM needed? scene()->update();
926 void VymModel::autosave()
931 cout << "VymModel::autosave rejected due to missing filePath\n";
934 QDateTime now=QDateTime().currentDateTime();
936 // Disable autosave, while we have gone back in history
937 int redosAvail=undoSet.readNumEntry (QString("/history/redosAvail"));
938 if (redosAvail>0) return;
940 // Also disable autosave for new map without filename
941 if (filePath.isEmpty()) return;
944 if (mapUnsaved &&mapChanged && settings.value ("/mainwindow/autosave/use",true).toBool() )
946 if (QFileInfo(filePath).lastModified()<=fileChangedTime)
947 mainWindow->fileSave (this);
950 cout <<" ME::autosave rejected, file on disk is newer than last save.\n";
955 void VymModel::fileChanged()
957 // Check if file on disk has changed meanwhile
958 if (!filePath.isEmpty())
960 QDateTime tmod=QFileInfo (filePath).lastModified();
961 if (tmod>fileChangedTime)
963 // FIXME-2 VM switch to current mapeditor and finish lineedits...
964 QMessageBox mb( vymName,
965 tr("The file of the map on disk has changed:\n\n"
966 " %1\n\nDo you want to reload that map with the new file?").arg(filePath),
967 QMessageBox::Question,
969 QMessageBox::Cancel | QMessageBox::Default,
970 QMessageBox::NoButton );
972 mb.setButtonText( QMessageBox::Yes, tr("Reload"));
973 mb.setButtonText( QMessageBox::No, tr("Ignore"));
976 case QMessageBox::Yes:
978 load (filePath,NewMap,fileType);
979 case QMessageBox::Cancel:
980 fileChangedTime=tmod; // allow autosave to overwrite newer file!
986 bool VymModel::isDefault()
991 void VymModel::makeDefault()
997 bool VymModel::hasChanged()
1002 void VymModel::setChanged()
1005 autosaveTimer->start(settings.value("/mainwindow/autosave/ms/",300000).toInt());
1009 latestAddedItem=NULL;
1013 QString VymModel::getObjectName (LinkableMapObj *lmo) // FIXME-3 should be obsolete
1015 if (!lmo || !lmo->getTreeItem() ) return QString();
1016 return getObjectName (lmo->getTreeItem() );
1020 QString VymModel::getObjectName (TreeItem *ti)
1023 if (!ti) return QString("Error: NULL has no name!");
1025 if (s=="") s="unnamed";
1027 return QString ("%1 (%2)").arg(ti->getTypeName()).arg(s);
1030 void VymModel::redo()
1032 // Can we undo at all?
1033 if (redosAvail<1) return;
1035 bool blockSaveStateOrg=blockSaveState;
1036 blockSaveState=true;
1040 if (undosAvail<stepsTotal) undosAvail++;
1042 if (curStep>stepsTotal) curStep=1;
1043 QString undoCommand= undoSet.readEntry (QString("/history/step-%1/undoCommand").arg(curStep));
1044 QString undoSelection=undoSet.readEntry (QString("/history/step-%1/undoSelection").arg(curStep));
1045 QString redoCommand= undoSet.readEntry (QString("/history/step-%1/redoCommand").arg(curStep));
1046 QString redoSelection=undoSet.readEntry (QString("/history/step-%1/redoSelection").arg(curStep));
1047 QString comment=undoSet.readEntry (QString("/history/step-%1/comment").arg(curStep));
1048 QString version=undoSet.readEntry ("/history/version");
1050 /* TODO Maybe check for version, if we save the history
1051 if (!checkVersion(version))
1052 QMessageBox::warning(0,tr("Warning"),
1053 tr("Version %1 of saved undo/redo data\ndoes not match current vym version %2.").arg(version).arg(vymVersion));
1056 // Find out current undo directory
1057 QString bakMapDir(QString(tmpMapDir+"/undo-%1").arg(curStep));
1061 cout << "VymModel::redo() begin\n";
1062 cout << " undosAvail="<<undosAvail<<endl;
1063 cout << " redosAvail="<<redosAvail<<endl;
1064 cout << " curStep="<<curStep<<endl;
1065 cout << " ---------------------------"<<endl;
1066 cout << " comment="<<comment.toStdString()<<endl;
1067 cout << " undoCom="<<undoCommand.toStdString()<<endl;
1068 cout << " undoSel="<<undoSelection.toStdString()<<endl;
1069 cout << " redoCom="<<redoCommand.toStdString()<<endl;
1070 cout << " redoSel="<<redoSelection.toStdString()<<endl;
1071 cout << " ---------------------------"<<endl<<endl;
1074 // select object before redo
1075 if (!redoSelection.isEmpty())
1076 select (redoSelection);
1079 parseAtom (redoCommand);
1082 blockSaveState=blockSaveStateOrg;
1084 undoSet.setEntry ("/history/undosAvail",QString::number(undosAvail));
1085 undoSet.setEntry ("/history/redosAvail",QString::number(redosAvail));
1086 undoSet.setEntry ("/history/curStep",QString::number(curStep));
1087 undoSet.writeSettings(histPath);
1089 mainWindow->updateHistory (undoSet);
1092 /* TODO remove testing
1093 cout << "ME::redo() end\n";
1094 cout << " undosAvail="<<undosAvail<<endl;
1095 cout << " redosAvail="<<redosAvail<<endl;
1096 cout << " curStep="<<curStep<<endl;
1097 cout << " ---------------------------"<<endl<<endl;
1103 bool VymModel::isRedoAvailable()
1105 if (undoSet.readNumEntry("/history/redosAvail",0)>0)
1111 void VymModel::undo()
1113 // Can we undo at all?
1114 if (undosAvail<1) return;
1116 mainWindow->statusMessage (tr("Autosave disabled during undo."));
1118 bool blockSaveStateOrg=blockSaveState;
1119 blockSaveState=true;
1121 QString undoCommand= undoSet.readEntry (QString("/history/step-%1/undoCommand").arg(curStep));
1122 QString undoSelection=undoSet.readEntry (QString("/history/step-%1/undoSelection").arg(curStep));
1123 QString redoCommand= undoSet.readEntry (QString("/history/step-%1/redoCommand").arg(curStep));
1124 QString redoSelection=undoSet.readEntry (QString("/history/step-%1/redoSelection").arg(curStep));
1125 QString comment=undoSet.readEntry (QString("/history/step-%1/comment").arg(curStep));
1126 QString version=undoSet.readEntry ("/history/version");
1128 /* TODO Maybe check for version, if we save the history
1129 if (!checkVersion(version))
1130 QMessageBox::warning(0,tr("Warning"),
1131 tr("Version %1 of saved undo/redo data\ndoes not match current vym version %2.").arg(version).arg(vymVersion));
1134 // Find out current undo directory
1135 QString bakMapDir(QString(tmpMapDir+"/undo-%1").arg(curStep));
1137 // select object before undo
1138 if (!select (undoSelection))
1140 qWarning ("VymModel::undo() Could not select object for undo");
1146 cout << "VymModel::undo() begin\n";
1147 cout << " undosAvail="<<undosAvail<<endl;
1148 cout << " redosAvail="<<redosAvail<<endl;
1149 cout << " curStep="<<curStep<<endl;
1150 cout << " ---------------------------"<<endl;
1151 cout << " comment="<<comment.toStdString()<<endl;
1152 cout << " undoCom="<<undoCommand.toStdString()<<endl;
1153 cout << " undoSel="<<undoSelection.toStdString()<<endl;
1154 cout << " redoCom="<<redoCommand.toStdString()<<endl;
1155 cout << " redoSel="<<redoSelection.toStdString()<<endl;
1156 cout << " ---------------------------"<<endl<<endl;
1158 parseAtom (undoCommand);
1163 if (curStep<1) curStep=stepsTotal;
1167 blockSaveState=blockSaveStateOrg;
1169 cout << "VymModel::undo() end\n";
1170 cout << " undosAvail="<<undosAvail<<endl;
1171 cout << " redosAvail="<<redosAvail<<endl;
1172 cout << " curStep="<<curStep<<endl;
1173 cout << " ---------------------------"<<endl<<endl;
1176 undoSet.setEntry ("/history/undosAvail",QString::number(undosAvail));
1177 undoSet.setEntry ("/history/redosAvail",QString::number(redosAvail));
1178 undoSet.setEntry ("/history/curStep",QString::number(curStep));
1179 undoSet.writeSettings(histPath);
1181 mainWindow->updateHistory (undoSet);
1183 emitSelectionChanged();
1186 bool VymModel::isUndoAvailable()
1188 if (undoSet.readNumEntry("/history/undosAvail",0)>0)
1194 void VymModel::gotoHistoryStep (int i)
1196 // Restore variables
1197 int undosAvail=undoSet.readNumEntry (QString("/history/undosAvail"));
1198 int redosAvail=undoSet.readNumEntry (QString("/history/redosAvail"));
1200 if (i<0) i=undosAvail+redosAvail;
1202 // Clicking above current step makes us undo things
1205 for (int j=0; j<undosAvail-i; j++) undo();
1208 // Clicking below current step makes us redo things
1210 for (int j=undosAvail; j<i; j++)
1212 if (debug) cout << "VymModel::gotoHistoryStep redo "<<j<<"/"<<undosAvail<<" i="<<i<<endl;
1216 // And ignore clicking the current row ;-)
1220 QString VymModel::getHistoryPath()
1222 QString histName(QString("history-%1").arg(curStep));
1223 return (tmpMapDir+"/"+histName);
1226 void VymModel::saveState(const SaveMode &savemode, const QString &undoSelection, const QString &undoCom, const QString &redoSelection, const QString &redoCom, const QString &comment, TreeItem *saveSel)
1228 sendData(redoCom); //FIXME-3 testing
1233 if (blockSaveState) return;
1235 if (debug) cout << "VM::saveState() for "<<qPrintable (mapName)<<endl;
1237 // Find out current undo directory
1238 if (undosAvail<stepsTotal) undosAvail++;
1240 if (curStep>stepsTotal) curStep=1;
1242 QString backupXML="";
1243 QString histDir=getHistoryPath();
1244 QString bakMapPath=histDir+"/map.xml";
1246 // Create histDir if not available
1249 makeSubDirs (histDir);
1251 // Save depending on how much needs to be saved
1253 backupXML=saveToDir (histDir,mapName+"-",false, QPointF (),saveSel);
1255 QString undoCommand="";
1256 if (savemode==UndoCommand)
1258 undoCommand=undoCom;
1260 else if (savemode==PartOfMap )
1262 undoCommand=undoCom;
1263 undoCommand.replace ("PATH",bakMapPath);
1267 if (!backupXML.isEmpty())
1268 // Write XML Data to disk
1269 saveStringToDisk (bakMapPath,backupXML);
1271 // We would have to save all actions in a tree, to keep track of
1272 // possible redos after a action. Possible, but we are too lazy: forget about redos.
1275 // Write the current state to disk
1276 undoSet.setEntry ("/history/undosAvail",QString::number(undosAvail));
1277 undoSet.setEntry ("/history/redosAvail",QString::number(redosAvail));
1278 undoSet.setEntry ("/history/curStep",QString::number(curStep));
1279 undoSet.setEntry (QString("/history/step-%1/undoCommand").arg(curStep),undoCommand);
1280 undoSet.setEntry (QString("/history/step-%1/undoSelection").arg(curStep),undoSelection);
1281 undoSet.setEntry (QString("/history/step-%1/redoCommand").arg(curStep),redoCom);
1282 undoSet.setEntry (QString("/history/step-%1/redoSelection").arg(curStep),redoSelection);
1283 undoSet.setEntry (QString("/history/step-%1/comment").arg(curStep),comment);
1284 undoSet.setEntry (QString("/history/version"),vymVersion);
1285 undoSet.writeSettings(histPath);
1289 // TODO remove after testing
1290 //cout << " into="<< histPath.toStdString()<<endl;
1291 cout << " stepsTotal="<<stepsTotal<<
1292 ", undosAvail="<<undosAvail<<
1293 ", redosAvail="<<redosAvail<<
1294 ", curStep="<<curStep<<endl;
1295 cout << " ---------------------------"<<endl;
1296 cout << " comment="<<comment.toStdString()<<endl;
1297 cout << " undoCom="<<undoCommand.toStdString()<<endl;
1298 cout << " undoSel="<<undoSelection.toStdString()<<endl;
1299 cout << " redoCom="<<redoCom.toStdString()<<endl;
1300 cout << " redoSel="<<redoSelection.toStdString()<<endl;
1301 if (saveSel) cout << " saveSel="<<qPrintable (getSelectString(saveSel))<<endl;
1302 cout << " ---------------------------"<<endl;
1305 mainWindow->updateHistory (undoSet);
1311 void VymModel::saveStateChangingPart(TreeItem *undoSel, TreeItem* redoSel, const QString &rc, const QString &comment)
1313 // save the selected part of the map, Undo will replace part of map
1314 QString undoSelection="";
1316 undoSelection=getSelectString(undoSel);
1318 qWarning ("VymModel::saveStateChangingPart no undoSel given!");
1319 QString redoSelection="";
1321 redoSelection=getSelectString(undoSel);
1323 qWarning ("VymModel::saveStateChangingPart no redoSel given!");
1326 saveState (PartOfMap,
1327 undoSelection, "addMapReplace (\"PATH\")",
1333 void VymModel::saveStateRemovingPart(TreeItem* redoSel, const QString &comment)
1337 qWarning ("VymModel::saveStateRemovingPart no redoSel given!");
1340 QString undoSelection;
1341 QString redoSelection=getSelectString(redoSel);
1342 if (redoSel->getType()==TreeItem::Branch)
1344 undoSelection=getSelectString (redoSel->parent());
1345 // save the selected branch of the map, Undo will insert part of map
1346 saveState (PartOfMap,
1347 undoSelection, QString("addMapInsert (\"PATH\",%1)").arg(redoSel->num()),
1348 redoSelection, "delete ()",
1352 if (redoSel->getType()==TreeItem::MapCenter)
1354 // save the selected branch of the map, Undo will insert part of map
1355 saveState (PartOfMap,
1356 undoSelection, QString("addMapInsert (\"PATH\")"),
1357 redoSelection, "delete ()",
1364 void VymModel::saveState(TreeItem *undoSel, const QString &uc, TreeItem *redoSel, const QString &rc, const QString &comment)
1366 // "Normal" savestate: save commands, selections and comment
1367 // so just save commands for undo and redo
1368 // and use current selection
1370 QString redoSelection="";
1371 if (redoSel) redoSelection=getSelectString(redoSel);
1372 QString undoSelection="";
1373 if (undoSel) undoSelection=getSelectString(undoSel);
1375 saveState (UndoCommand,
1382 void VymModel::saveState(const QString &undoSel, const QString &uc, const QString &redoSel, const QString &rc, const QString &comment)
1384 // "Normal" savestate: save commands, selections and comment
1385 // so just save commands for undo and redo
1386 // and use current selection
1387 saveState (UndoCommand,
1394 void VymModel::saveState(const QString &uc, const QString &rc, const QString &comment)
1396 // "Normal" savestate applied to model (no selection needed):
1397 // save commands and comment
1398 saveState (UndoCommand,
1406 QGraphicsScene* VymModel::getScene ()
1411 TreeItem* VymModel::findBySelectString(QString s)
1413 if (s.isEmpty() ) return NULL;
1415 // Old maps don't have multiple mapcenters and don't save full path
1416 if (s.left(2) !="mc")
1419 QStringList parts=s.split (",");
1422 TreeItem *ti=rootItem;
1424 while (!parts.isEmpty() )
1426 typ=parts.first().left(2);
1427 n=parts.first().right(parts.first().length() - 3).toInt();
1428 parts.removeFirst();
1429 if (typ=="mc" || typ=="bo")
1430 ti=ti->getBranchNum (n);
1432 ti=ti->getImageNum (n);
1434 ti=ti->getAttributeNum (n);
1436 ti=ti->getXLinkNum (n);
1437 if(!ti) return NULL;
1442 TreeItem* VymModel::findID (const QString &s)
1444 BranchItem *cur=NULL;
1445 BranchItem *prev=NULL;
1449 if (s==cur->getID() ) return cur;
1455 //////////////////////////////////////////////
1457 //////////////////////////////////////////////
1458 void VymModel::setVersion (const QString &s)
1463 void VymModel::setAuthor (const QString &s)
1466 QString ("setMapAuthor (\"%1\")").arg(author),
1467 QString ("setMapAuthor (\"%1\")").arg(s),
1468 QString ("Set author of map to \"%1\"").arg(s)
1473 QString VymModel::getAuthor()
1478 void VymModel::setComment (const QString &s)
1481 QString ("setMapComment (\"%1\")").arg(comment),
1482 QString ("setMapComment (\"%1\")").arg(s),
1483 QString ("Set comment of map")
1488 QString VymModel::getComment ()
1493 QString VymModel::getDate ()
1495 return QDate::currentDate().toString ("yyyy-MM-dd");
1498 int VymModel::branchCount() // FIXME-4 Optimize this: use internal counter instead of going through whole map each time...
1501 BranchItem *cur=NULL;
1502 BranchItem *prev=NULL;
1512 void VymModel::setHeading(const QString &s)
1514 BranchItem *selbi=getSelectedBranch();
1519 "setHeading (\""+selbi->getHeading()+"\")",
1521 "setHeading (\""+s+"\")",
1522 QString("Set heading of %1 to \"%2\"").arg(getObjectName(selbi)).arg(s) );
1523 selbi->setHeading(s );
1524 emitDataHasChanged ( selbi); //FIXME-3 maybe emit signal from TreeItem?
1526 emitSelectionChanged();
1530 QString VymModel::getHeading()
1532 TreeItem *selti=getSelectedItem();
1534 return selti->getHeading();
1539 BranchItem* VymModel::findText (QString s, bool cs)
1541 QTextDocument::FindFlags flags=0;
1542 if (cs) flags=QTextDocument::FindCaseSensitively;
1545 { // Nothing found or new find process
1547 // nothing found, start again
1551 next (findCurrent,findPrevious);
1553 bool searching=true;
1554 bool foundNote=false;
1555 while (searching && !EOFind)
1559 // Searching in Note
1560 if (findCurrent->getNote().contains(s,cs))
1562 select (findCurrent);
1564 if (getSelectedBranch()!=itFind)
1567 emitShowSelection();
1570 if (textEditor->findText(s,flags))
1576 // Searching in Heading
1577 if (searching && findCurrent->getHeading().contains (s,cs) )
1579 select(findCurrent);
1585 if (!next(findCurrent,findPrevious) )
1588 //cout <<"still searching... "<<qPrintable( itFind->getHeading())<<endl;
1591 return getSelectedBranch();
1596 void VymModel::findReset()
1597 { // Necessary if text to find changes during a find process
1603 void VymModel::setScene (QGraphicsScene *s)
1605 mapScene=s; // FIXME-2 VM should not be necessary anymore, move all occurences to MapEditor
1606 //init(); // Here we have a mapScene set,
1607 // which is (still) needed to create MapCenters
1610 void VymModel::setURL(const QString &url)
1612 TreeItem *selti=getSelectedItem();
1615 QString oldurl=selti->getURL();
1616 selti->setURL (url);
1619 QString ("setURL (\"%1\")").arg(oldurl),
1621 QString ("setURL (\"%1\")").arg(url),
1622 QString ("set URL of %1 to %2").arg(getObjectName(selti)).arg(url)
1625 emitDataHasChanged (selti);
1626 emitShowSelection();
1630 QString VymModel::getURL()
1632 TreeItem *selti=getSelectedItem();
1634 return selti->getURL();
1639 QStringList VymModel::getURLs()
1642 BranchItem *selbi=getSelectedBranch();
1643 BranchItem *cur=selbi;
1644 BranchItem *prev=NULL;
1647 if (!cur->getURL().isEmpty()) urls.append( cur->getURL());
1648 cur=next (cur,prev,selbi);
1654 void VymModel::setFrameType(const FrameObj::FrameType &t) //FIXME-4 not saved if there is no LMO
1656 BranchItem *bi=getSelectedBranch();
1659 BranchObj *bo=(BranchObj*)(bi->getLMO());
1662 QString s=bo->getFrameTypeName();
1663 bo->setFrameType (t);
1664 saveState (bi, QString("setFrameType (\"%1\")").arg(s),
1665 bi, QString ("setFrameType (\"%1\")").arg(bo->getFrameTypeName()),QString ("set type of frame to %1").arg(s));
1667 bo->updateLinkGeometry();
1672 void VymModel::setFrameType(const QString &s) //FIXME-4 not saved if there is no LMO
1674 BranchItem *bi=getSelectedBranch();
1677 BranchObj *bo=(BranchObj*)(bi->getLMO());
1680 saveState (bi, QString("setFrameType (\"%1\")").arg(bo->getFrameTypeName()),
1681 bi, QString ("setFrameType (\"%1\")").arg(s),QString ("set type of frame to %1").arg(s));
1682 bo->setFrameType (s);
1684 bo->updateLinkGeometry();
1689 void VymModel::setFramePenColor(const QColor &c) //FIXME-4 not saved if there is no LMO
1692 BranchItem *bi=getSelectedBranch();
1695 BranchObj *bo=(BranchObj*)(bi->getLMO());
1698 saveState (bi, QString("setFramePenColor (\"%1\")").arg(bo->getFramePenColor().name() ),
1699 bi, QString ("setFramePenColor (\"%1\")").arg(c.name() ),QString ("set pen color of frame to %1").arg(c.name() ));
1700 bo->setFramePenColor (c);
1705 void VymModel::setFrameBrushColor(const QColor &c) //FIXME-4 not saved if there is no LMO
1707 BranchItem *bi=getSelectedBranch();
1710 BranchObj *bo=(BranchObj*)(bi->getLMO());
1713 saveState (bi, QString("setFrameBrushColor (\"%1\")").arg(bo->getFrameBrushColor().name() ),
1714 bi, QString ("setFrameBrushColor (\"%1\")").arg(c.name() ),QString ("set brush color of frame to %1").arg(c.name() ));
1715 bo->setFrameBrushColor (c);
1720 void VymModel::setFramePadding (const int &i) //FIXME-4 not saved if there is no LMO
1722 BranchItem *bi=getSelectedBranch();
1725 BranchObj *bo=(BranchObj*)(bi->getLMO());
1728 saveState (bi, QString("setFramePadding (\"%1\")").arg(bo->getFramePadding() ),
1729 bi, QString ("setFramePadding (\"%1\")").arg(i),QString ("set brush color of frame to %1").arg(i));
1730 bo->setFramePadding (i);
1732 bo->updateLinkGeometry();
1737 void VymModel::setFrameBorderWidth(const int &i) //FIXME-4 not saved if there is no LMO
1739 BranchItem *bi=getSelectedBranch();
1742 BranchObj *bo=(BranchObj*)(bi->getLMO());
1745 saveState (bi, QString("setFrameBorderWidth (\"%1\")").arg(bo->getFrameBorderWidth() ),
1746 bi, QString ("setFrameBorderWidth (\"%1\")").arg(i),QString ("set border width of frame to %1").arg(i));
1747 bo->setFrameBorderWidth (i);
1749 bo->updateLinkGeometry();
1754 void VymModel::setIncludeImagesVer(bool b)
1756 BranchItem *bi=getSelectedBranch();
1759 QString u= b ? "false" : "true";
1760 QString r=!b ? "false" : "true";
1764 QString("setIncludeImagesVertically (%1)").arg(u),
1766 QString("setIncludeImagesVertically (%1)").arg(r),
1767 QString("Include images vertically in %1").arg(getObjectName(bi))
1769 bi->setIncludeImagesVer(b);
1770 emitDataHasChanged ( bi);
1775 void VymModel::setIncludeImagesHor(bool b)
1777 BranchItem *bi=getSelectedBranch();
1780 QString u= b ? "false" : "true";
1781 QString r=!b ? "false" : "true";
1785 QString("setIncludeImagesHorizontally (%1)").arg(u),
1787 QString("setIncludeImagesHorizontally (%1)").arg(r),
1788 QString("Include images horizontally in %1").arg(getObjectName(bi))
1790 bi->setIncludeImagesHor(b);
1791 emitDataHasChanged ( bi);
1796 void VymModel::setHideLinkUnselected (bool b)//FIXME-2
1798 TreeItem *ti=getSelectedItem();
1799 if (ti && (ti->getType()==TreeItem::Image ||ti->isBranchLikeType()))
1801 QString u= b ? "false" : "true";
1802 QString r=!b ? "false" : "true";
1806 QString("setHideLinkUnselected (%1)").arg(u),
1808 QString("setHideLinkUnselected (%1)").arg(r),
1809 QString("Hide link of %1 if unselected").arg(getObjectName(ti))
1811 ((MapItem*)ti)->setHideLinkUnselected(b);
1815 void VymModel::setHideExport(bool b)
1817 TreeItem *ti=getSelectedItem();
1819 (ti->getType()==TreeItem::Image ||ti->isBranchLikeType()))
1821 ti->setHideInExport (b);
1822 QString u= b ? "false" : "true";
1823 QString r=!b ? "false" : "true";
1827 QString ("setHideExport (%1)").arg(u),
1829 QString ("setHideExport (%1)").arg(r),
1830 QString ("Set HideExport flag of %1 to %2").arg(getObjectName(ti)).arg (r)
1832 emitDataHasChanged(ti);
1833 emitSelectionChanged();
1836 // emitSelectionChanged();
1837 // FIXME-3 VM needed? scene()->update();
1841 void VymModel::toggleHideExport()
1843 TreeItem *selti=getSelectedItem();
1845 setHideExport ( !selti->hideInExport() );
1849 void VymModel::copy()
1851 TreeItem *selti=getSelectedItem();
1853 (selti->getType() == TreeItem::Branch ||
1854 selti->getType() == TreeItem::MapCenter ||
1855 selti->getType() == TreeItem::Image ))
1857 if (redosAvail == 0)
1860 QString s=getSelectString(selti);
1861 saveState (PartOfMap, s, "nop ()", s, "copy ()","Copy selection to clipboard",selti );
1862 curClipboard=curStep;
1865 // Copy also to global clipboard, because we are at last step in history
1866 QString bakMapName(QString("history-%1").arg(curStep));
1867 QString bakMapDir(tmpMapDir +"/"+bakMapName);
1868 copyDir (bakMapDir,clipboardDir );
1870 clipboardEmpty=false;
1876 void VymModel::pasteNoSave(const int &n)
1878 bool old=blockSaveState;
1879 blockSaveState=true;
1880 bool zippedOrg=zipped;
1881 if (redosAvail > 0 || n!=0)
1883 // Use the "historical" buffer
1884 QString bakMapName(QString("history-%1").arg(n));
1885 QString bakMapDir(tmpMapDir +"/"+bakMapName);
1886 load (bakMapDir+"/"+clipboardFile,ImportAdd, VymMap);
1888 // Use the global buffer
1889 load (clipboardDir+"/"+clipboardFile,ImportAdd, VymMap);
1894 void VymModel::paste()
1896 BranchItem *selbi=getSelectedBranch();
1899 saveStateChangingPart(
1902 QString ("paste (%1)").arg(curClipboard),
1903 QString("Paste to %1").arg( getObjectName(selbi))
1910 void VymModel::cut()
1912 TreeItem *selti=getSelectedItem();
1913 if ( selti && (selti->isBranchLikeType() ||selti->getType()==TreeItem::Image))
1921 void VymModel::moveUp() //FIXME-2 crashes if trying to move MCO
1923 BranchItem *selbi=getSelectedBranch();
1926 if (!selbi->canMoveUp()) return;
1927 QString oldsel=getSelectString();
1928 if (relinkBranch (selbi,(BranchItem*)selbi->parent(),selbi->num()-1) )
1930 saveState (getSelectString(),"moveDown ()",oldsel,"moveUp ()",QString("Move up %1").arg(getObjectName(selbi)));
1934 void VymModel::moveDown()
1936 BranchItem *selbi=getSelectedBranch();
1939 if (!selbi->canMoveDown()) return;
1940 QString oldsel=getSelectString();
1941 if ( relinkBranch (selbi,(BranchItem*)selbi->parent(),selbi->num()+1) )
1943 saveState (getSelectString(),"moveUp ()",oldsel,"moveDown ()",QString("Move down %1").arg(getObjectName(selbi)));
1947 void VymModel::sortChildren() // FIXME-2 not implemented yet
1950 BranchObj* bo=getSelectedBranch();
1953 if(treeItem->branchCount()>1)
1955 saveStateChangingPart(bo,bo, "sortChildren ()",QString("Sort children of %1").arg(getObjectName(bo)));
1958 emitShowSelection();
1964 BranchItem* VymModel::createMapCenter()
1966 BranchItem *newbi=addMapCenter (QPointF (0,0) );
1970 BranchItem* VymModel::createBranch(BranchItem *dst)
1973 return addNewBranchInt (dst,-2);
1978 ImageItem* VymModel::createImage(BranchItem *dst)
1985 QList<QVariant> cData;
1986 cData << "new" << "undef";
1988 ImageItem *newii=new ImageItem(cData) ;
1989 //newii->setHeading (QApplication::translate("Heading of new image in map", "new image"));
1991 emit (layoutAboutToBeChanged() );
1994 if (!parix.isValid()) cout << "VM::createII invalid index\n";
1995 n=dst->getRowNumAppend(newii);
1996 beginInsertRows (parix,n,n);
1997 dst->appendChild (newii);
2000 emit (layoutChanged() );
2002 // save scroll state. If scrolled, automatically select
2003 // new branch in order to tmp unscroll parent...
2004 newii->createMapObj(mapScene);
2011 XLinkItem* VymModel::createXLink(BranchItem *bi,bool createMO)
2018 QList<QVariant> cData;
2019 cData << "new xLink"<<"undef";
2021 XLinkItem *newxli=new XLinkItem(cData) ;
2022 newxli->setBegin (bi);
2024 emit (layoutAboutToBeChanged() );
2027 n=bi->getRowNumAppend(newxli);
2028 beginInsertRows (parix,n,n);
2029 bi->appendChild (newxli);
2032 emit (layoutChanged() );
2034 // save scroll state. If scrolled, automatically select
2035 // new branch in order to tmp unscroll parent...
2038 newxli->createMapObj(mapScene);
2046 AttributeItem* VymModel::addAttribute() // FIXME-2 savestate missing
2048 BranchItem *selbi=getSelectedBranch();
2051 QList<QVariant> cData;
2052 cData << "new attribute" << "undef";
2053 AttributeItem *a=new AttributeItem (cData);
2055 emit (layoutAboutToBeChanged() );
2057 QModelIndex parix=index(selbi);
2058 int n=selbi->getRowNumAppend (a);
2059 beginInsertRows (parix,n,n);
2060 selbi->appendChild (a);
2063 emit (layoutChanged() );
2071 BranchItem* VymModel::addMapCenter ()
2073 BranchItem *bi=addMapCenter (contextPos);
2075 emitShowSelection();
2080 QString ("addMapCenter (%1,%2)").arg (contextPos.x()).arg(contextPos.y()),
2081 QString ("Adding MapCenter to (%1,%2)").arg (contextPos.x()).arg(contextPos.y())
2086 BranchItem* VymModel::addMapCenter(QPointF absPos)
2087 // createMapCenter could then probably be merged with createBranch
2091 QModelIndex parix=index(rootItem);
2093 QList<QVariant> cData;
2094 cData << "VM:addMapCenter" << "undef";
2095 BranchItem *newbi=new BranchItem (cData,rootItem);
2096 newbi->setHeading (QApplication::translate("Heading of mapcenter in new map", "New map"));
2097 int n=rootItem->getRowNumAppend (newbi);
2099 emit (layoutAboutToBeChanged() );
2100 beginInsertRows (parix,n,n);
2102 rootItem->appendChild (newbi);
2105 emit (layoutChanged() );
2108 newbi->setPositionMode (MapItem::Absolute);
2109 BranchObj *bo=newbi->createMapObj(mapScene);
2110 if (bo) bo->move (absPos);
2115 BranchItem* VymModel::addNewBranchInt(BranchItem *dst,int num)
2117 // Depending on pos:
2118 // -3 insert in children of parent above selection
2119 // -2 add branch to selection
2120 // -1 insert in children of parent below selection
2121 // 0..n insert in children of parent at pos
2124 QList<QVariant> cData;
2125 cData << "new" << "undef";
2130 BranchItem *newbi=new BranchItem (cData);
2131 newbi->setHeading (QApplication::translate("Heading of new branch in map", "new"));
2133 emit (layoutAboutToBeChanged() );
2139 n=parbi->getRowNumAppend (newbi);
2140 beginInsertRows (parix,n,n);
2141 parbi->appendChild (newbi);
2143 }else if (num==-1 || num==-3)
2145 // insert below selection
2146 parbi=(BranchItem*)dst->parent();
2149 n=dst->childNumber() + (3+num)/2; //-1 |-> 1;-3 |-> 0
2150 beginInsertRows (parix,n,n);
2151 parbi->insertBranch(n,newbi);
2154 emit (layoutChanged() );
2156 // save scroll state. If scrolled, automatically select
2157 // new branch in order to tmp unscroll parent...
2158 newbi->createMapObj(mapScene);
2163 BranchItem* VymModel::addNewBranch(int pos)
2165 // Different meaning than num in addNewBranchInt!
2169 BranchItem *newbi=NULL;
2170 BranchItem *selbi=getSelectedBranch();
2174 // FIXME-3 setCursor (Qt::ArrowCursor); //Still needed?
2176 newbi=addNewBranchInt (selbi,pos-2);
2184 QString ("addBranch (%1)").arg(pos),
2185 QString ("Add new branch to %1").arg(getObjectName(selbi)));
2188 // emitSelectionChanged(); FIXME-3
2189 latestAddedItem=newbi;
2190 // In Network mode, the client needs to know where the new branch is,
2191 // so we have to pass on this information via saveState.
2192 // TODO: Get rid of this positioning workaround
2193 /* FIXME-4 network problem: QString ps=qpointfToString (newbo->getAbsPos());
2194 sendData ("selectLatestAdded ()");
2195 sendData (QString("move %1").arg(ps));
2204 BranchItem* VymModel::addNewBranchBefore()
2206 BranchItem *newbi=NULL;
2207 BranchItem *selbi=getSelectedBranch();
2208 if (selbi && selbi->getType()==TreeItem::Branch)
2209 // We accept no MapCenter here, so we _have_ a parent
2211 //QPointF p=bo->getRelPos();
2214 // add below selection
2215 newbi=addNewBranchInt (selbi,-1);
2219 //newbi->move2RelPos (p);
2221 // Move selection to new branch
2222 relinkBranch (selbi,newbi,0);
2224 saveState (newbi, "deleteKeepChildren ()", newbi, "addBranchBefore ()",
2225 QString ("Add branch before %1").arg(getObjectName(selbi)));
2227 // FIXME-3 needed? reposition();
2228 // emitSelectionChanged(); FIXME-3
2234 bool VymModel::relinkBranch (BranchItem *branch, BranchItem *dst, int pos)
2238 if (branch->depth()==0)
2240 cout <<"VM::relinkBranch d=0 for "<<branch->getHeadingStd()<<endl;
2242 emit (layoutAboutToBeChanged() );
2243 BranchItem *branchpi=(BranchItem*)branch->parent();
2244 // Remove at current position
2245 int n=branch->childNum();
2246 beginRemoveRows (index(branchpi),n,n);
2247 branchpi->removeChild (n);
2250 if (pos<0 ||pos>dst->branchCount() ) pos=dst->branchCount();
2252 // Append as last branch to dst
2253 if (dst->branchCount()==0)
2256 n=dst->getFirstBranch()->childNumber();
2257 beginInsertRows (index(dst),n+pos,n+pos);
2258 dst->insertBranch (pos,branch);
2261 // Correct type if necessesary
2262 if (branch->getType()==TreeItem::MapCenter)
2263 branch->setType(TreeItem::Branch);
2265 // reset parObj, fonts, frame, etc in related LMO or other view-objects
2266 branch->updateStyles();
2268 emit (layoutChanged() );
2269 reposition(); // both for moveUp/Down and relinking
2270 if (dst->isScrolled() )
2273 branch->updateVisibility();
2282 bool VymModel::relinkImage (ImageItem *image, BranchItem *dst)
2286 emit (layoutAboutToBeChanged() );
2288 BranchItem *pi=(BranchItem*)(image->parent());
2289 QString oldParString=getSelectString (pi);
2290 // Remove at current position
2291 int n=image->childNum();
2292 beginRemoveRows (index(pi),n,n);
2293 pi->removeChild (n);
2297 QModelIndex dstix=index(dst);
2298 n=dst->getRowNumAppend (image);
2299 beginInsertRows (dstix,n,n+1);
2300 dst->appendChild (image);
2303 // Set new parent also for lmo
2304 if (image->getLMO() && dst->getLMO() )
2305 image->getLMO()->setParObj (dst->getLMO() );
2307 emit (layoutChanged() );
2310 QString("relinkTo (\"%1\")").arg(oldParString),
2312 QString ("relinkTo (\"%1\")").arg(getSelectString (dst)),
2313 QString ("Relink floatimage to %1").arg(getObjectName(dst)));
2319 void VymModel::deleteSelection()
2321 BranchItem *selbi=getSelectedBranch();
2326 saveStateRemovingPart (selbi, QString ("Delete %1").arg(getObjectName(selbi)));
2328 TreeItem *pi=deleteItem (selbi);
2332 emitShowSelection();
2336 TreeItem *ti=getSelectedItem();
2339 TreeItem *pi=ti->parent();
2341 if (ti->getType()==TreeItem::Image || ti->getType()==TreeItem::Attribute)
2343 saveStateChangingPart(
2347 QString("Delete %1").arg(getObjectName(ti))
2351 emitDataHasChanged (pi);
2354 emitShowSelection();
2355 } else if (ti->getType()==TreeItem::XLink)
2357 //FIXME-2 savestate missing
2360 qWarning ("VymmModel::deleteSelection() unknown type?!");
2364 void VymModel::deleteKeepChildren() //FIXME-3 does not work yet for mapcenters
2367 BranchItem *selbi=getSelectedBranch();
2371 // Don't use this on mapcenter
2372 if (selbi->depth()<2) return;
2374 pi=(BranchItem*)(selbi->parent());
2375 // Check if we have childs at all to keep
2376 if (selbi->branchCount()==0)
2383 if (selbi->getLMO()) p=selbi->getLMO()->getRelPos();
2384 saveStateChangingPart(
2387 "deleteKeepChildren ()",
2388 QString("Remove %1 and keep its children").arg(getObjectName(selbi))
2391 QString sel=getSelectString(selbi);
2393 int pos=selbi->num();
2394 BranchItem *bi=selbi->getFirstBranch();
2397 relinkBranch (bi,pi,pos);
2398 bi=selbi->getFirstBranch();
2404 BranchObj *bo=getSelectedBranchObj();
2407 bo->move2RelPos (p);
2413 void VymModel::deleteChildren()
2416 BranchItem *selbi=getSelectedBranch();
2419 saveStateChangingPart(
2422 "deleteChildren ()",
2423 QString( "Remove children of branch %1").arg(getObjectName(selbi))
2425 emit (layoutAboutToBeChanged() );
2427 QModelIndex ix=index (selbi);
2428 int n=selbi->branchCount()-1;
2429 beginRemoveRows (ix,0,n);
2430 removeRows (0,n+1,ix);
2432 if (selbi->isScrolled()) selbi->unScroll();
2433 emit (layoutChanged() );
2438 TreeItem* VymModel::deleteItem (TreeItem *ti)
2440 cout << "VM::deleteItem "<<ti<<" "<<getSelectString(ti).toStdString()<<endl;
2443 TreeItem *pi=ti->parent();
2444 QModelIndex parentIndex=index(pi);
2446 emit (layoutAboutToBeChanged() );
2448 int n=ti->childNum();
2449 beginRemoveRows (parentIndex,n,n);
2450 removeRows (n,1,parentIndex);
2454 emit (layoutChanged() );
2455 if (pi->depth()>=0) return pi;
2460 bool VymModel::scrollBranch(BranchItem *bi)
2464 if (bi->isScrolled()) return false;
2465 if (bi->branchCount()==0) return false;
2466 if (bi->depth()==0) return false;
2467 if (bi->toggleScroll())
2474 QString ("%1 ()").arg(u),
2476 QString ("%1 ()").arg(r),
2477 QString ("%1 %2").arg(r).arg(getObjectName(bi))
2479 emitDataHasChanged(bi);
2480 emitSelectionChanged();
2481 mapScene->update(); //Needed for _quick_ update, even in 1.13.x //FIXME-3 force update via signal...
2488 bool VymModel::unscrollBranch(BranchItem *bi)
2492 if (!bi->isScrolled()) return false;
2493 if (bi->branchCount()==0) return false;
2494 if (bi->depth()==0) return false;
2501 QString ("%1 ()").arg(u),
2503 QString ("%1 ()").arg(r),
2504 QString ("%1 %2").arg(r).arg(getObjectName(bi))
2507 emitDataHasChanged(bi);
2508 emitSelectionChanged();
2510 mapScene->update(); //Needed for _quick_ update, even in 1.13.x //FIXME-3 force update via signal...
2516 void VymModel::toggleScroll()
2518 BranchItem *bi=(BranchItem*)getSelectedBranch();
2519 if (bi && bi->isBranchLikeType() )
2521 if (bi->isScrolled())
2522 unscrollBranch (bi);
2526 // saveState is called in above functions
2529 void VymModel::unscrollChildren() // FIXME-2 first, next moved to vymmodel
2533 BranchObj *bo=getSelectedBranch();
2539 if (bo->isScrolled()) unscrollBranch (bo);
2546 void VymModel::emitExpandAll()
2548 emit (expandAll() );
2551 void VymModel::toggleStandardFlag (const QString &name, FlagRow *master)
2553 BranchItem *bi=getSelectedBranch();
2557 if (bi->isActiveStandardFlag(name))
2569 QString("%1 (\"%2\")").arg(u).arg(name),
2571 QString("%1 (\"%2\")").arg(r).arg(name),
2572 QString("Toggling standard flag \"%1\" of %2").arg(name).arg(getObjectName(bi)));
2573 bi->toggleStandardFlag (name, master);
2575 emitSelectionChanged();
2579 void VymModel::addFloatImage (const QPixmap &img)
2581 BranchItem *selbi=getSelectedBranch();
2584 ImageItem *ii=createImage (selbi);
2586 ii->setOriginalFilename("No original filename (image added by dropevent)");
2587 QString s=getSelectString(selbi);
2588 saveState (PartOfMap, s, "nop ()", s, "copy ()","Copy dropped image to clipboard",ii );
2589 saveState (ii,"delete ()", selbi,QString("paste(%1)").arg(curStep),"Pasting dropped image");
2591 // FIXME-3 VM needed? scene()->update();
2596 void VymModel::colorBranch (QColor c)
2598 BranchItem *selbi=getSelectedBranch();
2603 QString ("colorBranch (\"%1\")").arg(selbi->getHeadingColor().name()),
2605 QString ("colorBranch (\"%1\")").arg(c.name()),
2606 QString("Set color of %1 to %2").arg(getObjectName(selbi)).arg(c.name())
2608 selbi->setHeadingColor(c); // color branch
2612 void VymModel::colorSubtree (QColor c)
2614 BranchItem *selbi=getSelectedBranch();
2617 saveStateChangingPart(
2620 QString ("colorSubtree (\"%1\")").arg(c.name()),
2621 QString ("Set color of %1 and children to %2").arg(getObjectName(selbi)).arg(c.name())
2623 BranchItem *prev=NULL;
2624 BranchItem *cur=selbi;
2627 cur->setHeadingColor(c); // color links, color children
2628 cur=next (cur,prev,selbi);
2634 QColor VymModel::getCurrentHeadingColor()
2636 BranchItem *selbi=getSelectedBranch();
2637 if (selbi) return selbi->getHeadingColor();
2639 QMessageBox::warning(0,"Warning","Can't get color of heading,\nthere's no branch selected");
2645 void VymModel::editURL()
2647 TreeItem *selti=getSelectedItem();
2651 QString text = QInputDialog::getText(
2652 "VYM", tr("Enter URL:"), QLineEdit::Normal,
2653 selti->getURL(), &ok, NULL);
2655 // user entered something and pressed OK
2660 void VymModel::editLocalURL()
2662 TreeItem *selti=getSelectedItem();
2665 QStringList filters;
2666 filters <<"All files (*)";
2667 filters << tr("Text","Filedialog") + " (*.txt)";
2668 filters << tr("Spreadsheet","Filedialog") + " (*.odp,*.sxc)";
2669 filters << tr("Textdocument","Filedialog") +" (*.odw,*.sxw)";
2670 filters << tr("Images","Filedialog") + " (*.png *.bmp *.xbm *.jpg *.png *.xpm *.gif *.pnm)";
2671 QFileDialog *fd=new QFileDialog( NULL,vymName+" - " +tr("Set URL to a local file"));
2672 fd->setFilters (filters);
2673 fd->setCaption(vymName+" - " +tr("Set URL to a local file"));
2674 fd->setDirectory (lastFileDir);
2675 if (! selti->getVymLink().isEmpty() )
2676 fd->selectFile( selti->getURL() );
2679 if ( fd->exec() == QDialog::Accepted )
2681 lastFileDir=QDir (fd->directory().path());
2682 setURL (fd->selectedFile() );
2688 void VymModel::editHeading2URL()
2690 TreeItem *selti=getSelectedItem();
2692 setURL (selti->getHeading());
2695 void VymModel::editBugzilla2URL()
2697 TreeItem *selti=getSelectedItem();
2700 QString url= "https://bugzilla.novell.com/show_bug.cgi?id="+selti->getHeading();
2705 void VymModel::editFATE2URL()
2707 TreeItem *selti=getSelectedItem();
2710 QString url= "http://keeper.suse.de:8080/webfate/match/id?value=ID"+selti->getHeading();
2713 "setURL (\""+selti->getURL()+"\")",
2715 "setURL (\""+url+"\")",
2716 QString("Use heading of %1 as link to FATE").arg(getObjectName(selti))
2718 selti->setURL (url);
2719 // FIXME-4 updateActions();
2723 void VymModel::editVymLink()
2725 BranchItem *bi=getSelectedBranch();
2728 QStringList filters;
2729 filters <<"VYM map (*.vym)";
2730 QFileDialog *fd=new QFileDialog( NULL,vymName+" - " +tr("Link to another map"));
2731 fd->setFilters (filters);
2732 fd->setCaption(vymName+" - " +tr("Link to another map"));
2733 fd->setDirectory (lastFileDir);
2734 if (! bi->getVymLink().isEmpty() )
2735 fd->selectFile( bi->getVymLink() );
2739 if ( fd->exec() == QDialog::Accepted )
2741 lastFileDir=QDir (fd->directory().path());
2744 "setVymLink (\""+bi->getVymLink()+"\")",
2746 "setVymLink (\""+fd->selectedFile()+"\")",
2747 QString("Set vymlink of %1 to %2").arg(getObjectName(bi)).arg(fd->selectedFile())
2749 setVymLink (fd->selectedFile() ); // FIXME-2 ok?
2754 void VymModel::setVymLink (const QString &s) // FIXME-3 no savestate?
2756 // Internal function, no saveState needed
2757 TreeItem *selti=getSelectedItem();
2760 selti->setVymLink(s);
2762 emitDataHasChanged (selti);
2763 emitShowSelection();
2767 void VymModel::deleteVymLink()
2769 BranchItem *bi=getSelectedBranch();
2774 "setVymLink (\""+bi->getVymLink()+"\")",
2776 "setVymLink (\"\")",
2777 QString("Unset vymlink of %1").arg(getObjectName(bi))
2779 bi->setVymLink ("" );
2785 QString VymModel::getVymLink()
2787 BranchItem *bi=getSelectedBranch();
2789 return bi->getVymLink();
2795 QStringList VymModel::getVymLinks()
2798 BranchItem *selbi=getSelectedBranch();
2799 BranchItem *cur=selbi;
2800 BranchItem *prev=NULL;
2803 if (!cur->getVymLink().isEmpty()) links.append( cur->getVymLink());
2804 cur=next (cur,prev,selbi);
2810 void VymModel::followXLink(int i)
2813 BranchItem *selbi=getSelectedBranch();
2816 selbi=selbi->getXLinkNum(i)->getPartnerBranch();
2817 if (selbi) select (selbi);
2821 void VymModel::editXLink(int i)
2824 BranchItem *selbi=getSelectedBranch();
2827 XLinkItem *xli=selbi->getXLinkNum(i);
2830 EditXLinkDialog dia;
2832 dia.setSelection(selbi);
2833 if (dia.exec() == QDialog::Accepted)
2835 if (dia.useSettingsGlobal() )
2837 setMapDefXLinkColor (xli->getColor() );
2838 setMapDefXLinkWidth (xli->getWidth() );
2840 if (dia.deleteXLink()) deleteItem (xli);
2850 //////////////////////////////////////////////
2852 //////////////////////////////////////////////
2854 void VymModel::parseAtom(const QString &atom)
2856 TreeItem* selti=getSelectedItem();
2857 BranchItem *selbi=getSelectedBranch();
2863 // Split string s into command and parameters
2864 parser.parseAtom (atom);
2865 QString com=parser.getCommand();
2867 // External commands
2868 /////////////////////////////////////////////////////////////////////
2869 if (com=="addBranch")
2873 parser.setError (Aborted,"Nothing selected");
2874 } else if (! selbi )
2876 parser.setError (Aborted,"Type of selection is not a branch");
2881 if (parser.checkParCount(pl))
2883 if (parser.parCount()==0)
2887 n=parser.parInt (ok,0);
2888 if (ok ) addNewBranch (n);
2892 /////////////////////////////////////////////////////////////////////
2893 } else if (com=="addBranchBefore")
2897 parser.setError (Aborted,"Nothing selected");
2898 } else if (! selbi )
2900 parser.setError (Aborted,"Type of selection is not a branch");
2903 if (parser.parCount()==0)
2905 addNewBranchBefore ();
2908 /////////////////////////////////////////////////////////////////////
2909 } else if (com==QString("addMapCenter"))
2911 if (parser.checkParCount(2))
2913 x=parser.parDouble (ok,0);
2916 y=parser.parDouble (ok,1);
2917 if (ok) addMapCenter (QPointF(x,y));
2920 /////////////////////////////////////////////////////////////////////
2921 } else if (com==QString("addMapReplace"))
2925 parser.setError (Aborted,"Nothing selected");
2926 } else if (! selbi )
2928 parser.setError (Aborted,"Type of selection is not a branch");
2929 } else if (parser.checkParCount(1))
2931 //s=parser.parString (ok,0); // selection
2932 t=parser.parString (ok,0); // path to map
2933 if (QDir::isRelativePath(t)) t=(tmpMapDir + "/"+t);
2934 addMapReplaceInt(getSelectString(selbi),t);
2936 /////////////////////////////////////////////////////////////////////
2937 } else if (com==QString("addMapInsert"))
2939 if (parser.parCount()==2)
2944 parser.setError (Aborted,"Nothing selected");
2945 } else if (! selbi )
2947 parser.setError (Aborted,"Type of selection is not a branch");
2950 t=parser.parString (ok,0); // path to map
2951 n=parser.parInt(ok,1); // position
2952 if (QDir::isRelativePath(t)) t=(tmpMapDir + "/"+t);
2953 addMapInsertInt(t,n);
2955 } else if (parser.parCount()==1)
2957 t=parser.parString (ok,0); // path to map
2958 if (QDir::isRelativePath(t)) t=(tmpMapDir + "/"+t);
2961 parser.setError (Aborted,"Wrong number of parameters");
2962 /////////////////////////////////////////////////////////////////////
2963 } else if (com==QString("addXLink"))
2965 if (parser.parCount()>1)
2967 s=parser.parString (ok,0); // begin
2968 t=parser.parString (ok,1); // end
2969 BranchItem *begin=(BranchItem*)findBySelectString(s);
2970 BranchItem *end=(BranchItem*)findBySelectString(t);
2973 if (begin->isBranchLikeType() && end->isBranchLikeType())
2975 XLinkItem *xl=createXLink (begin,true);
2981 parser.setError (Aborted,"Failed to create xLink");
2984 parser.setError (Aborted,"begin or end of xLink are not branch or mapcenter");
2987 parser.setError (Aborted,"Couldn't select begin or end of xLink");
2989 parser.setError (Aborted,"Need at least 2 parameters for begin and end");
2990 /////////////////////////////////////////////////////////////////////
2991 } else if (com=="clearFlags")
2995 parser.setError (Aborted,"Nothing selected");
2996 } else if (! selbi )
2998 parser.setError (Aborted,"Type of selection is not a branch");
2999 } else if (parser.checkParCount(0))
3001 selbi->deactivateAllStandardFlags();
3003 /////////////////////////////////////////////////////////////////////
3004 } else if (com=="colorBranch")
3008 parser.setError (Aborted,"Nothing selected");
3009 } else if (! selbi )
3011 parser.setError (Aborted,"Type of selection is not a branch");
3012 } else if (parser.checkParCount(1))
3014 QColor c=parser.parColor (ok,0);
3015 if (ok) colorBranch (c);
3017 /////////////////////////////////////////////////////////////////////
3018 } else if (com=="colorSubtree")
3022 parser.setError (Aborted,"Nothing selected");
3023 } else if (! selbi )
3025 parser.setError (Aborted,"Type of selection is not a branch");
3026 } else if (parser.checkParCount(1))
3028 QColor c=parser.parColor (ok,0);
3029 if (ok) colorSubtree (c);
3031 /////////////////////////////////////////////////////////////////////
3032 } else if (com=="copy")
3036 parser.setError (Aborted,"Nothing selected");
3037 } else if ( selectionType()!=TreeItem::Branch &&
3038 selectionType()!=TreeItem::MapCenter &&
3039 selectionType()!=TreeItem::Image )
3041 parser.setError (Aborted,"Type of selection is not a branch or floatimage");
3042 } else if (parser.checkParCount(0))
3046 /////////////////////////////////////////////////////////////////////
3047 } else if (com=="cut")
3051 parser.setError (Aborted,"Nothing selected");
3052 } else if ( selectionType()!=TreeItem::Branch &&
3053 selectionType()!=TreeItem::MapCenter &&
3054 selectionType()!=TreeItem::Image )
3056 parser.setError (Aborted,"Type of selection is not a branch or floatimage");
3057 } else if (parser.checkParCount(0))
3061 /////////////////////////////////////////////////////////////////////
3062 } else if (com=="delete")
3066 parser.setError (Aborted,"Nothing selected");
3068 /*else if (selectionType() != TreeItem::Branch && selectionType() != TreeItem::Image )
3070 parser.setError (Aborted,"Type of selection is wrong.");
3073 else if (parser.checkParCount(0))
3077 /////////////////////////////////////////////////////////////////////
3078 } else if (com=="deleteKeepChildren")
3082 parser.setError (Aborted,"Nothing selected");
3083 } else if (! selbi )
3085 parser.setError (Aborted,"Type of selection is not a branch");
3086 } else if (parser.checkParCount(0))
3088 deleteKeepChildren();
3090 /////////////////////////////////////////////////////////////////////
3091 } else if (com=="deleteChildren")
3095 parser.setError (Aborted,"Nothing selected");
3098 parser.setError (Aborted,"Type of selection is not a branch");
3099 } else if (parser.checkParCount(0))
3103 /////////////////////////////////////////////////////////////////////
3104 } else if (com=="exportASCII")
3108 if (parser.parCount()>=1)
3109 // Hey, we even have a filename
3110 fname=parser.parString(ok,0);
3113 parser.setError (Aborted,"Could not read filename");
3116 exportASCII (fname,false);
3118 /////////////////////////////////////////////////////////////////////
3119 } else if (com=="exportImage")
3123 if (parser.parCount()>=2)
3124 // Hey, we even have a filename
3125 fname=parser.parString(ok,0);
3128 parser.setError (Aborted,"Could not read filename");
3131 QString format="PNG";
3132 if (parser.parCount()>=2)
3134 format=parser.parString(ok,1);
3136 exportImage (fname,false,format);
3138 /////////////////////////////////////////////////////////////////////
3139 } else if (com=="exportXHTML")
3143 if (parser.parCount()>=2)
3144 // Hey, we even have a filename
3145 fname=parser.parString(ok,1);
3148 parser.setError (Aborted,"Could not read filename");
3151 exportXHTML (fname,false);
3153 /////////////////////////////////////////////////////////////////////
3154 } else if (com=="exportXML")
3158 if (parser.parCount()>=2)
3159 // Hey, we even have a filename
3160 fname=parser.parString(ok,1);
3163 parser.setError (Aborted,"Could not read filename");
3166 exportXML (fname,false);
3168 /////////////////////////////////////////////////////////////////////
3169 } else if (com=="importDir")
3173 parser.setError (Aborted,"Nothing selected");
3174 } else if (! selbi )
3176 parser.setError (Aborted,"Type of selection is not a branch");
3177 } else if (parser.checkParCount(1))
3179 s=parser.parString(ok,0);
3180 if (ok) importDirInt(s);
3182 /////////////////////////////////////////////////////////////////////
3183 } else if (com=="relinkTo")
3187 parser.setError (Aborted,"Nothing selected");
3190 if (parser.checkParCount(4))
3192 // 0 selectstring of parent
3193 // 1 num in parent (for branches)
3194 // 2,3 x,y of mainbranch or mapcenter
3195 s=parser.parString(ok,0);
3196 TreeItem *dst=findBySelectString (s);
3199 if (dst->getType()==TreeItem::Branch)
3201 // Get number in parent
3202 n=parser.parInt (ok,1);
3205 relinkBranch (selbi,(BranchItem*)dst,n);
3206 emitSelectionChanged();
3208 } else if (dst->getType()==TreeItem::MapCenter)
3210 relinkBranch (selbi,(BranchItem*)dst);
3211 // Get coordinates of mainbranch
3212 x=parser.parDouble(ok,2);
3215 y=parser.parDouble(ok,3);
3218 if (selbi->getLMO()) selbi->getLMO()->move (x,y);
3219 emitSelectionChanged();
3225 } else if ( selti->getType() == TreeItem::Image)
3227 if (parser.checkParCount(1))
3229 // 0 selectstring of parent
3230 s=parser.parString(ok,0);
3231 TreeItem *dst=findBySelectString (s);
3234 if (dst->isBranchLikeType())
3235 relinkImage ( ((ImageItem*)selti),(BranchItem*)dst);
3237 parser.setError (Aborted,"Destination is not a branch");
3240 parser.setError (Aborted,"Type of selection is not a floatimage or branch");
3241 /////////////////////////////////////////////////////////////////////
3242 } else if (com=="loadImage")
3246 parser.setError (Aborted,"Nothing selected");
3247 } else if (! selbi )
3249 parser.setError (Aborted,"Type of selection is not a branch");
3250 } else if (parser.checkParCount(1))
3252 s=parser.parString(ok,0);
3253 if (ok) loadFloatImageInt (selbi,s);
3255 /////////////////////////////////////////////////////////////////////
3256 } else if (com=="moveUp")
3260 parser.setError (Aborted,"Nothing selected");
3261 } else if (! selbi )
3263 parser.setError (Aborted,"Type of selection is not a branch");
3264 } else if (parser.checkParCount(0))
3268 /////////////////////////////////////////////////////////////////////
3269 } else if (com=="moveDown")
3273 parser.setError (Aborted,"Nothing selected");
3274 } else if (! selbi )
3276 parser.setError (Aborted,"Type of selection is not a branch");
3277 } else if (parser.checkParCount(0))
3281 /////////////////////////////////////////////////////////////////////
3282 } else if (com=="move")
3286 parser.setError (Aborted,"Nothing selected");
3287 } else if ( selectionType()!=TreeItem::Branch &&
3288 selectionType()!=TreeItem::MapCenter &&
3289 selectionType()!=TreeItem::Image )
3291 parser.setError (Aborted,"Type of selection is not a branch or floatimage");
3292 } else if (parser.checkParCount(2))
3294 x=parser.parDouble (ok,0);
3297 y=parser.parDouble (ok,1);
3301 /////////////////////////////////////////////////////////////////////
3302 } else if (com=="moveRel")
3306 parser.setError (Aborted,"Nothing selected");
3307 } else if ( selectionType()!=TreeItem::Branch &&
3308 selectionType()!=TreeItem::MapCenter &&
3309 selectionType()!=TreeItem::Image )
3311 parser.setError (Aborted,"Type of selection is not a branch or floatimage");
3312 } else if (parser.checkParCount(2))
3314 x=parser.parDouble (ok,0);
3317 y=parser.parDouble (ok,1);
3318 if (ok) moveRel (x,y);
3321 /////////////////////////////////////////////////////////////////////
3322 } else if (com=="nop")
3324 /////////////////////////////////////////////////////////////////////
3325 } else if (com=="paste")
3329 parser.setError (Aborted,"Nothing selected");
3330 } else if (! selbi )
3332 parser.setError (Aborted,"Type of selection is not a branch");
3333 } else if (parser.checkParCount(1))
3335 n=parser.parInt (ok,0);
3336 if (ok) pasteNoSave(n);
3338 /////////////////////////////////////////////////////////////////////
3339 } else if (com=="qa")
3343 parser.setError (Aborted,"Nothing selected");
3344 } else if (! selbi )
3346 parser.setError (Aborted,"Type of selection is not a branch");
3347 } else if (parser.checkParCount(4))
3350 c=parser.parString (ok,0);
3353 parser.setError (Aborted,"No comment given");
3356 s=parser.parString (ok,1);
3359 parser.setError (Aborted,"First parameter is not a string");
3362 t=parser.parString (ok,2);
3365 parser.setError (Aborted,"Condition is not a string");
3368 u=parser.parString (ok,3);
3371 parser.setError (Aborted,"Third parameter is not a string");
3376 parser.setError (Aborted,"Unknown type: "+s);
3381 parser.setError (Aborted,"Unknown operator: "+t);
3386 parser.setError (Aborted,"Type of selection is not a branch");
3389 if (selbi->getHeading() == u)
3391 cout << "PASSED: " << qPrintable (c) << endl;
3394 cout << "FAILED: " << qPrintable (c) << endl;
3404 /////////////////////////////////////////////////////////////////////
3405 } else if (com=="saveImage")
3407 ImageItem *ii=getSelectedImage();
3410 parser.setError (Aborted,"No image selected");
3411 } else if (parser.checkParCount(2))
3413 s=parser.parString(ok,0);
3416 t=parser.parString(ok,1);
3417 if (ok) saveFloatImageInt (ii,t,s);
3420 /////////////////////////////////////////////////////////////////////
3421 } else if (com=="scroll")
3425 parser.setError (Aborted,"Nothing selected");
3426 } else if (! selbi )
3428 parser.setError (Aborted,"Type of selection is not a branch");
3429 } else if (parser.checkParCount(0))
3431 if (!scrollBranch (selbi))
3432 parser.setError (Aborted,"Could not scroll branch");
3434 /////////////////////////////////////////////////////////////////////
3435 } else if (com=="select")
3437 if (parser.checkParCount(1))
3439 s=parser.parString(ok,0);
3442 /////////////////////////////////////////////////////////////////////
3443 } else if (com=="selectLastBranch")
3447 parser.setError (Aborted,"Nothing selected");
3448 } else if (! selbi )
3450 parser.setError (Aborted,"Type of selection is not a branch");
3451 } else if (parser.checkParCount(0))
3453 BranchItem *bi=selbi->getLastBranch();
3455 parser.setError (Aborted,"Could not select last branch");
3456 select (bi); // FIXME-3 was selectInt
3459 /////////////////////////////////////////////////////////////////////
3460 } else /* FIXME-2 if (com=="selectLastImage")
3464 parser.setError (Aborted,"Nothing selected");
3465 } else if (! selbi )
3467 parser.setError (Aborted,"Type of selection is not a branch");
3468 } else if (parser.checkParCount(0))
3470 FloatImageObj *fio=selb->getLastFloatImage();
3472 parser.setError (Aborted,"Could not select last image");
3473 select (fio); // FIXME-3 was selectInt
3476 /////////////////////////////////////////////////////////////////////
3477 } else */ if (com=="selectLatestAdded")
3479 if (!latestAddedItem)
3481 parser.setError (Aborted,"No latest added object");
3484 if (!select (latestAddedItem))
3485 parser.setError (Aborted,"Could not select latest added object ");
3487 /////////////////////////////////////////////////////////////////////
3488 } else if (com=="setFrameType")
3490 if ( selectionType()!=TreeItem::Branch && selectionType()!= TreeItem::MapCenter && selectionType()!=TreeItem::Image)
3492 parser.setError (Aborted,"Type of selection does not allow setting frame type");
3494 else if (parser.checkParCount(1))
3496 s=parser.parString(ok,0);
3497 if (ok) setFrameType (s);
3499 /////////////////////////////////////////////////////////////////////
3500 } else if (com=="setFramePenColor")
3502 if ( selectionType()!=TreeItem::Branch && selectionType()!= TreeItem::MapCenter && selectionType()!=TreeItem::Image)
3504 parser.setError (Aborted,"Type of selection does not allow setting of pen color");
3506 else if (parser.checkParCount(1))
3508 QColor c=parser.parColor(ok,0);
3509 if (ok) setFramePenColor (c);
3511 /////////////////////////////////////////////////////////////////////
3512 } else if (com=="setFrameBrushColor")
3514 if ( selectionType()!=TreeItem::Branch && selectionType()!= TreeItem::MapCenter && selectionType()!=TreeItem::Image)
3516 parser.setError (Aborted,"Type of selection does not allow setting brush color");
3518 else if (parser.checkParCount(1))
3520 QColor c=parser.parColor(ok,0);
3521 if (ok) setFrameBrushColor (c);
3523 /////////////////////////////////////////////////////////////////////
3524 } else if (com=="setFramePadding")
3526 if ( selectionType()!=TreeItem::Branch && selectionType()!= TreeItem::MapCenter && selectionType()!=TreeItem::Image)
3528 parser.setError (Aborted,"Type of selection does not allow setting frame padding");
3530 else if (parser.checkParCount(1))
3532 n=parser.parInt(ok,0);
3533 if (ok) setFramePadding(n);
3535 /////////////////////////////////////////////////////////////////////
3536 } else if (com=="setFrameBorderWidth")
3538 if ( selectionType()!=TreeItem::Branch && selectionType()!= TreeItem::MapCenter && selectionType()!=TreeItem::Image)
3540 parser.setError (Aborted,"Type of selection does not allow setting frame border width");
3542 else if (parser.checkParCount(1))
3544 n=parser.parInt(ok,0);
3545 if (ok) setFrameBorderWidth (n);
3547 /////////////////////////////////////////////////////////////////////
3548 } else if (com=="setMapAuthor")
3550 if (parser.checkParCount(1))
3552 s=parser.parString(ok,0);
3553 if (ok) setAuthor (s);
3555 /////////////////////////////////////////////////////////////////////
3556 } else if (com=="setMapComment")
3558 if (parser.checkParCount(1))
3560 s=parser.parString(ok,0);
3561 if (ok) setComment(s);
3563 /////////////////////////////////////////////////////////////////////
3564 } else if (com=="setMapBackgroundColor")
3568 parser.setError (Aborted,"Nothing selected");
3569 } else if (! selbi )
3571 parser.setError (Aborted,"Type of selection is not a branch");
3572 } else if (parser.checkParCount(1))
3574 QColor c=parser.parColor (ok,0);
3575 if (ok) setMapBackgroundColor (c);
3577 /////////////////////////////////////////////////////////////////////
3578 } else if (com=="setMapDefLinkColor")
3582 parser.setError (Aborted,"Nothing selected");
3583 } else if (! selbi )
3585 parser.setError (Aborted,"Type of selection is not a branch");
3586 } else if (parser.checkParCount(1))
3588 QColor c=parser.parColor (ok,0);
3589 if (ok) setMapDefLinkColor (c);
3591 /////////////////////////////////////////////////////////////////////
3592 } else if (com=="setMapLinkStyle")
3594 if (parser.checkParCount(1))
3596 s=parser.parString (ok,0);
3597 if (ok) setMapLinkStyle(s);
3599 /////////////////////////////////////////////////////////////////////
3600 } else if (com=="setHeading")
3604 parser.setError (Aborted,"Nothing selected");
3605 } else if (! selbi )
3607 parser.setError (Aborted,"Type of selection is not a branch");
3608 } else if (parser.checkParCount(1))
3610 s=parser.parString (ok,0);
3614 /////////////////////////////////////////////////////////////////////
3615 } else if (com=="setHideExport")
3619 parser.setError (Aborted,"Nothing selected");
3620 } else if (selectionType()!=TreeItem::Branch && selectionType() != TreeItem::MapCenter &&selectionType()!=TreeItem::Image)
3622 parser.setError (Aborted,"Type of selection is not a branch or floatimage");
3623 } else if (parser.checkParCount(1))
3625 b=parser.parBool(ok,0);
3626 if (ok) setHideExport (b);
3628 /////////////////////////////////////////////////////////////////////
3629 } else if (com=="setIncludeImagesHorizontally")
3633 parser.setError (Aborted,"Nothing selected");
3636 parser.setError (Aborted,"Type of selection is not a branch");
3637 } else if (parser.checkParCount(1))
3639 b=parser.parBool(ok,0);
3640 if (ok) setIncludeImagesHor(b);
3642 /////////////////////////////////////////////////////////////////////
3643 } else if (com=="setIncludeImagesVertically")
3647 parser.setError (Aborted,"Nothing selected");
3650 parser.setError (Aborted,"Type of selection is not a branch");
3651 } else if (parser.checkParCount(1))
3653 b=parser.parBool(ok,0);
3654 if (ok) setIncludeImagesVer(b);
3656 /////////////////////////////////////////////////////////////////////
3657 } else if (com=="setHideLinkUnselected")
3661 parser.setError (Aborted,"Nothing selected");
3662 } else if ( selectionType()!=TreeItem::Branch && selectionType()!= TreeItem::MapCenter && selectionType()!=TreeItem::Image)
3664 parser.setError (Aborted,"Type of selection does not allow hiding the link");
3665 } else if (parser.checkParCount(1))
3667 b=parser.parBool(ok,0);
3668 if (ok) setHideLinkUnselected(b);
3670 /////////////////////////////////////////////////////////////////////
3671 } else if (com=="setSelectionColor")
3673 if (parser.checkParCount(1))
3675 QColor c=parser.parColor (ok,0);
3676 if (ok) setSelectionColorInt (c);
3678 /////////////////////////////////////////////////////////////////////
3679 } else if (com=="setURL")
3683 parser.setError (Aborted,"Nothing selected");
3684 } else if (! selbi )
3686 parser.setError (Aborted,"Type of selection is not a branch");
3687 } else if (parser.checkParCount(1))
3689 s=parser.parString (ok,0);
3692 /////////////////////////////////////////////////////////////////////
3693 } else if (com=="setVymLink")
3697 parser.setError (Aborted,"Nothing selected");
3698 } else if (! selbi )
3700 parser.setError (Aborted,"Type of selection is not a branch");
3701 } else if (parser.checkParCount(1))
3703 s=parser.parString (ok,0);
3704 if (ok) setVymLink(s);
3707 /////////////////////////////////////////////////////////////////////
3708 else if (com=="setFlag")
3712 parser.setError (Aborted,"Nothing selected");
3713 } else if (! selbi )
3715 parser.setError (Aborted,"Type of selection is not a branch");
3716 } else if (parser.checkParCount(1))
3718 s=parser.parString(ok,0);
3720 selbi->activateStandardFlag(s);
3722 /////////////////////////////////////////////////////////////////////
3723 } else /* FIXME-2 if (com=="setFrameType")
3727 parser.setError (Aborted,"Nothing selected");
3730 parser.setError (Aborted,"Type of selection is not a branch");
3731 } else if (parser.checkParCount(1))
3733 s=parser.parString(ok,0);
3737 /////////////////////////////////////////////////////////////////////
3738 } else*/ if (com=="sortChildren")
3742 parser.setError (Aborted,"Nothing selected");
3743 } else if (! selbi )
3745 parser.setError (Aborted,"Type of selection is not a branch");
3746 } else if (parser.checkParCount(0))
3750 /////////////////////////////////////////////////////////////////////
3751 } else if (com=="toggleFlag")
3755 parser.setError (Aborted,"Nothing selected");
3756 } else if (! selbi )
3758 parser.setError (Aborted,"Type of selection is not a branch");
3759 } else if (parser.checkParCount(1))
3761 s=parser.parString(ok,0);
3763 selbi->toggleStandardFlag(s);
3765 /////////////////////////////////////////////////////////////////////
3766 } else if (com=="unscroll")
3770 parser.setError (Aborted,"Nothing selected");
3771 } else if (! selbi )
3773 parser.setError (Aborted,"Type of selection is not a branch");
3774 } else if (parser.checkParCount(0))
3776 if (!unscrollBranch (selbi))
3777 parser.setError (Aborted,"Could not unscroll branch");
3779 /////////////////////////////////////////////////////////////////////
3780 } else if (com=="unscrollChildren")
3784 parser.setError (Aborted,"Nothing selected");
3785 } else if (! selbi )
3787 parser.setError (Aborted,"Type of selection is not a branch");
3788 } else if (parser.checkParCount(0))
3790 unscrollChildren ();
3792 /////////////////////////////////////////////////////////////////////
3793 } else if (com=="unsetFlag")
3797 parser.setError (Aborted,"Nothing selected");
3798 } else if (! selbi )
3800 parser.setError (Aborted,"Type of selection is not a branch");
3801 } else if (parser.checkParCount(1))
3803 s=parser.parString(ok,0);
3805 selbi->deactivateStandardFlag(s);
3808 parser.setError (Aborted,"Unknown command");
3811 if (parser.errorLevel()==NoError)
3813 // setChanged(); FIXME-2 should not be called e.g. for export?!
3818 // TODO Error handling
3819 qWarning("VymModel::parseAtom: Error!");
3820 qWarning(parser.errorMessage());
3824 void VymModel::runScript (QString script)
3826 parser.setScript (script);
3828 while (parser.next() )
3829 parseAtom(parser.getAtom());
3832 void VymModel::setExportMode (bool b)
3834 // should be called before and after exports
3835 // depending on the settings
3836 if (b && settings.value("/export/useHideExport","true")=="true")
3837 setHideTmpMode (TreeItem::HideExport);
3839 setHideTmpMode (TreeItem::HideNone);
3842 void VymModel::exportImage(QString fname, bool askName, QString format)
3846 fname=getMapName()+".png";
3853 QFileDialog *fd=new QFileDialog (NULL);
3854 fd->setCaption (tr("Export map as image"));
3855 fd->setDirectory (lastImageDir);
3856 fd->setFileMode(QFileDialog::AnyFile);
3857 fd->setFilters (imageIO.getFilters() );
3860 fl=fd->selectedFiles();
3862 format=imageIO.getType(fd->selectedFilter());
3866 setExportMode (true);
3867 QPixmap pix (mapEditor->getPixmap());
3868 pix.save(fname, format);
3869 setExportMode (false);
3873 void VymModel::exportXML(QString dir, bool askForName)
3877 dir=browseDirectory(NULL,tr("Export XML to directory"));
3878 if (dir =="" && !reallyWriteDirectory(dir) )
3882 // Hide stuff during export, if settings want this
3883 setExportMode (true);
3885 // Create subdirectories
3888 // write to directory //FIXME-4 check totalBBox here...
3889 QString saveFile=saveToDir (dir,mapName+"-",true,mapEditor->getTotalBBox().topLeft() ,NULL);
3892 file.setName ( dir + "/"+mapName+".xml");
3893 if ( !file.open( QIODevice::WriteOnly ) )
3895 // This should neverever happen
3896 QMessageBox::critical (0,tr("Critical Export Error"),tr("VymModel::exportXML couldn't open %1").arg(file.name()));
3900 // Write it finally, and write in UTF8, no matter what
3901 QTextStream ts( &file );
3902 ts.setEncoding (QTextStream::UnicodeUTF8);
3906 // Now write image, too
3907 exportImage (dir+"/images/"+mapName+".png",false,"PNG");
3909 setExportMode (false);
3912 void VymModel::exportASCII(QString fname,bool askName)
3917 ex.setFile (mapName+".txt");
3923 //ex.addFilter ("TXT (*.txt)");
3924 ex.setDir(lastImageDir);
3925 //ex.setCaption(vymName+ " -" +tr("Export as ASCII")+" "+tr("(still experimental)"));
3930 setExportMode(true);
3932 setExportMode(false);
3936 void VymModel::exportXHTML (const QString &dir, bool askForName)
3938 ExportXHTMLDialog dia(NULL);
3939 dia.setFilePath (filePath );
3940 dia.setMapName (mapName );
3942 if (dir!="") dia.setDir (dir);
3948 if (dia.exec()!=QDialog::Accepted)
3952 QDir d (dia.getDir());
3953 // Check, if warnings should be used before overwriting
3954 // the output directory
3955 if (d.exists() && d.count()>0)
3958 warn.showCancelButton (true);
3959 warn.setText(QString(
3960 "The directory %1 is not empty.\n"
3961 "Do you risk to overwrite some of its contents?").arg(d.path() ));
3962 warn.setCaption("Warning: Directory not empty");
3963 warn.setShowAgainName("mainwindow/overwrite-dir-xhtml");
3965 if (warn.exec()!=QDialog::Accepted) ok=false;
3972 exportXML (dia.getDir(),false );
3973 dia.doExport(mapName );
3974 //if (dia.hasChanged()) setChanged();
3978 void VymModel::exportOOPresentation(const QString &fn, const QString &cf)
3983 if (ex.setConfigFile(cf))
3985 setExportMode (true);
3986 ex.exportPresentation();
3987 setExportMode (false);
3994 //////////////////////////////////////////////
3996 //////////////////////////////////////////////
3998 void VymModel::registerEditor(QWidget *me)
4000 mapEditor=(MapEditor*)me;
4003 void VymModel::unregisterEditor(QWidget *)
4008 void VymModel::setContextPos(QPointF p)
4013 void VymModel::unsetContextPos()
4015 contextPos=QPointF();
4018 void VymModel::updateNoteFlag()
4021 TreeItem *selti=getSelectedItem();
4024 if (textEditor->isEmpty())
4027 selti->setNote (textEditor->getText());
4028 emitDataHasChanged(selti);
4029 emitSelectionChanged();
4034 void VymModel::updateRelPositions() //FIXME-3 VM should have no need to updateRelPos
4037 for (int i=0; i<rootItem->branchCount(); i++)
4038 ((MapCenterObj*)rootItem->getBranchObjNum(i))->updateRelPositions();
4041 void MapCenterObj::updateRelPositions()
4043 if (repositionRequest) unsetAllRepositionRequests();
4045 // update relative Positions of branches and floats
4046 for (int i=0; i<treeItem->branchCount(); ++i)
4048 treeItem->getBranchObjNum(i)->setRelPos();
4049 treeItem->getBranchObjNum(i)->setOrientation();
4052 for (int i=0; i<floatimage.size(); ++i)
4053 floatimage.at(i)->setRelPos();
4055 if (repositionRequest) reposition();
4060 void VymModel::reposition() //FIXME-3 VM should have no need to reposition, this is done in views???
4062 //cout << "VM::reposition blocked="<<blockReposition<<endl;
4063 if (blockReposition) return;
4065 for (int i=0;i<rootItem->branchCount(); i++)
4066 rootItem->getBranchObjNum(i)->reposition(); // for positioning heading
4067 emitSelectionChanged();
4071 QPolygonF VymModel::shape(BranchObj *bo) //FIXME-4
4073 return QPolygonF ();
4074 // Creating (arbitrary) shapes
4077 QRectF rb=bo->getBBox();
4078 if (bo->getDepth()==0)
4080 // Just take BBox of this mapCenter
4081 p<<rb.topLeft()<<rb.topRight()<<rb.bottomRight()<<rb.bottomLeft();
4085 // Take union of BBox and TotalBBox
4087 QRectF ra=bo->getTotalBBox();
4088 if (bo->getOrientation()==LinkableMapObj::LeftOfCenter)
4091 <<QPointF (rb.topLeft().x(), ra.topLeft().y() )
4094 <<QPointF (rb.bottomLeft().x(), ra.bottomLeft().y() ) ;
4096 p <<ra.bottomRight()
4098 <<QPointF (rb.topRight().x(), ra.topRight().y() )
4101 <<QPointF (rb.bottomRight().x(), ra.bottomRight().y() ) ;
4107 void VymModel::moveAway(LinkableMapObj *lmo) //FIXME-5
4111 // Move all branches and MapCenters away from lmo
4112 // to avoid collisions
4117 BranchObj *boA=(BranchObj*)lmo;
4119 for (int i=0; i<rootItem->branchCount(); i++)
4121 boB=rootItem->getBranchNum(i);
4124 PolygonCollisionResult r = PolygonCollision(pA, pB, QPoint(0,0));
4127 <<" ("<<qPrintable(boA->getHeading() )<<")"
4128 <<" with ("<< qPrintable (boB->getHeading() )
4131 <<" minT="<<r.minTranslation<<endl<<endl;
4137 void VymModel::setMapLinkStyle (const QString & s)
4142 case LinkableMapObj::Line :
4145 case LinkableMapObj::Parabel:
4146 snow="StyleParabel";
4148 case LinkableMapObj::PolyLine:
4149 snow="StylePolyLine";
4151 case LinkableMapObj::PolyParabel:
4152 snow="StylePolyParabel";
4155 snow="UndefinedStyle";
4160 QString("setMapLinkStyle (\"%1\")").arg(s),
4161 QString("setMapLinkStyle (\"%1\")").arg(snow),
4162 QString("Set map link style (\"%1\")").arg(s)
4166 linkstyle=LinkableMapObj::Line;
4167 else if (s=="StyleParabel")
4168 linkstyle=LinkableMapObj::Parabel;
4169 else if (s=="StylePolyLine")
4170 linkstyle=LinkableMapObj::PolyLine;
4171 else if (s=="StylePolyParabel")
4172 linkstyle=LinkableMapObj::PolyParabel;
4174 linkstyle=LinkableMapObj::UndefinedStyle;
4176 BranchItem *cur=NULL;
4177 BranchItem *prev=NULL;
4182 bo=(BranchObj*)(cur->getLMO() );
4183 bo->setLinkStyle(bo->getDefLinkStyle(cur->parent() )); //FIXME-3 better emit dataCHanged and leave the changes to View
4189 LinkableMapObj::Style VymModel::getMapLinkStyle ()
4194 void VymModel::setMapDefLinkColor(QColor col)
4196 if ( !col.isValid() ) return;
4198 QString("setMapDefLinkColor (\"%1\")").arg(getMapDefLinkColor().name()),
4199 QString("setMapDefLinkColor (\"%1\")").arg(col.name()),
4200 QString("Set map link color to %1").arg(col.name())
4204 BranchItem *cur=NULL;
4205 BranchItem *prev=NULL;
4210 bo=(BranchObj*)(cur->getLMO() );
4217 void VymModel::setMapLinkColorHintInt()
4219 // called from setMapLinkColorHint(lch) or at end of parse
4220 BranchItem *cur=NULL;
4221 BranchItem *prev=NULL;
4226 bo=(BranchObj*)(cur->getLMO() );
4232 void VymModel::setMapLinkColorHint(LinkableMapObj::ColorHint lch)
4235 setMapLinkColorHintInt();
4238 void VymModel::toggleMapLinkColorHint()
4240 if (linkcolorhint==LinkableMapObj::HeadingColor)
4241 linkcolorhint=LinkableMapObj::DefaultColor;
4243 linkcolorhint=LinkableMapObj::HeadingColor;
4244 BranchItem *cur=NULL;
4245 BranchItem *prev=NULL;
4250 bo=(BranchObj*)(cur->getLMO() );
4256 void VymModel::selectMapBackgroundImage () // FIXME-2 move to ME
4258 Q3FileDialog *fd=new Q3FileDialog( NULL);
4259 fd->setMode (Q3FileDialog::ExistingFile);
4260 fd->addFilter (QString (tr("Images") + " (*.png *.bmp *.xbm *.jpg *.png *.xpm *.gif *.pnm)"));
4261 ImagePreview *p =new ImagePreview (fd);
4262 fd->setContentsPreviewEnabled( TRUE );
4263 fd->setContentsPreview( p, p );
4264 fd->setPreviewMode( Q3FileDialog::Contents );
4265 fd->setCaption(vymName+" - " +tr("Load background image"));
4266 fd->setDir (lastImageDir);
4269 if ( fd->exec() == QDialog::Accepted )
4271 // TODO selectMapBackgroundImg in QT4 use: lastImageDir=fd->directory();
4272 lastImageDir=QDir (fd->dirPath());
4273 setMapBackgroundImage (fd->selectedFile());
4277 void VymModel::setMapBackgroundImage (const QString &fn) //FIXME-2 missing savestate, move to ME
4279 QColor oldcol=mapScene->backgroundBrush().color();
4283 QString ("setMapBackgroundImage (%1)").arg(oldcol.name()),
4285 QString ("setMapBackgroundImage (%1)").arg(col.name()),
4286 QString("Set background color of map to %1").arg(col.name()));
4289 brush.setTextureImage (QPixmap (fn));
4290 mapScene->setBackgroundBrush(brush);
4293 void VymModel::selectMapBackgroundColor() // FIXME-3 move to ME
4295 QColor col = QColorDialog::getColor( mapScene->backgroundBrush().color(), NULL);
4296 if ( !col.isValid() ) return;
4297 setMapBackgroundColor( col );
4301 void VymModel::setMapBackgroundColor(QColor col) // FIXME-3 move to ME
4303 QColor oldcol=mapScene->backgroundBrush().color();
4305 QString ("setMapBackgroundColor (\"%1\")").arg(oldcol.name()),
4306 QString ("setMapBackgroundColor (\"%1\")").arg(col.name()),
4307 QString("Set background color of map to %1").arg(col.name()));
4308 mapScene->setBackgroundBrush(col);
4311 QColor VymModel::getMapBackgroundColor() // FIXME-3 move to ME
4313 return mapScene->backgroundBrush().color();
4317 LinkableMapObj::ColorHint VymModel::getMapLinkColorHint() // FIXME-3 move to ME
4319 return linkcolorhint;
4322 QColor VymModel::getMapDefLinkColor() // FIXME-3 move to ME
4324 return defLinkColor;
4327 void VymModel::setMapDefXLinkColor(QColor col) // FIXME-3 move to ME
4332 QColor VymModel::getMapDefXLinkColor() // FIXME-3 move to ME
4334 return defXLinkColor;
4337 void VymModel::setMapDefXLinkWidth (int w) // FIXME-3 move to ME
4342 int VymModel::getMapDefXLinkWidth() // FIXME-3 move to ME
4344 return defXLinkWidth;
4347 void VymModel::move(const double &x, const double &y)
4350 MapItem *seli = (MapItem*)getSelectedItem();
4351 if (seli && (seli->isBranchLikeType() || seli->getType()==TreeItem::Image))
4353 LinkableMapObj *lmo=seli->getLMO();
4356 QPointF ap(lmo->getAbsPos());
4360 QString ps=qpointFToString(ap);
4361 QString s=getSelectString(seli);
4364 s, "move "+qpointFToString(to),
4365 QString("Move %1 to %2").arg(getObjectName(seli)).arg(ps));
4368 emitSelectionChanged();
4374 void VymModel::moveRel (const double &x, const double &y)
4377 MapItem *seli = (MapItem*)getSelectedItem();
4378 if (seli && (seli->isBranchLikeType() || seli->getType()==TreeItem::Image))
4380 LinkableMapObj *lmo=seli->getLMO();
4383 QPointF rp(lmo->getRelPos());
4387 QString ps=qpointFToString (lmo->getRelPos());
4388 QString s=getSelectString(seli);
4391 s, "moveRel "+qpointFToString(to),
4392 QString("Move %1 to relative position %2").arg(getObjectName(seli)).arg(ps));
4393 ((OrnamentedObj*)lmo)->move2RelPos (x,y);
4395 lmo->updateLinkGeometry();
4396 emitSelectionChanged();
4403 void VymModel::animate()
4405 animationTimer->stop();
4408 while (i<animObjList.size() )
4410 bo=(BranchObj*)animObjList.at(i);
4415 animObjList.removeAt(i);
4422 QItemSelection sel=selModel->selection();
4423 emit (selectionChanged(sel,sel));
4426 if (!animObjList.isEmpty()) animationTimer->start();
4430 void VymModel::startAnimation(BranchObj *bo, const QPointF &start, const QPointF &dest)
4432 if (bo && bo->getTreeItem()->depth()>0)
4435 ap.setStart (start);
4437 ap.setTicks (animationTicks);
4438 ap.setAnimated (true);
4439 bo->setAnimation (ap);
4440 animObjList.append( bo );
4441 animationTimer->setSingleShot (true);
4442 animationTimer->start(animationInterval);
4446 void VymModel::stopAnimation (MapObj *mo)
4448 int i=animObjList.indexOf(mo);
4450 animObjList.removeAt (i);
4453 void VymModel::sendSelection()
4455 if (netstate!=Server) return;
4456 sendData (QString("select (\"%1\")").arg(getSelectString()) );
4459 void VymModel::newServer()
4463 tcpServer = new QTcpServer(this);
4464 if (!tcpServer->listen(QHostAddress::Any,port)) {
4465 QMessageBox::critical(NULL, "vym server",
4466 QString("Unable to start the server: %1.").arg(tcpServer->errorString()));
4467 //FIXME-3 needed? we are no widget any longer... close();
4470 connect(tcpServer, SIGNAL(newConnection()), this, SLOT(newClient()));
4472 cout<<"Server is running on port "<<tcpServer->serverPort()<<endl;
4475 void VymModel::connectToServer()
4478 server="salam.suse.de";
4480 clientSocket = new QTcpSocket (this);
4481 clientSocket->abort();
4482 clientSocket->connectToHost(server ,port);
4483 connect(clientSocket, SIGNAL(readyRead()), this, SLOT(readData()));
4484 connect(clientSocket, SIGNAL(error(QAbstractSocket::SocketError)),
4485 this, SLOT(displayNetworkError(QAbstractSocket::SocketError)));
4487 cout<<"connected to "<<qPrintable (server)<<" port "<<port<<endl;
4492 void VymModel::newClient()
4494 QTcpSocket *newClient = tcpServer->nextPendingConnection();
4495 connect(newClient, SIGNAL(disconnected()),
4496 newClient, SLOT(deleteLater()));
4498 cout <<"ME::newClient at "<<qPrintable( newClient->peerAddress().toString() )<<endl;
4500 clientList.append (newClient);
4504 void VymModel::sendData(const QString &s)
4506 if (clientList.size()==0) return;
4508 // Create bytearray to send
4510 QDataStream out(&block, QIODevice::WriteOnly);
4511 out.setVersion(QDataStream::Qt_4_0);
4513 // Reserve some space for blocksize
4516 // Write sendCounter
4517 out << sendCounter++;
4522 // Go back and write blocksize so far
4523 out.device()->seek(0);
4524 quint16 bs=(quint16)(block.size() - 2*sizeof(quint16));
4528 cout << "ME::sendData bs="<<bs<<" counter="<<sendCounter<<" s="<<qPrintable(s)<<endl;
4530 for (int i=0; i<clientList.size(); ++i)
4532 //cout << "Sending \""<<qPrintable (s)<<"\" to "<<qPrintable (clientList.at(i)->peerAddress().toString())<<endl;
4533 clientList.at(i)->write (block);
4537 void VymModel::readData ()
4539 while (clientSocket->bytesAvailable() >=(int)sizeof(quint16) )
4542 cout <<"readData bytesAvail="<<clientSocket->bytesAvailable();
4546 QDataStream in(clientSocket);
4547 in.setVersion(QDataStream::Qt_4_0);
4555 cout << " t="<<qPrintable (t)<<endl;
4561 void VymModel::displayNetworkError(QAbstractSocket::SocketError socketError)
4563 switch (socketError) {
4564 case QAbstractSocket::RemoteHostClosedError:
4566 case QAbstractSocket::HostNotFoundError:
4567 QMessageBox::information(NULL, vymName +" Network client",
4568 "The host was not found. Please check the "
4569 "host name and port settings.");
4571 case QAbstractSocket::ConnectionRefusedError:
4572 QMessageBox::information(NULL, vymName + " Network client",
4573 "The connection was refused by the peer. "
4574 "Make sure the fortune server is running, "
4575 "and check that the host name and port "
4576 "settings are correct.");
4579 QMessageBox::information(NULL, vymName + " Network client",
4580 QString("The following error occurred: %1.")
4581 .arg(clientSocket->errorString()));
4585 /* FIXME-3 Playing with DBUS...
4586 QDBusVariant VymModel::query (const QString &query)
4588 TreeItem *selti=getSelectedItem();
4590 return QDBusVariant (selti->getHeading());
4592 return QDBusVariant ("Nothing selected.");
4596 void VymModel::testslot() //FIXME-3
4598 cout << "VM::testslot called\n";
4601 void VymModel::selectMapSelectionColor()
4603 QColor col = QColorDialog::getColor( defLinkColor, NULL);
4604 setSelectionColor (col);
4607 void VymModel::setSelectionColorInt (QColor col)
4609 if ( !col.isValid() ) return;
4611 QString("setSelectionColor (%1)").arg(mapEditor->getSelectionColor().name()),
4612 QString("setSelectionColor (%1)").arg(col.name()),
4613 QString("Set color of selection box to %1").arg(col.name())
4616 mapEditor->setSelectionColor (col);
4619 void VymModel::emitSelectionChanged(const QItemSelection &newsel)
4621 emit (selectionChanged(newsel,newsel)); // needed e.g. to update geometry in editor
4622 emitShowSelection();
4626 void VymModel::emitSelectionChanged()
4628 QItemSelection newsel=selModel->selection();
4629 emitSelectionChanged (newsel);
4632 void VymModel::setSelectionColor(QColor col)
4634 if ( !col.isValid() ) return;
4636 QString("setSelectionColor (%1)").arg(mapEditor->getSelectionColor().name()),
4637 QString("setSelectionColor (%1)").arg(col.name()),
4638 QString("Set color of selection box to %1").arg(col.name())
4640 setSelectionColorInt (col);
4643 QColor VymModel::getSelectionColor()
4645 return mapEditor->getSelectionColor();
4648 void VymModel::setHideTmpMode (TreeItem::HideTmpMode mode)
4651 for (int i=0;i<rootItem->childCount();i++)
4652 rootItem->child(i)->setHideTmp (mode);
4654 // FIXME-3 needed? scene()->update();
4657 //////////////////////////////////////////////
4658 // Selection related
4659 //////////////////////////////////////////////
4661 void VymModel::setSelectionModel (QItemSelectionModel *sm)
4666 QItemSelectionModel* VymModel::getSelectionModel()
4671 void VymModel::setSelectionBlocked (bool b)
4676 bool VymModel::isSelectionBlocked()
4678 return selectionBlocked;
4681 bool VymModel::select ()
4683 return select (selModel->selectedIndexes().first()); // TODO no multiselections yet
4686 bool VymModel::select (const QString &s)
4693 TreeItem *ti=findBySelectString(s);
4694 if (ti) return select (index(ti));
4698 bool VymModel::select (LinkableMapObj *lmo)
4700 QItemSelection oldsel=selModel->selection();
4703 return select (index (lmo->getTreeItem()) );
4708 bool VymModel::select (TreeItem *ti)
4710 if (ti) return select (index(ti));
4714 bool VymModel::select (const QModelIndex &index)
4716 if (index.isValid() )
4718 selModel->select (index,QItemSelectionModel::ClearAndSelect );
4719 BranchItem *bi=getSelectedBranch();
4720 if (bi) bi->setLastSelectedBranch();
4726 void VymModel::unselect()
4728 lastSelectString=getSelectString();
4729 selModel->clearSelection();
4732 bool VymModel::reselect()
4734 return select (lastSelectString);
4737 void VymModel::emitShowSelection()
4739 if (!blockReposition)
4740 emit (showSelection() );
4743 void VymModel::emitNoteHasChanged (TreeItem *ti)
4745 QModelIndex ix=index(ti);
4746 emit (noteHasChanged (ix) );
4749 void VymModel::emitDataHasChanged (TreeItem *ti)
4751 QModelIndex ix=index(ti);
4752 emit (dataChanged (ix,ix) );
4756 //bool VymModel::selectInt (LinkableMapObj *lmo) // FIXME-3 still needed?
4759 if (selection.select(lmo))
4761 //emitSelectionChanged();
4765 bool VymModel::selectInt (TreeItem *ti)
4767 if (selection.select(lmo))
4769 //emitSelectionChanged();
4774 bool VymModel::selectFirstBranch()
4776 TreeItem *ti=getSelectedBranch();
4779 TreeItem *par=ti->parent();
4782 TreeItem *ti2=par->getFirstBranch();
4783 if (ti2) return select(ti2);
4789 bool VymModel::selectLastBranch()
4791 TreeItem *ti=getSelectedBranch();
4794 TreeItem *par=ti->parent();
4797 TreeItem *ti2=par->getLastBranch();
4798 if (ti2) return select(ti2);
4804 bool VymModel::selectLastSelectedBranch()
4806 BranchItem *bi=getSelectedBranch();
4809 bi=bi->getLastSelectedBranch();
4810 if (bi) return select (bi);
4815 bool VymModel::selectParent()
4817 TreeItem *ti=getSelectedItem();
4828 TreeItem::Type VymModel::selectionType()
4830 QModelIndexList list=selModel->selectedIndexes();
4831 if (list.isEmpty()) return TreeItem::Undefined;
4832 TreeItem *ti = getItem (list.first() );
4833 return ti->getType();
4837 LinkableMapObj* VymModel::getSelectedLMO()
4839 QModelIndexList list=selModel->selectedIndexes();
4840 if (!list.isEmpty() )
4842 TreeItem *ti = getItem (list.first() );
4843 TreeItem::Type type=ti->getType();
4844 if (type ==TreeItem::Branch || type==TreeItem::MapCenter || type==TreeItem::Image)
4845 return ((MapItem*)ti)->getLMO();
4850 BranchObj* VymModel::getSelectedBranchObj() // FIXME-3 this should not be needed in the end!!!
4852 TreeItem *ti = getSelectedBranch();
4854 return (BranchObj*)( ((MapItem*)ti)->getLMO());
4859 BranchItem* VymModel::getSelectedBranch()
4861 QModelIndexList list=selModel->selectedIndexes();
4862 if (!list.isEmpty() )
4864 TreeItem *ti = getItem (list.first() );
4865 TreeItem::Type type=ti->getType();
4866 if (type ==TreeItem::Branch || type==TreeItem::MapCenter)
4867 return (BranchItem*)ti;
4872 ImageItem* VymModel::getSelectedImage()
4874 QModelIndexList list=selModel->selectedIndexes();
4875 if (!list.isEmpty())
4877 TreeItem *ti=getItem (list.first());
4878 if (ti && ti->getType()==TreeItem::Image)
4879 return (ImageItem*)ti;
4884 AttributeItem* VymModel::getSelectedAttribute()
4886 QModelIndexList list=selModel->selectedIndexes();
4887 if (!list.isEmpty() )
4889 TreeItem *ti = getItem (list.first() );
4890 TreeItem::Type type=ti->getType();
4891 if (type ==TreeItem::Attribute)
4892 return (AttributeItem*)ti;
4897 TreeItem* VymModel::getSelectedItem()
4899 QModelIndexList list=selModel->selectedIndexes();
4900 if (!list.isEmpty() )
4901 return getItem (list.first() );
4906 QModelIndex VymModel::getSelectedIndex()
4908 QModelIndexList list=selModel->selectedIndexes();
4909 if (list.isEmpty() )
4910 return QModelIndex();
4912 return list.first();
4915 QString VymModel::getSelectString ()
4917 return getSelectString (getSelectedItem());
4920 QString VymModel::getSelectString (LinkableMapObj *lmo) // only for convenience. Used in MapEditor
4922 if (!lmo) return QString();
4923 return getSelectString (lmo->getTreeItem() );
4926 QString VymModel::getSelectString (TreeItem *ti)
4930 switch (ti->getType())
4932 case TreeItem::MapCenter: s="mc:"; break;
4933 case TreeItem::Branch: s="bo:";break;
4934 case TreeItem::Image: s="fi:";break;
4935 case TreeItem::Attribute: s="ai:";break;
4936 case TreeItem::XLink: s="xl:";break;
4938 s="unknown type in VymModel::getSelectString()";
4941 s= s + QString("%1").arg(ti->num());
4943 // call myself recursively
4944 s= getSelectString(ti->parent()) +","+s;