/* Copyright 2007-2008 by Robert Knight This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ // Own #include "Part.h" // Qt #include #include // KDE #include #include #include #include #include #include // Konsole #include "ColorScheme.h" #include "EditProfileDialog.h" #include "Emulation.h" #include "KeyboardTranslator.h" #include "ManageProfilesDialog.h" #include "Session.h" #include "SessionController.h" #include "SessionManager.h" #include "TerminalDisplay.h" #include "ViewManager.h" #include "MainWindow.h" #include using namespace Konsole; K_PLUGIN_FACTORY(KonsolePartFactory, registerPlugin();) K_EXPORT_PLUGIN(KonsolePartFactory("konsole")) Part::Part(QWidget* parentWidget , QObject* parent, const QVariantList&) : KParts::ReadOnlyPart(parent) , _viewManager(0) , _pluggedController(0) , _manageProfilesAction(0) { // make sure the konsole catalog is loaded KGlobal::locale()->insertCatalog("konsole"); // setup global actions createGlobalActions(); // create view widget _viewManager = new ViewManager(this, actionCollection()); _viewManager->setNavigationMethod(ViewManager::NoNavigation); connect(_viewManager , SIGNAL(activeViewChanged(SessionController*)) , this , SLOT(activeViewChanged(SessionController*))); connect(_viewManager , SIGNAL(empty()) , this , SLOT(terminalExited())); connect(_viewManager , SIGNAL(newViewRequest()) , this , SLOT(newTab())); _viewManager->widget()->setParent(parentWidget); setWidget(_viewManager->widget()); actionCollection()->addAssociatedWidget(_viewManager->widget()); foreach(QAction * action, actionCollection()->actions()) action->setShortcutContext(Qt::WidgetWithChildrenShortcut); // Enable translucency support. _viewManager->widget()->setAttribute(Qt::WA_TranslucentBackground, true); TerminalDisplay::HAVE_TRANSPARENCY = KWindowSystem::compositingActive(); // create basic session createSession(); } Part::~Part() { SessionManager::instance()->saveSettings(); } void Part::createGlobalActions() { _manageProfilesAction = new QAction(i18n("Manage Profiles..."), this); connect(_manageProfilesAction, SIGNAL(triggered()), this, SLOT(showManageProfilesDialog())); } void Part::setupActionsForSession(SessionController* session) { // TODO: what meaningful operation should be placed here? Q_UNUSED(session); } bool Part::openFile() { return false; } void Part::terminalExited() { deleteLater(); } void Part::newTab() { createSession(); showShellInDir(QString()); } Session* Part::activeSession() const { if (_viewManager->activeViewController()) { Q_ASSERT(_viewManager->activeViewController()->session()); return _viewManager->activeViewController()->session(); } else { return 0; } } void Part::startProgram(const QString& program, const QStringList& arguments) { Q_ASSERT(activeSession()); if (!activeSession()->isRunning()) { if (!program.isEmpty() && !arguments.isEmpty()) { activeSession()->setProgram(program); activeSession()->setArguments(arguments); } activeSession()->run(); } } void Part::openTeletype(int fd) { Q_ASSERT(activeSession()); activeSession()->openTeletype(fd); } void Part::showShellInDir(const QString& dir) { Q_ASSERT(activeSession()); if (!activeSession()->isRunning()) { if (!dir.isEmpty()) activeSession()->setInitialWorkingDirectory(dir); activeSession()->run(); } } void Part::sendInput(const QString& text) { Q_ASSERT(activeSession()); activeSession()->emulation()->sendText(text); } int Part::terminalProcessId() { Q_ASSERT(activeSession()); return activeSession()->processId(); } int Part::foregroundProcessId() { Q_ASSERT(activeSession()); if (activeSession()->isForegroundProcessActive()) { return activeSession()->foregroundProcessId(); } else { return -1; } } QString Part::foregroundProcessName() { Q_ASSERT(activeSession()); if (activeSession()->isForegroundProcessActive()) { return activeSession()->foregroundProcessName(); } else { return ""; } } Session* Part::createSession(const Profile::Ptr profile) { Session* session = SessionManager::instance()->createSession(profile); _viewManager->createView(session); return session; } void Part::activeViewChanged(SessionController* controller) { Q_ASSERT(controller); Q_ASSERT(controller->view()); // remove existing controller if (_pluggedController) { removeChildClient(_pluggedController); disconnect(_pluggedController, SIGNAL(titleChanged(ViewProperties*)), this, SLOT(activeViewTitleChanged(ViewProperties*))); } // insert new controller setupActionsForSession(controller); insertChildClient(controller); connect(controller, SIGNAL(titleChanged(ViewProperties*)), this, SLOT(activeViewTitleChanged(ViewProperties*))); activeViewTitleChanged(controller); const char* displaySignal = SIGNAL(overrideShortcutCheck(QKeyEvent*, bool&)); const char* partSlot = SLOT(overrideTerminalShortcut(QKeyEvent*, bool&)); disconnect(controller->view(), displaySignal, this, partSlot); connect(controller->view(), displaySignal, this, partSlot); _pluggedController = controller; } void Part::overrideTerminalShortcut(QKeyEvent* event, bool& override) { // Shift+Insert is commonly used as the alternate shorcut for // pasting in KDE apps(including konsole), so it deserves some // special treatment. if ((event->modifiers() & Qt::ShiftModifier) && (event->key() == Qt::Key_Insert)) { override = false; return; } // override all shortcuts in the embedded terminal by default override = true; emit overrideShortcut(event, override); } void Part::activeViewTitleChanged(ViewProperties* properties) { emit setWindowCaption(properties->title()); } void Part::showManageProfilesDialog() { showManageProfilesDialog(_viewManager->widget()); } void Part::showManageProfilesDialog(QWidget* parent) { ManageProfilesDialog* dialog = new ManageProfilesDialog(parent); dialog->setAttribute(Qt::WA_DeleteOnClose); dialog->setShortcutEditorVisible(false); dialog->show(); } void Part::showEditCurrentProfileDialog(QWidget* parent) { Q_ASSERT(activeSession()); EditProfileDialog* dialog = new EditProfileDialog(parent); dialog->setAttribute(Qt::WA_DeleteOnClose); dialog->setProfile(SessionManager::instance()->sessionProfile(activeSession())); dialog->show(); } void Part::changeSessionSettings(const QString& text) { // send a profile change command, the escape code format // is the same as the normal X-Term commands used to change the window title or icon, // but with a magic value of '50' for the parameter which specifies what to change Q_ASSERT(activeSession()); QByteArray buffer; buffer.append("\033]50;").append(text.toUtf8()).append('\a'); activeSession()->emulation()->receiveData(buffer.constData(), buffer.length()); } // Konqueror integration bool Part::openUrl(const KUrl & _url) { if (url() == _url) { emit completed(); return true; } setUrl(_url); emit setWindowCaption(_url.pathOrUrl()); //kdDebug() << "Set Window Caption to " << url.pathOrUrl(); emit started(0); if (_url.isLocalFile() /*&& b_openUrls*/) { KDE_struct_stat buff; KDE::stat(QFile::encodeName(_url.path()), &buff); QString text = (S_ISDIR(buff.st_mode) ? _url.path() : _url.directory()); showShellInDir(text); } else { showShellInDir(QDir::homePath()); } emit completed(); return true; } void Part::setMonitorSilenceEnabled(bool enabled) { Q_ASSERT(activeSession()); if (enabled) { activeSession()->setMonitorSilence(true); connect(activeSession(), SIGNAL(stateChanged(int)), this, SLOT(sessionStateChanged(int)), Qt::UniqueConnection); } else { activeSession()->setMonitorSilence(false); disconnect(activeSession(), SIGNAL(stateChanged(int)), this, SLOT(sessionStateChanged(int))); } } void Part::setMonitorActivityEnabled(bool enabled) { Q_ASSERT(activeSession()); if (enabled) { activeSession()->setMonitorActivity(true); connect(activeSession(), SIGNAL(stateChanged(int)), this, SLOT(sessionStateChanged(int)), Qt::UniqueConnection); } else { activeSession()->setMonitorActivity(false); disconnect(activeSession(), SIGNAL(stateChanged(int)), this, SLOT(sessionStateChanged(int))); } } void Part::sessionStateChanged(int state) { if (state == NOTIFYSILENCE) emit silenceDetected(); else if (state == NOTIFYACTIVITY) emit activityDetected(); } #include "Part.moc"