Esempio n. 1
0
void PartManualTest::testShortcutOverride()
{
    // FIXME: This test asks the user to press shortcut key sequences manually because
    // the result is different than when sending the key press via QTest::keyClick()
    //
    // When the key presses are sent manually, Konsole::TerminalDisplay::event() is called
    // and the overrideShortcut() signal is emitted by the part.
    // When the key presses are sent automatically, the shortcut is triggered but
    // Konsole::TerminalDisplay::event() is not called and the overrideShortcut() signal is
    // not emitted by the part.

    // Create a main window with a menu and a test
    // action with a shortcut set to Ctrl+S, which is also used by the terminal
    KMainWindow* mainWindow = new KMainWindow();
    QMenu* fileMenu = mainWindow->menuBar()->addMenu("File");
    QAction* testAction = fileMenu->addAction("Test");
    testAction->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_S));
    connect(testAction, SIGNAL(triggered()), this, SLOT(shortcutTriggered()));

    // Create terminal part and embed in into the main window
    KParts::Part* terminalPart = createPart();
    QVERIFY(terminalPart);
    mainWindow->setCentralWidget(terminalPart->widget());
    TerminalInterface* terminal = qobject_cast<TerminalInterface*>(terminalPart);
    QVERIFY(terminal);
    terminal->sendInput("Press Ctrl+S twice.\n");
    mainWindow->show();

    // Test shortcut with override disabled, so the shortcut will be triggered
    _shortcutTriggered = false;
    _override = false;
    _overrideCalled = false;
    QVERIFY(connect(terminalPart, SIGNAL(overrideShortcut(QKeyEvent*,bool&)),
                    this, SLOT(overrideShortcut(QKeyEvent*,bool&))));

    //QTest::keyClick(terminalPart->widget(),Qt::Key_S,Qt::ControlModifier);
    _shortcutEventLoop = new QEventLoop();
    _shortcutEventLoop->exec();

    QVERIFY(_overrideCalled);
    QVERIFY(_shortcutTriggered);
    QVERIFY(!_override);

    // Test shortcut with override enabled, so the shortcut will not be triggered
    _override = true;
    _overrideCalled = false;
    _shortcutTriggered = false;

    //QTest::keyClick(terminalPart->widget(),Qt::Key_S,Qt::ControlModifier);
    _shortcutEventLoop->exec();

    QVERIFY(_overrideCalled);
    QVERIFY(!_shortcutTriggered);
    QVERIFY(_override);

    delete _shortcutEventLoop;
    delete terminalPart;
    delete mainWindow;
}
Esempio n. 2
0
QWidget* createTerminalWidget(QWidget* parent = 0)
{
    KPluginFactory* factory = KPluginLoader("libkonsolepart").factory();
    KParts::ReadOnlyPart* part = factory ? (factory->create<KParts::ReadOnlyPart>(parent)) : 0;

    if (!part) {
        printf("Failed to initialize part\n");
        return 0;
    }

    TerminalInterface* terminal = qobject_cast<TerminalInterface*>(part);
    if (!terminal) {
        printf("Failed to initialize terminal\n");
        return 0;
    }

    terminal->showShellInDir(KUrl().path());
    terminal->sendInput("cd " + KShell::quoteArg(KUrl().path()) + '\n');
    terminal->sendInput("clear\n");
    return part->widget();
}
Esempio n. 3
0
void TerminalInterfaceTest::testTerminalInterface()
{
    QString currentDirectory;
    QString retVal;
    bool result;

    // create a Konsole part and attempt to connect to it
    _terminalPart = createPart();
    if (!_terminalPart)
        QSKIP("konsolepart not found.", SkipSingle);

    TerminalInterface* terminal = qobject_cast<TerminalInterface*>(_terminalPart);
    QVERIFY(terminal);
    terminal->showShellInDir(QDir::home().path());

    int foregroundProcessId  = terminal->foregroundProcessId();
    QCOMPARE(foregroundProcessId, -1);
    QString foregroundProcessName  = terminal->foregroundProcessName();
    QCOMPARE(foregroundProcessName, QString(""));

    // terminalProcessId() is the user's default shell
    // FIXME: find a way to verify this
    // int terminalProcessId  = terminal->terminalProcessId();

    // Sleep is used to allow enough time for these to work
    // In Qt5 we can use QSignalSpy::wait()

    // Let's try using QSignalSpy
    // http://techbase.kde.org/Development/Tutorials/Unittests
    // QSignalSpy is really a QList of QLists, so we take the first
    // list, which corresponds to the arguments for the first signal
    // we caught.

    QSignalSpy stateSpy(_terminalPart, SIGNAL(currentDirectoryChanged(QString)));
    QVERIFY(stateSpy.isValid());
 
    // Now we check to make sure we don't have any signals already
    QCOMPARE(stateSpy.count(), 0);

    // Let's trigger some signals

    // #1A - Test signal currentDirectoryChanged(QString)
    currentDirectory = QString("/tmp");
    terminal->sendInput("cd " + currentDirectory + '\n');
    sleep(2000);
    QCOMPARE(stateSpy.count(), 1);

    // Correct result?
    QList<QVariant> firstSignalArgs = stateSpy.takeFirst();

    QString firstSignalState = firstSignalArgs.at(0).toString();
    QCOMPARE(firstSignalState, currentDirectory);

    // Test KonsolePart API currentWorkingDirectory()
    result = QMetaObject::invokeMethod(_terminalPart,
                                       "currentWorkingDirectory",
                                       Qt::DirectConnection,
                                       Q_RETURN_ARG(QString, retVal));
    QVERIFY(result);
    QCOMPARE(retVal, currentDirectory);

    // #1B - Test signal currentDirectoryChanged(QString)
    // Invalid directory - no signal should be emitted
    terminal->sendInput("cd /usrADADFASDF\n");
    sleep(2000);
    QCOMPARE(stateSpy.count(), 0);

    // Should be no change since the above cd didn't work
    result = QMetaObject::invokeMethod(_terminalPart,
                                       "currentWorkingDirectory",
                                       Qt::DirectConnection,
                                       Q_RETURN_ARG(QString, retVal));
    QVERIFY(result);
    QCOMPARE(retVal, currentDirectory);


    // Test starting a new program
    QString command = "top";
    terminal->sendInput(command + '\n');
    sleep(2000);
    // FIXME: find a good way to validate process id of 'top'
    foregroundProcessId  = terminal->foregroundProcessId();
    QVERIFY(foregroundProcessId != -1);
    foregroundProcessName  = terminal->foregroundProcessName();
    QCOMPARE(foregroundProcessName, command);

    terminal->sendInput("q");
    sleep(2000);

    // Nothing running in foreground
    foregroundProcessId  = terminal->foregroundProcessId();
    QCOMPARE(foregroundProcessId, -1);
    foregroundProcessName  = terminal->foregroundProcessName();
    QCOMPARE(foregroundProcessName, QString(""));

    // Test destroyed()
    QSignalSpy destroyedSpy(_terminalPart, SIGNAL(destroyed()));
    QVERIFY(destroyedSpy.isValid());
 
    // Now we check to make sure we don't have any signals already
    QCOMPARE(destroyedSpy.count(), 0);

    delete _terminalPart;
    QCOMPARE(destroyedSpy.count(), 1);

}
void
InteractiveTerminalPage::onActivate()
{
    if ( m_termHostWidget )
        return;
    // For whatever reason, instead of simply linking against a library we
    // need to do a runtime query to KService just to get a sodding terminal
    // widget.
    KService::Ptr service = KService::serviceByDesktopName( "konsolepart" );
    if ( !service )
    {
        // And all of this hoping the Konsole application is installed. If not,
        // tough cookies.
        // Maybe linking against a library seemed too simple and elegant so
        // someone decided to have a terminal widget depend on over 9000 other
        // KDElibs things that have nothing to do with a terminal widget, and
        // have the loading happen at runtime so it's more likely to fail at
        // an inconvenient time.
        QMessageBox::critical( this,
                               tr( "Konsole not installed"),
                               tr( "Please install the kde konsole and try again!" ),
                               QMessageBox::Ok);
        return ;
    }

    // Create one instance of konsolepart.
    KParts::ReadOnlyPart* p =
        service->createInstance< KParts::ReadOnlyPart >( this,
                                                         this,
                                                         {} );
    if ( !p )
    {
        // One more opportunity for the loading operation to fail.
        QMessageBox::critical( this,
                               tr( "Konsole not installed"),
                               tr( "Please install the kde konsole and try again!" ),
                               QMessageBox::Ok);
        return;
    }

    // Cast the konsolepart to the TerminalInterface...
    TerminalInterface* t = qobject_cast< TerminalInterface* >( p );
    if ( !t )
    {
        // This is why we can't have nice things.
        QMessageBox::critical( this,
                               tr( "Konsole not installed"),
                               tr( "Please install the kde konsole and try again!" ),
                               QMessageBox::Ok);
        return;
    }

    // Make the widget persist even if the KPart goes out of scope...
    p->setAutoDeleteWidget( false );
    // ... but kill the KPart if the widget goes out of scope.
    p->setAutoDeletePart( true );

    m_termHostWidget = p->widget();
    m_layout->addWidget( m_termHostWidget );
    cDebug() << "Part widget ought to be"
             << m_termHostWidget->metaObject()->className();

    t->showShellInDir( QDir::home().path() );
    t->sendInput( QString( "%1\n" ).arg( m_command ) );
}