11 #include "vymprocess.h"
13 #if defined(Q_OS_WIN32)
18 #if defined(Q_OS_MACX)
24 extern QString zipToolPath;
26 QString convertToRel (const QString &src, const QString &dst)
28 // Creates a relative path pointing from src to dst
36 // Special case, we just need the name of the file,
37 // not the complete path
38 i=d.lastIndexOf ("/");
39 d=d.right (d.length()-i-1);
42 // remove identical left parts
43 while (s.section("/",0,0) == d.section("/",0,0) )
46 s=s.right (s.length()-i-1);
47 d=d.right (d.length()-i-1);
50 // Now take care of paths where we have to go back first
51 int srcsep=s.count("/");
61 QString convertToAbs (const QString &src, const QString &dst)
63 // Creates a relative path pointing from src to dst
65 return dd.absoluteFilePath(dst);
69 QString basename(const QString &path)
71 return path.section ('/', -1);
74 QString dirname(const QString &path)
76 return path.section('/', 0, -2);
79 extern QString vymName;
80 bool reallyWriteDirectory(const QString &dir)
82 QStringList eList = QDir(dir).entryList();
83 if (eList.first() ==".") eList.pop_front(); // remove "."
84 if (eList.first() =="..") eList.pop_front(); // remove "."
87 QMessageBox mb( vymName,
88 QObject::tr("The directory %1 is not empty.\nDo you risk to overwrite its contents?","write directory").arg(dir),
91 QMessageBox::Cancel | QMessageBox::Default,
92 QMessageBox::NoButton );
94 mb.setButtonText( QMessageBox::Yes, QObject::tr("Overwrite") );
95 mb.setButtonText( QMessageBox::No, QObject::tr("Cancel"));
98 case QMessageBox::Yes:
101 case QMessageBox::Cancel:
109 QString makeTmpDir (bool &ok, QString prefix) //FIXME-3 use QTemporaryDir
112 QString path=makeUniqueDir (b,QDir::tempPath()+"/"+prefix+"-XXXXXX");
117 bool isInTmpDir(QString fn)
119 QString temp=QDir::tempPath();
121 return fn.left(l)==temp;
124 QString makeUniqueDir (bool &ok,QString s)
130 #if defined(Q_OS_WIN32)
133 // On Linux and friends use cstdlib
135 // Convert QString to string
138 int bytes=s.length();
139 p=(char*) malloc (bytes+1);
141 for (i=0;i<bytes;i++)
142 p[i]=s.at(i).unicode();
149 if (r.isEmpty()) ok=false;
153 void removeDir(QDir d)
155 // This check should_ not be necessary, but proved to be useful ;-)
156 if (!isInTmpDir(d.path()))
158 qWarning ()<<"file.cpp::removeDir should remove " + d.path() + " - aborted.";
162 // Traverse directories
163 d.setFilter( QDir::Dirs| QDir::Hidden | QDir::NoSymLinks );
164 QFileInfoList list = d.entryInfoList();
167 for (int i = 0; i < list.size(); ++i)
170 if (fi.fileName() != "." && fi.fileName() != ".." )
172 if ( !d.cd(fi.fileName()) )
173 qWarning ()<<"removeDir() cannot find the directory "+fi.fileName();
176 // Recursively remove subdirs
184 d.setFilter( QDir::Files| QDir::Hidden | QDir::NoSymLinks );
185 list = d.entryInfoList();
187 for (int i = 0; i < list.size(); ++i)
190 QFile (fi.filePath()).remove();
193 QString dirName = d.dirName();
195 if (!d.rmdir(dirName))
196 qWarning ()<< "removeDir(" + dirName + ") failed!";
199 bool copyDir (QDir src, QDir dst, const bool &override)
201 QStringList dirs = src.entryList(QDir::AllDirs | QDir::Hidden | QDir::NoDotAndDotDot);
202 QStringList files = src.entryList(QDir::Files );
204 // Check if dst is a subdir of src, which would cause endless recursion...
205 if (dst.absolutePath().contains(src.absolutePath())) return false;
207 // Traverse directories
208 QList<QString>::iterator d,f;
209 for (d = dirs.begin(); d != dirs.end(); ++d)
211 if (!QFileInfo(src.path() + "/" + (*d)).isDir()) continue;
213 QDir cdir(dst.path() + "/" + (*d));
214 cdir.mkpath(cdir.path());
216 if (!copyDir (QDir(src.path() + "/" + (*d)), QDir(dst.path() + "/" + (*d)), override))
221 for (f = files.begin(); f != files.end(); ++f)
223 QFile cfile(src.path() + "/" + (*f));
224 QFile destFile(dst.path()+ "/" + src.relativeFilePath(cfile.fileName()));
225 if (destFile.exists() && override)
228 if (!cfile.copy(dst.path() + "/" + src.relativeFilePath(cfile.fileName())))
234 void makeSubDirs (const QString &s)
242 ErrorCode zipDir ( QDir zipInputDir, QString zipName)
244 zipName = QDir::toNativeSeparators(zipName);
245 ErrorCode err = Success;
247 QString symLinkTarget;
250 // Move existing file away
254 symLinkTarget = file.symLinkTarget();
255 newName = zipName + ".tmp";
257 while (!file.rename (newName) && n < 5)
259 newName = newName + QString().setNum(n);
264 QMessageBox::critical( 0, QObject::tr( "Critical Error" ),
265 QObject::tr("Couldn't move existing file out of the way before saving."));
270 // zip the temporary directory
271 VymProcess *zipProc=new VymProcess ();
274 #if defined(Q_OS_WIN32)
275 zipProc->setWorkingDirectory (QDir::toNativeSeparators(zipInputDir.path() + "\\") );
276 args << "a" << zipName << "-tzip" << "-scsUTF-8" << "*";
277 zipProc->start(zipToolPath, args);
279 if (!zipProc->waitForStarted())
281 QMessageBox::critical( 0, QObject::tr( "Critical Error" ),
282 QObject::tr("Couldn't start tool to decompress data."));
286 while(zipProc->state()!=QProcess::NotRunning){
287 zipProc->waitForReadyRead();
288 result = zipProc->readAll();
291 if (!zipProc->waitForStarted() )
293 // zip could not be started
294 QMessageBox::critical( 0, QObject::tr( "Critical Error" ),
295 QObject::tr("Couldn't start zip to compress data."));
299 // zip could be started
300 zipProc->waitForFinished();
301 if (zipProc->exitStatus()!=QProcess::NormalExit )
303 QMessageBox::critical( 0, QObject::tr( "Critical Error" ),
304 QObject::tr("zip didn't exit normally")+
305 "\n" + zipProc->getErrout());
309 if (zipProc->exitCode()>0)
311 QMessageBox::critical( 0, QObject::tr( "Critical Error" ),
312 QString("zip exit code: %1").arg(zipProc->exitCode() )+
313 "\n" + zipProc->getErrout() );
318 // qDebug() <<"Output: " << zipProc->getStdout()<<flush;
320 zipProc->setWorkingDirectory (QDir::toNativeSeparators(zipInputDir.path() ));
325 zipProc->start ("zip",args);
326 if (!zipProc->waitForStarted() )
328 // zip could not be started
329 QMessageBox::critical( 0, QObject::tr( "Critical Error" ),
330 QObject::tr("Couldn't start zip to compress data."));
334 // zip could be started
335 zipProc->waitForFinished();
336 if (zipProc->exitStatus()!=QProcess::NormalExit )
338 QMessageBox::critical( 0, QObject::tr( "Critical Error" ),
339 QObject::tr("zip didn't exit normally")+
340 "\n" + zipProc->getErrout());
344 if (zipProc->exitCode()>0)
346 QMessageBox::critical( 0, QObject::tr( "Critical Error" ),
347 QString("zip exit code: %1").arg(zipProc->exitCode() )+
348 "\n" + zipProc->getErrout() );
354 // Try to restore previous file, if zipping failed
355 if (err == Aborted && !newName.isEmpty() && !file.rename (zipName) )
356 QMessageBox::critical( 0, QObject::tr( "Critical Error" ),
357 QObject::tr("Couldn't rename %1 back to %2").arg(newName).arg(zipName) );
360 // Take care of symbolic link
361 if (!symLinkTarget.isEmpty() )
363 if (!QFile(symLinkTarget).remove() )
365 QMessageBox::critical( 0, QObject::tr( "Critical Error" ),
366 QObject::tr("Couldn't remove target of old symbolic link %1").arg(symLinkTarget));
371 if (!QFile(zipName).rename(symLinkTarget) )
373 QMessageBox::critical( 0, QObject::tr( "Critical Error" ),
374 QObject::tr("Couldn't rename output to target of old symbolic link %1").arg(symLinkTarget));
378 if (!QFile(symLinkTarget).link(zipName) )
380 QMessageBox::critical( 0, QObject::tr( "Critical Error" ),
381 QObject::tr("Couldn't link from %1 to target of old symbolic link %2").arg(zipName).arg(symLinkTarget));
387 // Remove temporary file
388 if (!newName.isEmpty() && !file.remove() )
389 QMessageBox::critical( 0, QObject::tr( "Critical Error" ),
390 QObject::tr("Saved %1, but couldn't remove %2").arg(zipName).arg(newName));
396 File::ErrorCode unzipDir ( QDir zipOutputDir, QString zipName)
398 ErrorCode err=Success;
400 VymProcess *zipProc = new VymProcess ();
403 #if defined(Q_OS_WIN32)
404 zipProc->setWorkingDirectory (QDir::toNativeSeparators(zipOutputDir.path() + "\\") );
405 args << "-o" + zipOutputDir.path() << "x" << zipName.toUtf8() << "-scsUTF-8";
406 zipProc->start(zipToolPath, args);
408 if (!zipProc->waitForStarted())
410 QMessageBox::critical( 0, QObject::tr( "Critical Error" ),
411 QObject::tr("Couldn't start tool to decompress data."));
415 while(zipProc->state()!=QProcess::NotRunning){
416 zipProc->waitForReadyRead();
417 result = zipProc->readAll();
418 //qDebug() << result << flush;
420 //qDebug() << zipProc->getStdout()<<flush;
422 zipProc->setWorkingDirectory (QDir::toNativeSeparators(zipOutputDir.path()));
423 args << "-o"; // overwrite existing files!
426 args << zipOutputDir.path();
428 zipProc->start ("unzip",args);
430 if (!zipProc->waitForStarted() )
432 QMessageBox::critical( 0, QObject::tr( "Critical Error" ),
433 QObject::tr("Couldn't start %1 to decompress data.").arg(zipToolPath));
439 zipProc->waitForFinished();
440 if (zipProc->exitStatus()!=QProcess::NormalExit )
442 QMessageBox::critical( 0,QObject::tr( "Critical Error" ),
443 QObject::tr("%1 didn't exit normally").arg(zipToolPath) +
444 zipProc->getErrout() );
448 if (zipProc->exitCode()>0)
450 if (zipProc->exitCode()==9)
451 // no zipped file, but maybe .xml or old version? Try again.
455 QMessageBox::critical( 0, QObject::tr( "Critical Error" ),
456 QString("%1 exit code: %2").arg(zipToolPath).arg(zipProc->exitCode() ) +
457 zipProc->getErrout() );
466 bool loadStringFromDisk (const QString &fname, QString &s)
470 if (!file.open(QFile::ReadOnly | QFile::Text)) {
471 qWarning()<<QString("loadStringFromDisk: Cannot read file %1\n%2")
473 .arg(file.errorString());
477 QTextStream in(&file);
482 bool saveStringToDisk (const QString &fname, const QString &s)
485 // Write as binary (default), QFile::Text would convert linebreaks
486 if (!file.open(QFile::WriteOnly )) {
487 qWarning()<<QString("saveStringToDisk: Cannot write file %1:\n%2.")
489 .arg(file.errorString());
493 QTextStream out(&file);
494 out.setCodec("UTF-8");
500 FileType getMapType (const QString &fn)
502 int i=fn.lastIndexOf(".");
505 QString postfix=fn.mid(i+1);
506 if (postfix=="vym" || postfix=="vyp" || postfix=="xml") return VymMap;
507 if (postfix=="mm") return FreemindMap;
514 // Create list with supported image types
515 // foreach (QByteArray format, QImageWriter::supportedImageFormats())
516 // imageTypes.append( tr("%1...").arg(QString(format).toUpper()));
517 imageFilters.append ("Images (*.png *.jpg *.jpeg *.bmp *.bmp *.ppm *.xpm *.xbm)");
518 imageTypes.append ("PNG");
519 imageFilters.append ("Portable Network Graphics (*.png)");
520 imageTypes.append ("PNG");
521 imageFilters.append ("Joint Photographic Experts Group (*.jpg)");
522 imageTypes.append ("JPG");
523 imageFilters.append ("Joint Photographic Experts Group (*.jpeg)");
524 imageTypes.append ("JPG");
525 imageFilters.append ("Windows Bitmap (*.bmp)");
526 imageTypes.append ("BMP");
527 imageFilters.append ("Portable Pixmap (*.ppm)");
528 imageTypes.append ("PPM");
529 imageFilters.append ("X11 Bitmap (*.xpm)");
530 imageTypes.append ("XPM");
531 imageFilters.append ("X11 Bitmap (*.xbm)");
532 imageTypes.append ("XBM");
535 QStringList ImageIO::getFilters()
540 QString ImageIO::getType(QString filter)
542 for (int i=0;i<imageFilters.count()+1;i++)
543 if (imageFilters.at(i)==filter) return imageTypes.at(i);
547 QString ImageIO::guessType(QString fn)
549 int i=fn.lastIndexOf(".");
552 QString postfix=fn.mid(i+1);
553 for (int i=1;i<imageFilters.count();i++)
554 if (imageFilters.at(i).contains(postfix)) return imageTypes.at(i);