From 34a9e7ec42748e082edff2a627946a85fc87de19 Mon Sep 17 00:00:00 2001 From: Robert Knight Date: Fri, 2 May 2008 00:59:47 +0000 Subject: [PATCH] * Add option to show new tab button with delayed popup menu on tab bar. Go to Settings -> Edit Current Profile -> Tabs page and tick "Show 'New tab' button in tab bar" This was added for the benefit of users with existing habits from KDE 3 and is not shown by default. * Add close buttons on tabs using the new style ppenz added to KTabBar * Add confirmation when closing via middle-click/close button if a program other than a shell or nested shell is running in the foreground of that session. BUG: 157015 Squashed commit of the following: commit 54a5db9c31a5527e44d7358b30587c28bab965bc Author: Robert Knight Date: Fri May 2 01:48:05 2008 +0100 UI text correction: 'on tab bar' -> 'in tab bar' commit ed8e70238e2cc4240f8334cd091fa2707785a908 Author: Robert Knight Date: Fri May 2 01:46:42 2008 +0100 Do not show the confirm-on-close prompt if the foreground program is another shell. commit 010370c12950a532d93c99d0983c74c47e26ad07 Author: Robert Knight Date: Fri May 2 01:40:05 2008 +0100 Add a confirmation which is displayed when closing a tab via middle-click / close button if the program has an active program running in the session (other than the shell itself). commit 49812e26e5fd8c44dd01f1a6a4c0e7271c6366fd Author: Robert Knight Date: Fri May 2 01:25:29 2008 +0100 Add confirmClose() method to ViewProperties which is can be re-implemented to prompt whether to close the session. Make the presence of the close button in the ViewContainer dependent on a QuickCloseView feature being enabled. commit ece191ad5ad550af47cd2ca0bc75a517119e7189 Author: Robert Knight Date: Fri May 2 01:09:17 2008 +0100 Show 'close' button on tabs using the new close button style added to KTabBar by ppenz. commit f975f04c993effdd2afef588c5f765192b6fab5a Author: Robert Knight Date: Fri May 2 01:03:54 2008 +0100 Better UI text for 'Show New Tab' option. commit 642c5b1d07cd2288c78446efe395da050730decb Author: Robert Knight Date: Thu May 1 21:04:47 2008 +0100 Sync 'new tab' tab bar menu actions with profile list. commit c6c556980e43afcb1bb5fdfaaa9dd7e12e524688 Author: Robert Knight Date: Wed Apr 30 23:01:34 2008 +0100 Hook up actions in new tab popup menu so a new tab is created with the right profile when an action is chosen. commit dece8a23ff101dda47d495ba38e57e55059c4e63 Author: Robert Knight Date: Wed Apr 30 22:51:28 2008 +0100 Apply ShowNewTabButton profile property to current view container. commit e244a95512dc535198fa69c3afe34b597402de15 Author: Robert Knight Date: Wed Apr 30 22:50:57 2008 +0100 Add support for enabling/disabling a 'quick new view' widget in view containers. Add an implementation of it (quick new tab button) in TabbedViewContainerV2 commit 9fdc2e450aefb9b602f8fb6b66d3508e6750531b Author: Robert Knight Date: Wed Apr 30 22:50:22 2008 +0100 Hook up 'Show new tab button' UI option. commit 7326e6dccbc095f0f784fd6f4da532f250ca5437 Author: Robert Knight Date: Wed Apr 30 22:50:04 2008 +0100 Add ShowNewTabButton profile property and set a default for it (false) commit 273f85f0d21d8b755712c67c50a939400f15a169 Author: Robert Knight Date: Wed Apr 30 21:22:09 2008 +0100 Add checkbox for toggling new tab menu button. commit 200744ce620cd6bd9a9d1791e62863c618921788 Author: Robert Knight Date: Wed Apr 30 21:21:33 2008 +0100 Formatting. Remove extra lines. svn path=/trunk/KDE/kdebase/apps/konsole/; revision=803112 --- src/EditProfileDialog.cpp | 5 ++++ src/EditProfileDialog.h | 1 + src/EditProfileDialog.ui | 24 ++++++++++++---- src/MainWindow.cpp | 5 +++- src/Profile.cpp | 4 ++- src/Profile.h | 5 +++- src/ProfileList.cpp | 23 +++++++++++++-- src/ProfileList.h | 4 +++ src/SessionController.cpp | 30 ++++++++++++++++++++ src/SessionController.h | 1 + src/ViewContainer.cpp | 60 +++++++++++++++++++++++++++++++++------ src/ViewContainer.h | 56 +++++++++++++++++++++++++----------- src/ViewManager.cpp | 28 ++++++++++++++++++ src/ViewManager.h | 16 +++++------ src/ViewProperties.h | 31 +++++++++++++------- 15 files changed, 238 insertions(+), 55 deletions(-) diff --git a/src/EditProfileDialog.cpp b/src/EditProfileDialog.cpp index fd588fc62..d1a63b37f 100644 --- a/src/EditProfileDialog.cpp +++ b/src/EditProfileDialog.cpp @@ -280,12 +280,15 @@ void EditProfileDialog::setupTabsPage(const Profile::Ptr info) << i18n("Above Terminal Displays") ); _ui->tabBarPositionCombo->setCurrentIndex(tabPosition); + _ui->newTabButton->setChecked(info->property(Profile::ShowNewTabButton)); // signals and slots connect( _ui->tabBarVisibilityCombo , SIGNAL(activated(int)) , this , SLOT(tabBarVisibilityChanged(int)) ); connect( _ui->tabBarPositionCombo , SIGNAL(activated(int)) , this , SLOT(tabBarPositionChanged(int)) ); + connect( _ui->newTabButton , SIGNAL(toggled(bool)) , this , + SLOT(showNewTabButton(bool)) ); connect(_ui->tabTitleEdit , SIGNAL(textChanged(const QString&)) , this , SLOT(tabTitleFormatChanged(const QString&)) ); @@ -305,6 +308,8 @@ void EditProfileDialog::setupTabsPage(const Profile::Ptr info) connect( remoteTabTitleAction , SIGNAL(dynamicElementSelected(const QString&)) , this , SLOT(insertRemoteTabTitleText(const QString&)) ); } +void EditProfileDialog::showNewTabButton(bool show) +{ _tempProfile->setProperty(Profile::ShowNewTabButton,show); } void EditProfileDialog::tabBarVisibilityChanged(int newValue) { _tempProfile->setProperty( Profile::TabBarMode , newValue ); diff --git a/src/EditProfileDialog.h b/src/EditProfileDialog.h index 4a7c9ee17..0359217ab 100644 --- a/src/EditProfileDialog.h +++ b/src/EditProfileDialog.h @@ -123,6 +123,7 @@ private slots: void showEnvironmentEditor(); void tabBarVisibilityChanged(int); void tabBarPositionChanged(int); + void showNewTabButton(bool); // appearance page void setFontSize(int pointSize); diff --git a/src/EditProfileDialog.ui b/src/EditProfileDialog.ui index 78a4198f7..12013f7d3 100644 --- a/src/EditProfileDialog.ui +++ b/src/EditProfileDialog.ui @@ -246,7 +246,7 @@ 0 0 429 - 491 + 476 @@ -333,6 +333,9 @@ Tab bar display: + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + @@ -353,6 +356,9 @@ Tab bar position: + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + @@ -365,6 +371,13 @@ + + + + Show 'New Tab' button in tab bar + + + @@ -462,8 +475,7 @@ - - + @@ -573,7 +585,7 @@ 0 0 429 - 491 + 476 @@ -751,7 +763,7 @@ 0 0 429 - 491 + 476 @@ -841,7 +853,7 @@ 0 0 429 - 491 + 476 diff --git a/src/MainWindow.cpp b/src/MainWindow.cpp index 1184367d3..a99df3e92 100644 --- a/src/MainWindow.cpp +++ b/src/MainWindow.cpp @@ -78,7 +78,10 @@ MainWindow::MainWindow() connect( _viewManager , SIGNAL(setMenuBarVisibleRequest(bool)) , this , SLOT(setMenuBarVisibleOnce(bool)) ); - connect( _viewManager , SIGNAL(newViewRequest()) , this , SLOT(newTab()) ); + connect( _viewManager , SIGNAL(newViewRequest(Profile::Ptr)) , + this , SLOT(newFromProfile(Profile::Ptr)) ); + connect( _viewManager , SIGNAL(newViewRequest()) , + this , SLOT(newTab())); // create main window widgets setupWidgets(); diff --git a/src/Profile.cpp b/src/Profile.cpp index a2a8507c3..205826797 100644 --- a/src/Profile.cpp +++ b/src/Profile.cpp @@ -79,7 +79,8 @@ const Profile::PropertyInfo Profile::DefaultPropertyNames[] = , { TabBarMode , "TabBarMode" , GENERAL_GROUP , QVariant::Int } , { TabBarPosition , "TabBarPosition" , GENERAL_GROUP , QVariant::Int } , { StartInCurrentSessionDir , "StartInCurrentSessionDir" , GENERAL_GROUP , QVariant::Bool } - + , { ShowNewTabButton, "ShowNewTabButton" , GENERAL_GROUP , QVariant::Bool } + // Appearance , { Font , "Font" , APPEARANCE_GROUP , QVariant::Font } , { ColorScheme , "ColorScheme" , APPEARANCE_GROUP , QVariant::String } @@ -150,6 +151,7 @@ FallbackProfile::FallbackProfile() setProperty(TabBarPosition,TabBarBottom); setProperty(ShowMenuBar,true); setProperty(StartInCurrentSessionDir,true); + setProperty(ShowNewTabButton,false); setProperty(KeyBindings,"default"); setProperty(ColorScheme,"Linux"); diff --git a/src/Profile.h b/src/Profile.h index 245c798fe..97eddc988 100644 --- a/src/Profile.h +++ b/src/Profile.h @@ -188,7 +188,10 @@ public: /** (bool) Whether new sessions should be started in the same directory as the * currently active session. */ - StartInCurrentSessionDir + StartInCurrentSessionDir, + + /** (bool) Whether a 'New Tab' button should be shown on the tab bar */ + ShowNewTabButton }; /** diff --git a/src/ProfileList.cpp b/src/ProfileList.cpp index a42049155..1a461eaf5 100644 --- a/src/ProfileList.cpp +++ b/src/ProfileList.cpp @@ -119,6 +119,22 @@ void ProfileList::shortcutChanged(Profile::Ptr info,const QKeySequence& sequence action->setShortcut(sequence); } } +void ProfileList::syncWidgetActions(QWidget* widget, bool sync) +{ + if (!sync) + { + _registeredWidgets.remove(widget); + return; + } + + _registeredWidgets.insert(widget); + + const QList currentActions = widget->actions(); + foreach(QAction* currentAction, currentActions) + widget->removeAction(currentAction); + + widget->addActions(_group->actions()); +} void ProfileList::favoriteChanged(Profile::Ptr info,bool isFavorite) { SessionManager* manager = SessionManager::instance(); @@ -134,7 +150,9 @@ void ProfileList::favoriteChanged(Profile::Ptr info,bool isFavorite) } updateAction(action,info); - + + foreach(QWidget* widget,_registeredWidgets) + widget->addAction(action); emit actionsChanged(_group->actions()); } else @@ -144,13 +162,14 @@ void ProfileList::favoriteChanged(Profile::Ptr info,bool isFavorite) if ( action ) { _group->removeAction(action); + foreach(QWidget* widget,_registeredWidgets) + widget->removeAction(action); emit actionsChanged(_group->actions()); } } updateEmptyAction(); } - void ProfileList::triggered(QAction* action) { emit profileSelected( action->data().value() ); diff --git a/src/ProfileList.h b/src/ProfileList.h index 1d3741c82..3be32508e 100644 --- a/src/ProfileList.h +++ b/src/ProfileList.h @@ -21,6 +21,7 @@ #define PROFILELIST_H #include +#include #include #include "Profile.h" @@ -67,6 +68,8 @@ public: */ QList actions(); + /** TODO: Document me */ + void syncWidgetActions(QWidget* widget,bool sync); signals: /** * Emitted when the user selects an action from the list. @@ -95,6 +98,7 @@ private: // action to show when the list is empty QAction* _emptyListAction; + QSet _registeredWidgets; }; } diff --git a/src/SessionController.cpp b/src/SessionController.cpp index 7fd0f05e0..c37af7a53 100644 --- a/src/SessionController.cpp +++ b/src/SessionController.cpp @@ -685,6 +685,36 @@ void SessionController::saveSession() //SaveSessionDialog dialog(_view); //int result = dialog.exec(); } +bool SessionController::confirmClose() const +{ + if (_session->foregroundProcessId() != _session->processId()) + { + ProcessInfo* foregroundInfo = ProcessInfo::newInstance(_session->foregroundProcessId()); + foregroundInfo->update(); + bool ok = false; + QString title = foregroundInfo->name(&ok); + delete foregroundInfo; + + // hard coded for now. In future make it possible for the user to specify which programs + // are ignored when considering whether to display a confirmation + QStringList ignoreList; + ignoreList << QString(getenv("SHELL")).section('/',-1); + if (ignoreList.contains(title)) + return true; + + QString question; + if (ok) + question = i18n("The program '%1' is currently running in this session." + " Are you sure you want to close it?",title); + else + question = i18n("A program is currently running in this session." + " Are you sure you want to close it?"); + + int result = KMessageBox::warningYesNo(_view->window(),question,i18n("Confirm Close")); + return (result == KMessageBox::Yes) ? true : false; + } + return true; +} void SessionController::closeSession() { if (_preventClose) diff --git a/src/SessionController.h b/src/SessionController.h index 2c56c173f..23e4bcc05 100644 --- a/src/SessionController.h +++ b/src/SessionController.h @@ -129,6 +129,7 @@ public: virtual KUrl url() const; virtual QString currentDir() const; virtual void rename(); + virtual bool confirmClose() const; // Reimplemented to watch for events happening to the view virtual bool eventFilter(QObject* watched , QEvent* event); diff --git a/src/ViewContainer.cpp b/src/ViewContainer.cpp index ed61b3378..2057e68b6 100644 --- a/src/ViewContainer.cpp +++ b/src/ViewContainer.cpp @@ -28,7 +28,6 @@ #include #include #include -#include #include #include #include @@ -74,7 +73,10 @@ ViewContainer::~ViewContainer() emit destroyed(this); } void ViewContainer::moveViewWidget( int , int ) {} - +void ViewContainer::setFeatures(Features features) +{ _features = features; } +ViewContainer::Features ViewContainer::features() const +{ return _features; } void ViewContainer::moveActiveView( MoveDirection direction ) { const int currentIndex = _views.indexOf( activeView() ) ; @@ -613,17 +615,33 @@ TabbedViewContainerV2::TabbedViewContainerV2(NavigationPosition position , QObje _stackWidget = new QStackedWidget(); _tabBar = new ViewContainerTabBar(_containerWidget,this); _tabBar->setDrawBase(true); + _newTabButton = new KPushButton(KIcon("tab-new"),QString(),_containerWidget); + // The button width here is hard coded, it would be better to use the value from + // the current style (see QTabWidget::setUpLayout()) + _newTabButton->setFixedWidth(50); + _newTabButton->setFlat(true); + // new tab button is initially hidden, it will be shown when setFeatures() is called + // with the QuickNewView flag enabled + _newTabButton->setHidden(true); connect( _tabBar , SIGNAL(currentChanged(int)) , this , SLOT(currentTabChanged(int)) ); connect( _tabBar , SIGNAL(tabDoubleClicked(int)) , this , SLOT(tabDoubleClicked(int)) ); connect( _tabBar , SIGNAL(newTabRequest()) , this , SIGNAL(newViewRequest()) ); connect( _tabBar , SIGNAL(wheelDelta(int)) , this , SLOT(wheelScrolled(int)) ); connect( _tabBar , SIGNAL(mouseMiddleClick(int)) , this , SLOT(closeTab(int)) ); + connect( _tabBar , SIGNAL(closeRequest(int)) , this , SLOT(closeTab(int)) ); connect( _tabBar , SIGNAL(initiateDrag(int)) , this , SLOT(startTabDrag(int)) ); + connect( _newTabButton , SIGNAL(clicked()) , this , SIGNAL(newViewRequest()) ); + _layout = new TabbedViewContainerV2Layout; _layout->setSpacing(0); _layout->setMargin(0); + _tabBarLayout = new QHBoxLayout; + _tabBarLayout->setSpacing(0); + _tabBarLayout->setMargin(0); + _tabBarLayout->addWidget(_newTabButton); + _tabBarLayout->addWidget(_tabBar); _tabBarSpacer = new QSpacerItem(0,TabBarSpace); @@ -631,13 +649,13 @@ TabbedViewContainerV2::TabbedViewContainerV2(NavigationPosition position , QObje if ( position == NavigationPositionTop ) { - _layout->insertWidget(0,_tabBar); + _layout->insertLayout(0,_tabBarLayout); _layout->insertItemAt(0,_tabBarSpacer); _tabBar->setShape(QTabBar::RoundedNorth); } else if ( position == NavigationPositionBottom ) { - _layout->insertWidget(-1,_tabBar); + _layout->insertLayout(-1,_tabBarLayout); _layout->insertItemAt(-1,_tabBarSpacer); _tabBar->setShape(QTabBar::RoundedSouth); } @@ -646,14 +664,38 @@ TabbedViewContainerV2::TabbedViewContainerV2(NavigationPosition position , QObje _containerWidget->setLayout(_layout); } +void TabbedViewContainerV2::setNewViewMenu(QMenu* menu) +{ _newTabButton->setDelayedMenu(menu); } +ViewContainer::Features TabbedViewContainerV2::supportedFeatures() const +{ return QuickNewView; } +void TabbedViewContainerV2::setFeatures(Features features) +{ + ViewContainer::setFeatures(features); + + if (features & QuickNewView) + { + _newTabButton->setHidden(false); + _newTabButton->show(); + } + else + _newTabButton->setHidden(true); + + if (features & QuickCloseView) + _tabBar->setCloseButtonEnabled(true); + else + _tabBar->setCloseButtonEnabled(false); +} void TabbedViewContainerV2::closeTab(int tab) { Q_ASSERT(tab >= 0 && tab < _stackWidget->count()); - removeView(_stackWidget->widget(tab)); + + if (viewProperties(_stackWidget->widget(tab))->confirmClose()) + removeView(_stackWidget->widget(tab)); } void TabbedViewContainerV2::setTabBarVisible(bool visible) { _tabBar->setVisible(visible); + _newTabButton->setVisible(visible); if ( visible ) { _tabBarSpacer->changeSize(0,TabBarSpace); @@ -679,20 +721,20 @@ void TabbedViewContainerV2::navigationPositionChanged(NavigationPosition positio if ( position == NavigationPositionTop && _layout->indexOf(_stackWidget) == StackIndexWithTabBottom ) { - _layout->removeWidget(_tabBar); + _layout->removeItem(_tabBarLayout); _layout->removeItem(_tabBarSpacer); - _layout->insertWidget(0,_tabBar); + _layout->insertLayout(0,_tabBarLayout); _layout->insertItemAt(0,_tabBarSpacer); _tabBar->setShape(QTabBar::RoundedNorth); } else if ( position == NavigationPositionBottom && _layout->indexOf(_stackWidget) != StackIndexWithTabBottom ) { - _layout->removeWidget(_tabBar); + _layout->removeItem(_tabBarLayout); _layout->removeItem(_tabBarSpacer); - _layout->insertWidget(-1,_tabBar); + _layout->insertLayout(-1,_tabBarLayout); _layout->insertItemAt(-1,_tabBarSpacer); _tabBar->setShape(QTabBar::RoundedSouth); } diff --git a/src/ViewContainer.h b/src/ViewContainer.h index 27c972246..d8fd7ad98 100644 --- a/src/ViewContainer.h +++ b/src/ViewContainer.h @@ -26,10 +26,11 @@ #include #include #include -#include +#include // KDE #include +#include class QSpacerItem; class QStackedWidget; @@ -65,7 +66,6 @@ namespace Konsole * Subclasses should reimplement the addViewWidget() and removeViewWidget() functions * to actually add or remove view widgets from the container widget, as well * as updating any navigation aids. - * */ class ViewContainer : public QObject { @@ -137,9 +137,7 @@ public: * the view container's navigation widget. */ NavigationDisplayMode navigationDisplayMode() const; - - /** * Sets the position of the navigation widget with * respect to the main content area. @@ -194,15 +192,10 @@ public: */ virtual void setActiveView(QWidget* widget) = 0; - - /** - * Changes the active view to the next view - */ + /** Changes the active view to the next view */ void activateNextView(); - /** - * Changes the active view to the previous view - */ + /** Changes the active view to the previous view */ void activatePreviousView(); /** @@ -227,6 +220,34 @@ public: */ void moveActiveView( MoveDirection direction ); + /** Enum describing extra UI features which can be + * provided by the container. */ + enum Feature + { + /** Provides a button which can be clicked to create new views quickly. + * When the button is clicked, a newViewRequest() signal is emitted. */ + QuickNewView = 1, + /** Provides a button or buttons which can be clicked to close views quickly. */ + QuickCloseView = 2 + }; + Q_DECLARE_FLAGS(Features,Feature); + /** + * Sets which additional features are enabled in this container. + * The default implementation does thing. Sub-classes should re-implement this + * to hide or show the relevant parts of their UI + */ + virtual void setFeatures(Features features); + /** Returns a bitwise-OR of enabled extra UI features. See setFeatures() */ + Features features() const; + /** Returns a bitwise-OR of supported extra UI features. The default + * implementation returns 0 (no extra features) */ + virtual Features supportedFeatures() const + { return 0; } + /** Sets the menu to be shown when the new view button is clicked. + * Only valid if the QuickNewView feature is enabled. + * The default implementation does nothing. */ + virtual void setNewViewMenu(QMenu* menu) { Q_UNUSED(menu); } + signals: /** Emitted when the container is deleted */ void destroyed(ViewContainer* container); @@ -310,7 +331,9 @@ private: NavigationPosition _navigationPosition; QList _views; QHash _navigation; + Features _features; }; +Q_DECLARE_OPERATORS_FOR_FLAGS(ViewContainer::Features); /** * A view container which uses a QTabWidget to display the views and @@ -343,7 +366,6 @@ private slots: void showContextMenu(QWidget* widget , const QPoint& position); void currentTabChanged(int index); - private: KTabWidget* _tabWidget; QList _viewActions; @@ -435,7 +457,9 @@ public: virtual QWidget* activeView() const; virtual void setActiveView(QWidget* view); virtual QList supportedNavigationPositions() const; - + virtual void setFeatures(Features features); + virtual Features supportedFeatures() const; + virtual void setNewViewMenu(QMenu* menu); protected: virtual void addViewWidget(QWidget* view , int index); virtual void removeViewWidget(QWidget* view); @@ -464,13 +488,13 @@ private: QWidget* _containerWidget; QSpacerItem* _tabBarSpacer; TabbedViewContainerV2Layout* _layout; + QHBoxLayout* _tabBarLayout; + KPushButton* _newTabButton; static const int TabBarSpace = 2; }; -/** - * A plain view container with no navigation display - */ +/** A plain view container with no navigation display */ class StackedViewContainer : public ViewContainer { public: diff --git a/src/ViewManager.cpp b/src/ViewManager.cpp index b47b7640e..93567d61b 100644 --- a/src/ViewManager.cpp +++ b/src/ViewManager.cpp @@ -26,6 +26,7 @@ // Qt #include #include +#include // KDE #include @@ -37,6 +38,7 @@ // Konsole #include "ColorScheme.h" +#include "ProfileList.h" #include "Session.h" #include "TerminalDisplay.h" #include "SessionController.h" @@ -52,6 +54,7 @@ ViewManager::ViewManager(QObject* parent , KActionCollection* collection) , _actionCollection(collection) , _containerSignalMapper(new QSignalMapper(this)) , _navigationMethod(TabbedNavigation) + , _newViewMenu(0) { // create main view area _viewSplitter = new ViewSplitter(0); @@ -86,6 +89,20 @@ ViewManager::ViewManager(QObject* parent , KActionCollection* collection) ViewManager::~ViewManager() { + delete _newViewMenu; +} +QMenu* ViewManager::createNewViewMenu() +{ + if (_newViewMenu) + return _newViewMenu; + + _newViewMenu = new QMenu(0); + ProfileList* newViewProfiles = new ProfileList(false,_newViewMenu); + newViewProfiles->syncWidgetActions(_newViewMenu,true); + connect(newViewProfiles,SIGNAL(profileSelected(Profile::Ptr)),this, + SIGNAL(newViewRequest(Profile::Ptr))); + + return _newViewMenu; } QWidget* ViewManager::activeView() const { @@ -567,6 +584,7 @@ ViewContainer* ViewManager::createContainer(const Profile::Ptr info) default: container = new StackedViewContainer(_viewSplitter); } + container->setFeatures(ViewContainer::QuickCloseView); // connect signals and slots connect( container , SIGNAL(viewAdded(QWidget*,ViewProperties*)) , _containerSignalMapper , @@ -697,6 +715,7 @@ void ViewManager::applyProfile(TerminalDisplay* view , const Profile::Ptr info, ViewContainer* container = _viewSplitter->activeContainer(); int tabBarMode = info->property(Profile::TabBarMode); int tabBarPosition = info->property(Profile::TabBarPosition); + bool showNewTabButton = info->property(Profile::ShowNewTabButton); if ( tabBarMode == Profile::AlwaysHideTabBar ) container->setNavigationDisplayMode(ViewContainer::AlwaysHideNavigation); @@ -714,6 +733,15 @@ void ViewManager::applyProfile(TerminalDisplay* view , const Profile::Ptr info, if ( container->supportedNavigationPositions().contains(position) ) container->setNavigationPosition(position); + + if (showNewTabButton && + (container->supportedFeatures() & ViewContainer::QuickNewView)) + { + container->setFeatures(container->features() | ViewContainer::QuickNewView); + container->setNewViewMenu(createNewViewMenu()); + } + else + container->setFeatures(container->features() & ~ViewContainer::QuickNewView); } // load colour scheme diff --git a/src/ViewManager.h b/src/ViewManager.h index 8f0a37bf8..ae9db8c56 100644 --- a/src/ViewManager.h +++ b/src/ViewManager.h @@ -29,7 +29,7 @@ #include "Profile.h" class QSignalMapper; - +class QMenu; class KActionCollection; namespace Konsole @@ -184,10 +184,10 @@ signals: */ void setMenuBarVisibleRequest(bool); - /** - * Requests creation of a new view. - */ + /** Requests creation of a new view with the default profile. */ void newViewRequest(); + /** Requests creation of a new view, with the selected profile. */ + void newViewRequest(Profile::Ptr); private slots: // called when the "Split View Left/Right" menu item is selected @@ -278,10 +278,8 @@ private: // about the session ( such as title and associated icon ) to the display. SessionController* createController(Session* session , TerminalDisplay* display); - // save and load default size for new displays - //void setDefaultDisplaySize(int lines , int columns); - //void getDefaultDisplaySize(int& lines , int& columns) const; - + // create menu for 'new tab' button + QMenu* createNewViewMenu(); private: QPointer _viewSplitter; QPointer _pluggedController; @@ -291,6 +289,8 @@ private: KActionCollection* _actionCollection; QSignalMapper* _containerSignalMapper; NavigationMethod _navigationMethod; + + QMenu* _newViewMenu; }; } diff --git a/src/ViewProperties.h b/src/ViewProperties.h index 7a3184ec4..93718599c 100644 --- a/src/ViewProperties.h +++ b/src/ViewProperties.h @@ -61,7 +61,6 @@ public: /** * Returns the current directory associated with a view. * This may be the same as url() - * * The default implementation returns an empty string. */ virtual QString currentDir() const; @@ -72,13 +71,24 @@ public: */ int identifier() const; + /** + * Sub-classes may re-implement this method to display a message to the user + * to allow them to confirm whether to close a view. + * The default implementation always returns true + */ + virtual bool confirmClose() const + { return true; } + /** Finds a ViewProperties instance given its numeric identifier. */ static ViewProperties* propertiesById(int id); /** Name of mime format to use in drag-and-drop operations. */ static QString mimeType() { return _mimeType; } - + + /** Returns a new QMimeData instance which represents the view with the given @p id + * (See identifier()). The QMimeData instance returned must be deleted by the caller. + */ static QMimeData* createMimeData(int id) { QMimeData* mimeData = new QMimeData; @@ -86,6 +96,12 @@ public: mimeData->setData(mimeType(),data); return mimeData; } + /** Decodes a QMimeData instance created with createMimeData() and returns the identifier + * of the associated view. The associated ViewProperties instance can then be retrieved by + * calling propertiesById() + * + * The QMimeData instance must support the mime format returned by mimeType() + */ static int decodeMimeData(const QMimeData* mimeData) { return *(int*)(mimeData->data(ViewProperties::mimeType()).constData()); @@ -102,15 +118,12 @@ signals: public slots: /** * Requests the renaming of this view. - * * The default implementation does nothing. */ virtual void rename(); protected slots: - /** - * Emits the activity() signal. - */ + /** Emits the activity() signal. */ void fireActivity(); protected: @@ -124,12 +137,8 @@ protected: * an iconChanged() signal to be emitted */ void setIcon(const QIcon& icon); - /** - * Subclasses may call this method to change the identifier. - */ + /** Subclasses may call this method to change the identifier. */ void setIdentifier(int id); - - private: QIcon _icon; QString _title;