2 Copyright 2006-2008 by Robert Knight <robertknight@gmail.com>
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
21 #include "MainWindow.h"
22 #include "SessionManager.h"
25 #include <QtGui/QBoxLayout>
28 #include <KAcceleratorManager>
30 #include <KActionCollection>
31 #include <KActionMenu>
32 #include <KApplication>
33 #include <KShortcutsDialog>
37 #include <KMessageBox>
39 #include <KToggleAction>
40 #include <KToggleFullScreenAction>
41 #include <KToolInvocation>
42 #include <KStandardAction>
43 #include <KStandardGuiItem>
44 #include <KXMLGUIFactory>
45 #include <KNotifyConfigWidget>
48 #include "BookmarkHandler.h"
49 #include "IncrementalSearchBar.h"
50 #include "RemoteConnectionDialog.h"
51 #include "SessionController.h"
52 #include "ProfileList.h"
53 #include "ManageProfilesDialog.h"
55 #include "ViewManager.h"
56 #include "ViewSplitter.h"
58 using namespace Konsole
;
60 MainWindow::MainWindow()
63 _pluggedController(0),
64 _menuBarVisibilitySet(false)
66 // create actions for menus
67 // the directory ('konsole') is included in the path here so that the XML
68 // file can be found when this code is being used in the Konsole part.
69 setXMLFile("konsole/konsoleui.rc");
72 // create view manager
73 _viewManager
= new ViewManager(this,actionCollection());
74 connect( _viewManager
, SIGNAL(empty()) , this , SLOT(close()) );
75 connect( _viewManager
, SIGNAL(activeViewChanged(SessionController
*)) , this ,
76 SLOT(activeViewChanged(SessionController
*)) );
77 connect( _viewManager
, SIGNAL(viewPropertiesChanged(const QList
<ViewProperties
*>&)) ,
78 bookmarkHandler() , SLOT(setViews(const QList
<ViewProperties
*>&)) );
80 connect( _viewManager
, SIGNAL(setMenuBarVisibleRequest(bool)) , this ,
81 SLOT(setMenuBarVisibleOnce(bool)) );
82 connect( _viewManager
, SIGNAL(newViewRequest(Profile::Ptr
)) ,
83 this , SLOT(newFromProfile(Profile::Ptr
)) );
84 connect( _viewManager
, SIGNAL(newViewRequest()) ,
85 this , SLOT(newTab()));
87 // create main window widgets
90 // disable automatically generated accelerators in top-level
91 // menu items - to avoid conflicting with Alt+[Letter] shortcuts
92 // in terminal applications
93 KAcceleratorManager::setNoAccel(menuBar());
96 // remove accelerators for standard menu items (eg. &File, &View, &Edit)
97 // etc. which are defined in kdelibs/kdeui/xmlgui/ui_standards.rc, again,
98 // to avoid conflicting with Alt+[Letter] terminal shortcuts
100 // TODO - Modify XMLGUI so that it allows the text for standard actions
101 // defined in ui_standards.rc to be re-defined in the local application
102 // XMLGUI file (konsoleui.rc in this case) - the text for standard items
103 // can then be redefined there to exclude the standard accelerators
104 removeMenuAccelerators();
105 // replace standard shortcuts which cannot be used in a terminal
106 // (as they are reserved for use by terminal programs)
109 // enable save and restore of window size
110 setAutoSaveSettings("MainWindow",true);
112 void MainWindow::removeMenuAccelerators()
114 foreach(QAction
* menuItem
, menuBar()->actions())
116 QString itemText
= menuItem
->text();
117 itemText
= KGlobal::locale()->removeAcceleratorMarker(itemText
);
118 menuItem
->setText(itemText
);
121 void MainWindow::setMenuBarVisibleOnce(bool visible
)
123 if (_menuBarVisibilitySet
|| menuBar()->isTopLevelMenu() )
126 menuBar()->setVisible(visible
);
127 _toggleMenuBarAction
->setChecked(visible
);
129 _menuBarVisibilitySet
= true;
132 void MainWindow::correctShortcuts()
134 // replace F1 shortcut for help contents
135 QAction
* helpAction
= actionCollection()->action("help_contents");
137 Q_ASSERT( helpAction
);
139 helpAction
->setShortcut(QKeySequence());
141 // replace Ctrl+B shortcut for bookmarks
142 // TODO - Make this configurable
143 QAction
* bookmarkAction
= actionCollection()->action("add_bookmark");
144 Q_ASSERT(bookmarkAction
);
145 bookmarkAction
->setShortcut(QKeySequence(Qt::CTRL
+Qt::SHIFT
+Qt::Key_B
));
148 void MainWindow::setDefaultProfile(Profile::Ptr profile
)
150 _defaultProfile
= profile
;
152 Profile::Ptr
MainWindow::defaultProfile() const
154 return _defaultProfile
;
157 ViewManager
* MainWindow::viewManager() const
162 void MainWindow::disconnectController(SessionController
* controller
)
164 disconnect( controller
, SIGNAL(titleChanged(ViewProperties
*))
165 , this , SLOT(activeViewTitleChanged(ViewProperties
*)) );
167 // KXmlGuiFactory::removeClient() will try to access actions associated
168 // with the controller internally, which may not be valid after the controller
169 // itself is no longer valid (after the associated session and or view have
171 if (controller
->isValid())
172 guiFactory()->removeClient(controller
);
174 controller
->setSearchBar(0);
177 void MainWindow::activeViewChanged(SessionController
* controller
)
179 // associate bookmark menu with current session
180 bookmarkHandler()->setActiveView(controller
);
181 disconnect( bookmarkHandler() , SIGNAL(openUrl(const KUrl
&)) , 0 , 0 );
182 connect( bookmarkHandler() , SIGNAL(openUrl(const KUrl
&)) , controller
,
183 SLOT(openUrl(const KUrl
&)) );
185 if ( _pluggedController
)
186 disconnectController(_pluggedController
);
188 // listen for title changes from the current session
189 Q_ASSERT( controller
);
191 connect( controller
, SIGNAL(titleChanged(ViewProperties
*)) ,
192 this , SLOT(activeViewTitleChanged(ViewProperties
*)) );
194 controller
->setShowMenuAction( _toggleMenuBarAction
);
195 guiFactory()->addClient(controller
);
197 // set the current session's search bar
198 controller
->setSearchBar( searchBar() );
200 // update session title to match newly activated session
201 activeViewTitleChanged(controller
);
203 _pluggedController
= controller
;
206 void MainWindow::activeViewTitleChanged(ViewProperties
* properties
)
208 setPlainCaption(properties
->title());
211 IncrementalSearchBar
* MainWindow::searchBar() const
213 return _viewManager
->searchBar();
216 void MainWindow::setupActions()
218 KActionCollection
* collection
= actionCollection();
221 KAction
* newTabAction
= collection
->addAction("new-tab");
222 newTabAction
->setIcon( KIcon("tab-new") );
223 newTabAction
->setText( i18n("New &Tab") );
224 newTabAction
->setShortcut( QKeySequence(Qt::CTRL
+Qt::SHIFT
+Qt::Key_N
) );
225 connect( newTabAction
, SIGNAL(triggered()) , this , SLOT(newTab()) );
227 KAction
* newWindowAction
= collection
->addAction("new-window");
228 newWindowAction
->setIcon( KIcon("window-new") );
229 newWindowAction
->setText( i18n("New &Window") );
230 newWindowAction
->setShortcut( QKeySequence(Qt::CTRL
+Qt::SHIFT
+Qt::Key_M
) );
231 connect( newWindowAction
, SIGNAL(triggered()) , this , SLOT(newWindow()) );
233 KAction
* remoteConnectionAction
= collection
->addAction("remote-connection");
234 remoteConnectionAction
->setText( i18n("Remote Connection...") );
235 remoteConnectionAction
->setIcon( KIcon("network-connect") );
236 remoteConnectionAction
->setShortcut( QKeySequence(Qt::CTRL
+Qt::SHIFT
+Qt::Key_R
) );
237 connect( remoteConnectionAction
, SIGNAL(triggered()) , this , SLOT(showRemoteConnectionDialog()) );
239 KAction
* quitAction
= KStandardAction::quit( this , SLOT(close()) , collection
);
240 // the default shortcut for quit is typically Ctrl+[Some Letter, usually Q] but that is reserved for
241 // use by terminal applications
242 quitAction
->setShortcut(Qt::CTRL
+Qt::SHIFT
+Qt::Key_Q
);
245 KActionMenu
* bookmarkMenu
= new KActionMenu(i18n("&Bookmarks") , collection
);
246 _bookmarkHandler
= new BookmarkHandler( collection
, bookmarkMenu
->menu() , true , this );
247 collection
->addAction("bookmark" , bookmarkMenu
);
249 connect( _bookmarkHandler
, SIGNAL(openUrls(QList
<KUrl
>)) , this , SLOT(openUrls(QList
<KUrl
>)) );
251 //TODO - The 'Add Bookmark' menu action currently has a Ctrl+B shortcut by
252 // default which cannot be overridden
255 _toggleMenuBarAction
= new KToggleAction(this);
256 _toggleMenuBarAction
->setText( i18n("Show Menu Bar") );
257 _toggleMenuBarAction
->setIcon( KIcon("show-menu") );
258 _toggleMenuBarAction
->setChecked( !menuBar()->isHidden() );
259 connect( _toggleMenuBarAction
, SIGNAL(toggled(bool)) , menuBar() , SLOT(setVisible(bool)) );
260 collection
->addAction("show-menubar",_toggleMenuBarAction
);
262 // Hide the Show/Hide menubar item if the menu bar is a MacOS-style menu bar
263 if ( menuBar()->isTopLevelMenu() )
264 _toggleMenuBarAction
->setVisible(false);
267 KToggleFullScreenAction
* fullScreenAction
= new KToggleFullScreenAction(this);
268 fullScreenAction
->setWindow(this);
269 fullScreenAction
->setShortcut( Qt::CTRL
+ Qt::SHIFT
+ Qt::Key_F11
);
270 collection
->addAction("view-full-screen",fullScreenAction
);
271 connect( fullScreenAction
, SIGNAL(toggled(bool)) , this , SLOT(viewFullScreen(bool)) );
274 KStandardAction::configureNotifications( this , SLOT(configureNotifications()) , collection
);
275 KStandardAction::keyBindings( this , SLOT(showShortcutsDialog()) , collection
);
277 KAction
* manageProfilesAction
= collection
->addAction("manage-profiles");
278 manageProfilesAction
->setText( i18n("Manage Profiles...") );
279 manageProfilesAction
->setIcon( KIcon("configure") );
280 connect( manageProfilesAction
, SIGNAL(triggered()) , this , SLOT(showManageProfilesDialog()) );
284 void MainWindow::viewFullScreen(bool fullScreen
)
287 setWindowState( windowState() | Qt::WindowFullScreen
);
289 setWindowState( windowState() & ~Qt::WindowFullScreen
);
292 BookmarkHandler
* MainWindow::bookmarkHandler() const
294 return _bookmarkHandler
;
297 void MainWindow::setSessionList(ProfileList
* list
)
299 sessionListChanged(list
->actions());
301 connect( list
, SIGNAL(profileSelected(Profile::Ptr
)) , this ,
302 SLOT(newFromProfile(Profile::Ptr
)) );
304 connect( list
, SIGNAL(actionsChanged(const QList
<QAction
*>&)) , this ,
305 SLOT(sessionListChanged(const QList
<QAction
*>&)) );
308 void MainWindow::sessionListChanged(const QList
<QAction
*>& actions
)
310 unplugActionList("favorite-profiles");
311 plugActionList("favorite-profiles",actions
);
314 QString
MainWindow::activeSessionDir() const
316 if ( _pluggedController
)
317 return _pluggedController
->currentDir();
322 void MainWindow::openUrls(const QList
<KUrl
>& urls
)
324 // TODO Implement support for SSH bookmarks here
325 foreach( const KUrl
& url
, urls
)
327 if ( url
.isLocalFile() )
328 emit
newSessionRequest( _defaultProfile
, url
.path() , _viewManager
);
332 void MainWindow::newTab()
334 emit
newSessionRequest( _defaultProfile
, activeSessionDir() , _viewManager
);
337 void MainWindow::newWindow()
339 emit
newWindowRequest( _defaultProfile
, activeSessionDir() );
342 bool MainWindow::queryClose()
344 if (kapp
->sessionSaving() ||
345 _viewManager
->viewProperties().count() < 2)
348 int result
= KMessageBox::warningYesNoCancel(this,
349 i18n("You have multiple tabs in this window, "
350 "are you sure you want to quit?"),
351 i18n("Confirm Close"),
352 KStandardGuiItem::quit(),
353 KGuiItem(i18n("Close Current Tab"), "tab-close"),
354 KStandardGuiItem::cancel(),
359 case KMessageBox::Yes
:
361 case KMessageBox::No
:
362 if (_pluggedController
&& _pluggedController
->session())
364 disconnectController(_pluggedController
);
365 _pluggedController
->session()->close();
368 case KMessageBox::Cancel
:
375 void MainWindow::saveProperties(KConfigGroup
& group
)
378 group
.writePathEntry("Default Profile", _defaultProfile
->path());
379 _viewManager
->saveSessions(group
);
382 void MainWindow::readProperties(const KConfigGroup
& group
)
384 SessionManager
*manager
= SessionManager::instance();
385 QString profilePath
= group
.readPathEntry("Default Profile", QString());
386 Profile::Ptr profile
= manager
->defaultProfile();
387 if (!profilePath
.isEmpty())
388 profile
= manager
->loadProfile(profilePath
);
389 setDefaultProfile(profile
);
390 _viewManager
->restoreSessions(group
);
393 void MainWindow::saveGlobalProperties(KConfig
* config
)
395 SessionManager::instance()->saveSessions(config
);
398 void MainWindow::readGlobalProperties(KConfig
* config
)
400 SessionManager::instance()->restoreSessions(config
);
403 void MainWindow::syncActiveShortcuts(KActionCollection
* dest
, const KActionCollection
* source
)
405 foreach(QAction
* qAction
, source
->actions())
407 if (KAction
* kAction
= qobject_cast
<KAction
*>(qAction
))
409 if (KAction
* destKAction
= qobject_cast
<KAction
*>(dest
->action(kAction
->objectName())))
410 destKAction
->setShortcut(kAction
->shortcut(KAction::ActiveShortcut
),KAction::ActiveShortcut
);
414 void MainWindow::showShortcutsDialog()
416 KShortcutsDialog
dialog(KShortcutsEditor::AllActions
, KShortcutsEditor::LetterShortcutsDisallowed
, this);
418 // add actions from this window and the current session controller
419 foreach(KXMLGUIClient
* client
, guiFactory()->clients())
420 dialog
.addCollection(client
->actionCollection());
422 if (dialog
.configure())
424 // sync shortcuts for non-session actions (defined in "konsoleui.rc") in other main windows
425 foreach(QWidget
* widget
, QApplication::topLevelWidgets())
427 MainWindow
* window
= qobject_cast
<MainWindow
*>(widget
);
428 if (window
&& window
!= this)
429 syncActiveShortcuts(window
->actionCollection(),actionCollection());
431 // sync shortcuts for session actions (defined in "sessionui.rc") in other session controllers.
432 // Controllers which are currently plugged in (ie. their actions are part of the current menu)
433 // must be updated immediately via syncActiveShortcuts(). Other controllers will be updated
434 // when they are plugged into a main window.
435 foreach(SessionController
* controller
, SessionController::allControllers())
437 controller
->reloadXML();
438 if (controller
->factory() && controller
!= _pluggedController
)
439 syncActiveShortcuts(controller
->actionCollection(),_pluggedController
->actionCollection());
444 void MainWindow::newFromProfile(Profile::Ptr profile
)
446 emit
newSessionRequest(profile
, activeSessionDir(), _viewManager
);
448 void MainWindow::showManageProfilesDialog()
450 ManageProfilesDialog
* dialog
= new ManageProfilesDialog(this);
454 void MainWindow::showRemoteConnectionDialog()
456 // RemoteConnectionDialog dialog(this);
457 // if ( dialog.exec() == QDialog::Accepted )
458 // emit newSessionRequest(dialog.sessionKey(),QString(),_viewManager);
461 void MainWindow::setupWidgets()
463 QWidget
* widget
= new QWidget(this);
464 QVBoxLayout
* layout
= new QVBoxLayout();
466 layout
->addWidget( _viewManager
->widget() );
467 layout
->setMargin(0);
468 layout
->setSpacing(0);
470 widget
->setLayout(layout
);
472 setCentralWidget(widget
);
475 void MainWindow::configureNotifications()
477 KNotifyConfigWidget::configure( this );
480 #include "MainWindow.moc"
485 c-file-style: "stroustrup"
486 indent-tabs-mode: nil