1 #include <QApplication>
2 #include <QSvgGenerator>
5 #include <QtDBus/QDBusConnection>
14 #include <QColorDialog>
15 #include <QFileDialog>
16 #include <QMessageBox>
21 #include "attributeitem.h"
23 #include "branchitem.h"
25 #include "downloadagent.h"
26 #include "editxlinkdialog.h"
28 #include "exporthtmldialog.h"
30 #include "findresultmodel.h"
31 #include "lockedfiledialog.h"
32 #include "mainwindow.h"
34 #include "noteeditor.h"
37 #include "vymprocess.h"
38 #include "scripteditor.h"
39 #include "slideitem.h"
40 #include "slidemodel.h"
41 #include "taskeditor.h"
42 #include "taskmodel.h"
43 #include "warningdialog.h"
44 #include "xlinkitem.h"
46 #include "xml-freemind.h"
56 extern Main *mainWindow;
58 extern Settings settings;
59 extern QString tmpVymDir;
60 extern QString macroPath;
62 extern NoteEditor *noteEditor;
63 extern TaskEditor *taskEditor;
64 extern ScriptEditor *scriptEditor;
65 extern FlagRow *standardFlagsMaster;
67 extern Options options;
69 extern QString clipboardDir;
70 extern QString clipboardFile;
71 extern bool clipboardEmpty;
73 extern ImageIO imageIO;
75 extern TaskModel* taskModel;
77 extern QString vymName;
78 extern QString vymVersion;
79 extern QDir vymBaseDir;
81 extern QDir lastImageDir;
82 extern QDir lastMapDir;
83 extern QDir lastExportDir;
85 extern bool bugzillaClientAvailable;
87 extern Settings settings;
89 uint VymModel::idLast=0; // make instance
93 //qDebug()<< "Const VymModel";
95 rootItem->setModel (this);
100 //out << "Destr VymModel begin this="<<this<<" "<<mapName<<flush;
102 blockReposition=true;
103 autosaveTimer->stop();
104 fileChangedTimer->stop();
107 //qApp->processEvents(); // Update view (scene()->update() is not enough)
108 //qDebug() << "Destr VymModel end this="<<this;
111 void VymModel::clear()
113 while (rootItem->childCount() >0)
115 //qDebug()<<"VM::clear ri="<<rootItem<<" ri->count()="<<rootItem->childCount();
116 deleteItem (rootItem->getChildNum(0) );
120 void VymModel::init ()
125 // Use default author
126 author = settings.value("/user/name", tr("unknown user","default name for map author in settings")).toString();
137 selectionBlocked= false;
138 resetSelectionHistory();
143 makeTmpDirectories();
149 fileName = tr("unnamed");
151 blockReposition = false;
152 blockSaveState = false;
154 autosaveTimer = new QTimer (this);
155 connect(autosaveTimer, SIGNAL(timeout()), this, SLOT(autosave()));
157 fileChangedTimer= new QTimer (this);
158 fileChangedTimer->start(3000);
159 connect(fileChangedTimer, SIGNAL(timeout()), this, SLOT(fileChanged()));
164 // animations // FIXME-4 switch to new animation system
165 animationUse = settings.value ("/animation/use",false).toBool(); // FIXME-4 add options to control _what_ is animated
166 animationTicks = settings.value("/animation/ticks",20).toInt();
167 animationInterval=settings.value("/animation/interval",5).toInt();
169 animationTimer = new QTimer (this);
170 connect(animationTimer, SIGNAL(timeout()), this, SLOT(animate()));
173 defaultFont.setPointSizeF (16);
174 defLinkColor = QColor (0,0,255);
175 linkcolorhint = LinkableMapObj::DefaultColor;
176 linkstyle = LinkableMapObj::PolyParabel;
177 defXLinkPen.setWidth (1);
178 defXLinkPen.setColor ( QColor (50,50,255) );
179 defXLinkPen.setStyle ( Qt::DashLine );
180 defXLinkStyleBegin = "HeadFull";
181 defXLinkStyleEnd = "HeadFull";
183 hasContextPos = false;
185 hidemode = TreeItem::HideNone;
187 // Animation in MapEditor
191 animCurve = QEasingCurve::OutQuint;
193 // Initialize presentation slides
194 slideModel = new SlideModel (this);
195 blockSlideSelection=false;
197 // Avoid recursions later
198 cleaningUpLinks = false;
203 #if defined(VYM_DBUS)
204 // Announce myself on DBUS
205 new AdaptorModel(this); // Created and not deleted as documented in Qt
206 if (!QDBusConnection::sessionBus().registerObject (QString("/vymmodel_%1").arg(modelID),this))
207 qWarning ("VymModel: Couldn't register DBUS object!");
211 void VymModel::makeTmpDirectories()
213 // Create unique temporary directories
214 tmpMapDir = tmpVymDir+QString("/model-%1").arg(modelID);
215 histPath = tmpMapDir+"/history";
220 MapEditor* VymModel::getMapEditor()
225 bool VymModel::isRepositionBlocked()
227 return blockReposition;
230 void VymModel::updateActions()
232 // Tell mainwindow to update states of actions
233 mainWindow->updateActions();
238 QString VymModel::saveToDir(const QString &tmpdir, const QString &prefix, bool writeflags, const QPointF &offset, TreeItem *saveSel)
240 // tmpdir temporary directory to which data will be written
241 // prefix mapname, which will be appended to images etc.
243 // writeflags Only write flags for "real" save of map, not undo
244 // offset offset of bbox of whole map in scene.
245 // Needed for XML export
253 case LinkableMapObj::Line:
256 case LinkableMapObj::Parabel:
259 case LinkableMapObj::PolyLine:
263 ls="StylePolyParabel";
267 QString s="<?xml version=\"1.0\" encoding=\"utf-8\"?><!DOCTYPE vymmap>\n";
269 if (linkcolorhint==LinkableMapObj::HeadingColor)
270 colhint=xml.attribut("linkColorHint","HeadingColor");
272 QString mapAttr=xml.attribut("version",vymVersion);
274 mapAttr+= xml.attribut("author",author) +
275 xml.attribut("title",title) +
276 xml.attribut("comment",comment) +
277 xml.attribut("date",getDate()) +
278 xml.attribut("branchCount", QString().number(branchCount())) +
279 xml.attribut("backgroundColor", mapEditor->getScene()->backgroundBrush().color().name() ) +
280 xml.attribut("defaultFont", defaultFont.toString() ) +
281 xml.attribut("selectionColor", mapEditor->getSelectionColor().name() ) +
282 xml.attribut("linkStyle", ls ) +
283 xml.attribut("linkColor", defLinkColor.name() ) +
284 xml.attribut("defXLinkColor", defXLinkPen.color().name() ) +
285 xml.attribut("defXLinkWidth", QString().setNum(defXLinkPen.width(),10) ) +
286 xml.attribut("defXLinkPenStyle", penStyleToString (defXLinkPen.style() )) +
287 xml.attribut("defXLinkStyleBegin", defXLinkStyleBegin) +
288 xml.attribut("defXLinkStyleEnd", defXLinkStyleEnd) +
289 xml.attribut("mapZoomFactor", QString().setNum(mapEditor->getZoomFactorTarget()) ) +
290 xml.attribut("mapRotationAngle", QString().setNum(mapEditor->getAngleTarget()) ) +
292 s+=xml.beginElement("vymmap",mapAttr);
295 // Find the used flags while traversing the tree
296 standardFlagsMaster->resetUsedCounter();
299 // Temporary list of links
300 QList <Link*> tmpLinks;
302 // Build xml recursivly
305 // Save all mapcenters as complete map, if saveSel not set
306 s+=saveTreeToDir(tmpdir,prefix,offset,tmpLinks);
308 // Save local settings
309 s+=settings.getDataXML (destPath);
312 if (getSelectedItem() && !saveSel )
313 s+=xml.valueElement("select",getSelectString());
317 switch (saveSel->getType())
319 case TreeItem::Branch:
321 s+=((BranchItem*)saveSel)->saveToDir(tmpdir,prefix,offset,tmpLinks);
323 case TreeItem::MapCenter:
325 s+=((BranchItem*)saveSel)->saveToDir(tmpdir,prefix,offset,tmpLinks);
327 case TreeItem::Image:
329 s+=((ImageItem*)saveSel)->saveToDir(tmpdir,prefix);
332 // other types shouldn't be safed directly...
338 for (int i=0; i<tmpLinks.count();++i)
339 s+=tmpLinks.at(i)->saveToDir();
342 s+=slideModel->saveToDir();
345 s+=xml.endElement("vymmap");
347 if (writeflags) standardFlagsMaster->saveToDir (tmpdir+"/flags/","",writeflags);
351 QString VymModel::saveTreeToDir (const QString &tmpdir,const QString &prefix, const QPointF &offset, QList <Link*> &tmpLinks)
354 for (int i=0; i<rootItem->branchCount(); i++)
355 s+=rootItem->getBranchNum(i)->saveToDir (tmpdir,prefix,offset,tmpLinks);
359 void VymModel::setFilePath(QString fpath, QString destname)
361 if (fpath.isEmpty() || fpath=="")
368 filePath=fpath; // becomes absolute path
369 fileName=fpath; // gets stripped of path
370 destPath=destname; // needed for vymlinks and during load to reset fileChangedTime
372 // If fpath is not an absolute path, complete it
373 filePath=QDir(fpath).absolutePath();
374 fileDir=filePath.left (1+filePath.lastIndexOf ("/"));
376 // Set short name, too. Search from behind:
377 fileName=basename(fileName);
379 // Forget the .vym (or .xml) for name of map
380 mapName=fileName.left(fileName.lastIndexOf(".",-1,Qt::CaseSensitive) );
384 void VymModel::setFilePath(QString fpath)
386 setFilePath (fpath,fpath);
389 QString VymModel::getFileDir()
394 QString VymModel::getFilePath()
399 QString VymModel::getFileName()
404 QString VymModel::getMapName()
409 QString VymModel::getDestPath()
414 bool VymModel::parseVymText (const QString &s)
417 BranchItem *bi = getSelectedBranch();
420 parseBaseHandler *handler = new parseVYMHandler;
422 bool blockSaveStateOrg=blockSaveState;
423 blockReposition=true;
425 QXmlInputSource source;
427 QXmlSimpleReader reader;
428 reader.setContentHandler( handler );
429 reader.setErrorHandler( handler );
431 handler->setInputString (s);
432 handler->setModel ( this );
433 handler->setLoadMode (ImportReplace, 0);
435 ok = reader.parse( source );
436 blockReposition=false;
437 blockSaveState=blockSaveStateOrg;
440 emitNoteChanged( bi );
441 emitDataChanged( bi );
442 reposition(); // to generate bbox sizes
445 QMessageBox::critical( 0, tr( "Critical Parse Error" ),
446 tr( handler->errorProtocol().toUtf8() ) );
448 // Still return "success": the map maybe at least
449 // partially read by the parser
455 File::ErrorCode VymModel::loadMap (
457 const LoadMode &lmode,
458 const FileType &ftype,
459 const int &contentFilter,
462 File::ErrorCode err = File::Success;
464 // Get updated zoomFactor, before applying one read from file in the end
467 zoomFactor = mapEditor->getZoomFactorTarget();
468 rotationAngle = mapEditor->getAngleTarget();
471 parseBaseHandler *handler;
476 handler = new parseVYMHandler;
477 ((parseVYMHandler*)handler)->setContentFilter (contentFilter);
479 case FreemindMap : handler = new parseFreemindHandler; break;
481 QMessageBox::critical( 0, tr( "Critical Parse Error" ),
482 "Unknown FileType in VymModel::load()");
483 return File::Aborted;
486 bool zipped_org = zipped;
490 // Reset timestamp to check for later updates of file
491 fileChangedTime = QFileInfo (destPath).lastModified();
493 selModel->clearSelection();
496 // Create temporary directory for packing
498 QString tmpZipDir = makeTmpDir (ok,"vym-pack");
501 QMessageBox::critical( 0, tr( "Critical Load Error" ),
502 tr("Couldn't create temporary directory before load\n"));
503 return File::Aborted;
506 if (fname.right(4) == ".xml" || fname.right(3) == ".mm")
511 err = unzipDir (tmpZipDir,fname);
514 if (err == File::NoZip)
522 // Look for mapname.xml
523 xmlfile = fname.left(fname.lastIndexOf(".", -1, Qt::CaseSensitive));
524 xmlfile = xmlfile.section( '/', -1 );
525 QFile mfile( tmpZipDir + "/" + xmlfile + ".xml");
526 if (!mfile.exists() )
528 // mapname.xml does not exist, well,
529 // maybe someone renamed the mapname.vym file...
530 // Try to find any .xml in the toplevel
531 // directory of the .vym file
534 QStringList flist = QDir (tmpZipDir).entryList(filters);
535 if (flist.count() == 1)
537 // Only one entry, take this one
538 xmlfile = tmpZipDir + "/"+flist.first();
541 for ( QStringList::Iterator it = flist.begin(); it != flist.end(); ++it )
542 *it=tmpZipDir + "/" + *it;
543 // FIXME-4 Multiple entries, load all (but only the first one into this ME)
544 //mainWindow->fileLoadFromTmp (flist);
545 //returnCode=1; // Silently forget this attempt to load
546 qWarning ("MainWindow::load (fn) multimap found...");
549 if (flist.isEmpty() )
551 QMessageBox::critical( 0, tr( "Critical Load Error" ),
552 tr("Couldn't find a map (*.xml) in .vym archive.\n"));
555 } //file doesn't exist
557 xmlfile=mfile.fileName();
560 QFile file( xmlfile);
562 // I am paranoid: file should exist anyway
563 // according to check in mainwindow.
566 QMessageBox::critical( 0, tr( "Critical Parse Error" ),
567 tr(QString("Couldn't open map %1").arg(file.fileName()).toUtf8()));
571 bool blockSaveStateOrg = blockSaveState;
572 blockReposition = true;
573 blockSaveState = true;
574 mapEditor->setViewportUpdateMode (QGraphicsView::NoViewportUpdate);
575 QXmlInputSource source( &file);
576 QXmlSimpleReader reader;
577 reader.setContentHandler( handler );
578 reader.setErrorHandler( handler );
579 handler->setModel ( this);
581 // We need to set the tmpDir in order to load files with rel. path
586 tmpdir = fname.left(fname.lastIndexOf("/", -1));
587 handler->setTmpDir (tmpdir);
588 handler->setInputFile (file.fileName());
589 if (lmode == ImportReplace)
590 handler->setLoadMode (ImportReplace, pos);
592 handler->setLoadMode (lmode, pos);
594 bool ok = reader.parse( source );
595 blockReposition = false;
596 blockSaveState = blockSaveStateOrg;
597 mapEditor->setViewportUpdateMode (QGraphicsView::MinimalViewportUpdate);
601 reposition(); // to generate bbox sizes
602 emitSelectionChanged();
609 autosaveTimer->stop();
612 resetSelectionHistory();
614 if (! tryVymLock() && debug )
615 qWarning() << "VM::loadMap no lockfile created!";
618 // Recalc priorities and sort
619 taskModel->recalcPriorities();
622 QMessageBox::critical( 0, tr( "Critical Parse Error" ),
623 tr( handler->errorProtocol().toUtf8() ) );
625 // Still return "success": the map maybe at least
626 // partially read by the parser
631 removeDir (QDir(tmpZipDir));
633 // Restore original zip state
638 if (lmode!=NewMap) emitUpdateQueries();
642 mapEditor->setZoomFactorTarget (zoomFactor);
643 mapEditor->setAngleTarget (rotationAngle);
646 if (vymView) vymView->readSettings();
648 qApp->processEvents(); // Update view (scene()->update() is not enough)
652 File::ErrorCode VymModel::save (const SaveMode &savemode)
656 QString safeFilePath;
658 File::ErrorCode err=File::Success;
662 mapFileName=mapName+".xml";
664 // use name given by user, even if he chooses .doc
665 mapFileName=fileName;
667 // Look, if we should zip the data:
670 QMessageBox mb( vymName,
671 tr("The map %1\ndid not use the compressed "
672 "vym file format.\nWriting it uncompressed will also write images \n"
673 "and flags and thus may overwrite files in the "
674 "given directory\n\nDo you want to write the map").arg(filePath),
675 QMessageBox::Warning,
676 QMessageBox::Yes | QMessageBox::Default,
678 QMessageBox::Cancel | QMessageBox::Escape);
679 mb.setButtonText( QMessageBox::Yes, tr("compressed (vym default)") );
680 mb.setButtonText( QMessageBox::No, tr("uncompressed") );
681 mb.setButtonText( QMessageBox::Cancel, tr("Cancel"));
684 case QMessageBox::Yes:
685 // save compressed (default file format)
688 case QMessageBox::No:
692 case QMessageBox::Cancel:
694 return File::Aborted;
699 // First backup existing file, we
700 // don't want to add to old zip archives
704 if ( settings.value ("/mapeditor/writeBackupFile").toBool())
706 QString backupFileName(destPath + "~");
707 QFile backupFile(backupFileName);
708 if (backupFile.exists() && !backupFile.remove())
710 QMessageBox::warning(0, tr("Save Error"),
711 tr("%1\ncould not be removed before saving").arg(backupFileName));
713 else if (!f.rename(backupFileName))
715 QMessageBox::warning(0, tr("Save Error"),
716 tr("%1\ncould not be renamed before saving").arg(destPath));
723 // Create temporary directory for packing
725 tmpZipDir=makeTmpDir (ok,"vym-zip");
728 QMessageBox::critical( 0, tr( "Critical Save Error" ),
729 tr("Couldn't create temporary directory before save\n"));
730 return File::Aborted;
733 safeFilePath=filePath;
734 setFilePath (tmpZipDir+"/"+ mapName+ ".xml", safeFilePath);
737 // Create mapName and fileDir
738 makeSubDirs (fileDir);
741 if (savemode==CompleteMap || selModel->selection().isEmpty())
745 // Use defined name for map within zipfile to avoid problems
746 //with zip library and umlauts (see #98)
747 saveFile=saveToDir (fileDir, "", true, QPointF(), NULL);
749 saveFile=saveToDir (fileDir, mapName + "-", true, QPointF(), NULL);
752 autosaveTimer->stop();
757 if (selectionType() == TreeItem::Image)
760 saveFile = saveToDir (fileDir, mapName + "-", true, QPointF(), getSelectedBranch());
761 // TODO take care of multiselections
766 // Use defined map name "map.xml", if zipped. Introduce in 2.6.6
767 saved = saveStringToDisk(fileDir + "map.xml", saveFile);
769 // Use regular mapName, when saved as XML
770 saved = saveStringToDisk(fileDir + mapFileName, saveFile);
774 qWarning ("ME::saveStringToDisk failed!");
780 if (err==File::Success) err=zipDir (tmpZipDir,destPath);
783 removeDir (QDir(tmpZipDir));
785 // Restore original filepath outside of tmp zip dir
786 setFilePath (safeFilePath);
790 fileChangedTime=QFileInfo (destPath).lastModified();
794 void VymModel::loadImage (BranchItem *dst,const QString &fn)
796 if (!dst) dst=getSelectedBranch();
799 QString filter=QString (tr("Images") + " (*.png *.bmp *.xbm *.jpg *.png *.xpm *.gif *.pnm *.svg);;"+tr("All","Filedialog") +" (*.*)");
802 fns=QFileDialog::getOpenFileNames(
804 vymName+" - " + tr("Load image"),
812 lastImageDir.setPath(fns.first().left(fns.first().lastIndexOf ("/")) );
814 for (int j=0; j<fns.count(); j++)
817 ImageItem *ii=createImage(dst);
818 if (ii && ii->load (s) )
824 QString ("loadImage (\"%1\")").arg(s ),
825 QString("Add image %1 to %2").arg(s).arg(getObjectName(dst))
827 // Find nice position
828 FloatImageObj *fio=(FloatImageObj*)(ii->getMO() );
830 fio->move2RelPos (0,0);
832 // On default include image // FIXME-4 check, if we change default settings...
834 setIncludeImagesHor (false);
835 setIncludeImagesVer (true);
839 // FIXME-4 loadFIO error handling
840 qWarning ()<<"Failed to load "+s;
847 void VymModel::saveImage (ImageItem *ii, QString format, QString fn)
849 if (!ii) ii=getSelectedImage();
852 QString filter=QString (tr("Images") + " (*.png *.bmp *.xbm *.jpg *.png *.xpm *.gif *.pnm *.svg);;"+tr("All","Filedialog") +" (*.*)");
854 fn=QFileDialog::getSaveFileName(
856 vymName+" - " + tr("Save image"),
860 QFileDialog::DontConfirmOverwrite);
864 lastImageDir.setPath(fn.left(fn.lastIndexOf ("/")) );
865 if (QFile (fn).exists() )
867 QMessageBox mb( vymName,
868 tr("The file %1 exists already.\n"
869 "Do you want to overwrite it?").arg(fn),
870 QMessageBox::Warning,
871 QMessageBox::Yes | QMessageBox::Default,
872 QMessageBox::Cancel | QMessageBox::Escape,
873 QMessageBox::NoButton );
875 mb.setButtonText( QMessageBox::Yes, tr("Overwrite") );
876 mb.setButtonText( QMessageBox::No, tr("Cancel"));
879 case QMessageBox::Yes:
882 case QMessageBox::Cancel:
888 if (format.isEmpty() ) format=imageIO.guessType(fn);
889 if (format.isEmpty())
890 QMessageBox::critical (0,tr("Critical Error"),tr("Unsupported format in %1").arg(fn));
891 else if (!ii->save (fn, format) )
892 QMessageBox::critical (0,tr("Critical Error"),tr("Couldn't save %1").arg(fn));
898 void VymModel::importDirInt(BranchItem *dst, QDir d)
900 bool oldSaveState = blockSaveState;
901 blockSaveState = true;
902 BranchItem *bi = dst;
905 int beginDepth = bi->depth();
907 d.setFilter(QDir::AllEntries | QDir::Hidden);
908 QFileInfoList list = d.entryInfoList();
911 // Traverse directories
912 for (int i = 0; i < list.size(); ++i)
915 if (fi.isDir() && fi.fileName() != "." && fi.fileName() != ".." )
917 bi = addNewBranchInt(dst, -2);
918 bi->setHeadingPlainText (fi.fileName() );
919 bi->setHeadingColor (QColor("blue"));
920 if ( !d.cd(fi.fileName()) )
921 QMessageBox::critical (0,tr("Critical Import Error"),tr("Cannot find the directory %1").arg(fi.fileName()));
924 // Recursively add subdirs
925 qDebug() << "Add subdir " << bi->getHeadingPlain();
926 importDirInt (bi, d);
933 for (int i = 0; i < list.size(); ++i)
938 bi = addNewBranchInt (dst,-2);
939 bi->setHeadingPlainText (fi.fileName() );
940 bi->setHeadingColor (QColor("black"));
941 if (fi.fileName().right(4) == ".vym" )
942 bi->setVymLink (fi.filePath());
947 // Scroll at least some stuff
948 if (dst->branchCount()>1 && dst->depth()-beginDepth>2)
951 blockSaveState=oldSaveState;
954 void VymModel::importDirInt (const QString &s)
956 BranchItem *selbi = getSelectedBranch();
959 saveStateChangingPart (selbi, selbi, QString ("importDir (\"%1\")").arg(s),QString("Import directory structure from %1").arg(s));
962 importDirInt (selbi, d);
966 void VymModel::importDir()
968 BranchItem *selbi = getSelectedBranch();
972 filters <<"VYM map (*.vym)";
974 fd.setWindowTitle (vymName + " - " +tr("Choose directory structure to import"));
975 fd.setFileMode (QFileDialog::DirectoryOnly);
976 fd.setNameFilters (filters);
977 fd.setWindowTitle(vymName + " - " + tr("Choose directory structure to import"));
978 fd.setAcceptMode (QFileDialog::AcceptOpen);
981 if ( fd.exec() == QDialog::Accepted &&!fd.selectedFiles().isEmpty() )
983 importDirInt (fd.selectedFiles().first() );
989 bool VymModel::tryVymLock()
991 // Defaults for author and host in vymLock
992 QString defAuthor = settings.value("/user/name", tr( "unknown user", "Default for lockfiles of maps") ).toString();
993 QString defHost = QHostInfo::localHostName();
994 vymLock.setMapPath( filePath );
995 vymLock.setAuthor( settings.value( "/user/name", defAuthor ).toString() );
996 if ( getenv("HOST") != 0 )
997 vymLock.setHost( getenv("HOST") );
999 vymLock.setHost( defHost );
1002 if (!vymLock.tryLock() )
1004 if (debug) qDebug() << "VymModel::tryLock failed!";
1005 setReadOnly( true );
1006 if (vymLock.getState() == VymLock::lockedByOther)
1008 LockedFileDialog dia;
1009 QString a = vymLock.getAuthor();
1010 QString h = vymLock.getHost();
1011 QString s = QString( tr("Map seems to be already opened in another vym instance!\n\n "
1012 "Map is locked by \"%1\" on \"%2\"\n\n"
1013 "Please only delete the lockfile, if you are sure nobody else is currently working on this map." )) .arg(a).arg(h);
1015 dia.setWindowTitle(tr("Warning: Map already opended","VymModel"));
1016 if (dia.execDialog() == LockedFileDialog::DeleteLockfile)
1018 if (vymLock.removeLock() )
1020 mainWindow->statusMessage (tr("Removed lockfile for %1").arg(mapName));
1024 QMessageBox::warning(0,
1026 tr("Couldn't remove lockfile for %1").arg(mapName));
1028 } else if (vymLock.getState() == VymLock::notWritable)
1031 QString a = vymLock.getAuthor();
1032 QString h = vymLock.getHost();
1033 QString s = QString( tr("Cannot create lockfile of map! "
1034 "It will be opened in readonly mode.\n\n" ));
1036 dia.setWindowTitle(tr("Warning","VymModel"));
1037 dia.showCancelButton( false );
1038 //dia.setShowAgainName("/mainwindow/mapIsLocked");
1046 bool VymModel::renameMap( const QString &newPath)
1048 QString oldPath = filePath;
1049 setFilePath ( newPath );
1050 if (vymLock.getState() == VymLock::lockedByMyself)
1052 // vymModel owns the lockfile, try to rename it
1053 if (! vymLock.rename( fileName ))
1055 qWarning ("Warning: VymModel::renameMap failed");
1056 setFilePath( oldPath );
1062 // try to create new lockfile for the lock states: lockedByOther and notWritable
1063 return tryVymLock();
1066 void VymModel::setReadOnly( bool b )
1069 mainWindow->updateTabName( this );
1072 bool VymModel::isReadOnly()
1077 void VymModel::autosave()
1082 qDebug() << "VymModel::autosave rejected due to missing filePath\n";
1085 QDateTime now=QDateTime().currentDateTime();
1087 // Disable autosave, while we have gone back in history
1088 int redosAvail=undoSet.readNumValue (QString("/history/redosAvail"));
1089 if (redosAvail>0) return;
1091 // Also disable autosave for new map without filename
1092 if (filePath.isEmpty()) return;
1097 && mainWindow->useAutosave()
1100 if (QFileInfo(filePath).lastModified()<=fileChangedTime)
1101 mainWindow->fileSave (this);
1104 qDebug() <<" ME::autosave rejected, file on disk is newer than last save.\n";
1109 void VymModel::fileChanged()
1111 // Check if file on disk has changed meanwhile
1112 if (!filePath.isEmpty())
1116 // unset readonly if lockfile is gone
1117 if (vymLock.tryLock() ) setReadOnly( false );
1120 // FIXME-0 Check, if somebody else removed/replaced lockfile
1121 // Here a unique vym ID would be needed to be checked
1123 QDateTime tmod = QFileInfo (filePath).lastModified();
1124 if (tmod > fileChangedTime)
1126 // FIXME-4 VM switch to current mapeditor and finish lineedits...
1127 QMessageBox mb( vymName,
1128 tr("The file of the map on disk has changed:\n\n"
1129 " %1\n\nDo you want to reload that map with the new file?").arg(filePath),
1130 QMessageBox::Question,
1132 QMessageBox::Cancel | QMessageBox::Default,
1133 QMessageBox::NoButton );
1135 mb.setButtonText( QMessageBox::Yes, tr("Reload"));
1136 mb.setButtonText( QMessageBox::No, tr("Ignore"));
1139 case QMessageBox::Yes:
1141 mainWindow->initProgressCounter (1);
1143 mainWindow->removeProgressCounter ();
1145 case QMessageBox::Cancel:
1146 fileChangedTime=tmod; // allow autosave to overwrite newer file!
1153 bool VymModel::isDefault()
1158 void VymModel::makeDefault()
1164 bool VymModel::hasChanged()
1169 void VymModel::setChanged()
1172 autosaveTimer->start(settings.value("/system/autosave/ms/",300000).toInt());
1180 QString VymModel::getObjectName (LinkableMapObj *lmo)
1182 if (!lmo || !lmo->getTreeItem() ) return QString();
1183 return getObjectName (lmo->getTreeItem() );
1187 QString VymModel::getObjectName (TreeItem *ti)
1190 if (!ti) return QString("Error: NULL has no name!");
1191 s=ti->getHeadingPlain();
1192 if (s=="") s="unnamed";
1194 return QString ("%1 (%2)").arg(ti->getTypeName()).arg(s);
1197 void VymModel::redo()
1199 // Can we undo at all?
1200 if (redosAvail<1) return;
1202 bool blockSaveStateOrg=blockSaveState;
1203 blockSaveState=true;
1207 if (undosAvail<stepsTotal) undosAvail++;
1209 if (curStep>stepsTotal) curStep=1;
1210 QString undoCommand= undoSet.value (QString("/history/step-%1/undoCommand").arg(curStep));
1211 QString undoSelection=undoSet.value (QString("/history/step-%1/undoSelection").arg(curStep));
1212 QString redoCommand= undoSet.value (QString("/history/step-%1/redoCommand").arg(curStep));
1213 QString redoSelection=undoSet.value (QString("/history/step-%1/redoSelection").arg(curStep));
1214 QString comment=undoSet.value (QString("/history/step-%1/comment").arg(curStep));
1215 QString version=undoSet.value ("/history/version");
1217 /* TODO Maybe check for version, if we save the history
1218 if (!checkVersion(version))
1219 QMessageBox::warning(0,tr("Warning"),
1220 tr("Version %1 of saved undo/redo data\ndoes not match current vym version %2.").arg(version).arg(vymVersion));
1223 // Find out current undo directory
1224 QString bakMapDir(QString(tmpMapDir+"/undo-%1").arg(curStep));
1228 qDebug() << "VymModel::redo() begin\n";
1229 qDebug() << " undosAvail="<<undosAvail;
1230 qDebug() << " redosAvail="<<redosAvail;
1231 qDebug() << " curStep="<<curStep;
1232 qDebug() << " ---------------------------";
1233 qDebug() << " comment="<<comment;
1234 qDebug() << " undoCom="<<undoCommand;
1235 qDebug() << " undoSel="<<undoSelection;
1236 qDebug() << " redoCom="<<redoCommand;
1237 qDebug() << " redoSel="<<redoSelection;
1238 qDebug() << " ---------------------------";
1241 // select object before redo
1242 if (!redoSelection.isEmpty())
1243 select (redoSelection);
1247 parseAtom (redoCommand,noErr,errMsg);
1250 if (!options.isOn("batch") )
1251 QMessageBox::warning(0,tr("Warning"),tr("Redo failed:\n%1").arg(errMsg));
1252 qWarning()<< "VM::redo aborted:\n"<<errMsg;
1255 blockSaveState=blockSaveStateOrg;
1257 undoSet.setValue ("/history/undosAvail",QString::number(undosAvail));
1258 undoSet.setValue ("/history/redosAvail",QString::number(redosAvail));
1259 undoSet.setValue ("/history/curStep",QString::number(curStep));
1260 undoSet.writeSettings(histPath);
1262 mainWindow->updateHistory (undoSet);
1265 /* TODO remove testing
1266 qDebug() << "ME::redo() end\n";
1267 qDebug() << " undosAvail="<<undosAvail;
1268 qDebug() << " redosAvail="<<redosAvail;
1269 qDebug() << " curStep="<<curStep;
1270 qDebug() << " ---------------------------";
1274 bool VymModel::isRedoAvailable()
1276 if (undoSet.readNumValue("/history/redosAvail",0)>0)
1281 void VymModel::undo()
1283 // Can we undo at all?
1284 if (undosAvail<1) return;
1286 mainWindow->statusMessage (tr("Autosave disabled during undo."));
1288 bool blockSaveStateOrg=blockSaveState;
1289 blockSaveState=true;
1291 QString undoCommand= undoSet.value (QString("/history/step-%1/undoCommand").arg(curStep));
1292 QString undoSelection=undoSet.value (QString("/history/step-%1/undoSelection").arg(curStep));
1293 QString redoCommand= undoSet.value (QString("/history/step-%1/redoCommand").arg(curStep));
1294 QString redoSelection=undoSet.value (QString("/history/step-%1/redoSelection").arg(curStep));
1295 QString comment=undoSet.value (QString("/history/step-%1/comment").arg(curStep));
1296 QString version=undoSet.value ("/history/version");
1298 /* TODO Maybe check for version, if we save the history
1299 if (!checkVersion(version))
1300 QMessageBox::warning(0,tr("Warning"),
1301 tr("Version %1 of saved undo/redo data\ndoes not match current vym version %2.").arg(version).arg(vymVersion));
1304 // Find out current undo directory
1305 QString bakMapDir(QString(tmpMapDir+"/undo-%1").arg(curStep));
1307 // select object before undo
1308 if (!undoSelection.isEmpty() && !select (undoSelection))
1310 qWarning ("VymModel::undo() Could not select object for undo");
1316 qDebug() << "VymModel::undo() begin\n";
1317 qDebug() << " undosAvail="<<undosAvail;
1318 qDebug() << " redosAvail="<<redosAvail;
1319 qDebug() << " curStep="<<curStep;
1320 qDebug() << " ---------------------------";
1321 qDebug() << " comment="<<comment;
1322 qDebug() << " undoCom="<<undoCommand;
1323 qDebug() << " undoSel="<<undoSelection;
1324 qDebug() << " redoCom="<<redoCommand;
1325 qDebug() << " redoSel="<<redoSelection;
1326 qDebug() << " ---------------------------";
1329 // select object before undo
1330 if (!undoSelection.isEmpty())
1331 select (undoSelection);
1335 //parseAtom (undoCommand,noErr,errMsg);
1336 errMsg = QVariant(execute(undoCommand)).toString();
1337 // FIXME-3 add noErr to parameters of execute above or ignore (error message already within parseAtom)
1342 if (!options.isOn("batch") )
1343 QMessageBox::warning(0,tr("Warning"),tr("Undo failed:\n%1").arg(errMsg));
1344 qWarning()<< "VM::undo failed:\n"<<errMsg;
1350 if (curStep<1) curStep = stepsTotal;
1354 blockSaveState = blockSaveStateOrg;
1356 qDebug() << "VymModel::undo() end\n";
1357 qDebug() << " undosAvail="<<undosAvail;
1358 qDebug() << " redosAvail="<<redosAvail;
1359 qDebug() << " curStep="<<curStep;
1360 qDebug() << " ---------------------------";
1363 undoSet.setValue ("/history/undosAvail",QString::number(undosAvail));
1364 undoSet.setValue ("/history/redosAvail",QString::number(redosAvail));
1365 undoSet.setValue ("/history/curStep",QString::number(curStep));
1366 undoSet.writeSettings(histPath);
1368 mainWindow->updateHistory (undoSet);
1370 //emitSelectionChanged();
1373 bool VymModel::isUndoAvailable()
1375 if (undoSet.readNumValue("/history/undosAvail",0)>0)
1380 void VymModel::gotoHistoryStep (int i)
1382 // Restore variables
1383 int undosAvail=undoSet.readNumValue (QString("/history/undosAvail"));
1384 int redosAvail=undoSet.readNumValue (QString("/history/redosAvail"));
1386 if (i<0) i=undosAvail+redosAvail;
1388 // Clicking above current step makes us undo things
1391 for (int j=0; j<undosAvail-i; j++) undo();
1394 // Clicking below current step makes us redo things
1396 for (int j=undosAvail; j<i; j++)
1398 if (debug) qDebug() << "VymModel::gotoHistoryStep redo "<<j<<"/"<<undosAvail<<" i="<<i;
1402 // And ignore clicking the current row ;-)
1406 QString VymModel::getHistoryPath()
1408 QString histName(QString("history-%1").arg(curStep));
1409 return (tmpMapDir+"/"+histName);
1412 void VymModel::resetHistory()
1418 stepsTotal=settings.value("/history/stepsTotal",100).toInt();
1419 undoSet.setValue ("/history/stepsTotal",QString::number(stepsTotal));
1420 mainWindow->updateHistory (undoSet);
1423 void VymModel::saveState(
1424 const SaveMode &savemode,
1425 const QString &undoSelection,
1426 const QString &undoCom,
1427 const QString &redoSelection,
1428 const QString &redoCom,
1429 const QString &comment,
1433 sendData(redoCom); //FIXME-4 testing
1437 if (blockSaveState) return;
1439 if (debug) qDebug() << "VM::saveState() for "<<mapName;
1441 // Find out current undo directory
1442 if (undosAvail<stepsTotal) undosAvail++;
1444 if (curStep>stepsTotal) curStep=1;
1446 QString histDir=getHistoryPath();
1447 QString bakMapPath=histDir+"/map.xml";
1449 // Create histDir if not available
1452 makeSubDirs (histDir);
1454 // Save depending on how much needs to be saved
1455 QList <Link*> tmpLinks;
1457 dataXML=saveToDir (histDir,mapName+"-",false, QPointF (),saveSel);
1459 QString undoCommand=undoCom;
1460 QString redoCommand=redoCom;
1461 if (savemode==PartOfMap )
1463 undoCommand.replace ("PATH",bakMapPath);
1464 redoCommand.replace ("PATH",bakMapPath);
1467 if (!dataXML.isEmpty())
1468 // Write XML Data to disk
1469 saveStringToDisk (bakMapPath,dataXML);
1471 // We would have to save all actions in a tree, to keep track of
1472 // possible redos after a action. Possible, but we are too lazy: forget about redos.
1475 // Write the current state to disk
1476 undoSet.setValue ("/history/undosAvail",QString::number(undosAvail));
1477 undoSet.setValue ("/history/redosAvail",QString::number(redosAvail));
1478 undoSet.setValue ("/history/curStep",QString::number(curStep));
1479 undoSet.setValue (QString("/history/step-%1/undoCommand").arg(curStep),undoCommand);
1480 undoSet.setValue (QString("/history/step-%1/undoSelection").arg(curStep),undoSelection);
1481 undoSet.setValue (QString("/history/step-%1/redoCommand").arg(curStep),redoCommand);
1482 undoSet.setValue (QString("/history/step-%1/redoSelection").arg(curStep),redoSelection);
1483 undoSet.setValue (QString("/history/step-%1/comment").arg(curStep),comment);
1484 undoSet.setValue (QString("/history/version"),vymVersion);
1485 undoSet.writeSettings(histPath);
1489 //qDebug() << " into="<< histPath;
1490 qDebug() << " stepsTotal="<<stepsTotal<<
1491 ", undosAvail="<<undosAvail<<
1492 ", redosAvail="<<redosAvail<<
1493 ", curStep="<<curStep;
1494 qDebug() << " ---------------------------";
1495 qDebug() << " comment="<<comment;
1496 qDebug() << " undoCom="<<undoCommand;
1497 qDebug() << " undoSel="<<undoSelection;
1498 qDebug() << " redoCom="<<redoCommand;
1499 qDebug() << " redoSel="<<redoSelection;
1500 if (saveSel) qDebug() << " saveSel="<<qPrintable (getSelectString(saveSel));
1501 qDebug() << " ---------------------------";
1504 mainWindow->updateHistory (undoSet);
1511 void VymModel::saveStateChangingPart(TreeItem *undoSel, TreeItem* redoSel, const QString &rc, const QString &comment)
1513 // save the selected part of the map, Undo will replace part of map
1514 QString undoSelection="";
1516 undoSelection=getSelectString(undoSel);
1518 qWarning ("VymModel::saveStateChangingPart no undoSel given!");
1519 QString redoSelection="";
1521 redoSelection=getSelectString(undoSel);
1523 qWarning ("VymModel::saveStateChangingPart no redoSel given!");
1526 saveState (PartOfMap,
1527 undoSelection, "addMapReplace (\"PATH\")",
1533 void VymModel::saveStateRemovingPart(TreeItem* redoSel, const QString &comment)
1537 qWarning ("VymModel::saveStateRemovingPart no redoSel given!");
1540 QString undoSelection;
1541 QString redoSelection=getSelectString(redoSel);
1542 if (redoSel->isBranchLikeType() )
1544 // save the selected branch of the map, Undo will insert part of map
1545 if (redoSel->depth()>0)
1546 undoSelection=getSelectString (redoSel->parent());
1547 saveState (PartOfMap,
1548 undoSelection, QString("addMapInsert (\"PATH\",%1,%2)").arg(redoSel->num()).arg(SlideContent),
1549 redoSelection, "delete ()",
1555 void VymModel::saveState(TreeItem *undoSel, const QString &uc, TreeItem *redoSel, const QString &rc, const QString &comment)
1557 // "Normal" savestate: save commands, selections and comment
1558 // so just save commands for undo and redo
1559 // and use current selection, if empty parameter passed
1561 QString redoSelection="";
1562 if (redoSel) redoSelection=getSelectString(redoSel);
1563 QString undoSelection="";
1564 if (undoSel) undoSelection=getSelectString(undoSel);
1566 saveState (UndoCommand,
1573 void VymModel::saveState(const QString &undoSel, const QString &uc, const QString &redoSel, const QString &rc, const QString &comment)
1575 // "Normal" savestate: save commands, selections and comment
1576 // so just save commands for undo and redo
1577 // and use current selection
1578 saveState (UndoCommand,
1585 void VymModel::saveState(const QString &uc, const QString &rc, const QString &comment)
1587 // "Normal" savestate applied to model (no selection needed):
1588 // save commands and comment
1589 saveState (UndoCommand,
1596 void VymModel::saveStateMinimal(TreeItem *undoSel, const QString &uc, TreeItem *redoSel, const QString &rc, const QString &comment)
1597 { // Save a change in string and merge
1598 // minor sequential changes */
1599 QString redoSelection="";
1600 if (redoSel) redoSelection=getSelectString(redoSel);
1601 QString undoSelection="";
1602 if (undoSel) undoSelection=getSelectString(undoSel);
1604 saveState (UndoCommand,
1611 void VymModel::saveStateBeforeLoad (LoadMode lmode, const QString &fname)
1613 BranchItem *selbi=getSelectedBranch();
1616 if (lmode==ImportAdd)
1617 saveStateChangingPart(
1620 QString("addMapInsert (\"%1\")").arg(fname),
1621 QString("Add map %1 to %2").arg(fname).arg(getObjectName(selbi)));
1622 if (lmode==ImportReplace)
1624 BranchItem *pi=(BranchItem*)(selbi->parent());
1625 saveStateChangingPart(
1628 QString("addMapReplace(%1)").arg(fname),
1629 QString("Add map %1 to %2").arg(fname).arg(getObjectName(selbi)));
1636 QGraphicsScene* VymModel::getScene ()
1638 return mapEditor->getScene();
1641 TreeItem* VymModel::findBySelectString(QString s)
1643 if (s.isEmpty() ) return NULL;
1645 // Old maps don't have multiple mapcenters and don't save full path
1646 if (s.left(2) !="mc") s="mc:0,"+s;
1648 QStringList parts=s.split (",");
1651 TreeItem *ti=rootItem;
1653 while (!parts.isEmpty() )
1655 typ=parts.first().left(2);
1656 n=parts.first().right(parts.first().length() - 3).toInt();
1657 parts.removeFirst();
1658 if (typ=="mc" || typ=="bo")
1659 ti=ti->getBranchNum (n);
1661 ti=ti->getImageNum (n);
1663 ti=ti->getAttributeNum (n);
1665 ti=ti->getXLinkItemNum (n);
1666 if(!ti) return NULL;
1671 TreeItem* VymModel::findID (const uint &id)
1673 BranchItem *cur=NULL;
1674 BranchItem *prev=NULL;
1675 nextBranch(cur,prev);
1678 if (id==cur->getID() ) return cur;
1680 while (j<cur->xlinkCount() )
1682 XLinkItem *xli=cur->getXLinkItemNum (j);
1683 if (id==xli->getID() ) return xli;
1687 while (j<cur->imageCount() )
1689 ImageItem *ii=cur->getImageNum (j);
1690 if (id==ii->getID() ) return ii;
1693 nextBranch(cur,prev);
1698 TreeItem* VymModel::findUuid (const QUuid &id)
1700 BranchItem *cur=NULL;
1701 BranchItem *prev=NULL;
1702 nextBranch(cur,prev);
1705 if (id==cur->getUuid() ) return cur;
1707 while (j<cur->xlinkCount() )
1709 XLinkItem *xli=cur->getXLinkItemNum (j);
1710 if (id==xli->getUuid() ) return xli;
1714 while (j<cur->imageCount() )
1716 ImageItem *ii=cur->getImageNum (j);
1717 if (id==ii->getUuid() ) return ii;
1720 nextBranch(cur,prev);
1725 //////////////////////////////////////////////
1727 //////////////////////////////////////////////
1728 void VymModel::setVersion (const QString &s)
1733 QString VymModel::getVersion()
1738 void VymModel::setTitle (const QString &s)
1741 QString ("setMapTitle (\"%1\")").arg(title),
1742 QString ("setMapTitle (\"%1\")").arg(s),
1743 QString ("Set title of map to \"%1\"").arg(s)
1748 QString VymModel::getTitle()
1753 void VymModel::setAuthor (const QString &s)
1756 QString ("setMapAuthor (\"%1\")").arg(author),
1757 QString ("setMapAuthor (\"%1\")").arg(s),
1758 QString ("Set author of map to \"%1\"").arg(s)
1763 QString VymModel::getAuthor()
1768 void VymModel::setComment (const QString &s)
1771 QString ("setMapComment (\"%1\")").arg(comment),
1772 QString ("setMapComment (\"%1\")").arg(s),
1773 QString ("Set comment of map")
1778 QString VymModel::getComment ()
1783 QString VymModel::getDate ()
1785 return QDate::currentDate().toString ("yyyy-MM-dd");
1788 int VymModel::branchCount()
1791 BranchItem *cur=NULL;
1792 BranchItem *prev=NULL;
1793 nextBranch(cur,prev);
1797 nextBranch(cur,prev);
1802 void VymModel::setSortFilter (const QString &s)
1805 emit (sortFilterChanged (sortFilter));
1808 QString VymModel::getSortFilter ()
1813 void VymModel::setHeading(const VymText &vt, BranchItem *bi)
1818 QString s = vt.getTextASCII();
1819 if (!bi) bi=getSelectedBranch();
1822 h_old = bi->getHeading();
1823 if (h_old == h_new) return;
1825 bi, "parseVymText ('" + h_old.saveToDir() + "')",
1826 bi, "parseVymText ('" + h_new.saveToDir() + "')",
1827 QString("Set heading of %1 to \"%2\"").arg(getObjectName(bi)).arg(s) );
1829 emitDataChanged ( bi);
1830 emitUpdateQueries ();
1835 void VymModel::setHeadingPlainText(const QString &s, BranchItem *bi)
1837 if (!bi) bi=getSelectedBranch();
1840 VymText vt = bi->getHeading();
1842 if (bi->getHeading() == vt) return;
1843 setHeading (vt, bi);
1847 Heading VymModel::getHeading()
1849 TreeItem *selti=getSelectedItem();
1850 if (selti) return selti->getHeading();
1851 qWarning() << "VymModel::getHeading Nothing selected.";
1855 void VymModel::setNote(const VymNote &vn)
1857 TreeItem *selti=getSelectedItem();
1862 n_old = selti->getNote();
1866 "parseVymText ('" + n_old.saveToDir() + "')",
1868 "parseVymText ('" + n_new.saveToDir() + "')",
1869 QString("Set note of %1 to \"%2\"").arg(getObjectName(selti)).arg(n_new.getTextASCII().left(20) ) );
1870 selti->setNote( n_new );
1871 emitNoteChanged( selti );
1872 emitDataChanged( selti );
1876 VymNote VymModel::getNote()
1878 TreeItem *selti=getSelectedItem();
1881 VymNote n = selti->getNote();
1884 qWarning() << "VymModel::getNote Nothing selected.";
1888 bool VymModel::hasRichTextNote()
1890 TreeItem *selti=getSelectedItem();
1893 return selti->getNote().isRichText();
1898 void VymModel::loadNote (const QString &fn)
1900 BranchItem *selbi=getSelectedBranch();
1904 if (!loadStringFromDisk (fn,n))
1905 qWarning ()<<"VymModel::loadNote Couldn't load "<<fn;
1913 qWarning ("VymModel::loadNote no branch selected");
1916 void VymModel::saveNote (const QString &fn)
1918 BranchItem *selbi = getSelectedBranch();
1921 VymNote n = selbi->getNote();
1923 qWarning ()<<"VymModel::saveNote note is empty, won't save to "<<fn;
1926 if (!saveStringToDisk (fn, n.saveToDir() ))
1927 qWarning ()<<"VymModel::saveNote Couldn't save "<<fn;
1930 qWarning ("VymModel::saveNote no branch selected");
1933 void VymModel::findDuplicateURLs() // FIXME-3 needs GUI
1935 // Generate map containing _all_ URLs and branches
1937 QMap <QString,BranchItem*> map;
1938 BranchItem *cur=NULL;
1939 BranchItem *prev=NULL;
1940 nextBranch(cur,prev);
1945 map.insertMulti (u,cur);
1946 nextBranch(cur,prev);
1949 // Extract duplicate URLs
1950 QMap <QString, BranchItem*>::const_iterator i=map.constBegin();
1951 QMap <QString, BranchItem*>::const_iterator firstdup=map.constEnd(); //invalid
1952 while (i != map.constEnd())
1954 if (i!=map.constBegin() && i.key()==firstdup.key())
1956 if ( i-1==firstdup )
1958 qDebug() << firstdup.key();
1959 qDebug() << " - "<< firstdup.value() <<" - "<<firstdup.value()->getHeading().getText();
1961 qDebug() << " - "<< i.value() <<" - "<<i.value()->getHeading().getText();
1969 bool VymModel::findAll (FindResultModel *rmodel, QString s, Qt::CaseSensitivity cs)
1972 rmodel->setSearchString (s);
1973 rmodel->setSearchFlags (0); //FIXME-4 translate cs to QTextDocument::FindFlag
1976 BranchItem *cur = NULL;
1977 BranchItem *prev = NULL;
1978 nextBranch(cur,prev);
1980 FindResultItem *lastParent = NULL;
1984 if (cur->getHeading().getTextASCII().contains (s,cs))
1986 lastParent = rmodel->addItem (cur);
1989 QString n = cur->getNoteASCII();
1994 i = n.indexOf (s,i,cs);
1997 // If not there yet, add "parent" item
2000 lastParent = rmodel->addItem (cur);
2003 qWarning() << "VymModel::findAll still no lastParent?!";
2006 lastParent->setSelectable (false);
2010 // save index of occurence
2011 QString e = n.mid(i-15, 30);
2012 n.replace('\n', ' ');
2013 rmodel->addSubItem (lastParent, QString(tr("Note", "FindAll in VymModel") + ": \"...%1...\"").arg(n.mid(i-8,80)), cur, j);
2018 nextBranch(cur, prev);
2023 BranchItem* VymModel::findText (QString s,Qt::CaseSensitivity cs)
2025 if (!s.isEmpty() && s!=findString)
2031 QTextDocument::FindFlags flags=0;
2032 if (cs==Qt::CaseSensitive) flags=QTextDocument::FindCaseSensitively;
2035 { // Nothing found or new find process
2037 // nothing found, start again
2041 nextBranch (findCurrent,findPrevious);
2043 bool searching=true;
2044 bool foundNote=false;
2045 while (searching && !EOFind)
2049 // Searching in Note
2050 if (findCurrent->getNoteASCII().contains(findString,cs))
2052 select (findCurrent);
2053 if (noteEditor->findText(findString,flags))
2059 // Searching in Heading
2060 if (searching && findCurrent->getHeading().getTextASCII().contains (findString,cs) )
2062 select(findCurrent);
2068 nextBranch(findCurrent,findPrevious);
2069 if (!findCurrent) EOFind=true;
2073 return getSelectedBranch();
2078 void VymModel::findReset()
2079 { // Necessary if text to find changes during a find process
2086 void VymModel::setURL(QString url)
2088 TreeItem *selti=getSelectedItem();
2089 if (selti->getURL()==url) return;
2092 QString oldurl=selti->getURL();
2093 selti->setURL (url);
2096 QString ("setURL (\"%1\")").arg(oldurl),
2098 QString ("setURL (\"%1\")").arg(url),
2099 QString ("set URL of %1 to %2").arg(getObjectName(selti)).arg(url)
2101 if (url.contains("bugzilla.novell.com/"))
2102 getBugzillaData(false);
2103 emitDataChanged (selti);
2108 QString VymModel::getURL()
2110 TreeItem *selti=getSelectedItem();
2112 return selti->getURL();
2117 QStringList VymModel::getURLs(bool ignoreScrolled)
2120 BranchItem *selbi=getSelectedBranch();
2121 BranchItem *cur=NULL;
2122 BranchItem *prev=NULL;
2123 nextBranch (cur,prev,true,selbi);
2126 if (!cur->getURL().isEmpty() && !(ignoreScrolled && cur->hasScrolledParent() ))
2127 urls.append( cur->getURL());
2128 nextBranch(cur,prev,true,selbi);
2134 void VymModel::setFrameType(const FrameObj::FrameType &t)
2136 BranchItem *bi=getSelectedBranch();
2139 BranchObj *bo=(BranchObj*)(bi->getLMO());
2142 QString s=bo->getFrameTypeName();
2143 bo->setFrameType (t);
2144 saveState (bi, QString("setFrameType (\"%1\")").arg(s),
2145 bi, QString ("setFrameType (\"%1\")").arg(bo->getFrameTypeName()),QString ("set type of frame to %1").arg(s));
2147 bo->updateLinkGeometry();
2152 void VymModel::setFrameType(const QString &s)
2154 BranchItem *bi=getSelectedBranch();
2157 BranchObj *bo=(BranchObj*)(bi->getLMO());
2160 saveState (bi, QString("setFrameType (\"%1\")").arg(bo->getFrameTypeName()),
2161 bi, QString ("setFrameType (\"%1\")").arg(s),QString ("set type of frame to %1").arg(s));
2162 bo->setFrameType (s);
2164 bo->updateLinkGeometry();
2169 void VymModel::toggleFrameIncludeChildren ()
2171 BranchItem *bi=getSelectedBranch();
2174 bool b=bi->getFrameIncludeChildren();
2175 setFrameIncludeChildren (!b);
2179 void VymModel::setFrameIncludeChildren (bool b)
2181 BranchItem *bi=getSelectedBranch();
2184 QString u= b ? "false" : "true";
2185 QString r=!b ? "false" : "true";
2189 QString("setFrameIncludeChildren(%1)").arg(u),
2191 QString("setFrameIncludeChildren(%1)").arg(r),
2192 QString("Include children in %1").arg(getObjectName(bi))
2194 bi->setFrameIncludeChildren (b);
2195 emitDataChanged (bi);
2200 void VymModel::setFramePenColor(const QColor &c) //FIXME-4 not saved if there is no LMO
2203 BranchItem *bi=getSelectedBranch();
2206 BranchObj *bo=(BranchObj*)(bi->getLMO());
2209 saveState (bi, QString("setFramePenColor (\"%1\")").arg(bo->getFramePenColor().name() ),
2210 bi, QString ("setFramePenColor (\"%1\")").arg(c.name() ),QString ("set pen color of frame to %1").arg(c.name() ));
2211 bo->setFramePenColor (c);
2216 void VymModel::setFrameBrushColor(const QColor &c) //FIXME-4 not saved if there is no LMO
2218 BranchItem *bi=getSelectedBranch();
2221 BranchObj *bo=(BranchObj*)(bi->getLMO());
2224 saveState (bi, QString("setFrameBrushColor (\"%1\")").arg(bo->getFrameBrushColor().name() ),
2225 bi, QString ("setFrameBrushColor (\"%1\")").arg(c.name() ),QString ("set brush color of frame to %1").arg(c.name() ));
2226 bo->setFrameBrushColor (c);
2227 bi->setBackgroundColor (c); //FIXME-4 redundant with above
2232 void VymModel::setFramePadding (const int &i) //FIXME-4 not saved if there is no LMO
2234 BranchItem *bi=getSelectedBranch();
2237 BranchObj *bo=(BranchObj*)(bi->getLMO());
2240 saveState (bi, QString("setFramePadding (\"%1\")").arg(bo->getFramePadding() ),
2241 bi, QString ("setFramePadding (\"%1\")").arg(i),QString ("set brush color of frame to %1").arg(i));
2242 bo->setFramePadding (i);
2244 bo->updateLinkGeometry();
2249 void VymModel::setFrameBorderWidth(const int &i) //FIXME-4 not saved if there is no LMO
2251 BranchItem *bi=getSelectedBranch();
2254 BranchObj *bo=(BranchObj*)(bi->getLMO());
2257 saveState (bi, QString("setFrameBorderWidth (\"%1\")").arg(bo->getFrameBorderWidth() ),
2258 bi, QString ("setFrameBorderWidth (\"%1\")").arg(i),QString ("set border width of frame to %1").arg(i));
2259 bo->setFrameBorderWidth (i);
2261 bo->updateLinkGeometry();
2266 void VymModel::setIncludeImagesVer(bool b)
2268 BranchItem *bi=getSelectedBranch();
2269 if (bi && b!=bi->getIncludeImagesVer() )
2271 QString u= b ? "false" : "true";
2272 QString r=!b ? "false" : "true";
2276 QString("setIncludeImagesVertically (%1)").arg(u),
2278 QString("setIncludeImagesVertically (%1)").arg(r),
2279 QString("Include images vertically in %1").arg(getObjectName(bi))
2281 bi->setIncludeImagesVer(b);
2282 emitDataChanged ( bi);
2287 void VymModel::setIncludeImagesHor(bool b)
2289 BranchItem *bi=getSelectedBranch();
2290 if (bi && b!=bi->getIncludeImagesHor() )
2292 QString u= b ? "false" : "true";
2293 QString r=!b ? "false" : "true";
2297 QString("setIncludeImagesHorizontally (%1)").arg(u),
2299 QString("setIncludeImagesHorizontally (%1)").arg(r),
2300 QString("Include images horizontally in %1").arg(getObjectName(bi))
2302 bi->setIncludeImagesHor(b);
2303 emitDataChanged ( bi);
2308 void VymModel::setChildrenLayout(BranchItem::LayoutHint layoutHint) // FIXME-3 no savestate yet
2310 BranchItem *bi=getSelectedBranch();
2314 QString u= b ? "false" : "true";
2315 QString r=!b ? "false" : "true";
2319 QString("setIncludeImagesHorizontally (%1)").arg(u),
2321 QString("setIncludeImagesHorizontally (%1)").arg(r),
2322 QString("Include images horizontally in %1").arg(getObjectName(bi))
2325 bi->setChildrenLayout(layoutHint);
2326 emitDataChanged ( bi);
2331 void VymModel::setHideLinkUnselected (bool b)
2333 TreeItem *ti=getSelectedItem();
2334 if (ti && (ti->getType()==TreeItem::Image ||ti->isBranchLikeType()))
2336 QString u= b ? "false" : "true";
2337 QString r=!b ? "false" : "true";
2341 QString("setHideLinkUnselected (%1)").arg(u),
2343 QString("setHideLinkUnselected (%1)").arg(r),
2344 QString("Hide link of %1 if unselected").arg(getObjectName(ti))
2346 ((MapItem*)ti)->setHideLinkUnselected(b);
2350 void VymModel::setHideExport(bool b, TreeItem *ti)
2352 if (!ti) ti=getSelectedItem();
2354 (ti->getType()==TreeItem::Image ||ti->isBranchLikeType()) &&
2355 ti->hideInExport() !=b
2358 ti->setHideInExport (b);
2359 QString u= b ? "false" : "true";
2360 QString r=!b ? "false" : "true";
2364 QString ("setHideExport (%1)").arg(u),
2366 QString ("setHideExport (%1)").arg(r),
2367 QString ("Set HideExport flag of %1 to %2").arg(getObjectName(ti)).arg (r)
2369 emitDataChanged(ti);
2370 emitSelectionChanged();
2375 void VymModel::toggleHideExport()
2377 QList <TreeItem*> selItems=getSelectedItems();
2378 if (selItems.count()>0 )
2380 foreach (TreeItem* ti, selItems)
2382 bool b=!ti->hideInExport();
2383 setHideExport (b,ti );
2388 void VymModel::toggleTask()
2390 BranchItem *selbi=getSelectedBranch();
2393 saveStateChangingPart (
2396 QString ("toggleTask()"),
2397 QString ("Toggle task of %1").arg(getObjectName (selbi)) );
2398 Task *task=selbi->getTask();
2401 task=taskModel->createTask (selbi);
2402 taskEditor->select(task);
2405 taskModel->deleteTask (task);
2407 emitDataChanged(selbi);
2408 emitSelectionChanged();
2413 void VymModel::cycleTaskStatus(bool reverse)
2415 BranchItem *selbi=getSelectedBranch();
2418 Task *task=selbi->getTask();
2421 saveStateChangingPart (
2424 QString ("cycleTask()"),
2425 QString ("Toggle task of %1").arg(getObjectName (selbi)) );
2426 task->cycleStatus(reverse);
2427 task->setDateModified();
2429 // make sure task is still visible
2430 taskEditor->select (task);
2431 emitDataChanged(selbi);
2437 bool VymModel::setTaskSleep(const QString &s)
2439 BranchItem *selbi=getSelectedBranch();
2440 if (selbi && !s.isEmpty() )
2442 Task *task=selbi->getTask();
2450 QDate d=QDate::fromString(s,Qt::ISODate);
2451 d=QDate::fromString(s,Qt::ISODate);
2453 // ISO date YYYY-MM-DD
2457 d=QDate::fromString(s,Qt::DefaultLocaleShortDate);
2459 // Locale date, e.g. 24 Dec 2012
2463 QRegExp re ("(\\d+).(\\d+).(\\d+)");
2464 re.setMinimal(false);
2465 int pos=re.indexIn(s);
2466 QStringList list=re.capturedTexts();
2469 // German formate, e.g. 24.12.2012
2470 d=QDate(list.at(3).toInt(), list.at(2).toInt(), list.at(1).toInt());
2474 re.setPattern("(\\d+).(\\d+).");
2476 list=re.capturedTexts();
2479 // Short German formate, e.g. 24.12.
2480 int month=list.at(2).toInt();
2481 int day=list.at(1).toInt();
2482 int year=QDate::currentDate().year();
2483 d=QDate(year, month, day);
2484 if (QDate::currentDate().daysTo(d) < 0)
2487 d=QDate(year, month, day);
2492 re.setPattern("(\\d+).(\\d+).");
2497 if (ok) n=QDate::currentDate().daysTo(d);
2502 int oldsleep=task->getDaysSleep();
2503 task->setDateSleep (n);
2504 task->setDateModified();
2507 QString("setTaskSleep (%1)").arg(oldsleep),
2509 QString("setTaskSleep (%1)").arg(n),
2510 QString("setTaskSleep (%1)").arg(n) );
2511 emitDataChanged (selbi);
2520 int VymModel::taskCount()
2522 return taskModel->count (this);
2525 void VymModel::addTimestamp() //FIXME-4 new function, localize
2527 BranchItem *selbi=addNewBranch();
2530 QDate today=QDate::currentDate();
2532 selbi->setHeadingPlainText (
2533 QString ("%1-%2-%3")
2534 .arg(today.year(),4,10,c)
2535 .arg(today.month(),2,10,c)
2536 .arg(today.day(),2,10,c));
2537 emitDataChanged ( selbi);
2544 void VymModel::copy()
2546 if (readonly) return;
2548 TreeItem *selti=getSelectedItem();
2550 (selti->getType() == TreeItem::Branch ||
2551 selti->getType() == TreeItem::MapCenter ||
2552 selti->getType() == TreeItem::Image ))
2554 // Copy to global clipboard
2555 QString saveFile=saveToDir (clipboardDir, clipboardFile, true, QPointF(), selti);
2556 if (!saveStringToDisk(clipboardDir + "/" + clipboardFile,saveFile))
2557 qWarning ("ME::saveStringToDisk failed!");
2559 clipboardEmpty=false;
2561 if (redosAvail == 0)
2563 // Copy also to history
2564 QString s=getSelectString(selti);
2565 saveState (PartOfMap, s, "nop ()", s, "copy ()","Copy selection to clipboard",selti );
2566 curClipboard=curStep;
2572 void VymModel::paste()
2574 if (readonly) return;
2576 BranchItem *selbi=getSelectedBranch();
2579 saveStateChangingPart(
2582 QString ("paste ()"),
2585 bool zippedOrg=zipped;
2586 loadMap (clipboardDir+"/"+clipboardFile,ImportAdd, VymMap,SlideContent);
2592 void VymModel::cut()
2594 if (readonly) return;
2596 TreeItem *selti=getSelectedItem();
2597 if ( selti && (selti->isBranchLikeType() ||selti->getType()==TreeItem::Image))
2605 bool VymModel::moveUp(BranchItem *bi)
2607 if (readonly) return false;
2609 bool oldState=blockSaveState;
2610 blockSaveState=true;
2612 if (bi && bi->canMoveUp())
2613 result=relinkBranch (bi,(BranchItem*)bi->parent(),bi->num()-1,false);
2614 blockSaveState=oldState;
2618 void VymModel::moveUp()
2620 BranchItem *selbi=getSelectedBranch();
2623 QString oldsel=getSelectString(selbi);
2627 getSelectString(selbi),"moveDown ()",
2629 QString("Move up %1").arg(getObjectName(selbi)));
2635 bool VymModel::moveDown(BranchItem *bi)
2637 if (readonly) return false;
2639 bool oldState=blockSaveState;
2640 blockSaveState=true;
2642 if (bi && bi->canMoveDown())
2643 result=relinkBranch (bi,(BranchItem*)bi->parent(),bi->num()+1,false);
2644 blockSaveState=oldState;
2648 void VymModel::moveDown()
2650 BranchItem *selbi=getSelectedBranch();
2653 QString oldsel=getSelectString(selbi);
2654 if ( moveDown(selbi))
2657 getSelectString(selbi),"moveUp ()",
2658 oldsel,"moveDown ()",
2659 QString("Move down %1").arg(getObjectName(selbi)));
2665 void VymModel::detach()
2667 BranchItem *selbi=getSelectedBranch();
2668 if (selbi && selbi->depth()>0)
2670 // if no relPos have been set before, try to use current rel positions
2671 if (selbi->getLMO())
2672 for (int i=0; i<selbi->branchCount();++i)
2673 selbi->getBranchNum(i)->getBranchObj()->setRelPos();
2675 QString oldsel=getSelectString();
2678 BranchObj *bo=selbi->getBranchObj();
2679 if (bo) p=bo->getAbsPos();
2680 QString parsel=getSelectString(selbi->parent());
2681 if ( relinkBranch (selbi,rootItem,-1,true) )
2683 getSelectString (selbi),
2684 QString("relinkTo (\"%1\",%2,%3,%4)").arg(parsel).arg(n).arg(p.x()).arg(p.y()),
2687 QString("Detach %1").arg(getObjectName(selbi))
2692 void VymModel::sortChildren(bool inverse)
2694 BranchItem* selbi=getSelectedBranch();
2697 if(selbi->branchCount()>1)
2700 saveStateChangingPart(
2701 selbi,selbi, "sortChildren ()",
2702 QString("Sort children of %1").arg(getObjectName(selbi)));
2704 saveStateChangingPart(
2705 selbi,selbi, "sortChildren (false)",
2706 QString("Inverse sort children of %1").arg(getObjectName(selbi)));
2708 selbi->sortChildren(inverse);
2715 BranchItem* VymModel::createMapCenter()
2717 BranchItem *newbi=addMapCenter (QPointF (0,0) );
2721 BranchItem* VymModel::createBranch(BranchItem *dst)
2724 return addNewBranchInt (dst,-2);
2729 ImageItem* VymModel::createImage(BranchItem *dst)
2736 QList<QVariant> cData;
2737 cData << tr("Image","Default name for new image") << "undef";
2739 ImageItem *newii=new ImageItem(cData) ;
2740 //newii->setHeading (QApplication::translate("Heading of new image in map", "new image"));
2742 emit (layoutAboutToBeChanged() );
2745 if (!parix.isValid()) qDebug() << "VM::createII invalid index\n";
2746 n=dst->getRowNumAppend(newii);
2747 beginInsertRows (parix,n,n);
2748 dst->appendChild (newii);
2751 emit (layoutChanged() );
2753 // save scroll state. If scrolled, automatically select
2754 // new branch in order to tmp unscroll parent...
2755 newii->createMapObj();
2756 latestAddedItem=newii;
2763 bool VymModel::createLink(Link *link)
2765 BranchItem *begin=link->getBeginBranch();
2766 BranchItem *end =link->getEndBranch();
2770 qWarning ()<<"VM::createXLinkNew part of XLink is NULL";
2776 if (debug) qDebug()<<"VymModel::createLink begin==end, aborting";
2780 // check, if link already exists
2781 foreach (Link* l, xlinks)
2783 if ( (l->getBeginBranch()==begin && l->getEndBranch()==end ) ||
2784 (l->getBeginBranch()==end && l->getEndBranch()==begin) )
2786 qWarning()<<"VymModel::createLink link exists already, aborting";
2794 QList<QVariant> cData;
2796 cData << "new Link begin"<<"undef";
2797 XLinkItem *newli=new XLinkItem(cData) ;
2798 newli->setLink (link);
2799 link->setBeginLinkItem (newli);
2801 emit (layoutAboutToBeChanged() );
2804 n=begin->getRowNumAppend(newli);
2805 beginInsertRows (parix,n,n);
2806 begin->appendChild (newli);
2810 cData << "new Link end"<<"undef";
2811 newli=new XLinkItem(cData) ;
2812 newli->setLink (link);
2813 link->setEndLinkItem (newli);
2816 n=end->getRowNumAppend(newli);
2817 beginInsertRows (parix,n,n);
2818 end->appendChild (newli);
2821 emit (layoutChanged() );
2823 xlinks.append (link);
2826 latestAddedItem=newli;
2828 if (!link->getMO() )
2830 link->createMapObj();
2835 link->setStyleBegin( defXLinkStyleBegin );
2836 link->setStyleEnd ( defXLinkStyleEnd );
2840 QColor VymModel::getXLinkColor()
2842 Link *l=getSelectedXLink();
2844 return l->getPen().color();
2849 int VymModel::getXLinkWidth()
2851 Link *l=getSelectedXLink();
2853 return l->getPen().width();
2858 Qt::PenStyle VymModel::getXLinkPenStyle()
2860 Link *l=getSelectedXLink();
2862 return l->getPen().style();
2867 QString VymModel::getXLinkStyleBegin()
2869 Link *l=getSelectedXLink();
2871 return l->getStyleBeginString();
2876 QString VymModel::getXLinkStyleEnd()
2878 Link *l=getSelectedXLink();
2880 return l->getStyleEndString();
2885 AttributeItem* VymModel::addAttribute() // Experimental, savestate missing
2888 BranchItem* selbi=getSelectedBranch();
2891 QList<QVariant> cData;
2892 cData << "new attribute" << "undef";
2893 AttributeItem *a=new AttributeItem (cData);
2894 a->setType (AttributeItem::FreeString);
2895 a->setKey ("Foo Attrib");
2896 a->setValue ("Att val");
2898 if (addAttribute (selbi,a)) return a;
2903 AttributeItem* VymModel::addAttribute(BranchItem *dst,AttributeItem *ai){
2906 emit (layoutAboutToBeChanged() );
2908 QModelIndex parix=index(dst);
2909 int n=dst->getRowNumAppend (ai);
2910 beginInsertRows (parix,n,n);
2911 dst->appendChild (ai);
2914 emit (layoutChanged() );
2916 ai->createMapObj(mapEditor->getScene() );
2923 BranchItem* VymModel::addMapCenter (bool saveStateFlag)
2927 // E.g. when called via keypresss:
2928 // Place new MCO in middle of existing ones,
2929 // Useful for "brainstorming" mode...
2930 contextPos=QPointF();
2933 for (int i=0;i<rootItem->branchCount();++i)
2935 bi=rootItem->getBranchNum (i);
2936 bo=(BranchObj*)bi->getLMO();
2937 if (bo) contextPos+=bo->getAbsPos();
2940 if (rootItem->branchCount()>1)
2941 contextPos*=1/(qreal)(rootItem->branchCount());
2945 BranchItem *bi=addMapCenter (contextPos);
2947 emitShowSelection();
2953 QString ("addMapCenter (%1,%2)").arg (contextPos.x()).arg(contextPos.y()),
2954 QString ("Adding MapCenter to (%1,%2)").arg (contextPos.x()).arg(contextPos.y())
2960 BranchItem* VymModel::addMapCenter(QPointF absPos)
2961 // createMapCenter could then probably be merged with createBranch
2965 QModelIndex parix=index(rootItem);
2967 QList<QVariant> cData;
2968 cData << "VM:addMapCenter" << "undef";
2969 BranchItem *newbi=new BranchItem (cData,rootItem);
2970 newbi->setHeadingPlainText (tr("New map", "New map"));
2971 int n=rootItem->getRowNumAppend (newbi);
2973 emit (layoutAboutToBeChanged() );
2974 beginInsertRows (parix,n,n);
2976 rootItem->appendChild (newbi);
2979 emit (layoutChanged() );
2982 newbi->setPositionMode (MapItem::Absolute);
2983 BranchObj *bo=newbi->createMapObj(mapEditor->getScene() );
2984 if (bo) bo->move (absPos);
2989 BranchItem* VymModel::addNewBranchInt(BranchItem *dst,int pos)
2991 // Depending on pos:
2992 // -3 insert in children of parent above selection
2993 // -2 add branch to selection
2994 // -1 insert in children of parent below selection
2995 // 0..n insert in children of parent at pos
2998 QList<QVariant> cData;
2999 cData << "" << "undef";
3001 BranchItem *parbi = dst;
3003 BranchItem *newbi = new BranchItem (cData);
3005 emit (layoutAboutToBeChanged() );
3009 n = parbi->getRowNumAppend (newbi);
3010 beginInsertRows (index(parbi), n, n);
3011 parbi->appendChild (newbi);
3013 }else if (pos == -1 || pos == -3)
3015 // insert below selection
3016 parbi=(BranchItem*)dst->parent();
3017 n=dst->childNumber() + (3+pos)/2; //-1 |-> 1;-3 |-> 0
3018 beginInsertRows (index(parbi), n, n);
3019 parbi->insertBranch(n,newbi);
3023 n=parbi->getRowNumAppend (newbi) - (parbi->branchCount()-pos);
3024 beginInsertRows (index(parbi), n, n);
3025 parbi->insertBranch(pos,newbi);
3028 emit (layoutChanged() );
3030 newbi->createMapObj(mapEditor->getScene());
3032 // Set color of heading to that of parent
3033 newbi->setHeadingColor (parbi->getHeadingColor());
3039 BranchItem* VymModel::addNewBranch(BranchItem *bi, int pos)
3041 BranchItem *newbi=NULL;
3042 if (!bi) bi=getSelectedBranch();
3046 QString redosel=getSelectString(bi);
3047 newbi=addNewBranchInt (bi,pos);
3048 QString undosel=getSelectString(newbi);
3056 QString ("addBranch (%1)").arg(pos),
3057 QString ("Add new branch to %1").arg(getObjectName(bi)));
3060 latestAddedItem=newbi;
3061 // In Network mode, the client needs to know where the new branch is,
3062 // so we have to pass on this information via saveState.
3063 // TODO: Get rid of this positioning workaround
3064 /* FIXME-4 network problem: QString ps=qpointfToString (newbo->getAbsPos());
3065 sendData ("selectLatestAdded ()");
3066 sendData (QString("move %1").arg(ps));
3075 BranchItem* VymModel::addNewBranchBefore()
3077 BranchItem *newbi=NULL;
3078 BranchItem *selbi=getSelectedBranch();
3079 if (selbi && selbi->getType()==TreeItem::Branch)
3080 // We accept no MapCenter here, so we _have_ a parent
3082 // add below selection
3083 newbi=addNewBranchInt (selbi,-1);
3087 //newbi->move2RelPos (p);
3089 // Move selection to new branch
3090 relinkBranch (selbi,newbi,0,true);
3092 // Use color of child instead of parent
3093 newbi->setHeadingColor (selbi->getHeadingColor() );
3094 emitDataChanged (newbi);
3096 saveState (newbi, "deleteKeepChildren ()", newbi, "addBranchBefore ()",
3097 QString ("Add branch before %1").arg(getObjectName(selbi)));
3103 bool VymModel::relinkBranch (
3107 bool updateSelection,
3112 // Check if we relink to ourselves
3113 if (dst->isChildOf (branch) ) return false;
3115 if (updateSelection) unselectAll();
3117 // Do we need to update frame type?
3118 bool keepFrame=true;
3120 // Save old position for savestate
3121 QString preSelStr=getSelectString (branch);
3122 QString preNum=QString::number (branch->num(),10);
3123 QString preParStr=getSelectString (branch->parent());
3125 emit (layoutAboutToBeChanged() );
3126 BranchItem *branchpi=(BranchItem*)branch->parent();
3127 // Remove at current position
3128 int n=branch->childNum();
3130 beginRemoveRows (index(branchpi),n,n);
3131 branchpi->removeChild (n);
3134 if (pos<0 ||pos>dst->branchCount() ) pos=dst->branchCount();
3136 // Append as last branch to dst
3137 if (dst->branchCount()==0)
3140 n=dst->getFirstBranch()->childNumber();
3141 beginInsertRows (index(dst),n+pos,n+pos);
3142 dst->insertBranch (pos,branch);
3145 // Correct type if necessesary
3146 if ( branch->getType()==TreeItem::MapCenter && branch->depth() >0 )
3148 branch->setType(TreeItem::Branch);
3152 // reset parObj, fonts, frame, etc in related LMO or other view-objects
3153 branch->updateStyles(keepFrame);
3155 emitDataChanged( branch );
3156 reposition(); // both for moveUp/Down and relinking
3159 QString postSelStr=getSelectString(branch);
3160 QString postNum=QString::number (branch->num(),10);
3163 LinkableMapObj *lmosel=branch->getLMO();
3164 if (lmosel) savePos=lmosel->getAbsPos();
3166 if (!blockSaveState)
3167 { // Don't build strings when moving up/down
3168 QString undoCom="relinkTo (\""+
3169 preParStr+ "\"," + preNum +"," +
3170 QString ("%1,%2").arg(orgPos.x()).arg(orgPos.y())+ ")";
3172 QString redoCom="relinkTo (\""+
3173 getSelectString (dst) + "\"," + postNum + "," +
3174 QString ("%1,%2").arg(savePos.x()).arg(savePos.y())+ ")";
3179 QString("Relink %1 to %2").arg(getObjectName(branch)).arg(getObjectName(dst)) );
3182 // New parent might be invisible
3183 branch->updateVisibility();
3185 if (dst->isScrolled() )
3187 if (updateSelection) select (dst);
3190 if (updateSelection) select (branch);
3196 bool VymModel::relinkImage (ImageItem *image, BranchItem *dst)
3200 emit (layoutAboutToBeChanged() );
3202 BranchItem *pi=(BranchItem*)(image->parent());
3203 QString oldParString=getSelectString (pi);
3204 // Remove at current position
3205 int n=image->childNum();
3206 beginRemoveRows (index(pi),n,n);
3207 pi->removeChild (n);
3211 QModelIndex dstix=index(dst);
3212 n=dst->getRowNumAppend (image);
3213 beginInsertRows (dstix,n,n+1);
3214 dst->appendChild (image);
3217 // Set new parent also for lmo
3218 if (image->getLMO() && dst->getLMO() )
3219 image->getLMO()->setParObj (dst->getLMO() );
3221 emit (layoutChanged() );
3224 QString("relinkTo (\"%1\")").arg(oldParString),
3226 QString ("relinkTo (\"%1\")").arg(getSelectString (dst)),
3227 QString ("Relink floatimage to %1").arg(getObjectName(dst)));
3233 void VymModel::cleanupItems()
3235 while (!deleteLaterIDs.isEmpty())
3237 TreeItem *ti=findID (deleteLaterIDs.takeFirst());
3238 if (ti) deleteItem (ti);
3242 void VymModel::deleteLater(uint id)
3244 if (!deleteLaterIDs.contains(id))
3245 deleteLaterIDs.append (id);
3248 void VymModel::deleteSelection()
3250 QList <uint> selectedIDs=getSelectedIDs();
3251 foreach (uint id, selectedIDs)
3253 TreeItem *ti=findID (id);
3254 if (ti && ti->isBranchLikeType ())
3256 BranchItem *selbi=(BranchItem*)ti;
3258 saveStateRemovingPart (selbi, QString ("Delete %1").arg(getObjectName(selbi)));
3260 BranchItem *pi=(BranchItem*)(deleteItem (selbi));
3263 if (pi->isScrolled() && pi->branchCount()==0)
3265 emitDataChanged(pi);
3268 emitDataChanged(rootItem);
3272 // Delete other item
3275 TreeItem *pi=ti->parent();
3277 if (ti->getType()==TreeItem::Image || ti->getType()==TreeItem::Attribute||ti->getType()==TreeItem::XLink)
3279 saveStateChangingPart(
3283 QString("Delete %1").arg(getObjectName(ti))
3287 emitDataChanged (pi);
3291 qWarning ("VymmModel::deleteSelection() unknown type?!");
3296 void VymModel::deleteKeepChildren(bool saveStateFlag)
3297 //deleteKeepChildren FIXME-3+ does not work yet for mapcenters
3298 //deleteKeepChildren FIXME-3+ children of scrolled branch stay invisible...
3300 BranchItem *selbi=getSelectedBranch();
3304 // Don't use this on mapcenter
3305 if (selbi->depth()<1) return;
3307 pi=(BranchItem*)(selbi->parent());
3308 // Check if we have children at all to keep
3309 if (selbi->branchCount()==0)
3316 if (selbi->getLMO()) p=selbi->getLMO()->getRelPos();
3317 if (saveStateFlag) saveStateChangingPart(
3320 "deleteKeepChildren ()",
3321 QString("Remove %1 and keep its children").arg(getObjectName(selbi))
3324 QString sel=getSelectString(selbi);
3326 bool oldSaveState=blockSaveState;
3327 blockSaveState=true;
3328 int pos=selbi->num();
3329 BranchItem *bi=selbi->getFirstBranch();
3332 relinkBranch (bi,pi,pos,true);
3333 bi=selbi->getFirstBranch();
3338 emitDataChanged(pi);
3340 BranchObj *bo=getSelectedBranchObj();
3343 bo->move2RelPos (p);
3346 blockSaveState=oldSaveState;
3350 void VymModel::deleteChildren()
3353 BranchItem *selbi=getSelectedBranch();
3356 saveStateChangingPart(
3359 "deleteChildren ()",
3360 QString( "Remove children of branch %1").arg(getObjectName(selbi))
3362 emit (layoutAboutToBeChanged() );
3364 QModelIndex ix=index (selbi);
3365 int n=selbi->branchCount()-1;
3366 beginRemoveRows (ix,0,n);
3367 removeRows (0,n+1,ix);
3369 if (selbi->isScrolled()) unscrollBranch (selbi);
3370 emit (layoutChanged() );
3375 TreeItem* VymModel::deleteItem (TreeItem *ti)
3379 TreeItem *pi=ti->parent();
3380 //qDebug()<<"VM::deleteItem start ti="<<ti<<" "<<ti->getHeading()<<" pi="<<pi<<"="<<pi->getHeading();
3382 TreeItem::Type t=ti->getType();
3384 QModelIndex parentIndex=index(pi);
3386 emit (layoutAboutToBeChanged() );
3388 int n=ti->childNum();
3389 beginRemoveRows (parentIndex,n,n);
3390 removeRows (n,1,parentIndex);
3393 // Size of parent branch might change when deleting images
3394 if (t==TreeItem::Image)
3396 BranchObj *bo=(BranchObj*) ( ((BranchItem*)pi)->getMO() );
3397 if (bo) bo->calcBBoxSize();
3402 emit (layoutChanged() );
3403 emitUpdateQueries ();
3404 if (!cleaningUpLinks) cleanupItems();
3406 //qDebug()<<"VM::deleteItem end ti="<<ti;
3407 if (pi->depth()>=0) return pi;
3412 void VymModel::deleteLink(Link* l)
3414 if (xlinks.removeOne (l)) delete (l);
3417 void VymModel::clearItem (TreeItem *ti)
3421 // Clear task (or other data in item itself)
3424 QModelIndex parentIndex=index(ti);
3425 if (!parentIndex.isValid()) return;
3427 int n=ti->childCount();
3430 emit (layoutAboutToBeChanged() );
3432 beginRemoveRows (parentIndex,0,n-1);
3433 removeRows (0,n,parentIndex);
3439 emit (layoutChanged() );
3445 bool VymModel::scrollBranch(BranchItem *bi)
3449 if (bi->isScrolled()) return false;
3450 if (bi->branchCount()==0) return false;
3451 if (bi->depth()==0) return false;
3452 if (bi->toggleScroll())
3459 QString ("%1 ()").arg(u),
3461 QString ("%1 ()").arg(r),
3462 QString ("%1 %2").arg(r).arg(getObjectName(bi))
3464 emitDataChanged(bi);
3465 emitSelectionChanged();
3467 mapEditor->getScene()->update(); //Needed for _quick_ update, even in 1.13.x
3474 bool VymModel::unscrollBranch(BranchItem *bi)
3478 if (!bi->isScrolled()) return false;
3479 if (bi->toggleScroll())
3486 QString ("%1 ()").arg(u),
3488 QString ("%1 ()").arg(r),
3489 QString ("%1 %2").arg(r).arg(getObjectName(bi))
3491 emitDataChanged(bi);
3492 emitSelectionChanged();
3494 mapEditor->getScene()->update(); //Needed for _quick_ update, even in 1.13.x
3501 void VymModel::toggleScroll()
3503 BranchItem *selbi=getSelectedBranch();
3506 if (selbi->isScrolled())
3507 unscrollBranch (selbi);
3509 scrollBranch (selbi);
3510 // Note: saveState & reposition are called in above functions
3514 void VymModel::unscrollChildren()
3516 BranchItem *selbi=getSelectedBranch();
3519 saveStateChangingPart(
3522 QString ("unscrollChildren ()"),
3523 QString ("unscroll all children of %1").arg(getObjectName(selbi))
3525 BranchItem *prev=NULL;
3526 BranchItem *cur=NULL;
3527 nextBranch (cur,prev,true,selbi);
3530 if (cur->isScrolled())
3532 cur->toggleScroll();
3533 emitDataChanged (cur);
3535 nextBranch (cur,prev,true,selbi);
3539 // Would this help??? emitSelectionChanged();
3543 void VymModel::setScale(qreal xn, qreal yn)
3545 ImageItem *selii=getSelectedImage();
3548 qreal sx=selii->getScaleX();
3549 qreal sy=selii->getScaleY();
3550 selii->setScale (xn,yn);
3553 QString ("setScale(%1,%2)").arg(sx).arg(sy),
3555 QString ("setScale(%1,%2)").arg(xn).arg(yn),
3556 QString ("Scale %1").arg(getObjectName(selii))
3562 void VymModel::growSelectionSize() //FIXME-3 Also for heading in BranchItem?
3564 ImageItem *selii=getSelectedImage();
3568 qreal sx=selii->getScaleX();
3569 qreal sy=selii->getScaleY();
3570 setScale (sx+f,sy+f);
3574 void VymModel::shrinkSelectionSize()
3576 ImageItem *selii=getSelectedImage();
3580 qreal sx=selii->getScaleX();
3581 qreal sy=selii->getScaleY();
3582 setScale (sx-f,sy-f);
3586 void VymModel::resetSelectionSize()
3588 ImageItem *selii=getSelectedImage();
3589 if (selii) setScale (1,1);
3592 void VymModel::emitExpandAll()
3594 emit (expandAll() );
3597 void VymModel::emitExpandOneLevel()
3599 emit (expandOneLevel () );
3602 void VymModel::emitCollapseOneLevel()
3604 emit (collapseOneLevel () );
3607 void VymModel::emitCollapseUnselected()
3609 emit (collapseUnselected() );
3612 void VymModel::toggleTarget()
3614 BranchItem *selbi=getSelectedBranch();
3617 selbi->toggleTarget();
3628 ItemList VymModel::getTargets()
3632 //rmodel->setSearchString (s);
3634 BranchItem *cur=NULL;
3635 BranchItem *prev=NULL;
3636 nextBranch(cur,prev);
3640 if (cur->hasActiveSystemFlag("system-target"))
3641 targets[cur->getID()] = (cur->getHeading()).getTextASCII();
3642 nextBranch(cur,prev);
3647 void VymModel::toggleStandardFlag (const QString &name, FlagRow *master)
3649 BranchItem *bi=getSelectedBranch();
3653 if (bi->hasActiveStandardFlag(name))
3665 QString("%1 (\"%2\")").arg(u).arg(name),
3667 QString("%1 (\"%2\")").arg(r).arg(name),
3668 QString("Toggling standard flag \"%1\" of %2").arg(name).arg(getObjectName(bi)));
3669 bi->toggleStandardFlag (name, master);
3670 emitDataChanged (bi);
3675 void VymModel::addFloatImage (const QImage &img)
3677 BranchItem *selbi=getSelectedBranch();
3680 ImageItem *ii=createImage (selbi);
3682 ii->setOriginalFilename("No original filename (image added by dropevent)");
3683 QString s=getSelectString(selbi);
3684 saveState (PartOfMap, s, "nop ()", s, "copy ()","Copy dropped image to clipboard",ii );
3685 saveState (ii,"delete ()", selbi,QString("paste(%1)").arg(curStep),"Pasting dropped image");
3691 void VymModel::colorBranch (QColor c)
3693 QList <BranchItem*> selbis=getSelectedBranches();
3694 foreach (BranchItem* selbi, selbis)
3698 QString ("colorBranch (\"%1\")").arg(selbi->getHeadingColor().name()),
3700 QString ("colorBranch (\"%1\")").arg(c.name()),
3701 QString("Set color of %1 to %2").arg(getObjectName(selbi)).arg(c.name())
3703 selbi->setHeadingColor(c); // color branch
3704 emitDataChanged (selbi);
3705 taskEditor->showSelection();
3707 mapEditor->getScene()->update();
3710 void VymModel::colorSubtree (QColor c, BranchItem *b)
3712 QList <BranchItem*> selbis;
3716 selbis=getSelectedBranches();
3717 foreach (BranchItem *bi,selbis)
3719 saveStateChangingPart(
3722 QString ("colorSubtree (\"%1\")").arg(c.name()),
3723 QString ("Set color of %1 and children to %2").arg(getObjectName(bi)).arg(c.name())
3725 BranchItem *prev=NULL;
3726 BranchItem *cur=NULL;
3727 nextBranch (cur,prev,true,bi);
3730 cur->setHeadingColor(c); // color links, color children
3731 emitDataChanged (cur);
3732 nextBranch (cur,prev,true,bi);
3735 taskEditor->showSelection();
3736 mapEditor->getScene()->update();
3739 QColor VymModel::getCurrentHeadingColor()
3741 BranchItem *selbi=getSelectedBranch();
3742 if (selbi) return selbi->getHeadingColor();
3744 QMessageBox::warning(0,"Warning","Can't get color of heading,\nthere's no branch selected");
3748 void VymModel::note2URLs()
3750 BranchItem *selbi=getSelectedBranch();
3753 saveStateChangingPart(
3756 QString ("note2URLs()"),
3757 QString ("Extract URLs from note of %1").arg(getObjectName(selbi))
3760 QString n = selbi->getNoteASCII();
3761 if (n.isEmpty()) return;
3762 QRegExp re ("(http.*)(\\s|\"|')");
3763 re.setMinimal (true);
3767 while ((pos = re.indexIn(n, pos)) != -1)
3769 bi=createBranch (selbi);
3770 bi->setHeadingPlainText (re.cap(1));
3771 bi->setURL (re.cap(1));
3772 emitDataChanged (bi);
3773 pos += re.matchedLength();
3779 void VymModel::editHeading2URL()
3781 TreeItem *selti=getSelectedItem();
3783 setURL (selti->getHeadingPlain());
3786 void VymModel::editBugzilla2URL()
3788 TreeItem *selti=getSelectedItem();
3791 QString h=selti->getHeadingPlain();
3792 QRegExp rx("(\\d+)");
3793 if (rx.indexIn(h) !=-1)
3794 setURL ("https://bugzilla.novell.com/show_bug.cgi?id="+rx.cap(1) );
3798 void VymModel::getBugzillaData(bool subtree)
3800 if (!bugzillaClientAvailable)
3804 QObject::tr("No Bugzilla client found. "
3805 " For openSUSE you can install by (running as root):\n\n","VymModel, how to install Bugzilla client module")+
3806 " zypper ar http://download.opensuse.org/repositories/openSUSE:/Tools/openSUSE_XX.Y/ openSUSE:Tools_XX.Y\n"+
3807 " zypper in perl-SUSE-BugzillaClient\n\n"+
3808 " and replace XX.Y with your version of openSUSE, e.g. 11.4\n\n"+
3809 QObject::tr("Alternatively you can also add the repository\n"
3810 "and install the perl module for Bugzilla access using YaST","VymModel, how to install Bugzilla client module")
3812 dia.setWindowTitle(QObject::tr("Warning: Couldn't find Bugzilla client","VymModel"));
3813 dia.setShowAgainName("/BugzillaClient/missing");
3818 BranchItem *selbi=getSelectedBranch();
3822 BranchItem *prev=NULL;
3823 BranchItem *cur=NULL;
3824 nextBranch (cur,prev,true,selbi);
3830 // Don't run query again if we are in update mode
3831 if (!subtree || ! url.contains("buglist.cgi") )
3833 new BugAgent (cur,url);
3834 mainWindow->statusMessage (tr("Contacting Bugzilla...","VymModel"));
3838 nextBranch (cur,prev,true,selbi);
3845 void VymModel::editFATE2URL()
3847 TreeItem *selti=getSelectedItem();
3850 QString url= "http://keeper.suse.de:8080/webfate/match/id?value=ID"+selti->getHeadingPlain();
3853 "setURL (\""+selti->getURL()+"\")",
3855 "setURL (\""+url+"\")",
3856 QString("Use heading of %1 as link to FATE").arg(getObjectName(selti))
3858 selti->setURL (url);
3859 // FIXME-4 updateActions();
3863 void VymModel::setVymLink (const QString &s) //FIXME-4 fail, if s does not exist
3865 BranchItem *bi=getSelectedBranch();
3870 "setVymLink (\""+bi->getVymLink()+"\")",
3872 "setVymLink (\""+s+"\")",
3873 QString("Set vymlink of %1 to %2").arg(getObjectName(bi)).arg(s)
3876 emitDataChanged (bi);
3881 void VymModel::deleteVymLink()
3883 BranchItem *bi=getSelectedBranch();
3888 "setVymLink (\""+bi->getVymLink()+"\")",
3890 "setVymLink (\"\")",
3891 QString("Unset vymlink of %1").arg(getObjectName(bi))
3893 bi->setVymLink ("");
3894 emitDataChanged (bi);
3900 QString VymModel::getVymLink()
3902 BranchItem *bi=getSelectedBranch();
3904 return bi->getVymLink();
3910 QStringList VymModel::getVymLinks()
3913 BranchItem *selbi=getSelectedBranch();
3914 BranchItem *cur=NULL;
3915 BranchItem *prev=NULL;
3916 nextBranch (cur,prev,true,selbi);
3919 if (!cur->getVymLink().isEmpty()) links.append( cur->getVymLink());
3920 nextBranch (cur,prev,true,selbi);
3926 void VymModel::followXLink(int i)
3928 BranchItem *selbi=getSelectedBranch();
3931 selbi=selbi->getXLinkItemNum(i)->getPartnerBranch();
3932 if (selbi) select (selbi);
3936 void VymModel::editXLink()
3938 Link *l=getSelectedXLink();
3941 EditXLinkDialog dia;
3943 if (dia.exec() == QDialog::Accepted)
3945 if (dia.useSettingsGlobal() )
3947 setMapDefXLinkPen( l->getPen() );
3948 setMapDefXLinkStyleBegin( l->getStyleBeginString() );
3949 setMapDefXLinkStyleEnd( l->getStyleEndString() );
3955 void VymModel::setXLinkColor(const QString &new_col)
3957 Link *l = getSelectedXLink();
3960 QPen pen = l->getPen();
3961 QColor new_color = QColor( new_col );
3962 QColor old_color = pen.color();
3963 if (new_color == old_color) return;
3964 pen.setColor( new_color);
3967 l->getBeginLinkItem(),
3968 QString("setXLinkColor(\"%1\")").arg(old_color.name() ),
3969 l->getBeginLinkItem(),
3970 QString("setXLinkColor(\"%1\")").arg(new_color.name() ),
3971 QString("set color of xlink to %1").arg(new_color.name() ) );
3975 void VymModel::setXLinkLineStyle(const QString &new_style)
3977 Link *l = getSelectedXLink();
3980 QPen pen = l->getPen();
3981 QString old_style = penStyleToString( pen.style() );
3982 if (new_style == old_style) return;
3984 pen.setStyle( penStyle(new_style, ok) );
3987 l->getBeginLinkItem(),
3988 QString("setXLinkLineStyle(\"%1\")").arg(old_style),
3989 l->getBeginLinkItem(),
3990 QString("setXLinkLineStyle(\"%1\")").arg(new_style),
3991 QString("set style of xlink to %1").arg(new_style) );
3995 void VymModel::setXLinkStyleBegin(const QString &new_style)
3997 Link *l=getSelectedXLink();
4000 QString old_style = l->getStyleBeginString();
4001 if (new_style == old_style) return;
4002 l->setStyleBegin( new_style );
4004 l->getBeginLinkItem(),
4005 QString("setXLinkStyleBegin(\"%1\")").arg(old_style),
4006 l->getBeginLinkItem(),
4007 QString("setXLinkStyleBegin(\"%1\")").arg(new_style),
4008 "set style of xlink begin");
4012 void VymModel::setXLinkStyleEnd(const QString &new_style)
4014 Link *l=getSelectedXLink();
4017 QString old_style = l->getStyleEndString();
4018 if (new_style == old_style) return;
4019 l->setStyleEnd( new_style );
4021 l->getBeginLinkItem(),
4022 QString("setXLinkStyleEnd(\"%1\")").arg(old_style),
4023 l->getBeginLinkItem(),
4024 QString("setXLinkStyleEnd(\"%1\")").arg(new_style),
4025 "set style of xlink end");
4029 void VymModel::setXLinkWidth(int new_width)
4031 Link *l=getSelectedXLink();
4034 QPen pen = l->getPen();
4035 int old_width = pen.width();
4036 if (new_width == old_width) return;
4037 pen.setWidth( new_width);
4040 l->getBeginLinkItem(),
4041 QString("setXLinkWidth(%1)").arg(old_width),
4042 l->getBeginLinkItem(),
4043 QString("setXLinkWidth(%1)").arg(new_width),
4044 "set width of xlink");
4048 //////////////////////////////////////////////
4050 //////////////////////////////////////////////
4052 QVariant VymModel::parseAtom(const QString &atom, bool &noErr, QString &errorMsg)
4054 TreeItem* selti=getSelectedItem();
4055 BranchItem *selbi=getSelectedBranch();
4060 QVariant returnValue="";
4062 // Split string s into command and parameters
4063 parser.parseAtom (atom);
4065 if (parser.getCommand().length() == 0)
4072 // Check set of parameters
4073 if (parser.errorLevel()==NoError && parser.checkParameters(selti) )
4075 QString com=parser.getCommand();
4076 // - MS VS2013 compiler has nested if limit - work around that with
4077 // do{}while(0); and breaks
4079 /////////////////////////////////////////////////////////////////////
4080 if (com=="addBranch")
4082 if (parser.parCount()==0)
4085 addNewBranch ( selbi,parser.parInt (ok,0) );
4088 /////////////////////////////////////////////////////////////////////
4089 if (com=="addBranchBefore")
4091 addNewBranchBefore ();
4094 /////////////////////////////////////////////////////////////////////
4095 if (com==QString("addMapCenter"))
4097 x=parser.parDouble (ok,0);
4098 y=parser.parDouble (ok,1);
4101 /////////////////////////////////////////////////////////////////////
4102 if (com==QString("addMapInsert"))
4104 t=parser.parString (ok,0); // path to map
4105 int contentFilter=0x0000;
4107 int pc=parser.parCount();
4112 pos=parser.parInt(ok,1); // position
4114 parser.setError (Aborted,"Couldn't read position");
4117 // Get contentFilter (to filter e.g. slides)
4120 contentFilter=parser.parInt (ok,2);
4122 parser.setError (Aborted,"Couldn't read content Filter");
4125 if (parser.errorLevel() == NoError)
4127 if (QDir::isRelativePath(t))
4128 t=(QDir::currentPath() + "/"+t);
4129 saveStateBeforeLoad (ImportAdd, t);
4130 if (File::Aborted==loadMap (t,ImportAdd,VymMap,contentFilter,pos) )
4131 parser.setError (Aborted,QString("Couldn't load %1").arg(t) );
4135 /////////////////////////////////////////////////////////////////////
4136 if (com==QString("addMapReplace"))
4138 t=parser.parString (ok,0); // path to map
4139 if (QDir::isRelativePath(t))
4140 t=(QDir::currentPath() + "/"+t);
4141 saveStateBeforeLoad (ImportReplace, t);
4142 if (File::Aborted==loadMap (t,ImportReplace,VymMap) )
4143 parser.setError (Aborted,QString("Couldn't load %1").arg(t) );
4146 /////////////////////////////////////////////////////////////////////
4147 if (com==QString("addSlide"))
4152 /////////////////////////////////////////////////////////////////////
4153 if (com==QString("addXLink"))
4155 s=parser.parString (ok,0); // begin
4156 t=parser.parString (ok,1); // end
4157 BranchItem *begin=(BranchItem*)findBySelectString(s);
4158 BranchItem *end=(BranchItem*)findBySelectString(t);
4161 if (begin->isBranchLikeType() && end->isBranchLikeType())
4163 Link *li=new Link (this);
4164 li->setBeginBranch ( (BranchItem*)begin );
4165 li->setEndBranch ( (BranchItem*)end);
4168 QPen pen=li->getPen();
4169 if (parser.parCount()>2)
4171 int w=parser.parInt (ok,2);
4172 if (ok) pen.setWidth(w);
4174 if (parser.parCount()>3)
4176 QColor col=parser.parColor (ok,3);
4177 if (ok) pen.setColor (col);
4179 if (parser.parCount()>4)
4181 QString st0=parser.parString (ok,4);
4184 Qt::PenStyle st1=penStyle (st0,ok);
4188 parser.setError (Aborted, "Couldn't read penstyle");
4191 if (ok) li->setPen(pen);
4194 parser.setError (Aborted,"begin or end of xLink are not branch or mapcenter");
4197 parser.setError (Aborted,"Couldn't find begin or end of xLink");
4200 /////////////////////////////////////////////////////////////////////
4201 if (com=="branchCount")
4203 returnValue=selti->branchCount();
4206 /////////////////////////////////////////////////////////////////////
4207 if (com=="centerCount")
4209 returnValue=rootItem->branchCount();
4212 /////////////////////////////////////////////////////////////////////
4213 if (com=="centerOnID")
4215 s=parser.parString(ok,0);
4216 TreeItem *ti=findUuid(QUuid(s));
4219 LinkableMapObj *lmo=((MapItem*)ti)->getLMO();
4220 if (zoomFactor>0 && lmo)
4221 mapEditor->setViewCenterTarget (
4222 lmo->getBBox().center(),
4228 qWarning()<<"VymModel::centerOnID failed!";
4230 parser.setError(Aborted,QString("Could not find ID: \"%1\"").arg(s));
4233 /////////////////////////////////////////////////////////////////////
4234 if (com=="clearFlags")
4236 selbi->deactivateAllStandardFlags();
4238 emitDataChanged(selbi);
4242 /////////////////////////////////////////////////////////////////////
4243 if (com=="colorBranch")
4245 QColor c=parser.parColor (ok,0);
4249 /////////////////////////////////////////////////////////////////////
4250 if (com=="colorSubtree")
4252 QColor c=parser.parColor (ok,0);
4256 /////////////////////////////////////////////////////////////////////
4262 /////////////////////////////////////////////////////////////////////
4268 /////////////////////////////////////////////////////////////////////
4269 if (com=="cycleTask")
4272 if (parser.parCount()==0) b=false;
4273 if (parser.parCount()==1) b=parser.parBool(ok,0);
4274 if (ok) cycleTaskStatus (b);
4277 /////////////////////////////////////////////////////////////////////
4283 /////////////////////////////////////////////////////////////////////
4284 if (com=="deleteKeepChildren")
4286 deleteKeepChildren();
4289 /////////////////////////////////////////////////////////////////////
4290 if (com=="deleteChildren")
4295 /////////////////////////////////////////////////////////////////////
4296 if (com=="deleteSlide")
4298 n = parser.parInt (ok,0);
4299 if (!ok || n < 0 || n >= slideModel->count() - 1)
4300 parser.setError (Aborted,"Index out of range");
4305 /////////////////////////////////////////////////////////////////////
4306 if (com=="exportAO")
4308 QString fname=parser.parString(ok,0);
4309 exportAO (fname,false);
4312 /////////////////////////////////////////////////////////////////////
4313 if (com=="exportASCII")
4315 QString fname = parser.parString(ok, 0);
4316 bool listTasks = parser.parBool(ok, 1);
4317 exportASCII (listTasks, fname, false);
4320 /////////////////////////////////////////////////////////////////////
4321 if (com=="exportCSV")
4323 QString fname=parser.parString(ok,0);
4324 exportCSV (fname,false);
4327 /////////////////////////////////////////////////////////////////////
4328 if (com=="exportHTML")
4330 QString path=parser.parString(ok,0);
4331 QString fname=parser.parString(ok,1);
4332 exportHTML (path,fname,false);
4335 /////////////////////////////////////////////////////////////////////
4336 if (com=="exportImage")
4338 QString fname=parser.parString(ok,0);
4339 QString format="PNG";
4340 if (parser.parCount()>=2)
4341 format=parser.parString(ok,1);
4342 exportImage (fname,false,format);
4345 /////////////////////////////////////////////////////////////////////
4346 if (com=="exportImpress")
4348 QString fn=parser.parString(ok,0);
4349 QString cf=parser.parString(ok,1);
4350 exportImpress (fn,cf);
4353 /////////////////////////////////////////////////////////////////////
4354 if (com=="exportLast")
4359 /////////////////////////////////////////////////////////////////////
4360 if (com=="exportLaTeX")
4362 QString fname=parser.parString(ok,0);
4363 exportLaTeX (fname,false);
4366 /////////////////////////////////////////////////////////////////////
4367 if (com=="exportOrgMode")
4369 QString fname=parser.parString(ok,0);
4370 exportOrgMode (fname,false);
4373 /////////////////////////////////////////////////////////////////////
4374 if (com=="exportPDF")
4376 QString fname=parser.parString(ok,0);
4377 exportPDF(fname,false);
4380 /////////////////////////////////////////////////////////////////////
4381 if (com=="exportSVG")
4383 QString fname=parser.parString(ok,0);
4384 exportSVG(fname,false);
4387 /////////////////////////////////////////////////////////////////////
4388 if (com=="exportXML")
4390 QString dpath=parser.parString(ok,0);
4391 QString fpath=parser.parString(ok,1);
4392 exportXML (dpath,fpath,false);
4395 /////////////////////////////////////////////////////////////////////
4396 if (com=="getDestPath")
4398 returnValue=getDestPath();
4401 /////////////////////////////////////////////////////////////////////
4402 if (com=="getFileDir")
4404 returnValue=getFileDir();
4407 /////////////////////////////////////////////////////////////////////
4408 if (com=="getFrameType")
4410 BranchObj *bo=(BranchObj*)(selbi->getLMO());
4412 parser.setError (Aborted,"No BranchObj");
4414 returnValue=bo->getFrame()->getFrameTypeName();
4417 /////////////////////////////////////////////////////////////////////
4418 if (com=="getHeadingPlainText")
4420 returnValue = getHeading().getTextASCII();
4423 /////////////////////////////////////////////////////////////////////
4424 if (com=="getHeadingXML")
4426 returnValue = getHeading().saveToDir();
4429 /////////////////////////////////////////////////////////////////////
4430 if (com=="getMapAuthor")
4435 /////////////////////////////////////////////////////////////////////
4436 if (com=="getMapComment")
4438 returnValue=comment;
4441 /////////////////////////////////////////////////////////////////////
4442 if (com=="getMapTitle")
4447 /////////////////////////////////////////////////////////////////////
4448 if (com=="getNotePlainText")
4450 returnValue= getNote().getTextASCII();
4453 /////////////////////////////////////////////////////////////////////
4454 if (com=="getNoteXML")
4456 returnValue= getNote().saveToDir();
4459 /////////////////////////////////////////////////////////////////////
4460 if (com=="getSelectString")
4462 returnValue=getSelectString();
4465 /////////////////////////////////////////////////////////////////////
4466 if (com=="getTaskSleepDays")
4468 Task *task=selbi->getTask();
4470 returnValue=task->getDaysSleep();
4472 parser.setError (Aborted,"Branch has no task set");
4475 /////////////////////////////////////////////////////////////////////
4478 returnValue=selti->getURL();
4481 /////////////////////////////////////////////////////////////////////
4482 if (com=="getVymLink")
4484 returnValue=selti->getVymLink();
4487 /////////////////////////////////////////////////////////////////////
4488 if (com=="getXLinkColor")
4490 returnValue=getXLinkColor().name();
4493 /////////////////////////////////////////////////////////////////////
4494 if (com=="getXLinkWidth")
4496 returnValue=getXLinkWidth();
4499 /////////////////////////////////////////////////////////////////////
4500 if (com=="getXLinkPenStyle")
4502 returnValue=penStyleToString( getXLinkPenStyle() );
4505 /////////////////////////////////////////////////////////////////////
4506 if (com=="getXLinkStyleBegin")
4508 returnValue = getXLinkStyleBegin();
4511 /////////////////////////////////////////////////////////////////////
4512 if (com=="getXLinkStyleEnd")
4514 returnValue = getXLinkStyleEnd();
4517 /////////////////////////////////////////////////////////////////////
4518 if (com=="hasActiveFlag")
4520 s=parser.parString(ok,0);
4521 returnValue=selti->hasActiveStandardFlag(s);
4524 /////////////////////////////////////////////////////////////////////
4527 returnValue = !getNote().isEmpty();
4530 /////////////////////////////////////////////////////////////////////
4531 if (com=="hasRichTextNote")
4533 returnValue=hasRichTextNote();
4536 /////////////////////////////////////////////////////////////////////
4539 if (selbi && selbi->getTask() )
4545 /////////////////////////////////////////////////////////////////////
4546 if (com=="importDir")
4548 s=parser.parString(ok,0);
4552 /////////////////////////////////////////////////////////////////////
4553 if (com=="isScrolled")
4555 returnValue=selbi->isScrolled();
4558 /////////////////////////////////////////////////////////////////////
4559 if (com=="loadImage")
4561 s=parser.parString(ok,0);
4562 loadImage (selbi,s);
4565 /////////////////////////////////////////////////////////////////////
4566 if (com=="loadNote")
4568 s=parser.parString(ok,0);
4572 /////////////////////////////////////////////////////////////////////
4573 if (com=="moveDown")
4578 /////////////////////////////////////////////////////////////////////
4584 /////////////////////////////////////////////////////////////////////
4585 if (com=="moveSlideUp")
4587 n = parser.parInt (ok, 0);
4588 if (!ok || n < 0 || n >= slideModel->count() - 1)
4589 parser.setError (Aborted,"Index out of range");
4594 /////////////////////////////////////////////////////////////////////
4595 if (com=="moveSlideDown")
4597 n = parser.parInt (ok, 0);
4598 if (!ok || n < 0 || n >= slideModel->count() - 1)
4599 parser.setError (Aborted,"Index out of range");
4604 /////////////////////////////////////////////////////////////////////
4607 x=parser.parDouble (ok,0);
4608 y=parser.parDouble (ok,1);
4612 /////////////////////////////////////////////////////////////////////
4615 x=parser.parDouble (ok,0);
4616 y=parser.parDouble (ok,1);
4620 /////////////////////////////////////////////////////////////////////
4625 /////////////////////////////////////////////////////////////////////
4626 if (com=="note2URLs")
4631 /////////////////////////////////////////////////////////////////////
4632 if (com=="parseVymText")
4634 s = parser.parString(ok,0);
4638 /////////////////////////////////////////////////////////////////////
4644 /////////////////////////////////////////////////////////////////////
4650 /////////////////////////////////////////////////////////////////////
4651 if (com=="relinkTo")
4655 parser.setError (Aborted,"Nothing selected");
4658 if (parser.checkParCount(4))
4660 // 0 selectstring of parent
4661 // 1 num in parent (for branches)
4662 // 2,3 x,y of mainbranch or mapcenter (for images)
4663 s=parser.parString(ok,0);
4664 TreeItem *dst=findBySelectString (s);
4667 if (dst->getType()==TreeItem::Branch )
4669 // Get number in parent
4670 n=parser.parInt (ok,1);
4673 if (relinkBranch (selbi,(BranchItem*)dst,n,true))
4674 emitSelectionChanged();
4676 parser.setError(Aborted,"Relinking failed");
4678 } else if (dst->getType()==TreeItem::MapCenter)
4680 if (relinkBranch (selbi,(BranchItem*)dst,-1,true))
4682 // Get coordinates of mainbranch
4683 x=parser.parDouble(ok,2);
4686 y=parser.parDouble(ok,3);
4689 if (selbi->getLMO())
4691 ((BranchObj*)selbi->getLMO())->move (x,y);
4692 ((BranchObj*)selbi->getLMO())->setRelPos();
4697 emitSelectionChanged();
4699 parser.setError(Aborted,"Relinking failed");
4702 parser.setError (Aborted,"Couldn't find destination branch");
4704 } else if ( selti->getType() == TreeItem::Image)
4706 if (parser.checkParCount(1))
4708 // 0 selectstring of parent
4709 s=parser.parString(ok,0);
4710 TreeItem *dst=findBySelectString (s);
4713 if (dst->isBranchLikeType())
4714 if (!relinkImage ( ((ImageItem*)selti),(BranchItem*)dst))
4715 parser.setError(Aborted,"Relinking failed");
4718 parser.setError (Aborted,"Destination is not a branch");
4721 parser.setError (Aborted,"Type of selection is not a floatimage or branch");
4724 /////////////////////////////////////////////////////////////////////
4725 if (com=="saveImage")
4727 ImageItem *ii=getSelectedImage();
4728 s=parser.parString(ok,0);
4729 t=parser.parString(ok,1);
4733 /////////////////////////////////////////////////////////////////////
4734 if (com=="saveNote")
4736 s=parser.parString(ok,0);
4740 /////////////////////////////////////////////////////////////////////
4743 if (!scrollBranch (selbi))
4744 parser.setError (Aborted,"Could not scroll branch");
4747 /////////////////////////////////////////////////////////////////////
4750 s=parser.parString(ok,0);
4752 parser.setError(Aborted,QString("Could not select \"%1\"").arg(s));
4755 /////////////////////////////////////////////////////////////////////
4756 if (com=="selectID")
4758 s=parser.parString(ok,0);
4760 parser.setError(Aborted,QString("Could not select ID: \"%1\"").arg(s));
4763 /////////////////////////////////////////////////////////////////////
4764 if (com=="selectLastBranch")
4766 BranchItem *bi=selbi->getLastBranch();
4768 parser.setError (Aborted,"Could not select last branch");
4772 /////////////////////////////////////////////////////////////////////
4773 if (com=="selectLastImage")
4775 ImageItem *ii=selbi->getLastImage();
4777 parser.setError (Aborted,"Could not select last image");
4781 /////////////////////////////////////////////////////////////////////
4782 if (com=="selectParent")
4787 /////////////////////////////////////////////////////////////////////
4788 if (com=="selectLatestAdded")
4790 if (!latestAddedItem)
4792 parser.setError (Aborted,"No latest added object");
4795 if (!select (latestAddedItem))
4796 parser.setError (Aborted,"Could not select latest added object ");
4800 /////////////////////////////////////////////////////////////////////
4803 s=parser.parString(ok,0);
4804 selbi->activateStandardFlag(s);
4807 /////////////////////////////////////////////////////////////////////
4808 if (com=="setTaskSleep")
4810 s=parser.parString(ok,0);
4811 returnValue=setTaskSleep (s);
4814 /////////////////////////////////////////////////////////////////////
4815 if (com=="setFrameIncludeChildren")
4817 b=parser.parBool(ok,0);
4818 setFrameIncludeChildren(b);
4821 /////////////////////////////////////////////////////////////////////
4822 if (com=="setFrameType")
4824 s=parser.parString(ok,0);
4828 /////////////////////////////////////////////////////////////////////
4829 if (com=="setFramePenColor")
4831 QColor c=parser.parColor(ok,0);
4832 setFramePenColor (c);
4835 /////////////////////////////////////////////////////////////////////
4836 if (com=="setFrameBrushColor")
4838 QColor c=parser.parColor(ok,0);
4839 setFrameBrushColor (c);
4842 /////////////////////////////////////////////////////////////////////
4843 if (com=="setFramePadding")
4845 n=parser.parInt(ok,0);
4849 /////////////////////////////////////////////////////////////////////
4850 if (com=="setFrameBorderWidth")
4852 n=parser.parInt(ok,0);
4853 setFrameBorderWidth (n);
4856 /////////////////////////////////////////////////////////////////////
4857 if (com=="setHeadingPlainText")
4859 s=parser.parString (ok,0);
4860 setHeadingPlainText (s); // FIXME-3 what about RT? Nothing implemented.
4863 /////////////////////////////////////////////////////////////////////
4864 if (com=="setHideExport")
4866 b=parser.parBool(ok,0);
4870 /////////////////////////////////////////////////////////////////////
4871 if (com=="setIncludeImagesHorizontally")
4873 b=parser.parBool(ok,0);
4874 setIncludeImagesHor(b);
4877 /////////////////////////////////////////////////////////////////////
4878 if (com=="setIncludeImagesVertically")
4880 b=parser.parBool(ok,0);
4881 if (ok) setIncludeImagesVer(b);
4884 /////////////////////////////////////////////////////////////////////
4885 if (com=="setHideLinkUnselected")
4887 b=parser.parBool(ok,0);
4888 setHideLinkUnselected(b);
4891 /////////////////////////////////////////////////////////////////////
4892 if (com=="setMapAnimCurve")
4894 n=parser.parInt(ok,0);
4895 if (n<0 || n>QEasingCurve::OutInBounce)
4896 parser.setError (Aborted,"Unknown link style");
4900 c.setType ( (QEasingCurve::Type) n);
4905 /////////////////////////////////////////////////////////////////////
4906 if (com=="setMapAnimDuration")
4908 n=parser.parInt(ok,0);
4909 setMapAnimDuration(n);
4912 /////////////////////////////////////////////////////////////////////
4913 if (com=="setMapAuthor")
4915 s=parser.parString(ok,0);
4919 /////////////////////////////////////////////////////////////////////
4920 if (com=="setMapComment")
4922 s=parser.parString(ok,0);
4923 if (ok) setComment(s);
4926 if (com=="setMapTitle")
4928 s=parser.parString(ok,0);
4929 if (ok) setTitle(s);
4932 /////////////////////////////////////////////////////////////////////
4933 if (com=="setMapBackgroundColor")
4935 QColor c=parser.parColor (ok,0);
4936 setMapBackgroundColor (c);
4939 /////////////////////////////////////////////////////////////////////
4940 if (com=="setMapDefLinkColor")
4942 QColor c=parser.parColor (ok,0);
4943 setMapDefLinkColor (c);
4946 /////////////////////////////////////////////////////////////////////
4947 if (com=="setMapLinkStyle")
4949 s=parser.parString (ok,0);
4950 if (!setMapLinkStyle(s) )
4951 parser.setError (Aborted,"Unknown link style");
4954 /////////////////////////////////////////////////////////////////////
4955 if (com=="setMapRotation")
4957 x=parser.parDouble (ok,0);
4958 setMapRotationAngle(x);
4959 mapEditor->setAngleTarget(x);
4962 /////////////////////////////////////////////////////////////////////
4963 if (com=="setMapZoom")
4965 x=parser.parDouble (ok,0);
4966 setMapZoomFactor(x);
4967 mapEditor->setZoomFactorTarget(x);
4970 /////////////////////////////////////////////////////////////////////
4971 if (com=="setNotePlainText")
4973 s=parser.parString (ok,0);
4979 /////////////////////////////////////////////////////////////////////
4980 if (com=="setScale")
4982 x=parser.parDouble (ok,0);
4983 y=parser.parDouble (ok,1);
4987 /////////////////////////////////////////////////////////////////////
4988 if (com=="setSelectionColor")
4990 QColor c=parser.parColor (ok,0);
4991 setSelectionColorInt (c);
4994 /////////////////////////////////////////////////////////////////////
4997 s=parser.parString (ok,0);
5001 /////////////////////////////////////////////////////////////////////
5002 if (com=="setVymLink")
5004 s=parser.parString (ok,0);
5008 /////////////////////////////////////////////////////////////////////
5009 if (com=="setXLinkColor")
5011 s=parser.parString (ok,0);
5015 /////////////////////////////////////////////////////////////////////
5016 if (com=="setXLinkLineStyle")
5018 s=parser.parString (ok,0);
5019 setXLinkLineStyle(s);
5022 /////////////////////////////////////////////////////////////////////
5023 if (com=="setXLinkStyleBegin")
5025 s=parser.parString (ok,0);
5026 setXLinkStyleBegin(s);
5029 /////////////////////////////////////////////////////////////////////
5030 if (com=="setXLinkStyleEnd")
5032 s=parser.parString (ok,0);
5033 setXLinkStyleEnd(s);
5036 /////////////////////////////////////////////////////////////////////
5037 if (com=="setXLinkWidth")
5039 n=parser.parInt (ok,0);
5043 /////////////////////////////////////////////////////////////////////
5046 n=parser.parInt (ok,0);
5050 /////////////////////////////////////////////////////////////////////
5051 if (com=="sortChildren")
5054 if (parser.parCount()==1)
5055 b=parser.parBool(ok,0);
5059 /////////////////////////////////////////////////////////////////////
5060 if (com=="toggleFlag")
5062 s=parser.parString(ok,0);
5063 toggleStandardFlag (s);
5066 /////////////////////////////////////////////////////////////////////
5067 if (com=="toggleFrameIncludeChildren")
5069 toggleFrameIncludeChildren();
5072 /////////////////////////////////////////////////////////////////////
5073 if (com=="toggleScroll")
5078 /////////////////////////////////////////////////////////////////////
5079 if (com=="toggleTarget")
5084 /////////////////////////////////////////////////////////////////////
5085 if (com=="toggleTask")
5090 /////////////////////////////////////////////////////////////////////
5096 /////////////////////////////////////////////////////////////////////
5097 if (com=="unscroll")
5099 if (!unscrollBranch (selbi))
5100 parser.setError (Aborted,"Could not unscroll branch");
5103 /////////////////////////////////////////////////////////////////////
5104 if (com=="unscrollChildren")
5106 unscrollChildren ();
5109 /////////////////////////////////////////////////////////////////////
5110 if (com=="unselectAll")
5115 /////////////////////////////////////////////////////////////////////
5116 if (com=="unsetFlag")
5118 s=parser.parString(ok,0);
5119 selbi->deactivateStandardFlag(s);
5122 /////////////////////////////////////////////////////////////////////
5123 //else must be an Unknown command
5124 parser.setError (Aborted,"Unknown command");
5127 } while(0); // End of do{}while(0); MS VS2013 nested if bug workaround
5129 } // end check set of parameters if
5131 if (parser.errorLevel()==NoError)
5139 // TODO Error handling
5141 errorMsg=parser.errorMessage();
5142 returnValue=errorMsg;
5147 QVariant VymModel::execute (const QString &script)
5149 parser.setScript (script);
5154 while (parser.next() && noErr)
5156 r=parseAtom(parser.getAtom(),noErr,errMsg);
5159 if (!options.isOn("batch") && !testmode )
5160 QMessageBox::warning(0,tr("Warning"),tr("Script aborted:\n%1").arg(errMsg));
5161 qWarning()<< QString("VM::execute aborted: "+errMsg + "\n" + script);
5167 void VymModel::setExportMode (bool b)
5169 // should be called before and after exports
5170 // depending on the settings
5171 if (b && settings.value("/export/useHideExport","true")=="true")
5172 setHideTmpMode (TreeItem::HideExport);
5174 setHideTmpMode (TreeItem::HideNone);
5177 QPointF VymModel::exportImage(QString fname, bool askName, QString format)
5179 QPointF offset; // set later, when getting image from MapEditor
5185 qWarning("VymModel::exportImage called without filename (and askName==false)");
5189 fname=lastImageDir.absolutePath() + "/" + getMapName()+".png";
5194 ex.setName( "Image" );
5195 ex.setModel( this );
5196 ex.setFilePath( fname );
5197 ex.setWindowTitle ( tr("Export map as image") );
5198 ex.addFilter( "PNG (*.png);;All (* *.*)" ); // imageIO.getFilters().join(";;")
5199 ex.setLastCommand( settings.localValue(filePath,"/export/last/command","").toString() );
5203 if (! ex.execDialog() ) return offset;
5204 fname = ex.getFilePath();
5205 lastImageDir=dirname(fname);
5208 setExportMode (true);
5210 QImage img (mapEditor->getImage(offset));
5211 if (!img.save(fname, format.toLocal8Bit()))
5212 QMessageBox::critical (0,tr("Critical Error"),tr("Couldn't save QImage %1 in format %2").arg(fname).arg(format));
5213 setExportMode (false);
5215 ex.completeExport();
5220 void VymModel::exportPDF (QString fname, bool askName)
5226 qWarning("VymModel::exportPDF called without filename (and askName==false)");
5230 fname = lastExportDir.absolutePath() + "/" + getMapName()+".pdf";
5234 ex.setName( "PDF" );
5235 ex.setModel( this );
5236 ex.setFilePath( fname );
5237 ex.setWindowTitle ( tr("Export map as PDF") );
5238 ex.addFilter( "PDF (*.pdf);;All (* *.*)" );
5239 ex.setLastCommand( settings.localValue(filePath,"/export/last/command","").toString() );
5243 if (! ex.execDialog() ) return;
5244 fname = ex.getFilePath();
5247 setExportMode (true);
5250 QPrinter printer(QPrinter::HighResolution);
5251 printer.setOutputFormat(QPrinter::PdfFormat);
5252 printer.setOutputFileName(fname);
5253 printer.setPageSize(QPrinter::A3);
5255 QRectF bbox=mapEditor->getTotalBBox();
5256 if (bbox.width()>bbox.height())
5257 // recommend landscape
5258 printer.setOrientation (QPrinter::Landscape);
5260 // recommend portrait
5261 printer.setOrientation (QPrinter::Portrait);
5263 QPainter *pdfPainter = new QPainter(&printer);
5264 getScene()->render(pdfPainter);
5268 setExportMode (false);
5270 ex.completeExport();
5273 QPointF VymModel::exportSVG (QString fname, bool askName)
5275 QPointF offset; // FIXME-3 not needed?
5281 qWarning("VymModel::exportSVG called without filename (and askName==false)");
5285 fname=lastImageDir.absolutePath() + "/" + getMapName()+".png";
5289 ex.setName( "SVG" );
5290 ex.setModel( this );
5291 ex.setFilePath( fname );
5292 ex.setWindowTitle ( tr("Export map as SVG") );
5293 ex.addFilter( "SVG (*.svg);;All (* *.*)" );
5294 ex.setLastCommand( settings.localValue(filePath,"/export/last/command","").toString() );
5298 if (! ex.execDialog() ) return offset;
5299 fname = ex.getFilePath();
5300 lastImageDir = dirname(fname);
5303 setExportMode (true);
5305 QSvgGenerator generator;
5306 generator.setFileName(fname);
5307 QSize sceneSize = getScene()->sceneRect().size().toSize();
5308 generator.setSize(sceneSize);
5309 generator.setViewBox(QRect(0, 0, sceneSize.width(), sceneSize.height()));
5310 QPainter *svgPainter = new QPainter(&generator);
5311 getScene()->render(svgPainter);
5315 setExportMode (false);
5316 ex.completeExport();
5321 void VymModel::exportXML (QString dpath, QString fpath, bool useDialog)
5324 ex.setName( "XML" );
5325 ex.setModel( this );
5326 ex.setWindowTitle ( tr("Export map as XML") );
5327 ex.addFilter( "XML (*.xml);;All (* *.*)" );
5328 ex.setLastCommand( settings.localValue(filePath,"/export/last/command","").toString() );
5333 fd.setWindowTitle (vymName+ " - " + tr("Export XML to directory"));
5334 fd.setFileMode (QFileDialog::DirectoryOnly);
5335 QStringList filters;
5336 filters << "XML data (*.xml)";
5337 fd.setNameFilters (filters);
5338 fd.setConfirmOverwrite (false);
5339 fd.setAcceptMode (QFileDialog::AcceptSave);
5342 if (fd.exec() != QDialog::Accepted || fd.selectedFiles().isEmpty() ) return;
5344 dpath = fd.selectedFiles().first();
5345 //dpath = dpath.left(dpath.lastIndexOf("/"));
5346 fpath = dpath + "/" + mapName + ".xml";
5348 if (!reallyWriteDirectory(dpath) ) return;
5350 ex.setFilePath( fpath );
5352 QString mname = basename(fpath);
5354 // Hide stuff during export, if settings want this
5355 setExportMode (true);
5357 // Create subdirectories
5358 makeSubDirs (dpath);
5360 // write image and calculate offset (Remember old mapSaved setting while exporting image)
5361 bool mchanged = mapChanged;
5362 bool munsaved = mapUnsaved;
5364 QPointF offset = exportImage (dpath + "/images/" + mname + ".png",false,"PNG");
5366 mapChanged = mchanged;
5367 mapUnsaved = munsaved;
5369 // write to directory //FIXME-3 check totalBBox here...
5370 QString saveFile=saveToDir (dpath , mname + "-", true, offset, NULL);
5373 file.setFileName (fpath);
5374 if ( !file.open( QIODevice::WriteOnly ) )
5376 // This should neverever happen
5377 QMessageBox::critical (
5379 tr("Critical Export Error"),
5380 QString("VymModel::exportXML couldn't open %1").arg(file.fileName())
5385 // Write it finally, and write in UTF8, no matter what
5386 QTextStream ts( &file );
5387 ts.setCodec("UTF-8");
5391 setExportMode (false);
5393 ex.completeExport( QString("\"%1\",\"%2\"").arg(dpath).arg(fpath) );
5396 void VymModel::exportAO (QString fname,bool askName)
5400 ex.setLastCommand( settings.localValue(filePath,"/export/last/command","").toString() );
5403 ex.setFilePath (mapName+".txt");
5405 ex.setFilePath (fname);
5409 ex.setDirPath (lastExportDir.absolutePath());
5414 setExportMode(true);
5416 setExportMode(false);
5420 void VymModel::exportASCII(bool listTasks, const QString &fname, bool askName)
5424 ex.setListTasks(listTasks);
5425 ex.setLastCommand( settings.localValue(filePath,"/export/last/command","").toString() );
5428 ex.setFilePath (mapName+".txt");
5430 ex.setFilePath (fname);
5434 ex.setDirPath (lastExportDir.absolutePath());
5440 setExportMode(true);
5442 setExportMode(false);
5446 void VymModel::exportCSV(const QString &fname, bool askName)
5450 ex.setLastCommand( settings.localValue(filePath,"/export/last/command","").toString() );
5453 ex.setFilePath (mapName+".csv");
5455 ex.setFilePath (fname);
5459 ex.addFilter ("CSV (*.csb);;All (* *.*)");
5460 ex.setDirPath (lastExportDir.absolutePath());
5461 ex.setWindowTitle(vymName+ " -" +tr("Export as csv")+" "+tr("(still experimental)"));
5467 setExportMode(true);
5469 setExportMode(false);
5473 void VymModel::exportHTML (const QString &dpath, const QString &fpath,bool useDialog)
5475 ExportHTML ex (this);
5476 ex.setLastCommand( settings.localValue(filePath,"/export/last/command","").toString() );
5478 if (!dpath.isEmpty()) ex.setDirPath (dpath);
5479 if (!fpath.isEmpty()) ex.setFilePath (fpath);
5480 setExportMode(true);
5481 ex.doExport(useDialog);
5482 setExportMode(false);
5485 void VymModel::exportImpress(const QString &fn, const QString &cf)
5488 ex.setFilePath (fn);
5490 ex.setLastCommand( settings.localValue(filePath,"/export/last/command","").toString() );
5492 if (ex.setConfigFile(cf))
5494 QString lastCommand = settings.localValue(filePath,"/export/last/command","").toString();
5496 setExportMode (true);
5497 ex.exportPresentation();
5498 setExportMode (false);
5500 QString command = settings.localValue(filePath,"/export/last/command","").toString();
5501 if (lastCommand != command) setChanged();
5505 bool VymModel::exportLastAvailable(QString &description, QString &command, QString &path, QString &configFile)
5507 command = settings.localValue(filePath,"/export/last/command","").toString();
5508 description = settings.localValue(filePath,"/export/last/description","").toString();
5509 path = settings.localValue(filePath,"/export/last/exportPath","").toString();
5510 configFile = settings.localValue(filePath,"/export/last/configFile","").toString();
5511 if (!command.isEmpty() && command.startsWith("export"))
5517 void VymModel::exportLast()
5519 QString desc, command, path, configFile; //FIXME-3 better integrate configFile into command
5520 if (exportLastAvailable(desc, command, path, configFile) )
5524 if (!configFile.isEmpty() && command=="exportImpress")
5525 execute (QString ("%1 (\"%2\",\"%3\")").arg(command).arg(path).arg(configFile) );
5527 execute (QString ("%1 (\"%2\")").arg(command).arg(path) );
5532 void VymModel::exportLaTeX (const QString &fname,bool askName)
5536 ex.setLastCommand( settings.localValue(filePath,"/export/last/command","").toString() );
5539 ex.setFilePath (mapName+".tex");
5541 ex.setFilePath (fname);
5543 if (askName) ex.execDialog() ;
5546 setExportMode(true);
5548 setExportMode(false);
5552 void VymModel::exportOrgMode (const QString &fname, bool askName)
5556 ex.setLastCommand( settings.localValue(filePath,"/export/last/command","").toString() );
5559 ex.setFilePath (mapName+".org");
5561 ex.setFilePath (fname);
5565 ex.setDirPath (lastExportDir.absolutePath());
5571 setExportMode(true);
5573 setExportMode(false);
5578 //////////////////////////////////////////////
5580 //////////////////////////////////////////////
5582 void VymModel::registerEditor(QWidget *me)
5584 mapEditor=(MapEditor*)me;
5587 void VymModel::unregisterEditor(QWidget *)
5592 void VymModel::setMapZoomFactor (const double &d)
5597 void VymModel::setMapRotationAngle(const double &d)
5602 void VymModel::setMapAnimDuration(const int &d)
5607 void VymModel::setMapAnimCurve(const QEasingCurve &c)
5612 void VymModel::setContextPos(QPointF p)
5618 void VymModel::unsetContextPos()
5620 contextPos=QPointF();
5621 hasContextPos=false;
5624 void VymModel::updateNoteFlag()
5626 TreeItem *selti=getSelectedItem();
5635 if (noteEditor->isEmpty())
5638 selti->setNote(noteEditor->getNote());
5639 emitDataChanged(selti);
5644 void VymModel::reposition() //FIXME-4 VM should have no need to reposition, but the views...
5646 if (blockReposition) return;
5649 for (int i=0;i<rootItem->branchCount(); i++)
5651 bo=rootItem->getBranchObjNum(i);
5653 bo->reposition(); // for positioning heading
5655 qDebug()<<"VM::reposition bo=0";
5657 mapEditor->getTotalBBox();
5658 emitSelectionChanged();
5662 bool VymModel::setMapLinkStyle (const QString & s)
5667 case LinkableMapObj::Line :
5670 case LinkableMapObj::Parabel:
5671 snow="StyleParabel";
5673 case LinkableMapObj::PolyLine:
5674 snow="StylePolyLine";
5676 case LinkableMapObj::PolyParabel:
5677 snow="StylePolyParabel";
5685 QString("setMapLinkStyle (\"%1\")").arg(s),
5686 QString("setMapLinkStyle (\"%1\")").arg(snow),
5687 QString("Set map link style (\"%1\")").arg(s)
5691 linkstyle=LinkableMapObj::Line;
5692 else if (s=="StyleParabel")
5693 linkstyle=LinkableMapObj::Parabel;
5694 else if (s=="StylePolyLine")
5695 linkstyle=LinkableMapObj::PolyLine;
5696 else if (s=="StylePolyParabel")
5697 linkstyle=LinkableMapObj::PolyParabel;
5699 linkstyle=LinkableMapObj::UndefinedStyle;
5701 BranchItem *cur=NULL;
5702 BranchItem *prev=NULL;
5704 nextBranch (cur,prev);
5707 bo=(BranchObj*)(cur->getLMO() );
5708 bo->setLinkStyle(bo->getDefLinkStyle(cur->parent() )); //FIXME-4 better emit dataCHanged and leave the changes to View
5709 nextBranch(cur,prev);
5715 LinkableMapObj::Style VymModel::getMapLinkStyle ()
5720 uint VymModel::getModelID()
5725 void VymModel::setView (VymView *vv)
5730 void VymModel::setMapDefLinkColor(QColor col)
5732 if ( !col.isValid() ) return;
5734 QString("setMapDefLinkColor (\"%1\")").arg(getMapDefLinkColor().name()),
5735 QString("setMapDefLinkColor (\"%1\")").arg(col.name()),
5736 QString("Set map link color to %1").arg(col.name())
5740 BranchItem *cur=NULL;
5741 BranchItem *prev=NULL;
5743 nextBranch(cur,prev);
5746 bo=(BranchObj*)(cur->getLMO() );
5748 nextBranch(cur,prev);
5753 void VymModel::setMapLinkColorHintInt()
5755 // called from setMapLinkColorHint(lch) or at end of parse
5756 BranchItem *cur=NULL;
5757 BranchItem *prev=NULL;
5759 nextBranch(cur,prev);
5762 bo=(BranchObj*)(cur->getLMO() );
5764 nextBranch(cur,prev);
5768 void VymModel::setMapLinkColorHint(LinkableMapObj::ColorHint lch)
5771 setMapLinkColorHintInt();
5774 void VymModel::toggleMapLinkColorHint()
5776 if (linkcolorhint==LinkableMapObj::HeadingColor)
5777 linkcolorhint=LinkableMapObj::DefaultColor;
5779 linkcolorhint=LinkableMapObj::HeadingColor;
5780 BranchItem *cur=NULL;
5781 BranchItem *prev=NULL;
5783 nextBranch(cur,prev);
5786 bo=(BranchObj*)(cur->getLMO() );
5788 nextBranch(cur,prev);
5792 void VymModel::selectMapBackgroundImage () // FIXME-3 for using background image: view.setCacheMode(QGraphicsView::CacheBackground); Also this belongs into ME
5794 QStringList filters;
5795 filters<< tr("Images") + " (*.png *.bmp *.xbm *.jpg *.png *.xpm *.gif *.pnm)";
5797 fd.setFileMode (QFileDialog::ExistingFile);
5798 fd.setWindowTitle(vymName + " - " + tr("Load background image"));
5799 fd.setDirectory (lastImageDir);
5800 fd.setAcceptMode (QFileDialog::AcceptOpen);
5802 if ( fd.exec() == QDialog::Accepted &&!fd.selectedFiles().isEmpty())
5804 // TODO selectMapBackgroundImg in QT4 use: lastImageDir=fd.directory();
5805 lastImageDir=QDir ( fd.directory().path() );
5806 setMapBackgroundImage ( fd.selectedFiles().first() );
5810 void VymModel::setMapBackgroundImage (const QString &fn) //FIXME-3 missing savestate, move to ME
5813 QColor oldcol=mapEditor->getScene()->backgroundBrush().color();
5816 QString ("setMapBackgroundImage (%1)").arg(oldcol.name()),
5818 QString ("setMapBackgroundImage (%1)").arg(col.name()),
5819 QString("Set background color of map to %1").arg(col.name()));
5822 brush.setTextureImage (QImage (fn));
5823 mapEditor->getScene()->setBackgroundBrush(brush);
5826 void VymModel::selectMapBackgroundColor()
5828 QColor col = QColorDialog::getColor( mapEditor->getScene()->backgroundBrush().color(), NULL);
5829 if ( !col.isValid() ) return;
5830 setMapBackgroundColor( col );
5834 void VymModel::setMapBackgroundColor(QColor col) // FIXME-4 move to ME
5836 QColor oldcol=mapEditor->getScene()->backgroundBrush().color();
5838 QString ("setMapBackgroundColor (\"%1\")").arg(oldcol.name()),
5839 QString ("setMapBackgroundColor (\"%1\")").arg(col.name()),
5840 QString("Set background color of map to %1").arg(col.name()));
5841 mapEditor->getScene()->setBackgroundBrush(col);
5844 QColor VymModel::getMapBackgroundColor() // FIXME-4 move to ME
5846 return mapEditor->getScene()->backgroundBrush().color();
5849 QFont VymModel::getMapDefaultFont ()
5854 void VymModel::setMapDefaultFont (const QFont &f)
5859 LinkableMapObj::ColorHint VymModel::getMapLinkColorHint() // FIXME-4 move to ME
5861 return linkcolorhint;
5864 QColor VymModel::getMapDefLinkColor() // FIXME-4 move to ME
5866 return defLinkColor;
5869 void VymModel::setMapDefXLinkPen (const QPen &p) // FIXME-4 move to ME
5874 QPen VymModel::getMapDefXLinkPen() // FIXME-4 move to ME
5879 void VymModel::setMapDefXLinkStyleBegin( const QString &s)
5881 defXLinkStyleBegin = s;
5884 QString VymModel::getMapDefXLinkStyleBegin()
5886 return defXLinkStyleBegin;
5889 void VymModel::setMapDefXLinkStyleEnd( const QString &s)
5891 defXLinkStyleEnd = s;
5894 QString VymModel::getMapDefXLinkStyleEnd()
5896 return defXLinkStyleEnd;
5899 void VymModel::move(const double &x, const double &y)
5901 MapItem *seli = (MapItem*)getSelectedItem();
5902 if (seli && (seli->isBranchLikeType() || seli->getType()==TreeItem::Image))
5904 LinkableMapObj *lmo=seli->getLMO();
5907 QPointF ap(lmo->getAbsPos());
5911 QString ps=qpointFToString(ap);
5912 QString s=getSelectString(seli);
5915 s, "move "+qpointFToString(to),
5916 QString("Move %1 to %2").arg(getObjectName(seli)).arg(ps));
5919 emitSelectionChanged();
5925 void VymModel::moveRel (const double &x, const double &y)
5927 MapItem *seli = (MapItem*)getSelectedItem();
5928 if (seli && (seli->isBranchLikeType() || seli->getType()==TreeItem::Image))
5930 LinkableMapObj *lmo=seli->getLMO();
5933 QPointF rp(lmo->getRelPos());
5937 QString ps=qpointFToString (lmo->getRelPos());
5938 QString s=getSelectString(seli);
5941 s, "moveRel "+qpointFToString(to),
5942 QString("Move %1 to relative position %2").arg(getObjectName(seli)).arg(ps));
5943 ((OrnamentedObj*)lmo)->move2RelPos (x,y);
5945 lmo->updateLinkGeometry();
5946 emitSelectionChanged();
5953 void VymModel::animate()
5955 animationTimer->stop();
5958 while (i<animObjList.size() )
5960 bo=(BranchObj*)animObjList.at(i);
5965 animObjList.removeAt(i);
5972 emitSelectionChanged();
5974 if (!animObjList.isEmpty()) animationTimer->start(animationInterval);
5978 void VymModel::startAnimation(BranchObj *bo, const QPointF &v)
5982 if (bo->getUseRelPos())
5983 startAnimation (bo,bo->getRelPos(),bo->getRelPos()+v);
5985 startAnimation (bo,bo->getAbsPos(),bo->getAbsPos()+v);
5988 void VymModel::startAnimation(BranchObj *bo, const QPointF &start, const QPointF &dest)
5990 if (start==dest) return;
5991 if (bo && bo->getTreeItem()->depth()>=0)
5994 ap.setStart (start);
5996 ap.setTicks (animationTicks);
5997 ap.setAnimated (true);
5998 bo->setAnimation (ap);
5999 if (!animObjList.contains(bo))
6000 animObjList.append( bo );
6001 animationTimer->setSingleShot (true);
6002 animationTimer->start(animationInterval);
6006 void VymModel::stopAnimation (MapObj *mo)
6008 int i=animObjList.indexOf(mo);
6010 animObjList.removeAt (i);
6013 void VymModel::stopAllAnimation ()
6017 while (i<animObjList.size() )
6019 bo=(BranchObj*)animObjList.at(i);
6020 bo->stopAnimation();
6021 bo->requestReposition();
6027 void VymModel::sendSelection()
6029 if (netstate!=Server) return;
6030 sendData (QString("select (\"%1\")").arg(getSelectString()) );
6033 void VymModel::newServer()
6037 tcpServer = new QTcpServer(this);
6038 if (!tcpServer->listen(QHostAddress::Any,port)) {
6039 QMessageBox::critical(NULL, "vym server",
6040 QString("Unable to start the server: %1.").arg(tcpServer->errorString()));
6041 //FIXME-3 needed? we are no widget any longer... close();
6044 connect(tcpServer, SIGNAL(newConnection()), this, SLOT(newClient()));
6046 qDebug()<<"Server is running on port "<<tcpServer->serverPort();
6049 void VymModel::connectToServer()
6052 server="salam.suse.de";
6054 clientSocket = new QTcpSocket (this);
6055 clientSocket->abort();
6056 clientSocket->connectToHost(server ,port);
6057 connect(clientSocket, SIGNAL(readyRead()), this, SLOT(readData()));
6058 connect(clientSocket, SIGNAL(error(QAbstractSocket::SocketError)),
6059 this, SLOT(displayNetworkError(QAbstractSocket::SocketError)));
6061 qDebug()<<"connected to "<<qPrintable (server)<<" port "<<port;
6066 void VymModel::newClient()
6068 QTcpSocket *newClient = tcpServer->nextPendingConnection();
6069 connect(newClient, SIGNAL(disconnected()),
6070 newClient, SLOT(deleteLater()));
6072 qDebug() <<"ME::newClient at "<<qPrintable( newClient->peerAddress().toString() );
6074 clientList.append (newClient);
6078 void VymModel::sendData(const QString &s)
6080 if (clientList.size()==0) return;
6082 // Create bytearray to send
6084 QDataStream out(&block, QIODevice::WriteOnly);
6085 out.setVersion(QDataStream::Qt_4_0);
6087 // Reserve some space for blocksize
6090 // Write sendCounter
6091 out << sendCounter++;
6096 // Go back and write blocksize so far
6097 out.device()->seek(0);
6098 quint16 bs=(quint16)(block.size() - 2*sizeof(quint16));
6102 qDebug() << "ME::sendData bs="<<bs<<" counter="<<sendCounter<<" s="<<qPrintable(s);
6104 for (int i=0; i<clientList.size(); ++i)
6106 //qDebug() << "Sending \""<<qPrintable (s)<<"\" to "<<qPrintable (clientList.at(i)->peerAddress().toString());
6107 clientList.at(i)->write (block);
6111 void VymModel::readData ()
6113 while (clientSocket->bytesAvailable() >=(int)sizeof(quint16) )
6116 qDebug() <<"readData bytesAvail="<<clientSocket->bytesAvailable();
6120 QDataStream in(clientSocket);
6121 in.setVersion(QDataStream::Qt_4_0);
6129 qDebug() << "VymModel::readData command="<<qPrintable (t);
6132 parseAtom (t,noErr,errMsg);
6138 void VymModel::displayNetworkError(QAbstractSocket::SocketError socketError)
6140 switch (socketError) {
6141 case QAbstractSocket::RemoteHostClosedError:
6143 case QAbstractSocket::HostNotFoundError:
6144 QMessageBox::information(NULL, vymName +" Network client",
6145 "The host was not found. Please check the "
6146 "host name and port settings.");
6148 case QAbstractSocket::ConnectionRefusedError:
6149 QMessageBox::information(NULL, vymName + " Network client",
6150 "The connection was refused by the peer. "
6151 "Make sure the fortune server is running, "
6152 "and check that the host name and port "
6153 "settings are correct.");
6156 QMessageBox::information(NULL, vymName + " Network client",
6157 QString("The following error occurred: %1.")
6158 .arg(clientSocket->errorString()));
6162 void VymModel::downloadImage (const QUrl &url, BranchItem *bi)
6164 if (!bi) bi=getSelectedBranch();
6167 qWarning ("VM::download bi==NULL");
6171 // FIXME-3 download img to tmpfile and delete after running script in mainWindow
6173 script += QString("selectID(\"%1\");").arg(bi->getUuid().toString());
6174 script += QString("loadImage(\"$TMPFILE\");");
6176 DownloadAgent *agent = new DownloadAgent(url);
6177 agent->setFinishedAction (this, script);
6178 connect (agent, SIGNAL (downloadFinished()), mainWindow, SLOT (downloadFinished()));
6179 QTimer::singleShot(0, agent, SLOT(execute()));
6182 void VymModel::selectMapSelectionColor()
6184 QColor col = QColorDialog::getColor( defLinkColor, NULL);
6185 setSelectionColor (col);
6188 void VymModel::setSelectionColorInt (QColor col)
6190 if ( !col.isValid() ) return;
6192 QString("setSelectionColor (\"%1\")").arg(mapEditor->getSelectionColor().name()),
6193 QString("setSelectionColor (\"%1\")").arg(col.name()),
6194 QString("Set color of selection box to %1").arg(col.name())
6197 mapEditor->setSelectionColor (col);
6200 void VymModel::emitSelectionChanged(const QItemSelection &newsel)
6202 emit (selectionChanged(newsel,newsel)); // needed e.g. to update geometry in editor
6206 void VymModel::emitSelectionChanged()
6208 QItemSelection newsel=selModel->selection();
6209 emitSelectionChanged (newsel);
6212 void VymModel::setSelectionColor(QColor col)
6214 if ( !col.isValid() ) return;
6215 setSelectionColorInt (col);
6218 QColor VymModel::getSelectionColor()
6220 return mapEditor->getSelectionColor();
6223 void VymModel::setHideTmpMode (TreeItem::HideTmpMode mode)
6226 for (int i=0;i<rootItem->branchCount();i++)
6227 rootItem->getBranchNum(i)->setHideTmp (mode);
6229 if (mode==TreeItem::HideExport)
6234 qApp->processEvents();
6237 //////////////////////////////////////////////
6238 // Selection related
6239 //////////////////////////////////////////////
6241 void VymModel::updateSelection(QItemSelection newsel,QItemSelection dsel)
6246 bool do_reposition=false;
6247 foreach (ix, dsel.indexes() )
6249 mi = static_cast<MapItem*>(ix.internalPointer());
6250 if (mi->isBranchLikeType() )
6251 do_reposition=do_reposition || ((BranchItem*)mi)->resetTmpUnscroll();
6252 if (mi->getType()==TreeItem::XLink)
6254 Link *li=((XLinkItem*)mi)->getLink();
6255 XLinkObj *xlo=li->getXLinkObj();
6257 xlo->setSelection (XLinkObj::Unselected);
6259 do_reposition=do_reposition || li->getBeginBranch()->resetTmpUnscroll();
6260 do_reposition=do_reposition || li->getEndBranch()->resetTmpUnscroll();
6264 foreach (ix, newsel.indexes() )
6266 mi = static_cast<MapItem*>(ix.internalPointer());
6267 if (mi->isBranchLikeType() )
6270 if (bi->hasScrolledParent() )
6276 if (mi->getType()==TreeItem::XLink)
6278 ((XLinkItem*)mi)->setSelection();
6280 // begin/end branches need to be tmp unscrolled
6281 Link *li=((XLinkItem*)mi)->getLink();
6282 bi=li->getBeginBranch();
6283 if (bi->hasScrolledParent() )
6288 bi=li->getEndBranch();
6289 if (bi->hasScrolledParent() )
6296 if ( do_reposition ) reposition();
6299 void VymModel::setSelectionModel (QItemSelectionModel *sm)
6304 QItemSelectionModel* VymModel::getSelectionModel()
6309 void VymModel::setSelectionBlocked (bool b)
6314 bool VymModel::isSelectionBlocked()
6316 return selectionBlocked;
6319 bool VymModel::select (const QString &s)
6321 if (s.isEmpty()) return false;
6322 TreeItem *ti=findBySelectString(s);
6323 if (ti) return select (index(ti));
6327 bool VymModel::selectID (const QString &s)
6329 if (s.isEmpty()) return false;
6330 TreeItem *ti=findUuid(QUuid(s));
6331 if (ti) return select (index(ti));
6335 bool VymModel::select (LinkableMapObj *lmo)
6337 QItemSelection oldsel=selModel->selection();
6340 return select (lmo->getTreeItem() );
6345 bool VymModel::selectToggle (TreeItem *ti)
6349 selModel->select ( index(ti), QItemSelectionModel::Toggle);
6350 //appendSelection(); // FIXME-4 selection history not implemented yet for multiselections
6356 bool VymModel::select (TreeItem *ti)
6359 return select (index(ti));
6364 bool VymModel::select (const QModelIndex &index)
6366 if (index.isValid() )
6368 TreeItem *ti=getItem (index);
6369 if (ti->isBranchLikeType() )
6370 ((BranchItem*)ti)->tmpUnscroll();
6372 selModel->select (index,QItemSelectionModel::ClearAndSelect );
6379 void VymModel::unselectAll ()
6381 unselect (selModel->selection() );
6384 void VymModel::unselect(QItemSelection desel)
6386 if (!desel.isEmpty())
6388 lastSelectString=getSelectString();
6389 selModel->clearSelection();
6393 bool VymModel::reselect()
6395 bool b=select (lastSelectString);
6399 bool VymModel::canSelectPrevious()
6401 if (currentSelection>0)
6407 bool VymModel::selectPrevious()
6409 keepSelectionHistory=true;
6411 while (currentSelection>0)
6414 TreeItem *ti=findID (selectionHistory.at(currentSelection));
6420 selectionHistory.removeAt (currentSelection);
6422 keepSelectionHistory=false;
6426 bool VymModel::canSelectNext()
6428 if (currentSelection < selectionHistory.count()-1 )
6434 bool VymModel::selectNext()
6436 keepSelectionHistory=true;
6438 while (currentSelection<selectionHistory.count()-1)
6441 TreeItem *ti=findID (selectionHistory.at(currentSelection));
6447 selectionHistory.removeAt (currentSelection);
6449 keepSelectionHistory=false;
6453 void VymModel::resetSelectionHistory()
6455 selectionHistory.clear();
6456 currentSelection=-1;
6457 keepSelectionHistory=false;
6461 void VymModel::appendSelection() // FIXME-4 history unable to cope with multiple selections
6464 TreeItem *ti=getSelectedItem();
6465 if (ti && !keepSelectionHistory)
6467 if (ti->isBranchLikeType())
6468 ((BranchItem*)ti)->setLastSelectedBranch();
6470 selectionHistory.append (id);
6471 currentSelection=selectionHistory.count()-1;
6476 void VymModel::emitShowSelection()
6478 if (!blockReposition) emit (showSelection() );
6481 void VymModel::emitNoteChanged (TreeItem *ti)
6483 QModelIndex ix=index(ti);
6484 emit (noteChanged (ix) );
6487 void VymModel::emitDataChanged (TreeItem *ti)
6489 QModelIndex ix=index(ti);
6490 emit ( dataChanged (ix,ix) );
6491 if (!blockReposition)
6493 if ( ti->isBranchLikeType() && ((BranchItem*)ti)->getTask() )
6495 taskModel->emitDataChanged ( ((BranchItem*)ti)->getTask() );
6496 taskModel->recalcPriorities();
6501 void VymModel::emitUpdateQueries ()
6503 // Used to tell MainWindow to update query results
6504 if (blockReposition) return;
6505 emit (updateQueries (this) );
6507 void VymModel::emitUpdateLayout()
6509 if (settings.value("/mainwindow/autoLayout/use","true")=="true")
6510 emit (updateLayout());
6513 bool VymModel::selectFirstBranch()
6515 TreeItem *ti=getSelectedBranch();
6518 TreeItem *par=ti->parent();
6521 TreeItem *ti2=par->getFirstBranch();
6522 if (ti2) return select(ti2);
6528 bool VymModel::selectLastBranch()
6530 TreeItem *ti=getSelectedBranch();
6533 TreeItem *par=ti->parent();
6536 TreeItem *ti2=par->getLastBranch();
6537 if (ti2) return select(ti2);
6543 bool VymModel::selectLastSelectedBranch()
6545 BranchItem *bi=getSelectedBranch();
6548 bi=bi->getLastSelectedBranch();
6549 if (bi) return select (bi);
6554 bool VymModel::selectLastImage()
6556 TreeItem *ti=getSelectedBranch();
6559 TreeItem *par=ti->parent();
6562 TreeItem *ti2=par->getLastImage();
6563 if (ti2) return select(ti2);
6569 bool VymModel::selectParent()
6571 TreeItem *ti=getSelectedItem();
6582 TreeItem::Type VymModel::selectionType()
6584 TreeItem *ti = getSelectedItem();
6586 return ti->getType();
6588 return TreeItem::Undefined;
6591 LinkableMapObj* VymModel::getSelectedLMO()
6593 QModelIndexList list=selModel->selectedIndexes();
6594 if (list.count()==1 )
6596 TreeItem *ti = getItem (list.first() );
6597 TreeItem::Type type=ti->getType();
6598 if (type ==TreeItem::Branch || type==TreeItem::MapCenter || type==TreeItem::Image)
6599 return ((MapItem*)ti)->getLMO();
6604 BranchObj* VymModel::getSelectedBranchObj() // convenience function
6606 TreeItem *ti = getSelectedBranch();
6608 return (BranchObj*)( ((MapItem*)ti)->getLMO());
6613 BranchItem* VymModel::getSelectedBranch()
6615 TreeItem *ti=getSelectedItem();
6618 TreeItem::Type type=ti->getType();
6619 if (type ==TreeItem::Branch || type==TreeItem::MapCenter)
6620 return (BranchItem*)ti;
6625 QList <BranchItem*> VymModel::getSelectedBranches()
6627 QList <BranchItem*> bis;
6628 foreach (TreeItem *ti,getSelectedItems() )
6630 TreeItem::Type type=ti->getType();
6631 if (type ==TreeItem::Branch || type==TreeItem::MapCenter)
6632 bis.append ( (BranchItem*)ti );
6637 ImageItem* VymModel::getSelectedImage()
6639 TreeItem *ti=getSelectedItem();
6640 if (ti && ti->getType()==TreeItem::Image)
6641 return (ImageItem*)ti;
6646 Task* VymModel::getSelectedTask()
6648 BranchItem *selbi=getSelectedBranch();
6650 return selbi->getTask();
6655 Link* VymModel::getSelectedXLink()
6657 XLinkItem *xli=getSelectedXLinkItem();
6658 if (xli) return xli->getLink();
6662 XLinkItem* VymModel::getSelectedXLinkItem()
6664 TreeItem *ti=getSelectedItem();
6665 if (ti && ti->getType()==TreeItem::XLink)
6666 return (XLinkItem*)ti;
6671 AttributeItem* VymModel::getSelectedAttribute()
6673 TreeItem *ti=getSelectedItem();
6674 if (ti && ti->getType()==TreeItem::Attribute)
6675 return (AttributeItem*)ti;
6680 TreeItem* VymModel::getSelectedItem()
6682 if (!selModel) return NULL;
6683 QModelIndexList list=selModel->selectedIndexes();
6684 if (list.count()==1 )
6685 return getItem (list.first() );
6690 QList <TreeItem*> VymModel::getSelectedItems()
6692 QList <TreeItem*> l;
6693 if (!selModel) return l;
6694 QModelIndexList list=selModel->selectedIndexes();
6695 foreach (QModelIndex ix,list)
6696 l.append (getItem (ix) );
6700 QModelIndex VymModel::getSelectedIndex()
6702 QModelIndexList list=selModel->selectedIndexes();
6703 if (list.count()==1 )
6704 return list.first();
6706 return QModelIndex();
6709 QList <uint> VymModel::getSelectedIDs()
6712 foreach (TreeItem* ti,getSelectedItems() )
6713 uids.append (ti->getID() );
6717 bool VymModel::isSelected(TreeItem *ti)
6719 return getSelectedItems().contains (ti);
6722 QString VymModel::getSelectString ()
6724 return getSelectString (getSelectedItem());
6727 QString VymModel::getSelectString (LinkableMapObj *lmo) // only for convenience. Used in MapEditor
6729 if (!lmo) return QString();
6730 return getSelectString (lmo->getTreeItem() );
6733 QString VymModel::getSelectString (TreeItem *ti)
6736 if (!ti || ti->depth()<0) return s;
6737 switch (ti->getType())
6739 case TreeItem::MapCenter: s="mc:"; break;
6740 case TreeItem::Branch: s="bo:";break;
6741 case TreeItem::Image: s="fi:";break;
6742 case TreeItem::Attribute: s="ai:";break;
6743 case TreeItem::XLink: s="xl:";break;
6745 s="unknown type in VymModel::getSelectString()";
6748 s= s + QString("%1").arg(ti->num());
6750 // call myself recursively
6751 s= getSelectString(ti->parent()) +","+s;
6755 QString VymModel::getSelectString (BranchItem *bi)
6757 return getSelectString ((TreeItem*)bi);
6760 QString VymModel::getSelectString (const uint &i)
6762 return getSelectString ( findID (i) );
6765 SlideModel* VymModel::getSlideModel()
6770 int VymModel::slideCount()
6772 return slideModel->count();
6775 SlideItem* VymModel::addSlide()
6777 SlideItem *si=slideModel->getSelectedItem();
6779 si=slideModel->addSlide (NULL,si->childNumber()+1 );
6781 si=slideModel->addSlide();
6783 TreeItem *seli=getSelectedItem();
6788 if (!loadStringFromDisk(macroPath + "slideeditor-snapshot.vys", inScript) )
6790 qWarning()<<"VymModel::addSlide couldn't load template for taking snapshot";
6794 inScript.replace("CURRENT_ZOOM", QString().setNum(getMapEditor()->getZoomFactorTarget()) );
6795 inScript.replace("CURRENT_ANGLE", QString().setNum(getMapEditor()->getAngleTarget()) );
6796 inScript.replace("CURRENT_ID", "\"" + seli->getUuid().toString() + "\"");
6798 si->setInScript(inScript);
6799 slideModel->setData ( slideModel->index(si), seli->getHeadingPlain() );
6801 QString s="<vymmap>" + si->saveToDir() + "</vymmap>";
6802 int pos=si->childNumber();
6805 getSelectString(), QString("deleteSlide (%1)").arg(pos),
6806 getSelectString(), QString("addMapInsert (\"PATH\",%1)").arg(pos),
6813 void VymModel::deleteSlide(SlideItem *si)
6817 QString s="<vymmap>" + si->saveToDir() + "</vymmap>";
6818 int pos=si->childNumber();
6821 getSelectString(), QString("addMapInsert (\"PATH\",%1)").arg(pos),
6822 getSelectString(), QString("deleteSlide (%1)").arg(pos),
6826 slideModel->deleteSlide (si);
6830 void VymModel::deleteSlide(int n)
6832 deleteSlide (slideModel->getSlide (n));
6835 void VymModel::relinkSlide(SlideItem *si, int pos)
6838 slideModel->relinkSlide (si, si->parent(), pos);
6841 void VymModel::moveSlideUp(int n)
6844 if (n<0) // default if called without parameters
6846 si=slideModel->getSelectedItem();
6847 if (si) n=si->childNumber();
6849 si=slideModel->getSlide(n);
6850 if (si && n>0 && n<slideModel->count())
6852 blockSlideSelection=true;
6853 slideModel->relinkSlide (si, si->parent(), n-1);
6854 blockSlideSelection=false;
6856 getSelectString(),QString("moveSlideDown (%1)").arg(n-1),
6857 getSelectString(),QString("moveSlideUp (%1)").arg(n),
6858 QString("Move slide %1 up").arg(n));
6862 void VymModel::moveSlideDown(int n)
6865 if (n<0) // default if called without parameters
6867 si=slideModel->getSelectedItem();
6868 if (si) n=si->childNumber();
6870 si=slideModel->getSlide(n);
6871 if (si && n>=0 && n < slideModel->count()-1)
6873 blockSlideSelection=true;
6874 slideModel->relinkSlide (si, si->parent(), n+1);
6875 blockSlideSelection=false;
6877 getSelectString(),QString("moveSlideUp (%1)").arg(n+1),
6878 getSelectString(),QString("moveSlideDown (%1)").arg(n),
6879 QString("Move slide %1 down").arg(n));
6883 void VymModel::updateSlideSelection (QItemSelection newsel,QItemSelection)
6885 if (blockSlideSelection) return;
6887 foreach (ix,newsel.indexes() )
6889 SlideItem *si= static_cast<SlideItem*>(ix.internalPointer());
6890 QString inScript=si->getInScript();
6892 // show inScript in ScriptEditor
6893 scriptEditor->setSlideScript(modelID, si->getID(), inScript );