Example #1
0
Q_DECL_EXPORT int main(int argc, char *argv[])
{
    QSettings *settings = new QSettings(QDir::homePath()+"/.config/thumbterm/settings.ini", QSettings::IniFormat);
    defaultSettings(settings);

    QCoreApplication::setApplicationName("Thumbterm");

    // fork the child process before creating QGuiApplication
    int socketM;
    int pid = forkpty(&socketM,NULL,NULL,NULL);
    if( pid==-1 ) {
        qFatal("forkpty failed");
        exit(1);
    } else if( pid==0 ) {
        setenv("TERM", settings->value("terminal/envVarTERM").toByteArray(), 1);

        QString execCmd;
        for(int i=0; i<argc-1; i++) {
            if( QString(argv[i]) == "-e" )
                execCmd = QString(argv[i+1]);
        }
        if(execCmd.isEmpty()) {
            execCmd = settings->value("gen/execCmd").toString();
        }
        if(execCmd.isEmpty()) {
            // Unset POSIXLY_CORRECT as having it set causes bash to start in POSIX mode (http://www.delorie.com/gnu/docs/bash/bashref_62.html#IDX214)
            // which causes it to not read the .bashrc on startup (http://lists.gnu.org/archive/html/bug-bash/2001-10/msg00117.html)
            unsetenv("POSIXLY_CORRECT");

            // execute the user's default shell
            passwd *pwdstruct = getpwuid(getuid());
            execCmd = QString(pwdstruct->pw_shell);
            execCmd.append(" --login");
        }

        if(settings)
            delete settings; // don't need 'em here

        QStringList execParts = execCmd.split(' ', QString::SkipEmptyParts);
        if(execParts.length()==0)
            exit(0);
        char *ptrs[execParts.length()+1];
        for(int i=0; i<execParts.length(); i++) {
            ptrs[i] = new char[execParts.at(i).toLatin1().length()+1];
            memcpy(ptrs[i], execParts.at(i).toLatin1().data(), execParts.at(i).toLatin1().length());
            ptrs[i][execParts.at(i).toLatin1().length()] = 0;
        }
        ptrs[execParts.length()] = 0;

        execvp(execParts.first().toLatin1(), ptrs);
        exit(0);
    }

    QGuiApplication app(argc, argv);
    QQuickWindow::setDefaultAlphaBuffer(true);

    QScreen* sc = app.primaryScreen();
    if(sc){
    sc->setOrientationUpdateMask(Qt::PrimaryOrientation
                                 | Qt::LandscapeOrientation
                                 | Qt::PortraitOrientation
                                 | Qt::InvertedLandscapeOrientation
                                 | Qt::InvertedPortraitOrientation);
    }

    qmlRegisterType<TextRender>("TextRender",1,0,"TextRender");
    MainWindow view;

    Terminal term;
    Util util(settings);
    term.setUtil(&util);
    QString startupErrorMsg;

    // copy the default config files to the config dir if they don't already exist
    copyFileFromResources(":/data/menu.xml", util.configPath()+"/menu.xml");
    copyFileFromResources(":/data/english.layout", util.configPath()+"/english.layout");
    copyFileFromResources(":/data/finnish.layout", util.configPath()+"/finnish.layout");
    copyFileFromResources(":/data/french.layout", util.configPath()+"/french.layout");
    copyFileFromResources(":/data/german.layout", util.configPath()+"/german.layout");
    copyFileFromResources(":/data/qwertz.layout", util.configPath()+"/qwertz.layout");

    KeyLoader keyLoader;
    keyLoader.setUtil(&util);
    bool ret = keyLoader.loadLayout( settings->value("ui/keyboardLayout").toString() );
    if(!ret) {
        // on failure, try to load the default one (english) directly from resources
        startupErrorMsg = "There was an error loading the keyboard layout.<br>\nUsing the default one instead.";
        settings->setValue("ui/keyboardLayout", "english");
        ret = keyLoader.loadLayout(":/data/english.layout");
        if(!ret)
            qFatal("failure loading keyboard layout");
    }

    QQmlContext *context = view.rootContext();
    context->setContextProperty( "term", &term );
    context->setContextProperty( "util", &util );
    context->setContextProperty( "keyLoader", &keyLoader );

    view.setSource(QUrl("qrc:/qml/Main.qml"));

    QObject *root = view.rootObject();
    if(!root)
        qFatal("no root object - qml error");

    QObject* win = root->findChild<QObject*>("window");

    if(!startupErrorMsg.isEmpty())
        QMetaObject::invokeMethod(win, "showErrorMessage", Qt::QueuedConnection, Q_ARG(QVariant, startupErrorMsg));

    TextRender *tr = root->findChild<TextRender*>("textrender");
    tr->setUtil(&util);
    tr->setTerminal(&term);
    term.setRenderer(tr);
    term.setWindow(&view);
    util.setWindow(&view);
    util.setTerm(&term);
    util.setRenderer(tr);

    QObject::connect(&term,SIGNAL(displayBufferChanged()),win,SLOT(displayBufferChanged()));
    QObject::connect(view.engine(),SIGNAL(quit()),&app,SLOT(quit()));

    QSize screenSize = QGuiApplication::primaryScreen()->size();
    if ((screenSize.width() < 1024 || screenSize.height() < 768 || app.arguments().contains("-fs"))
            && !app.arguments().contains("-nofs"))
    {
        view.showFullScreen();
    } else
        view.show();

    PtyIFace ptyiface(pid, socketM, &term,
                       settings->value("terminal/charset").toString());

    if( ptyiface.failed() )
        qFatal("pty failure");

    return app.exec();
}