Exemple #1
0
const QString&
CLArgs::getImageFilename() const
{
    if ( _imp->imageFilename.isEmpty() && !_imp->args.empty() ) {
        ///Check for image file passed to command line
        QStringList::iterator it = _imp->args.begin();
        // first argument is the program name, skip it
        ++it;
        for (; it != _imp->args.end(); ++it) {
            if ( !it->startsWith( QChar::fromLatin1('-') ) ) {
                QString fileCopy = *it;
                QString ext = QtCompat::removeFileExtension(fileCopy);
                if ( !ext.isEmpty() ) {
                    std::string readerId = appPTR->isImageFileSupportedByNatron( ext.toStdString() );
                    if ( !readerId.empty() ) {
                        _imp->imageFilename = *it;
                        _imp->args.erase(it);
                        break;
                    }
                }
            }
        }
    }

    return _imp->imageFilename;
}
void ComposerTextEdit::slotPasteAsQuotation()
{
    QString text = qApp->clipboard()->text();
    if (text.isEmpty())
        return;

    QStringList lines = text.split(QLatin1Char('\n'));
    for (QStringList::iterator it = lines.begin(); it != lines.end(); ++it) {
        it->remove(QLatin1Char('\r'));
        if (it->startsWith(QLatin1Char('>'))) {
            *it = QLatin1Char('>') + *it;
        } else {
            *it = QLatin1String("> ") + *it;
        }
    }
    text = lines.join(QStringLiteral("\n"));
    if (!text.endsWith(QLatin1Char('\n'))) {
        text += QLatin1Char('\n');
    }

    QTextCursor cursor = textCursor();
    cursor.beginEditBlock();
    cursor.insertBlock();
    cursor.insertText(text);
    cursor.endEditBlock();
    setTextCursor(cursor);
}
Exemple #3
0
int main( int argc, char *argv[] )
{
#ifdef _IS_UNIX_
  signal(SIGQUIT,onSigQuit);
  signal(SIGINT,onSigQuit);
#endif
  QApplication app( argc, argv );
  app.setWindowIcon( QIcon(":images/gmic_hat.png") );
  QCoreApplication::setOrganizationName("GREYC");
  QCoreApplication::setOrganizationDomain("greyc.fr");
  QCoreApplication::setApplicationName("ZArt");

  QStringList args = app.arguments();
  QStringList::iterator it = args.begin();
  while (it != args.end()) {
    if ( it->startsWith("-h") || it->startsWith("--help") ) {
      cout << "Usage:" << endl
           << "       "
           << QFileInfo(argv[0]).baseName().toLatin1().constData()
          << " [options]" << endl
          << "  " << "Options: " << endl
          << "      --help | -h   : print this help." << endl
          << endl;
      exit(EXIT_SUCCESS);
    }
    ++it;
  }
  QSplashScreen splashScreen(QPixmap(":/images/splash.png"));
  splashScreen.show();
  app.processEvents();
  WebcamSource::retrieveWebcamResolutions(WebcamSource::getWebcamList(),
                                          &splashScreen);
  if ( ! gmic::init_rc() ) {
    cerr << "[ZArt] Warning: Could not create resources directory.\n";
  }
  MainWindow mainWindow;
  mainWindow.show();
  splashScreen.finish(&mainWindow);
  return app.exec();
}
Exemple #4
0
void VideoScannerThread::SetDirs(QStringList dirs)
{
    QString master = gCoreContext->GetMasterHostName().toLower();
    QStringList searchhosts, mdirs;
    m_offlineSGHosts.clear();

    QStringList::iterator iter = dirs.begin(), iter2;
    while ( iter != dirs.end() )
    {
        if (iter->startsWith("myth://"))
        {
            QUrl sgurl = *iter;
            QString host = sgurl.host().toLower();
            QString path = sgurl.path();

            if (!m_liveSGHosts.contains(host))
            {
                // mark host as offline to warn user
                if (!m_offlineSGHosts.contains(host))
                    m_offlineSGHosts.append(host);
                // erase from directory list to skip scanning
                iter = dirs.erase(iter);
                continue;
            }
            else if ((host == master) &&  (!mdirs.contains(path)))
                // collect paths defined on master backend so other
                // online backends can be set to fall through to them
                mdirs.append(path);
            else if (!searchhosts.contains(host))
                // mark host as having directories defined so it
                // does not fall through to those on the master
                searchhosts.append(host);
        }

        ++iter;
    }

    for (iter = m_liveSGHosts.begin(); iter != m_liveSGHosts.end(); ++iter)
        if ((!searchhosts.contains(*iter)) && (master != *iter))
            for (iter2 = mdirs.begin(); iter2 != mdirs.end(); ++iter2)
                // backend is online, but has no directories listed
                // fall back to those on the master backend
                dirs.append(gCoreContext->GenMythURL(*iter,
                                            0, *iter2, "Videos"));

    m_directories = dirs;
}
EngineOption* XboardEngine::parseOption(const QString& line)
{
	int start = line.indexOf('-');
	if (start < 2)
		return 0;

	QString name(line.left(start - 1));

	start++;
	int end = line.indexOf(' ', start);
	if (end == -1)
		end = line.length();
	QString type(line.mid(start, end - start));

	if (type == "button" || type == "save")
		return new EngineButtonOption(name);
	if (type == "check")
	{
		bool value = line.mid(end + 1) == "1";
		return new EngineCheckOption(name, value, value);
	}
	if (type == "string" || type == "file" || type == "path")
	{
		QString value(line.mid(end + 1));
		EngineTextOption::EditorType editorType;

		if (type == "file")
			editorType = EngineTextOption::FileDialog;
		else if (type == "path")
			editorType = EngineTextOption::FolderDialog;
		else
			editorType = EngineTextOption::LineEdit;

		return new EngineTextOption(name, value, value, QString(), editorType);
	}
	if (type == "spin" || type == "slider")
	{
		QStringList params(line.mid(end + 1).split(' ', QString::SkipEmptyParts));
		if (params.size() != 3)
			return 0;

		bool ok = false;
		int value = params.at(0).toInt(&ok);
		if (!ok)
			return 0;

		int min = params.at(1).toInt(&ok);
		if (!ok || min > value)
			return 0;

		int max = params.at(2).toInt(&ok);
		if (!ok || max < value)
			return 0;

		return new EngineSpinOption(name, value, value, min, max);
	}
	if (type == "combo")
	{
		QStringList choices = line.mid(end + 1).split(" /// ", QString::SkipEmptyParts);
		if (choices.isEmpty())
			return 0;

		QString value;
		QStringList::iterator it;
		for (it = choices.begin(); it != choices.end(); ++it)
		{
			if (it->startsWith('*'))
			{
				it->remove(0, 1);
				value = *it;
			}
		}
		if (value.isEmpty())
			value = choices.first();

		return new EngineComboOption(name, value, value, choices);
	}

	return 0;
}
Exemple #6
0
int
main(int argc, char **argv)
{
    svSystemSpecificInitialisation();

#ifdef Q_WS_X11
#if QT_VERSION >= 0x040500
//    QApplication::setGraphicsSystem("raster");
#endif
#endif

#ifdef Q_OS_MAC
    if (QSysInfo::MacintoshVersion > QSysInfo::MV_10_8) {
        // Fix for OS/X 10.9 font problem
        QFont::insertSubstitution(".Lucida Grande UI", "Lucida Grande");
    }
#endif

    SVApplication application(argc, argv);

    QStringList args = application.arguments();

    signal(SIGINT,  signalHandler);
    signal(SIGTERM, signalHandler);

#ifndef Q_OS_WIN32
    signal(SIGHUP,  signalHandler);
    signal(SIGQUIT, signalHandler);
#endif

    bool audioOutput = true;
    bool oscSupport = true;

    if (args.contains("--help") || args.contains("-h") || args.contains("-?")) {
        cerr << QApplication::tr(
            "\nSonic Visualiser is a program for viewing and exploring audio data\nfor semantic music analysis and annotation.\n\nUsage:\n\n  %1 [--no-audio] [--no-osc] [<file> ...]\n\n  --no-audio: Do not attempt to open an audio output device\n  --no-osc: Do not provide an Open Sound Control port for remote control\n  <file>: One or more Sonic Visualiser (.sv) and audio files may be provided.\n").arg(argv[0]) << endl;
        exit(2);
    }

    if (args.contains("--no-audio")) audioOutput = false;
    if (args.contains("--no-osc")) oscSupport = false;

    QApplication::setOrganizationName("sonic-visualiser");
    QApplication::setOrganizationDomain("sonicvisualiser.org");
    QApplication::setApplicationName(QApplication::tr("Sonic Visualiser"));

    QSplashScreen *splash = 0;

    QSettings settings;

    settings.beginGroup("Preferences");
    if (settings.value("show-splash", true).toBool()) {
        QPixmap pixmap(":/icons/sv-splash.png");
        QPainter painter;
        painter.begin(&pixmap);
        QString text = QString("v%1").arg(SV_VERSION);
        painter.drawText
            (pixmap.width() - painter.fontMetrics().width(text) - 10,
             10 + painter.fontMetrics().ascent(),
             text);
        painter.end();
        splash = new QSplashScreen(pixmap);
        splash->show();
        QTimer::singleShot(5000, splash, SLOT(hide()));
        application.processEvents();
    }
    settings.endGroup();

    settings.beginGroup("RDF");
    if (!settings.contains("rdf-indices")) {
        QStringList list;
        list << "http://www.vamp-plugins.org/rdf/plugins/index.txt";
        settings.setValue("rdf-indices", list);
    }
    settings.endGroup();

    QIcon icon;
    int sizes[] = { 16, 22, 24, 32, 48, 64, 128 };
    for (int i = 0; i < int(sizeof(sizes)/sizeof(sizes[0])); ++i) {
        icon.addFile(QString(":icons/sv-%1x%2.png").arg(sizes[i]).arg(sizes[i]));
    }
    QApplication::setWindowIcon(icon);

    QString language = QLocale::system().name();

    settings.beginGroup("Preferences");
    language = settings.value("locale", language).toString();
    settings.endGroup();

    QTranslator qtTranslator;
    QString qtTrName = QString("qt_%1").arg(language);
    SVDEBUG << "Loading " << qtTrName << "... ";
    bool success = false;
    if (!(success = qtTranslator.load(qtTrName))) {
        QString qtDir = getenv("QTDIR");
        if (qtDir != "") {
            success = qtTranslator.load
                (qtTrName, QDir(qtDir).filePath("translations"));
        }
    }
    if (!success) {
        SVDEBUG << "Failed\nFailed to load Qt translation for locale" << endl;
    } else {
        cerr << "Done" << endl;
    }
    application.installTranslator(&qtTranslator);

    QTranslator svTranslator;
    QString svTrName = QString("sonic-visualiser_%1").arg(language);
    SVDEBUG << "Loading " << svTrName << "... ";
    svTranslator.load(svTrName, ":i18n");
    SVDEBUG << "Done" << endl;
    application.installTranslator(&svTranslator);

    StoreStartupLocale();

    // Permit size_t and PropertyName to be used as args in queued signal calls
    qRegisterMetaType<PropertyContainer::PropertyName>("PropertyContainer::PropertyName");

    MainWindow *gui = new MainWindow(audioOutput, oscSupport);
    application.setMainWindow(gui);
    InteractiveFileFinder::setParentWidget(gui);
    TransformUserConfigurator::setParentWidget(gui);
    if (splash) {
        QObject::connect(gui, SIGNAL(hideSplash()), splash, SLOT(hide()));
    }

    QDesktopWidget *desktop = QApplication::desktop();
    QRect available = desktop->availableGeometry();

    int width = (available.width() * 2) / 3;
    int height = available.height() / 2;
    if (height < 450) height = (available.height() * 2) / 3;
    if (width > height * 2) width = height * 2;

    settings.beginGroup("MainWindow");

    QSize size = settings.value("size", QSize(width, height)).toSize();
    gui->resizeConstrained(size);

    if (settings.contains("position")) {
        QRect prevrect(settings.value("position").toPoint(), size);
        if (!(available & prevrect).isEmpty()) {
            gui->move(prevrect.topLeft());
        }
    }

    if (settings.value("maximised", false).toBool()) {
        gui->setWindowState(Qt::WindowMaximized);
    }

    settings.endGroup();
    
    gui->show();

    // The MainWindow class seems to have trouble dealing with this if
    // it tries to adapt to this preference before the constructor is
    // complete.  As a lazy hack, apply it explicitly from here
    gui->preferenceChanged("Property Box Layout");

    application.m_readyForFiles = true; // Ready to receive files from e.g. Apple Events

    for (QStringList::iterator i = args.begin(); i != args.end(); ++i) {

        if (i == args.begin()) continue;
        if (i->startsWith('-')) continue;

        QString path = *i;

        application.handleFilepathArgument(path, splash);
    }
    
    for (QStringList::iterator i = application.m_filepathQueue.begin(); i != application.m_filepathQueue.end(); ++i) {
        QString path = *i;
        application.handleFilepathArgument(path, splash);
    }
    
#ifdef HAVE_FFTW3F
    settings.beginGroup("FFTWisdom");
    QString wisdom = settings.value("wisdom").toString();
    if (wisdom != "") {
        fftwf_import_wisdom_from_string(wisdom.toLocal8Bit().data());
    }
#ifdef HAVE_FFTW3
    wisdom = settings.value("wisdom_d").toString();
    if (wisdom != "") {
        fftw_import_wisdom_from_string(wisdom.toLocal8Bit().data());
    }
#endif
    settings.endGroup();
#endif

    if (splash) splash->finish(gui);
    delete splash;

/*
    TipDialog tipDialog;
    if (tipDialog.isOK()) {
        tipDialog.exec();
    }
*/
    int rv = application.exec();

    gui->hide();

    cleanupMutex.lock();

    if (!cleanedUp) {
        TransformFactory::deleteInstance();
        TempDirectory::getInstance()->cleanup();
        cleanedUp = true;
    }

    application.releaseMainWindow();

#ifdef HAVE_FFTW3F
    settings.beginGroup("FFTWisdom");
    char *cwisdom = fftwf_export_wisdom_to_string();
    if (cwisdom) {
        settings.setValue("wisdom", cwisdom);
        free(cwisdom);
    }
#ifdef HAVE_FFTW3
    cwisdom = fftw_export_wisdom_to_string();
    if (cwisdom) {
        settings.setValue("wisdom_d", cwisdom);
        free(cwisdom);
    }
#endif
    settings.endGroup();
#endif

    FileSource::debugReport();
    
    delete gui;

    cleanupMutex.unlock();

    return rv;
}
Exemple #7
0
MixxxLibraryFeature::MixxxLibraryFeature(QObject* parent,
                                         TrackCollection* pTrackCollection,
                                         ConfigObject<ConfigValue>* pConfig)
        : LibraryFeature(parent),
          kMissingTitle(tr("Missing Tracks")),
          kHiddenTitle(tr("Hidden Tracks")),
          m_pMissingView(NULL),
          m_pHiddenView(NULL),
          m_trackDao(pTrackCollection->getTrackDAO()),
          m_pConfig(pConfig),
          m_pTrackCollection(pTrackCollection) {
    QStringList columns;
    columns << "library." + LIBRARYTABLE_ID
            << "library." + LIBRARYTABLE_PLAYED
            << "library." + LIBRARYTABLE_TIMESPLAYED
            //has to be up here otherwise Played and TimesPlayed are not show
            << "library." + LIBRARYTABLE_ARTIST
            << "library." + LIBRARYTABLE_TITLE
            << "library." + LIBRARYTABLE_ALBUM
            << "library." + LIBRARYTABLE_ALBUMARTIST
            << "library." + LIBRARYTABLE_YEAR
            << "library." + LIBRARYTABLE_DURATION
            << "library." + LIBRARYTABLE_RATING
            << "library." + LIBRARYTABLE_GENRE
            << "library." + LIBRARYTABLE_COMPOSER
            << "library." + LIBRARYTABLE_GROUPING
            << "library." + LIBRARYTABLE_FILETYPE
            << "library." + LIBRARYTABLE_TRACKNUMBER
            << "library." + LIBRARYTABLE_KEY
            << "library." + LIBRARYTABLE_KEY_ID
            << "library." + LIBRARYTABLE_DATETIMEADDED
            << "library." + LIBRARYTABLE_BPM
            << "library." + LIBRARYTABLE_BPM_LOCK
            << "library." + LIBRARYTABLE_BITRATE
            << "track_locations.location"
            << "track_locations.fs_deleted"
            << "library." + LIBRARYTABLE_COMMENT
            << "library." + LIBRARYTABLE_MIXXXDELETED;

    QSqlQuery query(pTrackCollection->getDatabase());
    QString tableName = "library_cache_view";
    QString queryString = QString(
        "CREATE TEMPORARY VIEW IF NOT EXISTS %1 AS "
        "SELECT %2 FROM library "
        "INNER JOIN track_locations ON library.location = track_locations.id")
            .arg(tableName, columns.join(","));
    query.prepare(queryString);
    if (!query.exec()) {
        LOG_FAILED_QUERY(query);
    }

    // Strip out library. and track_locations.
    for (QStringList::iterator it = columns.begin();
         it != columns.end(); ++it) {
        if (it->startsWith("library.")) {
            *it = it->replace("library.", "");
        } else if (it->startsWith("track_locations.")) {
            *it = it->replace("track_locations.", "");
        }
    }

    BaseTrackCache* pBaseTrackCache = new BaseTrackCache(
        pTrackCollection, tableName, LIBRARYTABLE_ID, columns, true);
    connect(&m_trackDao, SIGNAL(trackDirty(int)),
            pBaseTrackCache, SLOT(slotTrackDirty(int)));
    connect(&m_trackDao, SIGNAL(trackClean(int)),
            pBaseTrackCache, SLOT(slotTrackClean(int)));
    connect(&m_trackDao, SIGNAL(trackChanged(int)),
            pBaseTrackCache, SLOT(slotTrackChanged(int)));
    connect(&m_trackDao, SIGNAL(tracksAdded(QSet<int>)),
            pBaseTrackCache, SLOT(slotTracksAdded(QSet<int>)));
    connect(&m_trackDao, SIGNAL(tracksRemoved(QSet<int>)),
            pBaseTrackCache, SLOT(slotTracksRemoved(QSet<int>)));
    connect(&m_trackDao, SIGNAL(dbTrackAdded(TrackPointer)),
            pBaseTrackCache, SLOT(slotDbTrackAdded(TrackPointer)));

    m_pBaseTrackCache = QSharedPointer<BaseTrackCache>(pBaseTrackCache);
    pTrackCollection->addTrackSource(QString("default"), m_pBaseTrackCache);

    // These rely on the 'default' track source being present.
    m_pLibraryTableModel = new LibraryTableModel(this, pTrackCollection);

    TreeItem* pRootItem = new TreeItem();
    TreeItem* pmissingChildItem = new TreeItem(kMissingTitle, kMissingTitle,
                                       this, pRootItem);
    TreeItem* phiddenChildItem = new TreeItem(kHiddenTitle, kHiddenTitle,
                                       this, pRootItem);
    pRootItem->appendChild(pmissingChildItem);
    pRootItem->appendChild(phiddenChildItem);

    m_childModel.setRootItem(pRootItem);
}
Exemple #8
0
void
CLArgsPrivate::parse()
{
    {
        QStringList::iterator it = hasToken( QString::fromUtf8("version"), QString::fromUtf8("v") );
        if ( it != args.end() ) {
            QString msg = QObject::tr("%1 version %2 at commit %3 on branch %4 built on %4").arg( QString::fromUtf8(NATRON_APPLICATION_NAME) ).arg( QString::fromUtf8(NATRON_VERSION_STRING) ).arg( QString::fromUtf8(GIT_COMMIT) ).arg( QString::fromUtf8(GIT_BRANCH) ).arg( QString::fromUtf8(__DATE__) );
            std::cout << msg.toStdString() << std::endl;
            error = 1;

            return;
        }
    }

    {
        QStringList::iterator it = hasToken( QString::fromUtf8("help"), QString::fromUtf8("h") );
        if ( it != args.end() ) {
            CLArgs::printUsage( args[0].toStdString() );
            error = 1;

            return;
        }
    }

    {
        QStringList::iterator it = hasToken( QString::fromUtf8("background"), QString::fromUtf8("b") );
        if ( it != args.end() ) {
            isBackground = true;
            args.erase(it);
        }
    }

    {
        QStringList::iterator it = hasToken( QString::fromUtf8("interpreter"), QString::fromUtf8("t") );
        if ( it != args.end() ) {
            isInterpreterMode = true;
            isBackground = true;
            std::cout << QObject::tr("Note: -t argument given, loading in command-line interpreter mode, only Python commands / scripts are accepted").toStdString()
                      << std::endl;
            args.erase(it);
        }
    }

    {
        QStringList::iterator it = hasToken( QString::fromUtf8("render-stats"), QString::fromUtf8("s") );
        if ( it != args.end() ) {
            enableRenderStats = true;
            args.erase(it);
        }
    }

    {
        QStringList::iterator it = hasToken( QString::fromUtf8(NATRON_BREAKPAD_PROCESS_PID), QString() );
        if ( it != args.end() ) {
            ++it;
            if ( it != args.end() ) {
                breakpadProcessPID = it->toLongLong();
                args.erase(it);
            } else {
                std::cout << QObject::tr("You must specify the breakpad process executable file path").toStdString() << std::endl;
                error = 1;

                return;
            }
        }
    }

    {
        QStringList::iterator it = hasToken( QString::fromUtf8(NATRON_BREAKPAD_PROCESS_EXEC), QString() );
        if ( it != args.end() ) {
            ++it;
            if ( it != args.end() ) {
                breakpadProcessFilePath = *it;
                args.erase(it);
            } else {
                std::cout << QObject::tr("You must specify the breakpad process executable file path").toStdString() << std::endl;
                error = 1;

                return;
            }
        }
    }

    {
        QStringList::iterator it = hasToken( QString::fromUtf8(NATRON_BREAKPAD_CLIENT_FD_ARG), QString() );
        if ( it != args.end() ) {
            ++it;
            if ( it != args.end() ) {
                breakpadPipeClientID = it->toInt();
                args.erase(it);
            } else {
                std::cout << QObject::tr("You must specify the breakpad pipe client FD").toStdString() << std::endl;
                error = 1;

                return;
            }
        }
    }

    {
        QStringList::iterator it = hasToken( QString::fromUtf8(NATRON_BREAKPAD_PIPE_ARG), QString() );
        if ( it != args.end() ) {
            ++it;
            if ( it != args.end() ) {
                breakpadPipeFilePath = *it;
                args.erase(it);
            } else {
                std::cout << QObject::tr("You must specify the breakpad pipe path").toStdString() << std::endl;
                error = 1;

                return;
            }
        }
    }

    {
        QStringList::iterator it = hasToken( QString::fromUtf8(NATRON_BREAKPAD_COM_PIPE_ARG), QString() );
        if ( it != args.end() ) {
            ++it;
            if ( it != args.end() ) {
                breakpadComPipeFilePath = *it;
                args.erase(it);
            } else {
                std::cout << QObject::tr("You must specify the breakpad communication pipe path").toStdString() << std::endl;
                error = 1;

                return;
            }
        }
    }

    {
        QStringList::iterator it = hasToken( QString::fromUtf8("export-docs"), QString() );
        if ( it != args.end() ) {
            ++it;
            if ( it != args.end() ) {
                exportDocsPath = *it;
                args.erase(it);
            } else {
                std::cout << QObject::tr("You must specify the doc dir path").toStdString() << std::endl;
                error = 1;

                return;
            }
        }
    }

    {
        QStringList::iterator it = hasToken( QString::fromUtf8("IPCpipe"), QString() );
        if ( it != args.end() ) {
            ++it;
            if ( it != args.end() ) {
                ipcPipe = *it;
                args.erase(it);
            } else {
                std::cout << QObject::tr("You must specify the IPC pipe filename").toStdString() << std::endl;
                error = 1;

                return;
            }
        }
    }

    {
        QStringList::iterator it = hasToken( QString::fromUtf8("onload"), QString::fromUtf8("l") );
        if ( it != args.end() ) {
            ++it;
            if ( it != args.end() ) {
                defaultOnProjectLoadedScript = *it;
#ifdef __NATRON_UNIX__
                defaultOnProjectLoadedScript = AppManager::qt_tildeExpansion(defaultOnProjectLoadedScript);
#endif
                QFileInfo fi(defaultOnProjectLoadedScript);
                if ( !fi.exists() ) {
                    std::cout << QObject::tr("WARNING: --onload %1 ignored because the file does not exist.").arg(defaultOnProjectLoadedScript).toStdString() << std::endl;
                    defaultOnProjectLoadedScript.clear();
                } else {
                    defaultOnProjectLoadedScript = fi.canonicalFilePath();
                }

                args.erase(it);
                if ( !defaultOnProjectLoadedScript.endsWith( QString::fromUtf8(".py") ) ) {
                    std::cout << QObject::tr("The optional on project load script must be a Python script (.py).").toStdString() << std::endl;
                    error = 1;

                    return;
                }
            } else {
                std::cout << QObject::tr("--onload or -l specified, you must enter a script filename afterwards.").toStdString() << std::endl;
                error = 1;

                return;
            }
        }
    }

    {
        QStringList::iterator it = findFileNameWithExtension( QString::fromUtf8(NATRON_PROJECT_FILE_EXT) );
        if ( it == args.end() ) {
            it = findFileNameWithExtension( QString::fromUtf8("py") );
            if ( ( it == args.end() ) && !isInterpreterMode && isBackground ) {
                std::cout << QObject::tr("You must specify the filename of a script or %1 project. (.%2)").arg( QString::fromUtf8(NATRON_APPLICATION_NAME) ).arg( QString::fromUtf8(NATRON_PROJECT_FILE_EXT) ).toStdString() << std::endl;
                error = 1;

                return;
            }
            isPythonScript = true;
        }
        if ( it != args.end() ) {
            filename = *it;
#ifdef __NATRON_UNIX__
            filename = AppManager::qt_tildeExpansion(filename);
#endif
            QFileInfo fi(filename);
            if ( fi.exists() ) {
                filename = fi.canonicalFilePath();
            }
            args.erase(it);
        }
    }

    //Parse frame range
    for (QStringList::iterator it = args.begin(); it != args.end(); ++it) {
        if ( tryParseMultipleFrameRanges(*it, frameRanges) ) {
            args.erase(it);
            rangeSet = true;
            break;
        }
    }

    //Parse python commands
    for (;; ) {
        QStringList::iterator it = hasToken( QString::fromUtf8("cmd"), QString::fromUtf8("c") );
        if ( it == args.end() ) {
            break;
        }

        if (!isBackground) {
            std::cout << QObject::tr("You cannot use the -c option in interactive mode").toStdString() << std::endl;
            error = 1;

            return;
        }

        QStringList::iterator next = it;
        if ( next != args.end() ) {
            ++next;
        }
        if ( next == args.end() ) {
            std::cout << QObject::tr("You must specify a command when using the -c option").toStdString() << std::endl;
            error = 1;

            return;
        }

        pythonCommands.push_back( next->toStdString() );

        ++next;
        args.erase(it, next);
    } // for (;;)

    //Parse writers
    for (;; ) {
        QStringList::iterator it = hasToken( QString::fromUtf8("writer"), QString::fromUtf8("w") );
        if ( it == args.end() ) {
            break;
        }

        if (!isBackground || isInterpreterMode) {
            std::cout << QObject::tr("You cannot use the -w option in interactive or interpreter mode").toStdString() << std::endl;
            error = 1;

            return;
        }

        QStringList::iterator next = it;
        if ( next != args.end() ) {
            ++next;
        }
        if ( next == args.end() ) {
            std::cout << QObject::tr("You must specify the name of a Write node when using the -w option").toStdString() << std::endl;
            error = 1;

            return;
        }


        //Check that the name is conform to a Python acceptable script name
        std::string pythonConform = NATRON_PYTHON_NAMESPACE::makeNameScriptFriendly( next->toStdString() );
        if (next->toStdString() != pythonConform) {
            std::cout << QObject::tr("The name of the Write node specified is not valid: it cannot contain non alpha-numerical "
                                     "characters and must not start with a digit.").toStdString() << std::endl;
            error = 1;

            return;
        }

        CLArgs::WriterArg w;
        w.name = *next;

        QStringList::iterator nextNext = next;
        if ( nextNext != args.end() ) {
            ++nextNext;
        }
        if ( nextNext != args.end() ) {
            //Check for an optional filename
            if ( !nextNext->startsWith( QChar::fromLatin1('-') ) && !nextNext->startsWith( QString::fromUtf8("--") ) ) {
                w.filename = *nextNext;
#ifdef __NATRON_UNIX__
                w.filename = AppManager::qt_tildeExpansion(w.filename);
#endif
            }
        }

        writers.push_back(w);
        if ( nextNext != args.end() ) {
            ++nextNext;
        }
        args.erase(it, nextNext);
    } // for (;;)


    //Parse readers
    for (;; ) {
        QStringList::iterator it = hasToken( QString::fromUtf8("reader"), QString::fromUtf8("i") );
        if ( it == args.end() ) {
            break;
        }

        if (!isBackground || isInterpreterMode) {
            std::cout << QObject::tr("You cannot use the -i option in interactive or interpreter mode").toStdString() << std::endl;
            error = 1;

            return;
        }

        QStringList::iterator next = it;
        if ( next != args.end() ) {
            ++next;
        }
        if ( next == args.end() ) {
            std::cout << QObject::tr("You must specify the name of a Read node when using the -i option").toStdString() << std::endl;
            error = 1;

            return;
        }


        //Check that the name is conform to a Python acceptable script name
        std::string pythonConform = NATRON_PYTHON_NAMESPACE::makeNameScriptFriendly( next->toStdString() );
        if (next->toStdString() != pythonConform) {
            std::cout << QObject::tr("The name of the Read node specified is not valid: it cannot contain non alpha-numerical "
                                     "characters and must not start with a digit.").toStdString() << std::endl;
            error = 1;

            return;
        }

        CLArgs::ReaderArg r;
        r.name = *next;

        QStringList::iterator nextNext = next;
        if ( nextNext != args.end() ) {
            ++nextNext;
        }
        if ( nextNext == args.end() ) {
            std::cout << QObject::tr("You must specify the filename for the following Read node: ").toStdString()  << r.name.toStdString() << std::endl;
            error = 1;

            return;
        }


        //Check for  filename
        if ( !nextNext->startsWith( QChar::fromLatin1('-') ) && !nextNext->startsWith( QString::fromUtf8("--") ) ) {
            r.filename = *nextNext;
#ifdef __NATRON_UNIX__
            r.filename = AppManager::qt_tildeExpansion(r.filename);
#endif
        } else {
            std::cout << QObject::tr("You must specify the filename for the following Read node: ").toStdString()  << r.name.toStdString() << std::endl;
            error = 1;

            return;
        }


        readers.push_back(r);
        if ( nextNext != args.end() ) {
            ++nextNext;
        }
        args.erase(it, nextNext);
    } // for (;;)

    bool atLeastOneOutput = false;
    ///Parse outputs
    for (;; ) {
        QString indexStr;
        QStringList::iterator it  = hasOutputToken(indexStr);
        if (error > 0) {
            return;
        }
        if ( it == args.end() ) {
            break;
        }

        if (!isBackground) {
            std::cout << QObject::tr("You cannot use the -o option in interactive or interpreter mode").toStdString() << std::endl;
            error = 1;

            return;
        }

        CLArgs::WriterArg w;
        w.name = QString( QString::fromUtf8("Output%1") ).arg(indexStr);
        w.mustCreate = true;
        atLeastOneOutput = true;

        //Check for a mandatory file name
        QStringList::iterator next = it;
        if ( next != args.end() ) {
            ++next;
        }
        if ( next == args.end() ) {
            std::cout << QObject::tr("Filename is not optional with the -o option").toStdString() << std::endl;
            error = 1;

            return;
        }

        //Check for an optional filename
        if ( !next->startsWith( QChar::fromLatin1('-') ) && !next->startsWith( QString::fromUtf8("--") ) ) {
            w.filename = *next;
        }

        writers.push_back(w);

        QStringList::iterator endToErase = next;
        ++endToErase;
        args.erase(it, endToErase);
    }

    if (atLeastOneOutput && !rangeSet) {
        std::cout << QObject::tr("A frame range must be set when using the -o option").toStdString() << std::endl;
        error = 1;

        return;
    }
} // CLArgsPrivate::parse
bool TWScript::doParseHeader(const QString& beginComment, const QString& endComment,
							 const QString& Comment, bool skipEmpty /* = true */)
{
	QFile file(m_Filename);
	QStringList lines;
	QString line;
	bool codecChanged = true;
	bool success = false;
	QTextCodec* codec;

	if (!file.exists() || !file.open(QIODevice::ReadOnly))
		return false;
	
	m_Codec = QTextCodec::codecForName("UTF-8");
	if (!m_Codec)
		m_Codec = QTextCodec::codecForLocale();

	while (codecChanged) {
		codec = m_Codec;
		file.seek(0);
		lines = codec->toUnicode(file.readAll()).split(QRegExp("\r\n|[\n\r]"));
	
		// skip any empty lines
		if (skipEmpty) {
			while (!lines.isEmpty() && lines.first().isEmpty())
				lines.removeFirst();
		}
		if (lines.isEmpty())
			break;
	
		// is this a valid TW script?
		line = lines.takeFirst();
		if (!beginComment.isEmpty()) {
			if (!line.startsWith(beginComment))
				break;
			line = line.mid(beginComment.size()).trimmed();
		}
		else if (!Comment.isEmpty()) {
			if (!line.startsWith(Comment))
				break;
			line = line.mid(Comment.size()).trimmed();
		}
		if (!line.startsWith("TeXworksScript"))
			break;
	
		// scan to find the extent of the header lines
		QStringList::iterator i;
		for (i = lines.begin(); i != lines.end(); ++i) {
			// have we reached the end?
			if (skipEmpty && i->isEmpty()) {
				i = lines.erase(i);
				--i;
				continue;
			}
			if (!endComment.isEmpty()) {
				if (i->startsWith(endComment))
					break;
			}
			if (!i->startsWith(Comment))
				break;
			*i = i->mid(Comment.size()).trimmed();
		}
		lines.erase(i, lines.end());
		
		codecChanged = false;
		switch (doParseHeader(lines)) {
			case ParseHeader_OK:
				success = true;
				break;
			case ParseHeader_Failed:
				success = false;
				break;
			case ParseHeader_CodecChanged:
				codecChanged = true;
				break;
		}
	}
	
	file.close();
	return success;
}