--- /dev/null
+#include <QDir>
+#include <QMessageBox>
+#include <QPixmap>
+#include <QLabel>
+#include <QTextStream>
+#include <iostream>
+#include <QUrl>
+
+#include "file.h"
+#include "process.h"
+
+#if defined(Q_OS_WIN32)
+#include "mkdtemp.h"
+#include <windows.h>
+#endif
+
+QString maskPath(QString p)
+{
+ // Change " " to "\ " to enable blanks in filenames
+ p=p.replace(QChar('&'),"\\&");
+ return p.replace(QChar(' '),"\\ ");
+}
+
+QString convertToRel (const QString &src, const QString &dst)
+{
+ QString s=src;
+ QString d=dst;
+ int i;
+
+ if (s==d)
+ {
+ // Special case, we just need the name of the file,
+ // not the complete path
+ i=d.findRev ("/");
+ d=d.right (d.length()-i-1);
+ } else
+ {
+ // Find relative path from src to dst
+
+ // Remove the first "/"
+ if (s.section ("/",0,0).isEmpty())
+ {
+ s=s.right (s.length()-1);
+ d=d.right (d.length()-1);
+ }
+
+ // remove identical left parts
+ while (s.section("/",0,0) == d.section("/",0,0) )
+ {
+ i=s.find ("/");
+ s=s.right (s.length()-i-1);
+ d=d.right (d.length()-i-1);
+ }
+
+ // Now take care of paths where we have to go back first
+ int srcsep=s.count("/");
+ int dstsep=d.count("/");
+ if (srcsep <= dstsep )
+ {
+ // find path to go up first and then back to dst
+ i=1;
+ while (i<=srcsep)
+ {
+ d="../"+d;
+ i++;
+ }
+ }
+ }
+ return d;
+}
+
+#include <QFileDialog>
+extern QString vymName;
+extern QDir lastFileDir;
+
+QString browseDirectory (QWidget *parent,const QString &caption)
+{
+ QFileDialog fd(parent,caption);
+ fd.setMode (QFileDialog::DirectoryOnly);
+ fd.setCaption(vymName+ " - "+caption);
+ fd.setDir (lastFileDir);
+ fd.show();
+
+ if ( fd.exec() == QDialog::Accepted )
+ return fd.selectedFile();
+ else
+ return "";
+}
+
+
+
+bool reallyWriteDirectory(const QString &dir)
+{
+ QStringList eList = QDir(dir).entryList();
+ if (eList.first() ==".") eList.pop_front(); // remove "."
+ if (eList.first() =="..") eList.pop_front(); // remove "."
+ if (!eList.isEmpty())
+ {
+ QMessageBox mb( vymName,
+ QObject::tr("The directory %1 is not empty.\nDo you risk to overwrite its contents?","write directory").arg(dir),
+ QMessageBox::Warning,
+ QMessageBox::Yes ,
+ QMessageBox::Cancel | QMessageBox::Default,
+ QMessageBox::NoButton );
+
+ mb.setButtonText( QMessageBox::Yes, QObject::tr("Overwrite") );
+ mb.setButtonText( QMessageBox::No, QObject::tr("Cancel"));
+ switch( mb.exec() )
+ {
+ case QMessageBox::Yes:
+ // save
+ return true;
+ case QMessageBox::Cancel:
+ // do nothing
+ return false;
+ }
+ }
+ return true;
+}
+
+QString makeTmpDir (bool &ok, QString prefix)
+{
+ bool b;
+ QString path=makeUniqueDir (b,QDir::tempPath()+"/"+prefix+"-XXXXXX");
+ ok=b;
+ return path;
+}
+
+bool isInTmpDir(QString fn)
+{
+ QString temp=QDir::tempPath();
+ int l=temp.length();
+ return fn.left(l)==temp;
+}
+
+QString makeUniqueDir (bool &ok,QString s)
+{
+ // Create unique directory e.g. for s="/tmp/vym-XXXXXX"
+
+ // Convert Separators
+ s=QDir::convertSeparators(s);
+
+ // Convert QString to string
+ ok=true;
+ char *p;
+ int bytes=s.length();
+ p=(char*) malloc (bytes+1);
+ int i;
+ for (i=0;i<bytes;i++)
+ p[i]=s.at(i).latin1();
+ p[bytes]=0;
+
+ QString r=mkdtemp (p);
+ if (r.isEmpty()) ok=false;
+ free (p);
+ return r;
+}
+
+void removeDir(QDir d)
+{
+ // This check should_ not be necessary, but proved to be useful ;-)
+ if (!isInTmpDir(d.path()))
+ {
+ qWarning ("file.cpp::removeDir should remove "+d.path()+" - aborted.");
+ return;
+ }
+
+ // Traverse directories
+ d.setFilter( QDir::Dirs| QDir::Hidden | QDir::NoSymLinks );
+ QFileInfoList list = d.entryInfoList();
+ QFileInfo fi;
+
+ for (int i = 0; i < list.size(); ++i)
+ {
+ fi=list.at(i);
+ if (fi.fileName() != "." && fi.fileName() != ".." )
+ {
+ if ( !d.cd(fi.fileName()) )
+ qWarning ("removeDir() cannot find the directory "+fi.fileName());
+ else
+ {
+ // Recursively remove subdirs
+ removeDir (d);
+ d.cdUp();
+ }
+ }
+ }
+
+ // Traverse files
+ d.setFilter( QDir::Files| QDir::Hidden | QDir::NoSymLinks );
+ list = d.entryInfoList();
+
+ for (int i = 0; i < list.size(); ++i)
+ {
+ fi=list.at(i);
+ QFile (fi.filePath()).remove();
+ }
+
+ if (!d.rmdir(d.path()))
+ qWarning ("removeDir("+d.path()+") failed!");
+}
+
+void copyDir (QDir src, QDir dst)
+{
+ system ("cp -r "+src.path()+"/* "+dst.path());
+
+ /*
+ ErrorCode err=success;
+
+ Process *cpProc=new Process ();
+ QStringList args;
+ cpProc->setWorkingDirectory (src.path());
+ args <<"-r";
+ args <<src.path();
+ args <<dst.path();
+
+ cpProc->start ("cp",args);
+ if (!cpProc->waitForStarted() )
+ {
+ // zip could not be started
+ QMessageBox::critical( 0, QObject::tr( "Critical Error" ),
+ QObject::tr("Couldn't start zip to compress data."));
+ err=aborted;
+ } else
+ {
+ // zip could be started
+ cpProc->waitForFinished();
+ if (cpProc->exitStatus()!=QProcess::NormalExit )
+ {
+ QMessageBox::critical( 0, QObject::tr( "Critical Error" ),
+ QObject::tr("cp didn't exit normally")+
+ "\n" + cpProc->getErrout());
+ err=aborted;
+ } else
+ {
+ if (cpProc->exitCode()>0)
+ {
+ QMessageBox::critical( 0, QObject::tr( "Critical Error" ),
+ QString("cp exit code: %1").arg(cpProc->exitCode() )+
+ "\n" + cpProc->getErrout() );
+ err=aborted;
+ }
+ }
+ } // cp could be started
+ */
+}
+
+void makeSubDirs (const QString &s)
+{
+ QDir d(s);
+ d.mkdir(s);
+ d.mkdir ("images");
+ d.mkdir ("flags");
+}
+
+ErrorCode zipDir (const QDir &zipDir, const QString &zipName)
+{
+ ErrorCode err=success;
+
+ // zip the temporary directory
+ QStringList args;
+ Process *zipProc=new Process ();
+ zipProc->setWorkingDirectory (zipDir.path());
+ args <<"-r";
+ args <<zipName;
+ args <<".";
+
+ zipProc->start ("zip",args);
+ if (!zipProc->waitForStarted() )
+ {
+ // zip could not be started
+ QMessageBox::critical( 0, QObject::tr( "Critical Error" ),
+ QObject::tr("Couldn't start zip to compress data."));
+ err=aborted;
+ } else
+ {
+ // zip could be started
+ zipProc->waitForFinished();
+ if (zipProc->exitStatus()!=QProcess::NormalExit )
+ {
+ QMessageBox::critical( 0, QObject::tr( "Critical Error" ),
+ QObject::tr("zip didn't exit normally")+
+ "\n" + zipProc->getErrout());
+ err=aborted;
+ } else
+ {
+ if (zipProc->exitCode()>0)
+ {
+ QMessageBox::critical( 0, QObject::tr( "Critical Error" ),
+ QString("zip exit code: %1").arg(zipProc->exitCode() )+
+ "\n" + zipProc->getErrout() );
+ err=aborted;
+ }
+ }
+ } // zip could be started
+ return err;
+}
+
+ErrorCode unzipDir (const QDir &zipDir, const QString &zipName)
+{
+ ErrorCode err=success;
+
+ // Try to unzip file
+#if !defined(Q_OS_WIN32)
+ QStringList args;
+ Process *zipProc=new Process ();
+ zipProc->setWorkingDirectory (zipDir.path());
+ args << "-o"; // overwrite existing files!
+ args << zipName ;
+ args << "-d";
+ args << zipDir.path();
+
+ zipProc->start ("unzip",args);
+ if (!zipProc->waitForStarted() )
+ {
+ QMessageBox::critical( 0, QObject::tr( "Critical Error" ),
+ QObject::tr("Couldn't start unzip to decompress data."));
+ err=aborted;
+
+ } else
+ {
+ zipProc->waitForFinished();
+ if (zipProc->exitStatus()!=QProcess::NormalExit )
+ {
+ QMessageBox::critical( 0,QObject::tr( "Critical Error" ),
+ QObject::tr("unzip didn't exit normally") +
+ zipProc->getErrout() );
+ err=aborted;
+ } else
+ {
+ if (zipProc->exitCode()>0)
+ {
+ if (zipProc->exitCode()==9)
+ // no zipped file, but maybe .xml or old version? Try again.
+ err=nozip;
+ else
+ {
+ QMessageBox::critical( 0, QObject::tr( "Critical Error" ),
+ QString("unzip exit code: %1").arg(zipProc->exitCode() ) +
+ zipProc->getErrout() );
+ err=aborted;
+ }
+ }
+ }
+ }
+#else
+ // Do this process creation using Win32 API.
+ //! Create process.
+ PROCESS_INFORMATION piProcInfo;
+ STARTUPINFO siStartInfo;
+
+ // Initialize members of the PROCESS_INFORMATION structure.
+ ::ZeroMemory( &piProcInfo, sizeof(PROCESS_INFORMATION) );
+
+ // Set up members of the STARTUPINFO structure.
+ ::ZeroMemory( &siStartInfo, sizeof(STARTUPINFO) );
+ siStartInfo.cb = sizeof(STARTUPINFO);
+
+ // Create command line.
+ QString argv("unzip -o ");
+ argv.append(QDir::convertSeparators(zipName));
+ argv.append(" -d ");
+ argv.append(QDir::convertSeparators(zipDir.path()));
+
+ // Create the child process.
+ if( !::CreateProcess(NULL,
+ (LPWSTR)argv.unicode(), // command line
+ NULL, // process security attributes
+ NULL, // primary thread security attributes
+ TRUE, // handles are inherited
+ 0, // creation flags
+ NULL, // use parent's environment
+ NULL, // use parent's current directory
+ &siStartInfo, // STARTUPINFO pointer
+ &piProcInfo) ) // receives PROCESS_INFORMATION
+ {
+ err = aborted;
+ }
+ else
+ {
+ // Wait for it to finish.
+ ::WaitForSingleObject( piProcInfo.hProcess, 10000 );
+ }
+#endif
+ return err;
+}
+
+bool loadStringFromDisk (const QString &fname, QString &s)
+{
+ s="";
+ QFile file ( fname);
+ if ( !file.open( QIODevice::ReadOnly ) ) return false;
+
+ QTextStream ts( &file );
+ ts.setEncoding (QTextStream::UnicodeUTF8);
+ while ( !ts.atEnd() )
+ s+=ts.readLine()+"\n";
+ file.close();
+ return true;
+}
+
+bool saveStringToDisk (const QString &fname, const QString &s)
+{
+ QFile file( fname);
+
+ file.setName ( fname);
+ if ( !file.open( QIODevice::WriteOnly ) )
+ {
+ file.close();
+ return false;
+ }
+
+ // Write it finally, and write in UTF8, no matter what
+ QTextStream ts( &file );
+ ts.setEncoding (QTextStream::UnicodeUTF8);
+ ts << s;
+ file.close();
+ return true;
+}
+
+
+ImagePreview::ImagePreview (QWidget *par=0): QLabel (par)
+{
+ fdia=(QFileDialog*)par;
+}
+
+void ImagePreview::previewUrl( const QUrl &u )
+{
+ QString path = u.path();
+ QPixmap pix( path );
+ if ( pix.isNull() )
+ {
+ // Strange: If we have fd->setMode (QFileDialog::ExistingFiles)
+ // in the filedialog, then there are 3 calls to previewURL
+ // for each selection. And only the first is the actual selected file
+ // while the following 2 point to the directory above the current one.
+ // So here's my workaround:
+
+ if (fdia && fdia->selectedFiles().count()==0)
+ setText( QObject::tr("This is not an image.") );
+ if (fdia &&fdia->selectedFiles().count()>1)
+ setText( QObject::tr("Sorry, no preview for\nmultiple selected files.") );
+ }
+ else
+ {
+ float max_w=300;
+ float max_h=300;
+ float r;
+ if (pix.width()>max_w)
+ {
+ r=max_w / pix.width();
+ pix.resize(qRound(pix.width()*r), qRound(pix.height()*r));
+ // TODO not a resize, but a shrink/enlarge is needed here...
+ }
+ if (pix.height()>max_h)
+ {
+ r=max_h / pix.height();
+ pix.resize(qRound(pix.width()*r), qRound(pix.height()*r));
+ // TODO not a resize, but a shrink/enlarge is needed here...
+ }
+ setPixmap( pix );
+ }
+}
+
+ImageIO::ImageIO ()
+{
+ // Create list with supported image types
+ // foreach (QByteArray format, QImageWriter::supportedImageFormats())
+ // imageTypes.append( tr("%1...").arg(QString(format).toUpper()));
+ imageFilters.append ("Images (*.png *.jpg *.jpeg *.bmp *.bmp *.ppm *.xpm *.xbm)");
+ imageTypes.append ("PNG");
+ imageFilters.append ("Portable Network Graphics (*.png)");
+ imageTypes.append ("PNG");
+ imageFilters.append ("Joint Photographic Experts Group (*.jpg)");
+ imageTypes.append ("JPG");
+ imageFilters.append ("Joint Photographic Experts Group (*.jpeg)");
+ imageTypes.append ("JPG");
+ imageFilters.append ("Windows Bitmap (*.bmp)");
+ imageTypes.append ("BMP");
+ imageFilters.append ("Portable Pixmap (*.ppm)");
+ imageTypes.append ("PPM");
+ imageFilters.append ("X11 Bitmap (*.xpm)");
+ imageTypes.append ("XPM");
+ imageFilters.append ("X11 Bitmap (*.xbm)");
+ imageTypes.append ("XBM");
+}
+
+QStringList ImageIO::getFilters()
+{
+ return imageFilters;
+}
+
+QString ImageIO::getType(QString filter)
+{
+ for (int i=0;i<imageFilters.count()+1;i++)
+ if (imageFilters.at(i)==filter) return imageTypes.at(i);
+ return QString();
+}
+
+