diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 4bd972ea9..e1688bf22 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -72,6 +72,7 @@ set(konsole_KDEINIT_SRCS ScreenWindow.cpp SessionController.cpp ShellCommand.cpp + Profile.cpp ProfileList.cpp ProfileListWidget.cpp SessionManager.cpp @@ -145,6 +146,7 @@ set(konsolepart_PART_SRCS MainWindow.cpp Part.cpp ProcessInfo.cpp + Profile.cpp Pty.cpp RemoteConnectionDialog.cpp Screen.cpp diff --git a/src/EditProfileDialog.cpp b/src/EditProfileDialog.cpp index d74e35e9f..e763189a2 100644 --- a/src/EditProfileDialog.cpp +++ b/src/EditProfileDialog.cpp @@ -40,6 +40,7 @@ #include "ui_EditProfileDialog.h" #include "KeyBindingEditor.h" #include "KeyboardTranslator.h" +#include "Profile.h" #include "SessionManager.h" #include "ShellCommand.h" #include "TabTitleFormatAction.h" @@ -49,7 +50,7 @@ using namespace Konsole; EditProfileDialog::EditProfileDialog(QWidget* parent) : KDialog(parent) { - setCaption("Edit Profile"); + setCaption(i18n("Edit Profile")); setButtons( KDialog::Ok | KDialog::Cancel | KDialog::Apply | KDialog::Default ); connect( this , SIGNAL(applyClicked()) , this , SLOT(save()) ); @@ -102,7 +103,7 @@ void EditProfileDialog::setProfile(const QString& key) Q_ASSERT( info ); // update caption - setCaption( QString("Edit Profile \"%1\"").arg(info->name()) ); + setCaption( i18n("Edit Profile \"%1\"",info->name()) ); // setup each page of the dialog setupGeneralPage(info); diff --git a/src/MainWindow.cpp b/src/MainWindow.cpp index 4c9812b1b..121d05b12 100644 --- a/src/MainWindow.cpp +++ b/src/MainWindow.cpp @@ -58,20 +58,14 @@ MainWindow::MainWindow() _bookmarkHandler(0), _pluggedController(0) { - // add a small amount of space between the top of the window and the main widget - // to prevent the menu bar and main widget borders touching (which looks very ugly) in styles - // where the menu bar has a lower border - //setContentsMargins(0,2,0,0); - // create actions for menus + // the directory ('konsole') is included in the path here so that the XML + // file can be found when this code is being used in the Konsole part. setXMLFile("konsole/konsoleui.rc"); setupActions(); // create view manager - // the directory ('konsole') is included in the path here so that the XML - // file can be found when this code is being used in the Konsole part. - //setXMLFile("konsole/konsoleui.rc"); - _viewManager = new ViewManager(this,actionCollection()); + _viewManager = new ViewManager(this,actionCollection()); connect( _viewManager , SIGNAL(empty()) , this , SLOT(close()) ); connect( _viewManager , SIGNAL(activeViewChanged(SessionController*)) , this , SLOT(activeViewChanged(SessionController*)) ); @@ -256,27 +250,6 @@ void MainWindow::showRemoteConnectionDialog() emit requestSession(dialog.sessionKey(),_viewManager); } -void MainWindow::mergeWindows() -{ - // merges all of the open Konsole windows into this window - // by merging the view manager associated with the other Konsole windows - // into this window's view manager - - QListIterator topLevelIter( QApplication::topLevelWidgets() ); - - while (topLevelIter.hasNext()) - { - QWidget* w = topLevelIter.next(); - qDebug() << "Top level widget: " << w->metaObject()->className(); - MainWindow* window = qobject_cast(w); - if ( window && window != this ) - { - _viewManager->merge( window->_viewManager ); - //window->close(); - } - } -} - void MainWindow::setupWidgets() { QWidget* widget = new QWidget(this); diff --git a/src/MainWindow.h b/src/MainWindow.h index 8d90c406d..8694fd582 100644 --- a/src/MainWindow.h +++ b/src/MainWindow.h @@ -79,19 +79,11 @@ class MainWindow : public KXmlGuiWindow */ BookmarkHandler* bookmarkHandler() const; - public slots: - /** - * Merges all of the MainWindow widgets in the application into this window. - * Note: Only the active container in other MainWindow widgets are considered, - * other containers are currently just deleted - */ - void mergeWindows(); - signals: /** * Emitted by the main window to request the creation of a new session. * - * @param key Specifies the type of session to create + * @param key The key for the profile to use to create the new session. * @param view The view manager owned by this main window */ void requestSession(const QString& key , ViewManager* view); diff --git a/src/ManageProfilesDialog.cpp b/src/ManageProfilesDialog.cpp index ac1fd3a64..bd86f764a 100644 --- a/src/ManageProfilesDialog.cpp +++ b/src/ManageProfilesDialog.cpp @@ -39,7 +39,7 @@ using namespace Konsole; ManageProfilesDialog::ManageProfilesDialog(QWidget* parent) : KDialog(parent) { - setCaption("Manage Profiles"); + setCaption(i18n("Manage Profiles")); _ui = new Ui::ManageProfilesDialog(); _ui->setupUi(mainWidget()); @@ -76,16 +76,32 @@ ManageProfilesDialog::~ManageProfilesDialog() { delete _ui; } +void ManageProfilesDialog::itemDataChanged(QStandardItem* item) +{ + static const int ShortcutColumn = 2; + + if ( item->column() == ShortcutColumn ) + { + QKeySequence sequence = QKeySequence::fromString(item->text()); + + qDebug() << "New key sequence: " << item->text(); + + SessionManager::instance()->setShortcut(item->data(Qt::UserRole+1).value(), + sequence); + } +} void ManageProfilesDialog::updateTableModel() { // ensure profiles list is complete + // this may be EXPENSIVE, but will only be done the first time + // that the dialog is shown. SessionManager::instance()->loadAllProfiles(); // setup session table _sessionModel = new QStandardItemModel(this); - _sessionModel->setHorizontalHeaderLabels( QStringList() << "Name" - << "Show in Menu" - << "Shortcut" ); + _sessionModel->setHorizontalHeaderLabels( QStringList() << i18n("Name") + << i18n("Show in Menu") + << i18n("Shortcut") ); QListIterator keyIter( SessionManager::instance()->availableProfiles() ); while ( keyIter.hasNext() ) { @@ -105,6 +121,7 @@ void ManageProfilesDialog::updateTableModel() const bool isFavorite = SessionManager::instance()->findFavorites().contains(key); + // favorite column QStandardItem* favoriteItem = new QStandardItem(); if ( isFavorite ) favoriteItem->setData(KIcon("favorites"),Qt::DecorationRole); @@ -113,11 +130,22 @@ void ManageProfilesDialog::updateTableModel() favoriteItem->setData(key,Qt::UserRole+1); - itemList << item << favoriteItem; + // shortcut column + QStandardItem* shortcutItem = new QStandardItem(); + QString shortcut = SessionManager::instance()->shortcut(key). + toString(); + shortcutItem->setText(shortcut); + shortcutItem->setData(key,Qt::UserRole+1); + + itemList << item << favoriteItem << shortcutItem; _sessionModel->appendRow(itemList); } updateDefaultItem(); + + connect( _sessionModel , SIGNAL(itemChanged(QStandardItem*)) , this , + SLOT(itemDataChanged(QStandardItem*)) ); + _ui->sessionTable->setModel(_sessionModel); // listen for changes in the table selection and update the state of the form's buttons diff --git a/src/ManageProfilesDialog.h b/src/ManageProfilesDialog.h index 9db7e769a..cfdfa01d9 100644 --- a/src/ManageProfilesDialog.h +++ b/src/ManageProfilesDialog.h @@ -58,6 +58,8 @@ private slots: void newType(); void editSelected(); + void itemDataChanged(QStandardItem* item); + // enables or disables Edit/Delete/Set as Default buttons when the // selection changes void tableSelectionChanged(const QItemSelection&); diff --git a/src/Profile.cpp b/src/Profile.cpp new file mode 100644 index 000000000..ee51be9f8 --- /dev/null +++ b/src/Profile.cpp @@ -0,0 +1,370 @@ +/* + This source file is part of Konsole, a terminal emulator. + + Copyright (C) 2006-7 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 "Profile.h" + +// Qt +#include +#include + +// KDE +#include +#include +#include +#include +#include + +// Konsole +#include "ShellCommand.h" + +using namespace Konsole; + +QHash Profile::_propertyNames; + +FallbackProfile::FallbackProfile() + : Profile(0) +{ + // Fallback settings + setProperty(Name,i18n("Shell")); + setProperty(Command,getenv("SHELL")); + setProperty(Icon,"konsole"); + setProperty(Arguments,QStringList() << getenv("SHELL")); + setProperty(LocalTabTitleFormat,"%d : %n"); + setProperty(RemoteTabTitleFormat,"%H : %u"); + setProperty(TabBarMode,AlwaysShowTabBar); + setProperty(ShowMenuBar,true); + + setProperty(KeyBindings,"default"); + + setProperty(Font,QFont("Monospace")); + + setProperty(HistoryMode,FixedSizeHistory); + setProperty(HistorySize,1000); + setProperty(ScrollBarPosition,ScrollBarRight); + + setProperty(FlowControlEnabled,true); + setProperty(AllowProgramsToResizeWindow,true); + setProperty(BlinkingTextEnabled,true); + + setProperty(BlinkingCursorEnabled,false); + setProperty(CursorShape,BlockCursor); + setProperty(UseCustomCursorColor,false); + setProperty(CustomCursorColor,Qt::black); + + // default taken from KDE 3 + setProperty(WordCharacters,":@-./_~?&=%+#"); + + // Fallback should not be shown in menus + setHidden(true); +} + +Profile::Profile(Profile* parent) + : _parent(parent) + ,_hidden(false) +{ +} + +bool Profile::isHidden() const { return _hidden; } +void Profile::setHidden(bool hidden) { _hidden = hidden; } + +void Profile::setParent(Profile* parent) { _parent = parent; } +const Profile* Profile::parent() const { return _parent; } + +bool Profile::isEmpty() const +{ + return _propertyValues.isEmpty(); +} +QHash Profile::setProperties() const +{ + return _propertyValues; +} + +QVariant Profile::property(Property property) const +{ + if ( _propertyValues.contains(property) ) + return _propertyValues[property]; + else if ( _parent ) + return _parent->property(property); + else + return QVariant(); +} +void Profile::setProperty(Property property , const QVariant& value) +{ + _propertyValues.insert(property,value); +} +bool Profile::isPropertySet(Property property) const +{ + return _propertyValues.contains(property); +} + +bool Profile::isNameRegistered(const QString& name) +{ + return _propertyNames.contains(name); +} + +Profile::Property Profile::lookupByName(const QString& name) +{ + return _propertyNames[name]; +} + +QList Profile::namesForProperty(Property property) +{ + return _propertyNames.keys(property); +} +void Profile::registerName(Property property , const QString& name) +{ + _propertyNames.insert(name,property); +} + +QString KDE4ProfileWriter::getPath(const Profile* info) +{ + QString newPath; + + if ( info->isPropertySet(Profile::Path) ) + newPath=info->path(); + + // if the path is not specified, use the profile name + ".profile" + if ( newPath.isEmpty() ) + newPath = info->name() + ".profile"; + + QFileInfo fileInfo(newPath); + if (!fileInfo.isAbsolute()) + newPath = KGlobal::dirs()->saveLocation("data","konsole/") + newPath; + + qDebug() << "Saving profile under name: " << newPath; + + return newPath; +} +void KDE4ProfileWriter::writeStandardElement(KConfigGroup& group , char* name , const Profile* profile , + Profile::Property attribute) +{ + if ( profile->isPropertySet(attribute) ) + group.writeEntry(name,profile->property(attribute)); +} +bool KDE4ProfileWriter::writeProfile(const QString& path , const Profile* profile) +{ + KConfig config(path,KConfig::NoGlobals); + + // Basic Profile Settings + KConfigGroup general = config.group("General"); + + if ( profile->isPropertySet(Profile::Name) ) + general.writeEntry("Name",profile->name()); + + if ( profile->isPropertySet(Profile::Command) + || profile->isPropertySet(Profile::Arguments) ) + general.writeEntry("Command", + ShellCommand(profile->command(),profile->arguments()).fullCommand()); + + if ( profile->isPropertySet(Profile::Directory) ) + general.writeEntry("Directory",profile->defaultWorkingDirectory()); + + writeStandardElement( general , "Icon" , profile , Profile::Icon ); + + // Tab Titles + writeStandardElement( general , "LocalTabTitleFormat" , profile , Profile::LocalTabTitleFormat ); + writeStandardElement( general , "RemoteTabTitleFormat" , profile , Profile::RemoteTabTitleFormat ); + + // Menu and Tab Bar + writeStandardElement( general , "TabBarMode" , profile , Profile::TabBarMode ); + writeStandardElement( general , "ShowMenuBar" , profile , Profile::ShowMenuBar ); + + // Keyboard + KConfigGroup keyboard = config.group("Keyboard"); + writeStandardElement( keyboard , "KeyBindings" , profile , Profile::KeyBindings ); + + // Appearance + KConfigGroup appearance = config.group("Appearance"); + + writeStandardElement( appearance , "ColorScheme" , profile , Profile::ColorScheme ); + writeStandardElement( appearance , "Font" , profile , Profile::Font ); + + // Scrolling + KConfigGroup scrolling = config.group("Scrolling"); + + writeStandardElement( scrolling , "HistoryMode" , profile , Profile::HistoryMode ); + writeStandardElement( scrolling , "HistorySize" , profile , Profile::HistorySize ); + writeStandardElement( scrolling , "ScrollBarPosition" , profile , Profile::ScrollBarPosition ); + + // Terminal Features + KConfigGroup terminalFeatures = config.group("Terminal Features"); + + writeStandardElement( terminalFeatures , "FlowControl" , profile , Profile::FlowControlEnabled ); + writeStandardElement( terminalFeatures , "BlinkingCursor" , profile , Profile::BlinkingCursorEnabled ); + + // Cursor + KConfigGroup cursorOptions = config.group("Cursor Options"); + + writeStandardElement( cursorOptions , "UseCustomCursorColor" , profile , Profile::UseCustomCursorColor ); + writeStandardElement( cursorOptions , "CustomCursorColor" , profile , Profile::CustomCursorColor ); + writeStandardElement( cursorOptions , "CursorShape" , profile , Profile::CursorShape ); + + // Interaction + KConfigGroup interactionOptions = config.group("Interaction Options"); + + writeStandardElement( interactionOptions , "WordCharacters" , profile , Profile::WordCharacters ); + + return true; +} + +QStringList KDE4ProfileReader::findProfiles() +{ + return KGlobal::dirs()->findAllResources("data","konsole/*.profile", + KStandardDirs::NoDuplicates); +} +bool KDE4ProfileReader::readProfile(const QString& path , Profile* profile) +{ + qDebug() << "KDE 4 Profile Reader:" << path; + + KConfig config(path,KConfig::NoGlobals); + + // general + KConfigGroup general = config.group("General"); + + if ( general.hasKey("Name") ) + profile->setProperty(Profile::Name,general.readEntry("Name")); + else + return false; + + if ( general.hasKey("Command") ) + { + ShellCommand shellCommand(general.readEntry("Command")); + + profile->setProperty(Profile::Command,shellCommand.command()); + profile->setProperty(Profile::Arguments,shellCommand.arguments()); + } + + readStandardElement(general,"Directory",profile,Profile::Directory); + + readStandardElement(general,"Icon",profile,Profile::Icon); + readStandardElement(general,"LocalTabTitleFormat",profile,Profile::LocalTabTitleFormat); + readStandardElement(general,"RemoteTabTitleFormat",profile,Profile::RemoteTabTitleFormat); + + readStandardElement(general,"TabBarMode",profile,Profile::TabBarMode); + readStandardElement(general,"ShowMenuBar",profile,Profile::ShowMenuBar); + + // keyboard + KConfigGroup keyboard = config.group("Keyboard"); + readStandardElement(keyboard,"KeyBindings",profile,Profile::KeyBindings); + + // appearence + KConfigGroup appearance = config.group("Appearance"); + + readStandardElement(appearance,"ColorScheme",profile,Profile::ColorScheme); + readStandardElement(appearance,"Font",profile,Profile::Font); + + // scrolling + KConfigGroup scrolling = config.group("Scrolling"); + + readStandardElement(scrolling,"HistoryMode",profile,Profile::HistoryMode); + readStandardElement(scrolling,"HistorySize",profile,Profile::HistorySize); + readStandardElement(scrolling,"ScrollBarPosition",profile,Profile::ScrollBarPosition); + + // terminal features + KConfigGroup terminalFeatures = config.group("Terminal Features"); + + readStandardElement(terminalFeatures,"FlowControl",profile,Profile::FlowControlEnabled); + readStandardElement(terminalFeatures,"BlinkingCursor",profile,Profile::BlinkingCursorEnabled); + + // cursor settings + KConfigGroup cursorOptions = config.group("Cursor Options"); + + readStandardElement(cursorOptions,"UseCustomCursorColor",profile,Profile::UseCustomCursorColor); + readStandardElement(cursorOptions,"CustomCursorColor",profile,Profile::CustomCursorColor); + readStandardElement(cursorOptions,"CursorShape",profile,Profile::CursorShape); + + // interaction options + KConfigGroup interactionOptions = config.group("Interaction Options"); + + readStandardElement(interactionOptions,"WordCharacters",profile,Profile::WordCharacters); + + return true; +} +template +void KDE4ProfileReader::readStandardElement(const KConfigGroup& group , + char* name , + Profile* info , + Profile::Property property) +{ + if ( group.hasKey(name) ) + info->setProperty(property,group.readEntry(name,T())); +} + +QStringList KDE3ProfileReader::findProfiles() +{ + return KGlobal::dirs()->findAllResources("data", "konsole/*.desktop", + KStandardDirs::NoDuplicates); +} +bool KDE3ProfileReader::readProfile(const QString& path , Profile* profile) +{ + if (!QFile::exists(path)) + return false; + + KDesktopFile* desktopFile = new KDesktopFile(path); + KConfigGroup* config = new KConfigGroup( desktopFile->desktopGroup() ); + + if ( config->hasKey("Name") ) + profile->setProperty(Profile::Name,config->readEntry("Name")); + + qDebug() << "reading KDE 3 profile " << profile->name(); + + if ( config->hasKey("Icon") ) + profile->setProperty(Profile::Icon,config->readEntry("Icon")); + if ( config->hasKey("Exec") ) + { + const QString& fullCommand = config->readEntry("Exec"); + ShellCommand shellCommand(fullCommand); + + profile->setProperty(Profile::Command,shellCommand.command()); + profile->setProperty(Profile::Arguments,shellCommand.arguments()); + } + if ( config->hasKey("Schema") ) + { + profile->setProperty(Profile::ColorScheme,config->readEntry("Schema").replace + (".schema",QString())); + } + if ( config->hasKey("defaultfont") ) + { + profile->setProperty(Profile::Font,config->readEntry("defaultfont")); + } + if ( config->hasKey("KeyTab") ) + { + profile->setProperty(Profile::KeyBindings,config->readEntry("KeyTab")); + } + if ( config->hasKey("Term") ) + { + profile->setProperty(Profile::Environment, + QStringList() << "TERM="+config->readEntry("Term")); + } + if ( config->hasKey("Cwd") ) + { + profile->setProperty(Profile::Directory,config->readEntry("Cwd")); + } + + delete desktopFile; + delete config; + + return true; +} + +#include "Profile.moc" + diff --git a/src/Profile.h b/src/Profile.h new file mode 100644 index 000000000..8d27a35f6 --- /dev/null +++ b/src/Profile.h @@ -0,0 +1,409 @@ +/* + This source file is part of Konsole, a terminal emulator. + + Copyright (C) 2006-7 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. +*/ + +#ifndef PROFILE_H +#define PROFILE_H + +// Qt +#include +#include +#include +#include +#include + +#include + +class KConfigGroup; + +namespace Konsole +{ + +/** + * Represents a terminal set-up which can be used to + * set the initial state of new terminal sessions or applied + * to existing sessions. + * + * Profiles can be loaded from disk using ProfileReader instances + * and saved to disk using ProfileWriter instances. + */ +class Profile : public QObject +{ +Q_OBJECT + +public: + /** + * This enum describes the available properties + * which a Profile may consist of. + * + * Properties can be set using setProperty() and read + * using property() + */ + enum Property + { + /** (QString) Path to the profile's configuration file on-disk. */ + Path, + + /** (QString) The descriptive name of this profile. */ + Name, + /** (QString) TODO: Document me. */ + Title, + /** (QString) The name of the icon associated with this profile. This + * is used in menus and tabs to represent the profile. + */ + Icon, + /** + * (QString) The command to execute ( excluding arguments ) when creating a new terminal + * session using this profile. + */ + Command, + /** + * (QStringList) The arguments which are passed to the program specified by the Command property + * when creating a new terminal session using this profile. + */ + Arguments, + /** + * (QStringList) Additional environment variables ( in the form of NAME=VALUE pairs ) + * which are passed to the program specified by the Command property + * when creating a new terminal session using this profile. + */ + Environment, + /** (QString) The initial working directory for sessions created using this profile. */ + Directory, // QString + + /** (QString) The format used for tab titles when running normal commands. */ + LocalTabTitleFormat, + /** (QString) The format used for tab titles when the session is running a remote command (eg. SSH) */ + RemoteTabTitleFormat, + + /** (bool) Specifies whether the menu bar should be shown in the main application window. */ + ShowMenuBar, + /** (TabBarModeEnum) Specifies when the tab bar should be shown in the main application window. */ + TabBarMode, + + /** (QFont) The font to use in terminal displays using this profile. */ + Font, + /** (QString) + * The name of the color scheme to use in terminal displays using this profile. + * Color schemes are managed by the ColorSchemeManager class. + */ + ColorScheme, + + /** (QString) The name of the key bindings. + * Key bindings are managed by the KeyboardTranslatorManager class. + */ + KeyBindings, + + /** (HistoryModeEnum) Specifies the storage type used for keeping the output produced + * by terminal sessions using this profile. + */ + HistoryMode, + /** (int) Specifies the number of lines of output to remember in terminal sessions + * using this profile. Once the limit is reached, the oldest lines are lost. + * Only applicable if the HistoryMode property is FixedSizeHistory + */ + HistorySize, + /** + * (ScrollBarPositionEnum) Specifies the position of the scroll bar in + * terminal displays using this profile. + */ + ScrollBarPosition, + + /** TODO Document me*/ + SelectWordCharacters, + /** (bool) Specifies whether text in terminal displays is allowed to blink. */ + BlinkingTextEnabled, + /** (bool) Specifies whether the flow control keys ( typically Ctrl+S , Ctrl+Q ) + * have any effect. Also known as Xon/Xoff + */ + FlowControlEnabled, + /** (bool) Specifies whether programs running in the terminal are allowed to + * resize the terminal display. + */ + AllowProgramsToResizeWindow, + /** (bool) Specifies whether the cursor blinks ( in a manner similar + * to text editing applications ) + */ + BlinkingCursorEnabled, // bool + + /** (bool) If true, terminal displays use a fixed color to draw the cursor, + * specified by the CustomCursorColor property. Otherwise the cursor changes + * color to match the character underneath it. + */ + UseCustomCursorColor, + /** (CursorShapeEnum) The shape used by terminal displays to represent the cursor. */ + CursorShape, + /** (QColor) The color used by terminal displays to draw the cursor. Only applicable + * if the UseCustomCursorColor property is true. */ + CustomCursorColor, + + /** TODO Document me */ + // FIXME - Is this a duplicate of SelectWordCharacters? + WordCharacters // QString + }; + + /** This enum describes the available modes for showing or hiding the tab bar. */ + enum TabBarModeEnum + { + /** The tab bar is never shown. */ + AlwaysHideTabBar, + /** The tab bar is shown if there are multiple tabs open or hidden otherwise. */ + ShowTabBarAsNeeded, + /** The tab bar is always shown. */ + AlwaysShowTabBar + }; + + /** + * This enum describes the modes available to remember lines of output produced + * by the terminal. + */ + enum HistoryModeEnum + { + /** No output is remembered. As soon as lines of text are scrolled off-screen they are lost. */ + DisableHistory, + /** A fixed number of lines of output are remembered. Once the limit is reached, the oldest + * lines are lost. */ + FixedSizeHistory, + /** All output is remembered for the duration of the session. + * Typically this means that lines are recorded to + * a file as they are scrolled off-screen. + */ + UnlimitedHistory + }; + + /** + * This enum describes the positions where the terminal display's scroll bar may be placed. + */ + enum ScrollBarPositionEnum + { + /** Show the scroll-bar on the left of the terminal display. */ + ScrollBarLeft, + /** Show the scroll-bar on the right of the terminal display. */ + ScrollBarRight, + /** Do not show the scroll-bar. */ + ScrollBarHidden + }; + + /** This enum describes the shapes used to draw the cursor in terminal displays. */ + enum CursorShapeEnum + { + /** Use a solid rectangular block to draw the cursor. */ + BlockCursor, + /** Use an 'I' shape, similar to that used in text editing applications, to draw the cursor. */ + IBeamCursor, + /** Draw a line underneath the cursor's position. */ + UnderlineCursor + }; + + /** + * Constructs a new profile + */ + Profile(Profile* parent = 0); + virtual ~Profile() {} + + /** + * Changes the parent profile. When calling the property() method, + * if the specified property has not been set for this profile, + * the parent's value for the property will be returned instead. + */ + void setParent(Profile* parent); + + /** Returns the parent profile. */ + const Profile* parent() const; + + /** + * Returns the current value of the specified @p property. + * + * If the specified @p property has not been set in this profile, + * and a non-null parent was specified in the Profile's constructor, + * the parent's value for @p property will be returned. + */ + virtual QVariant property(Property property) const; + /** Sets the value of the specified @p property to @p value. */ + virtual void setProperty(Property property,const QVariant& value); + /** Returns true if the specified property has been set in this Profile instance. */ + virtual bool isPropertySet(Property property) const; + + /** Returns a map of the properties set in this Profile instance. */ + virtual QHash setProperties() const; + + /** Returns true if no properties have been set in this Profile instance. */ + bool isEmpty() const; + + /** + * Returns true if this is a 'hidden' profile which should not be displayed + * in menus. + */ + bool isHidden() const; + + /** Specifies whether this is a hidden profile. See isHidden() */ + void setHidden(bool hidden); + + // + // Convenience methods for property() and setProperty() go here + // + + /** Convenience method for property(Profile::Path) */ + QString path() const { return property(Profile::Path).value(); } + + /** Convenience method for property(Profile::Name) */ + QString name() const { return property(Profile::Name).value(); } + + /** Convenience method for property(Profile::Directory) */ + QString defaultWorkingDirectory() const + { return property(Profile::Directory).value(); } + + /** Convenience method for property(Profile::Icon) */ + QString icon() const { return property(Profile::Icon).value(); } + + /** Convenience method for property(Profile::Command) */ + QString command() const { return property(Profile::Command).value(); } + + /** Convenience method for property(Profile::Arguments) */ + QStringList arguments() const { return property(Profile::Arguments).value(); } + + /** Convenience method for property(Profile::Font) */ + QFont font() const { return property(Profile::Font).value(); } + + /** Convenience method for property(Profile::ColorScheme) */ + QString colorScheme() const { return property(Profile::ColorScheme).value(); } + + /** Convenience method for property(Profile::Environment) */ + QStringList environment() const { return property(Profile::Environment).value(); } + + /** + * Convenience method. + * Returns the value of the "TERM" value in the environment list. + */ + QString terminal() const { return "xterm"; } + + /** + * Returns true if @p name has been associated with an element + * from the Property enum or false otherwise. + */ + static bool isNameRegistered(const QString& name); + + /** + * Returns the element from the Property enum associated with the + * specified @p name. + */ + static Property lookupByName(const QString& name); + /** + * Returns the string names associated with the specified @p property from + * the Property enum, in the order the associations were created using + * registerName() + */ + static QList namesForProperty(Property property); + /** + * Adds an association between a string @p name and a @p property. + * Subsequent calls to lookupByName() with @p name as the argument + * will return @p property. + */ + static void registerName(Property property , const QString& name); + +private: + QHash _propertyValues; + QPointer _parent; + + bool _hidden; + + static QHash _propertyNames; +}; + +/** + * A profile which contains a number of default settings for various properties. + * This can be used as a parent for other profiles or a fallback in case + * a profile cannot be loaded from disk. + */ +class FallbackProfile : public Profile +{ +public: + FallbackProfile(); +}; + +/** Interface for all classes which can load profile settings from a file. */ +class ProfileReader +{ +public: + virtual ~ProfileReader() {} + /** Returns a list of paths to profiles which this reader can read. */ + virtual QStringList findProfiles() { return QStringList(); } + /** + * Attempts to read a profile from @p path and + * save the property values described into @p profile. + * + * Returns true if the profile was successfully read or false otherwise. + */ + virtual bool readProfile(const QString& path , Profile* profile) = 0; +}; +/** Reads a KDE 3 profile .desktop file. */ +class KDE3ProfileReader : public ProfileReader +{ +public: + virtual QStringList findProfiles(); + virtual bool readProfile(const QString& path , Profile* profile); +}; +/** Reads a KDE 4 .profile file. */ +class KDE4ProfileReader : public ProfileReader +{ +public: + virtual QStringList findProfiles(); + virtual bool readProfile(const QString& path , Profile* profile); +private: + template + void readStandardElement(const KConfigGroup& group , + char* name , + Profile* info , + Profile::Property property); +}; +/** Interface for all classes which can write profile settings to a file. */ +class ProfileWriter +{ +public: + virtual ~ProfileWriter() {} + /** + * Returns a suitable path-name for writing + * @p profile to. The path-name should be accepted by + * the corresponding ProfileReader class. + */ + virtual QString getPath(const Profile* profile) = 0; + /** + * Writes the properties and values from @p profile to the file specified by + * @p path. This profile should be readable by the corresponding ProfileReader class. + */ + virtual bool writeProfile(const QString& path , const Profile* profile) = 0; +}; +/** Writes a KDE 4 .profile file. */ +class KDE4ProfileWriter : public ProfileWriter +{ +public: + virtual QString getPath(const Profile* profile); + virtual bool writeProfile(const QString& path , const Profile* profile); + +private: + void writeStandardElement(KConfigGroup& group, + char* name, + const Profile* profile, + Profile::Property property); +}; + +} + +#endif // PROFILE_H diff --git a/src/RemoteConnectionDialog.cpp b/src/RemoteConnectionDialog.cpp index 998dcc37c..775a228a7 100644 --- a/src/RemoteConnectionDialog.cpp +++ b/src/RemoteConnectionDialog.cpp @@ -36,7 +36,7 @@ using namespace Konsole; RemoteConnectionDialog::RemoteConnectionDialog(QWidget* parent) : KDialog(parent) { - setCaption("New Remote Connection"); + setCaption(i18n("New Remote Connection")); setButtons( KDialog::Ok | KDialog::Cancel ); setButtonText( KDialog::Ok , i18n("Connect") ); diff --git a/src/SessionManager.cpp b/src/SessionManager.cpp index c74522e5c..cbefb8984 100644 --- a/src/SessionManager.cpp +++ b/src/SessionManager.cpp @@ -1,7 +1,7 @@ /* This source file is part of Konsole, a terminal emulator. - Copyright (C) 2006 by Robert Knight + Copyright (C) 2006-7 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 @@ -45,333 +45,6 @@ using namespace Konsole; SessionManager* SessionManager::_instance = 0; -QHash Profile::_propertyNames; - -FallbackProfile::FallbackProfile() - : Profile(0) -{ - // Fallback settings - setProperty(Name,i18n("Shell")); - setProperty(Command,getenv("SHELL")); - setProperty(Icon,"konsole"); - setProperty(Arguments,QStringList() << getenv("SHELL")); - setProperty(LocalTabTitleFormat,"%d : %n"); - setProperty(RemoteTabTitleFormat,"%H : %u"); - setProperty(TabBarMode,AlwaysShowTabBar); - setProperty(ShowMenuBar,true); - - setProperty(KeyBindings,"default"); - - setProperty(Font,QFont("Monospace")); - - setProperty(HistoryMode,FixedSizeHistory); - setProperty(HistorySize,1000); - setProperty(ScrollBarPosition,ScrollBarRight); - - setProperty(FlowControlEnabled,true); - setProperty(AllowProgramsToResizeWindow,true); - setProperty(BlinkingTextEnabled,true); - - setProperty(BlinkingCursorEnabled,false); - setProperty(CursorShape,BlockCursor); - setProperty(UseCustomCursorColor,false); - setProperty(CustomCursorColor,Qt::black); - - // default taken from KDE 3 - setProperty(WordCharacters,":@-./_~?&=%+#"); - - // Fallback should not be shown in menus - setHidden(true); -} - -Profile::Profile(Profile* parent) - : _parent(parent) - ,_hidden(false) -{ -} - -bool Profile::isHidden() const { return _hidden; } -void Profile::setHidden(bool hidden) { _hidden = hidden; } - -void Profile::setParent(Profile* parent) { _parent = parent; } -const Profile* Profile::parent() const { return _parent; } - -bool Profile::isEmpty() const -{ - return _propertyValues.isEmpty(); -} -QHash Profile::setProperties() const -{ - return _propertyValues; -} - -QVariant Profile::property(Property property) const -{ - if ( _propertyValues.contains(property) ) - return _propertyValues[property]; - else if ( _parent ) - return _parent->property(property); - else - return QVariant(); -} -void Profile::setProperty(Property property , const QVariant& value) -{ - _propertyValues.insert(property,value); -} -bool Profile::isPropertySet(Property property) const -{ - return _propertyValues.contains(property); -} - -bool Profile::isNameRegistered(const QString& name) -{ - return _propertyNames.contains(name); -} - -Profile::Property Profile::lookupByName(const QString& name) -{ - return _propertyNames[name]; -} - -QList Profile::namesForProperty(Property property) -{ - return _propertyNames.keys(property); -} -void Profile::registerName(Property property , const QString& name) -{ - _propertyNames.insert(name,property); -} - -QString KDE4ProfileWriter::getPath(const Profile* info) -{ - QString newPath; - - if ( info->isPropertySet(Profile::Path) ) - newPath=info->path(); - - // if the path is not specified, use the profile name + ".profile" - if ( newPath.isEmpty() ) - newPath = info->name() + ".profile"; - - QFileInfo fileInfo(newPath); - if (!fileInfo.isAbsolute()) - newPath = KGlobal::dirs()->saveLocation("data","konsole/") + newPath; - - qDebug() << "Saving profile under name: " << newPath; - - return newPath; -} -void KDE4ProfileWriter::writeStandardElement(KConfigGroup& group , char* name , const Profile* profile , - Profile::Property attribute) -{ - if ( profile->isPropertySet(attribute) ) - group.writeEntry(name,profile->property(attribute)); -} -bool KDE4ProfileWriter::writeProfile(const QString& path , const Profile* profile) -{ - KConfig config(path,KConfig::NoGlobals); - - // Basic Profile Settings - KConfigGroup general = config.group("General"); - - if ( profile->isPropertySet(Profile::Name) ) - general.writeEntry("Name",profile->name()); - - if ( profile->isPropertySet(Profile::Command) - || profile->isPropertySet(Profile::Arguments) ) - general.writeEntry("Command", - ShellCommand(profile->command(),profile->arguments()).fullCommand()); - - if ( profile->isPropertySet(Profile::Directory) ) - general.writeEntry("Directory",profile->defaultWorkingDirectory()); - - writeStandardElement( general , "Icon" , profile , Profile::Icon ); - - // Tab Titles - writeStandardElement( general , "LocalTabTitleFormat" , profile , Profile::LocalTabTitleFormat ); - writeStandardElement( general , "RemoteTabTitleFormat" , profile , Profile::RemoteTabTitleFormat ); - - // Menu and Tab Bar - writeStandardElement( general , "TabBarMode" , profile , Profile::TabBarMode ); - writeStandardElement( general , "ShowMenuBar" , profile , Profile::ShowMenuBar ); - - // Keyboard - KConfigGroup keyboard = config.group("Keyboard"); - writeStandardElement( keyboard , "KeyBindings" , profile , Profile::KeyBindings ); - - // Appearance - KConfigGroup appearance = config.group("Appearance"); - - writeStandardElement( appearance , "ColorScheme" , profile , Profile::ColorScheme ); - writeStandardElement( appearance , "Font" , profile , Profile::Font ); - - // Scrolling - KConfigGroup scrolling = config.group("Scrolling"); - - writeStandardElement( scrolling , "HistoryMode" , profile , Profile::HistoryMode ); - writeStandardElement( scrolling , "HistorySize" , profile , Profile::HistorySize ); - writeStandardElement( scrolling , "ScrollBarPosition" , profile , Profile::ScrollBarPosition ); - - // Terminal Features - KConfigGroup terminalFeatures = config.group("Terminal Features"); - - writeStandardElement( terminalFeatures , "FlowControl" , profile , Profile::FlowControlEnabled ); - writeStandardElement( terminalFeatures , "BlinkingCursor" , profile , Profile::BlinkingCursorEnabled ); - - // Cursor - KConfigGroup cursorOptions = config.group("Cursor Options"); - - writeStandardElement( cursorOptions , "UseCustomCursorColor" , profile , Profile::UseCustomCursorColor ); - writeStandardElement( cursorOptions , "CustomCursorColor" , profile , Profile::CustomCursorColor ); - writeStandardElement( cursorOptions , "CursorShape" , profile , Profile::CursorShape ); - - // Interaction - KConfigGroup interactionOptions = config.group("Interaction Options"); - - writeStandardElement( interactionOptions , "WordCharacters" , profile , Profile::WordCharacters ); - - return true; -} - -QStringList KDE4ProfileReader::findProfiles() -{ - return KGlobal::dirs()->findAllResources("data","konsole/*.profile", - KStandardDirs::NoDuplicates); -} -bool KDE4ProfileReader::readProfile(const QString& path , Profile* profile) -{ - qDebug() << "KDE 4 Profile Reader:" << path; - - KConfig config(path,KConfig::NoGlobals); - - // general - KConfigGroup general = config.group("General"); - - if ( general.hasKey("Name") ) - profile->setProperty(Profile::Name,general.readEntry("Name")); - else - return false; - - if ( general.hasKey("Command") ) - { - ShellCommand shellCommand(general.readEntry("Command")); - - profile->setProperty(Profile::Command,shellCommand.command()); - profile->setProperty(Profile::Arguments,shellCommand.arguments()); - } - - readStandardElement(general,"Directory",profile,Profile::Directory); - - readStandardElement(general,"Icon",profile,Profile::Icon); - readStandardElement(general,"LocalTabTitleFormat",profile,Profile::LocalTabTitleFormat); - readStandardElement(general,"RemoteTabTitleFormat",profile,Profile::RemoteTabTitleFormat); - - readStandardElement(general,"TabBarMode",profile,Profile::TabBarMode); - readStandardElement(general,"ShowMenuBar",profile,Profile::ShowMenuBar); - - // keyboard - KConfigGroup keyboard = config.group("Keyboard"); - readStandardElement(keyboard,"KeyBindings",profile,Profile::KeyBindings); - - // appearence - KConfigGroup appearance = config.group("Appearance"); - - readStandardElement(appearance,"ColorScheme",profile,Profile::ColorScheme); - readStandardElement(appearance,"Font",profile,Profile::Font); - - // scrolling - KConfigGroup scrolling = config.group("Scrolling"); - - readStandardElement(scrolling,"HistoryMode",profile,Profile::HistoryMode); - readStandardElement(scrolling,"HistorySize",profile,Profile::HistorySize); - readStandardElement(scrolling,"ScrollBarPosition",profile,Profile::ScrollBarPosition); - - // terminal features - KConfigGroup terminalFeatures = config.group("Terminal Features"); - - readStandardElement(terminalFeatures,"FlowControl",profile,Profile::FlowControlEnabled); - readStandardElement(terminalFeatures,"BlinkingCursor",profile,Profile::BlinkingCursorEnabled); - - // cursor settings - KConfigGroup cursorOptions = config.group("Cursor Options"); - - readStandardElement(cursorOptions,"UseCustomCursorColor",profile,Profile::UseCustomCursorColor); - readStandardElement(cursorOptions,"CustomCursorColor",profile,Profile::CustomCursorColor); - readStandardElement(cursorOptions,"CursorShape",profile,Profile::CursorShape); - - // interaction options - KConfigGroup interactionOptions = config.group("Interaction Options"); - - readStandardElement(interactionOptions,"WordCharacters",profile,Profile::WordCharacters); - - return true; -} -template -void KDE4ProfileReader::readStandardElement(const KConfigGroup& group , - char* name , - Profile* info , - Profile::Property property) -{ - if ( group.hasKey(name) ) - info->setProperty(property,group.readEntry(name,T())); -} - -QStringList KDE3ProfileReader::findProfiles() -{ - return KGlobal::dirs()->findAllResources("data", "konsole/*.desktop", - KStandardDirs::NoDuplicates); -} -bool KDE3ProfileReader::readProfile(const QString& path , Profile* profile) -{ - if (!QFile::exists(path)) - return false; - - KDesktopFile* desktopFile = new KDesktopFile(path); - KConfigGroup* config = new KConfigGroup( desktopFile->desktopGroup() ); - - if ( config->hasKey("Name") ) - profile->setProperty(Profile::Name,config->readEntry("Name")); - - qDebug() << "reading KDE 3 profile " << profile->name(); - - if ( config->hasKey("Icon") ) - profile->setProperty(Profile::Icon,config->readEntry("Icon")); - if ( config->hasKey("Exec") ) - { - const QString& fullCommand = config->readEntry("Exec"); - ShellCommand shellCommand(fullCommand); - - profile->setProperty(Profile::Command,shellCommand.command()); - profile->setProperty(Profile::Arguments,shellCommand.arguments()); - } - if ( config->hasKey("Schema") ) - { - profile->setProperty(Profile::ColorScheme,config->readEntry("Schema").replace - (".schema",QString())); - } - if ( config->hasKey("defaultfont") ) - { - profile->setProperty(Profile::Font,config->readEntry("defaultfont")); - } - if ( config->hasKey("KeyTab") ) - { - profile->setProperty(Profile::KeyBindings,config->readEntry("KeyTab")); - } - if ( config->hasKey("Term") ) - { - profile->setProperty(Profile::Environment, - QStringList() << "TERM="+config->readEntry("Term")); - } - if ( config->hasKey("Cwd") ) - { - profile->setProperty(Profile::Directory,config->readEntry("Cwd")); - } - - delete desktopFile; - delete config; - - return true; -} #if 0 @@ -418,9 +91,9 @@ SessionManager::SessionManager() Q_ASSERT( _types.count() > 0 ); Q_ASSERT( !_defaultProfile.isEmpty() ); - // now that the session types have been loaded, - // get the list of favorite sessions - //loadFavorites(); + // get shortcuts and paths of profiles associated with + // them + loadShortcuts(); } QString SessionManager::loadProfile(const QString& path) { @@ -430,7 +103,7 @@ QString SessionManager::loadProfile(const QString& path) { iter.next(); if ( iter.value()->path() == path ) - return QString(); + return iter.key(); } // load the profile @@ -483,6 +156,9 @@ SessionManager::~SessionManager() // save default profile setDefaultProfile( _defaultProfile ); + // save shortcuts + saveShortcuts(); + // free profiles QListIterator infoIter(_types.values()); @@ -803,6 +479,57 @@ void SessionManager::setFavorite(const QString& key , bool favorite) } } +void SessionManager::loadShortcuts() +{ + KSharedConfigPtr appConfig = KGlobal::config(); + KConfigGroup shortcutGroup = appConfig->group("Profile Shortcuts"); + + QMap entries = shortcutGroup.entryMap(); + + QMapIterator iter(entries); + while ( iter.hasNext() ) + { + iter.next(); + + QKeySequence shortcut = QKeySequence::fromString(iter.key()); + QString profilePath = iter.value(); + + ShortcutData data; + data.profilePath = profilePath; + + _shortcuts.insert(shortcut,data); + } +} +void SessionManager::saveShortcuts() +{ + KSharedConfigPtr appConfig = KGlobal::config(); + KConfigGroup shortcutGroup = appConfig->group("Profile Shortcuts"); + shortcutGroup.deleteGroup(); + + QMapIterator iter(_shortcuts); + while ( iter.hasNext() ) + { + iter.next(); + + QString shortcutString = iter.key().toString(); + + shortcutGroup.writeEntry(shortcutString, + iter.value().profilePath); + } +} +void SessionManager::setShortcut(const QString& profileKey , + const QKeySequence& keySequence ) +{ + QKeySequence existingShortcut = shortcut(profileKey); + _shortcuts.remove(existingShortcut); + + ShortcutData data; + data.profileKey = profileKey; + data.profilePath = profile(profileKey)->path(); + // TODO - This won't work if the profile doesn't + // have a path yet + _shortcuts.insert(keySequence,data); +} void SessionManager::loadFavorites() { KSharedConfigPtr appConfig = KGlobal::config(); @@ -859,6 +586,41 @@ void SessionManager::saveFavorites() favoriteGroup.writeEntry("Favorites",paths); } + +QList SessionManager::shortcuts() +{ + return _shortcuts.keys(); +} + +QString SessionManager::findByShortcut(const QKeySequence& shortcut) +{ + Q_ASSERT( _shortcuts.contains(shortcut) ); + + if ( _shortcuts[shortcut].profileKey.isEmpty() ) + { + QString key = loadProfile(_shortcuts[shortcut].profilePath); + _shortcuts[shortcut].profileKey = key; + } + + return _shortcuts[shortcut].profileKey; +} + +QKeySequence SessionManager::shortcut(const QString& profileKey) const +{ + Profile* info = profile(profileKey); + + QMapIterator iter(_shortcuts); + while (iter.hasNext()) + { + iter.next(); + if ( iter.value().profileKey == profileKey + || iter.value().profilePath == info->path() ) + return iter.key(); + } + // dummy + return QKeySequence(Qt::CTRL+Qt::ALT+Qt::Key_B); +} + void SessionManager::setInstance(SessionManager* instance) { _instance = instance; @@ -868,4 +630,5 @@ SessionManager* SessionManager::instance() return _instance; } + #include "SessionManager.moc" diff --git a/src/SessionManager.h b/src/SessionManager.h index 19018587a..9f9beed92 100644 --- a/src/SessionManager.h +++ b/src/SessionManager.h @@ -24,6 +24,8 @@ // Qt #include +#include + #include #include #include @@ -32,6 +34,9 @@ #include #include +// Konsole +#include "Profile.h" + class QSignalMapper; class KConfigGroup; @@ -43,378 +48,10 @@ namespace Konsole class Session; -/** - * Represents a terminal set-up which can be used to - * set the initial state of new terminal sessions or applied - * to existing sessions. - * - * Profiles can be loaded from disk using ProfileReader instances - * and saved to disk using ProfileWriter instances. - */ -class Profile : public QObject -{ -public: - /** - * This enum describes the available properties - * which a Profile may consist of. - * - * Properties can be set using setProperty() and read - * using property() - */ - enum Property - { - /** (QString) Path to the profile's configuration file on-disk. */ - Path, - - /** (QString) The descriptive name of this profile. */ - Name, - /** (QString) TODO: Document me. */ - Title, - /** (QString) The name of the icon associated with this profile. This - * is used in menus and tabs to represent the profile. - */ - Icon, - /** - * (QString) The command to execute ( excluding arguments ) when creating a new terminal - * session using this profile. - */ - Command, - /** - * (QStringList) The arguments which are passed to the program specified by the Command property - * when creating a new terminal session using this profile. - */ - Arguments, - /** - * (QStringList) Additional environment variables ( in the form of NAME=VALUE pairs ) - * which are passed to the program specified by the Command property - * when creating a new terminal session using this profile. - */ - Environment, - /** (QString) The initial working directory for sessions created using this profile. */ - Directory, // QString - - /** (QString) The format used for tab titles when running normal commands. */ - LocalTabTitleFormat, - /** (QString) The format used for tab titles when the session is running a remote command (eg. SSH) */ - RemoteTabTitleFormat, - - /** (bool) Specifies whether the menu bar should be shown in the main application window. */ - ShowMenuBar, - /** (TabBarModeEnum) Specifies when the tab bar should be shown in the main application window. */ - TabBarMode, - - /** (QFont) The font to use in terminal displays using this profile. */ - Font, - /** (QString) - * The name of the color scheme to use in terminal displays using this profile. - * Color schemes are managed by the ColorSchemeManager class. - */ - ColorScheme, - - /** (QString) The name of the key bindings. - * Key bindings are managed by the KeyboardTranslatorManager class. - */ - KeyBindings, - - /** (HistoryModeEnum) Specifies the storage type used for keeping the output produced - * by terminal sessions using this profile. - */ - HistoryMode, - /** (int) Specifies the number of lines of output to remember in terminal sessions - * using this profile. Once the limit is reached, the oldest lines are lost. - * Only applicable if the HistoryMode property is FixedSizeHistory - */ - HistorySize, - /** - * (ScrollBarPositionEnum) Specifies the position of the scroll bar in - * terminal displays using this profile. - */ - ScrollBarPosition, - - /** TODO Document me*/ - SelectWordCharacters, - /** (bool) Specifies whether text in terminal displays is allowed to blink. */ - BlinkingTextEnabled, - /** (bool) Specifies whether the flow control keys ( typically Ctrl+S , Ctrl+Q ) - * have any effect. Also known as Xon/Xoff - */ - FlowControlEnabled, - /** (bool) Specifies whether programs running in the terminal are allowed to - * resize the terminal display. - */ - AllowProgramsToResizeWindow, - /** (bool) Specifies whether the cursor blinks ( in a manner similar - * to text editing applications ) - */ - BlinkingCursorEnabled, // bool - - /** (bool) If true, terminal displays use a fixed color to draw the cursor, - * specified by the CustomCursorColor property. Otherwise the cursor changes - * color to match the character underneath it. - */ - UseCustomCursorColor, - /** (CursorShapeEnum) The shape used by terminal displays to represent the cursor. */ - CursorShape, - /** (QColor) The color used by terminal displays to draw the cursor. Only applicable - * if the UseCustomCursorColor property is true. */ - CustomCursorColor, - - /** TODO Document me */ - // FIXME - Is this a duplicate of SelectWordCharacters? - WordCharacters // QString - }; - - /** This enum describes the available modes for showing or hiding the tab bar. */ - enum TabBarModeEnum - { - /** The tab bar is never shown. */ - AlwaysHideTabBar, - /** The tab bar is shown if there are multiple tabs open or hidden otherwise. */ - ShowTabBarAsNeeded, - /** The tab bar is always shown. */ - AlwaysShowTabBar - }; - - /** - * This enum describes the modes available to remember lines of output produced - * by the terminal. - */ - enum HistoryModeEnum - { - /** No output is remembered. As soon as lines of text are scrolled off-screen they are lost. */ - DisableHistory, - /** A fixed number of lines of output are remembered. Once the limit is reached, the oldest - * lines are lost. */ - FixedSizeHistory, - /** All output is remembered for the duration of the session. - * Typically this means that lines are recorded to - * a file as they are scrolled off-screen. - */ - UnlimitedHistory - }; - - /** - * This enum describes the positions where the terminal display's scroll bar may be placed. - */ - enum ScrollBarPositionEnum - { - /** Show the scroll-bar on the left of the terminal display. */ - ScrollBarLeft, - /** Show the scroll-bar on the right of the terminal display. */ - ScrollBarRight, - /** Do not show the scroll-bar. */ - ScrollBarHidden - }; - - /** This enum describes the shapes used to draw the cursor in terminal displays. */ - enum CursorShapeEnum - { - /** Use a solid rectangular block to draw the cursor. */ - BlockCursor, - /** Use an 'I' shape, similar to that used in text editing applications, to draw the cursor. */ - IBeamCursor, - /** Draw a line underneath the cursor's position. */ - UnderlineCursor - }; - - /** - * Constructs a new profile - */ - Profile(Profile* parent = 0); - virtual ~Profile() {} - - /** - * Changes the parent profile. When calling the property() method, - * if the specified property has not been set for this profile, - * the parent's value for the property will be returned instead. - */ - void setParent(Profile* parent); - - /** Returns the parent profile. */ - const Profile* parent() const; - - /** - * Returns the current value of the specified @p property. - * - * If the specified @p property has not been set in this profile, - * and a non-null parent was specified in the Profile's constructor, - * the parent's value for @p property will be returned. - */ - virtual QVariant property(Property property) const; - /** Sets the value of the specified @p property to @p value. */ - virtual void setProperty(Property property,const QVariant& value); - /** Returns true if the specified property has been set in this Profile instance. */ - virtual bool isPropertySet(Property property) const; - - /** Returns a map of the properties set in this Profile instance. */ - virtual QHash setProperties() const; - - /** Returns true if no properties have been set in this Profile instance. */ - bool isEmpty() const; - - /** - * Returns true if this is a 'hidden' profile which should not be displayed - * in menus. - */ - bool isHidden() const; - - /** Specifies whether this is a hidden profile. See isHidden() */ - void setHidden(bool hidden); - - // - // Convenience methods for property() and setProperty() go here - // - - /** Convenience method for property(Profile::Path) */ - QString path() const { return property(Profile::Path).value(); } - - /** Convenience method for property(Profile::Name) */ - QString name() const { return property(Profile::Name).value(); } - - /** Convenience method for property(Profile::Directory) */ - QString defaultWorkingDirectory() const - { return property(Profile::Directory).value(); } - - /** Convenience method for property(Profile::Icon) */ - QString icon() const { return property(Profile::Icon).value(); } - - /** Convenience method for property(Profile::Command) */ - QString command() const { return property(Profile::Command).value(); } - - /** Convenience method for property(Profile::Arguments) */ - QStringList arguments() const { return property(Profile::Arguments).value(); } - - /** Convenience method for property(Profile::Font) */ - QFont font() const { return property(Profile::Font).value(); } - - /** Convenience method for property(Profile::ColorScheme) */ - QString colorScheme() const { return property(Profile::ColorScheme).value(); } - - /** Convenience method for property(Profile::Environment) */ - QStringList environment() const { return property(Profile::Environment).value(); } - - /** - * Convenience method. - * Returns the value of the "TERM" value in the environment list. - */ - QString terminal() const { return "xterm"; } - - /** - * Returns true if @p name has been associated with an element - * from the Property enum or false otherwise. - */ - static bool isNameRegistered(const QString& name); - - /** - * Returns the element from the Property enum associated with the - * specified @p name. - */ - static Property lookupByName(const QString& name); - /** - * Returns the string names associated with the specified @p property from - * the Property enum, in the order the associations were created using - * registerName() - */ - static QList namesForProperty(Property property); - /** - * Adds an association between a string @p name and a @p property. - * Subsequent calls to lookupByName() with @p name as the argument - * will return @p property. - */ - static void registerName(Property property , const QString& name); - -private: - QHash _propertyValues; - QPointer _parent; - - bool _hidden; - - static QHash _propertyNames; -}; - -/** - * A profile which contains a number of default settings for various properties. - * This can be used as a parent for other profiles or a fallback in case - * a profile cannot be loaded from disk. - */ -class FallbackProfile : public Profile -{ -public: - FallbackProfile(); -}; - -/** Interface for all classes which can load profile settings from a file. */ -class ProfileReader -{ -public: - virtual ~ProfileReader() {} - /** Returns a list of paths to profiles which this reader can read. */ - virtual QStringList findProfiles() { return QStringList(); } - /** - * Attempts to read a profile from @p path and - * save the property values described into @p profile. - * - * Returns true if the profile was successfully read or false otherwise. - */ - virtual bool readProfile(const QString& path , Profile* profile) = 0; -}; -/** Reads a KDE 3 profile .desktop file. */ -class KDE3ProfileReader : public ProfileReader -{ -public: - virtual QStringList findProfiles(); - virtual bool readProfile(const QString& path , Profile* profile); -}; -/** Reads a KDE 4 .profile file. */ -class KDE4ProfileReader : public ProfileReader -{ -public: - virtual QStringList findProfiles(); - virtual bool readProfile(const QString& path , Profile* profile); -private: - template - void readStandardElement(const KConfigGroup& group , - char* name , - Profile* info , - Profile::Property property); -}; -/** Interface for all classes which can write profile settings to a file. */ -class ProfileWriter -{ -public: - virtual ~ProfileWriter() {} - /** - * Returns a suitable path-name for writing - * @p profile to. The path-name should be accepted by - * the corresponding ProfileReader class. - */ - virtual QString getPath(const Profile* profile) = 0; - /** - * Writes the properties and values from @p profile to the file specified by - * @p path. This profile should be readable by the corresponding ProfileReader class. - */ - virtual bool writeProfile(const QString& path , const Profile* profile) = 0; -}; -/** Writes a KDE 4 .profile file. */ -class KDE4ProfileWriter : public ProfileWriter -{ -public: - virtual QString getPath(const Profile* profile); - virtual bool writeProfile(const QString& path , const Profile* profile); - -private: - void writeStandardElement(KConfigGroup& group, - char* name, - const Profile* profile, - Profile::Property property); -}; - /** * Manages running terminal sessions and the profiles which specify various * settings for terminal sessions and their displays. * - * - * * Profiles in the manager have a concept of favorite status, which can be used * by widgets and dialogs in the application decide which sessions to list and * how to display them. The favorite status of a profile can be altered using @@ -526,6 +163,32 @@ public: */ QSet findFavorites() ; + /** + * Returns the list of shortcut key sequences which + * can be used to create new sessions based on + * existing profiles + * + * When one of the shortcuts is activated, + * use findByShortcut() to load the profile associated + * with the shortcut and obtain its key. + */ + QList shortcuts(); + + /** + * Finds and loads the profile associated with + * the specified @p shortcut key sequence and returns + * its string key. + */ + QString findByShortcut(const QKeySequence& shortcut); + + /** + * Associates a shortcut with a particular profile. + */ + void setShortcut(const QString& key , const QKeySequence& shortcut); + + /** Returns the shortcut associated with a particular profile. */ + QKeySequence shortcut(const QString& profileKey) const; + /** * Specifies whether a profile should be included in the user's * list of favorite sessions. @@ -570,6 +233,13 @@ protected Q_SLOTS: void sessionTerminated( QObject* session ); private: + // loads the mappings between shortcut key sequences and + // profile paths + void loadShortcuts(); + // saves the mappings between shortcut key sequences and + // profile paths + void saveShortcuts(); + //loads the set of favorite sessions void loadFavorites(); //saves the set of favorite sessions @@ -590,14 +260,22 @@ private: // returns true ) void applyProfile(Session* session , const Profile* info , bool modifiedPropertiesOnly); - QHash _types; - QList _sessions; - - QString _defaultProfile; + QHash _types; // profile key -> Profile instance - QSet _favorites; + struct ShortcutData + { + QString profileKey; + QString profilePath; + }; + QMap _shortcuts; // shortcut keys -> profile path - bool _loadedAllProfiles; + QList _sessions; // list of running sessions + + QString _defaultProfile; // profile key of default profile + + QSet _favorites; // list of profile keys for favorite profiles + + bool _loadedAllProfiles; // set to true after loadAllProfiles has been called QSignalMapper* _sessionMapper; diff --git a/src/ViewManager.cpp b/src/ViewManager.cpp index 50d3b767c..09c4af491 100644 --- a/src/ViewManager.cpp +++ b/src/ViewManager.cpp @@ -469,49 +469,6 @@ void ViewManager::viewCloseRequest(QWidget* view) focusActiveView(); } -void ViewManager::merge(ViewManager* otherManager) -{ - // iterate over the views in otherManager's active container and take them from that - // manager and put them in the active container in this manager - // - // TODO - This currently does not consider views in containers other than - // the active one in the other manager - // - ViewSplitter* otherSplitter = otherManager->_viewSplitter; - ViewContainer* otherContainer = otherSplitter->activeContainer(); - - QListIterator otherViewIter(otherContainer->views()); - - ViewContainer* activeContainer = _viewSplitter->activeContainer(); - - while ( otherViewIter.hasNext() ) - { - TerminalDisplay* view = dynamic_cast(otherViewIter.next()); - - assert(view); - assert( otherManager->_sessionMap[view] ); - - createView(otherManager->_sessionMap[view]); - } -} - - -/*void ViewManager::takeView(ViewManager* otherManager , ViewContainer* otherContainer, - ViewContainer* newContainer, TerminalDisplay* view) -{ - // FIXME - the controller associated with the display which is being moved - // may have signals which are connected to otherManager. they need - // to be redirected to slots in this view manager - ViewProperties* properties = otherContainer->viewProperties(view); - otherContainer->removeView(view); - - newContainer->addView(view,properties); - - // transfer the session map entries - _sessionMap.insert(view,otherManager->_sessionMap[view]); - otherManager->_sessionMap.remove(view); -}*/ - TerminalDisplay* ViewManager::createTerminalDisplay() { TerminalDisplay* display = new TerminalDisplay(0); diff --git a/src/ViewManager.h b/src/ViewManager.h index 930dd5529..b7613456a 100644 --- a/src/ViewManager.h +++ b/src/ViewManager.h @@ -87,12 +87,6 @@ public: */ void applyProfile(TerminalDisplay* view , const QString& profile); - /** - * Merges views from another view manager into this manager. - * Only views from the active container in the other manager are merged. - */ - void merge(ViewManager* manager); - /** * Return the main widget for the view manager which * holds all of the views managed by this ViewManager instance. diff --git a/src/SPLIT-VIEW-TODO b/src/old/SPLIT-VIEW-TODO similarity index 100% rename from src/SPLIT-VIEW-TODO rename to src/old/SPLIT-VIEW-TODO