Fix crash if key bindings specified in profile cannot be found. Improve
[personal-kdebase.git] / apps / konsole / src / Application.cpp
blob7bbc38fc1fb4ef45560864a96b7fd9d3355eb21e
1 /*
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
17 02110-1301 USA.
20 // Own
21 #include "Application.h"
23 // std
24 #include <iostream>
26 #include "kdebug.h"
28 // Qt
29 #include <QHashIterator>
30 #include <QFileInfo>
32 // KDE
33 #include <KAction>
34 #include <KCmdLineArgs>
35 #include <KDebug>
36 #include <KWindowSystem>
38 // Konsole
39 #include "ColorScheme.h"
40 #include "ProfileList.h"
41 #include "SessionManager.h"
42 #include "KeyboardTranslator.h"
43 #include "MainWindow.h"
44 #include "Session.h"
45 #include "TerminalDisplay.h"
46 #include "ViewManager.h"
48 using namespace Konsole;
50 #ifdef Q_WS_X11
51 Application::Application(Display* display , Qt::HANDLE visual, Qt::HANDLE colormap)
52 : KUniqueApplication(display,visual,colormap)
54 init();
56 #endif
58 Application::Application() : KUniqueApplication()
60 init();
63 void Application::init()
65 _sessionList = 0;
66 _backgroundInstance = 0;
68 // check for compositing functionality
69 TerminalDisplay::setTransparencyEnabled( KWindowSystem::compositingActive() );
72 Application* Application::self()
74 return (Application*)KApp;
77 MainWindow* Application::newMainWindow()
79 MainWindow* window = new MainWindow();
80 window->setSessionList( new ProfileList(true,window) );
82 connect( window , SIGNAL(newSessionRequest(Profile::Ptr,const QString&,ViewManager*)),
83 this , SLOT(createSession(Profile::Ptr,const QString&,ViewManager*)));
84 connect( window , SIGNAL(newWindowRequest(Profile::Ptr,const QString&)),
85 this , SLOT(createWindow(Profile::Ptr,const QString&)) );
86 connect( window->viewManager() , SIGNAL(viewDetached(Session*)) , this , SLOT(detachView(Session*)) );
88 return window;
91 void Application::listAvailableProfiles()
93 QList<QString> paths = SessionManager::instance()->availableProfilePaths();
94 QListIterator<QString> iter(paths);
96 while ( iter.hasNext() )
98 QFileInfo info(iter.next());
99 std::cout << info.baseName().toLocal8Bit().data() << std::endl;
103 int Application::newInstance()
105 KCmdLineArgs* args = KCmdLineArgs::parsedArgs();
106 static bool firstInstance = true;
108 // handle session management
109 if ((args->count() != 0) || !firstInstance || !isSessionRestored())
111 // check for arguments to print help or other information to the terminal,
112 // quit if such an argument was found
113 if ( processHelpArgs(args) )
114 return 0;
116 // create a new window or use an existing one
117 MainWindow* window = processWindowArgs(args);
119 // select profile to use
120 processProfileSelectArgs(args,window);
122 // process various command-line options which cause a property of the
123 // default profile to be changed
124 processProfileChangeArgs(args,window);
126 // create new session
127 Session* session = createSession( window->defaultProfile() , QString() , window->viewManager() );
128 if ( !args->isSet("close") )
129 session->setAutoClose(false);
131 // if the background-mode argument is supplied, start the background session
132 // ( or bring to the front if it already exists )
133 if ( args->isSet("background-mode") )
134 startBackgroundMode(window);
135 else
137 // Qt constrains top-level windows which have not been manually resized
138 // (via QWidget::resize()) to a maximum of 2/3rds of the screen size.
140 // This means that the terminal display might not get the width/height
141 // it asks for. To work around this, the widget must be manually resized
142 // to its sizeHint().
144 // This problem only affects the first time the application is run. After
145 // that KMainWindow will have manually resized the window to its saved size
146 // at this point (so the Qt::WA_Resized attribute will be set)
147 if (!window->testAttribute(Qt::WA_Resized))
148 window->resize(window->sizeHint());
150 window->show();
154 firstInstance = false;
155 args->clear();
156 return 0;
159 MainWindow* Application::processWindowArgs(KCmdLineArgs* args)
161 MainWindow* window = 0;
162 if ( args->isSet("new-tab") )
164 QListIterator<QWidget*> iter(topLevelWidgets());
165 iter.toBack();
166 while ( iter.hasPrevious() )
168 window = qobject_cast<MainWindow*>(iter.previous());
169 if ( window != 0 )
170 break;
174 if ( window == 0 )
176 window = newMainWindow();
178 return window;
181 void Application::processProfileSelectArgs(KCmdLineArgs* args,MainWindow* window)
183 if ( args->isSet("profile") )
185 Profile::Ptr profile = SessionManager::instance()->loadProfile(args->getOption("profile"));
186 if (!profile)
187 profile = SessionManager::instance()->defaultProfile();
189 window->setDefaultProfile(profile);
193 bool Application::processHelpArgs(KCmdLineArgs* args)
195 if ( args->isSet("list-profiles") )
197 listAvailableProfiles();
198 return true;
200 return false;
202 void Application::processProfileChangeArgs(KCmdLineArgs* args,MainWindow* window)
204 Profile::Ptr defaultProfile = window->defaultProfile();
205 if (!defaultProfile)
206 defaultProfile = SessionManager::instance()->defaultProfile();
207 Profile::Ptr newProfile = Profile::Ptr(new Profile(defaultProfile));
208 newProfile->setHidden(true);
209 // run a custom command
210 if ( args->isSet("e") )
212 QStringList arguments;
213 arguments << args->getOption("e");
214 for ( int i = 0 ; i < args->count() ; i++ )
215 arguments << args->arg(i);
217 newProfile->setProperty(Profile::Command,args->getOption("e"));
218 newProfile->setProperty(Profile::Arguments,arguments);
221 // change the initial working directory
222 if( args->isSet("workdir") )
224 newProfile->setProperty(Profile::Directory,args->getOption("workdir"));
227 // temporary changes to profile options specified on the command line
228 foreach( const QString &value , args->getOptionList("p") )
230 ProfileCommandParser parser;
232 QHashIterator<Profile::Property,QVariant> iter(parser.parse(value));
233 while ( iter.hasNext() )
235 iter.next();
236 newProfile->setProperty(iter.key(),iter.value());
240 if (!newProfile->isEmpty())
242 window->setDefaultProfile(newProfile);
246 void Application::startBackgroundMode(MainWindow* window)
248 if ( _backgroundInstance )
250 return;
253 KAction* action = new KAction(window);
254 KShortcut shortcut = action->shortcut();
255 action->setObjectName("Konsole Background Mode");
256 //TODO - Customisable key sequence for this
257 action->setGlobalShortcut( KShortcut(QKeySequence(Qt::Key_F12)) );
259 _backgroundInstance = window;
261 connect( action , SIGNAL(triggered()) , this , SLOT(toggleBackgroundInstance()) );
264 void Application::toggleBackgroundInstance()
266 Q_ASSERT( _backgroundInstance );
268 if ( !_backgroundInstance->isVisible() )
270 _backgroundInstance->show();
271 // ensure that the active terminal display has the focus.
272 // without this, an odd problem occurred where the focus widgetwould change
273 // each time the background instance was shown
274 _backgroundInstance->viewManager()->activeView()->setFocus();
276 else
278 _backgroundInstance->hide();
282 Application::~Application()
284 SessionManager::instance()->closeAll();
285 SessionManager::instance()->saveState();
288 void Application::detachView(Session* session)
290 MainWindow* window = newMainWindow();
291 window->viewManager()->createView(session);
292 window->show();
295 void Application::createWindow(Profile::Ptr profile , const QString& directory)
297 MainWindow* window = newMainWindow();
298 window->setDefaultProfile(profile);
299 createSession(profile,directory,window->viewManager());
300 window->show();
303 Session* Application::createSession(Profile::Ptr profile, const QString& directory , ViewManager* view)
305 if (!profile)
306 profile = SessionManager::instance()->defaultProfile();
308 Session* session = SessionManager::instance()->createSession(profile);
310 if (!directory.isEmpty() && profile->property<bool>(Profile::StartInCurrentSessionDir))
311 session->setInitialWorkingDirectory(directory);
313 // create view before starting the session process so that the session doesn't suffer
314 // a change in terminal size right after the session starts. some applications such as GNU Screen
315 // and Midnight Commander don't like this happening
316 view->createView(session);
317 session->run();
319 return session;
322 #include "Application.moc"
325 Local Variables:
326 mode: c++
327 c-file-style: "stroustrup"
328 indent-tabs-mode: nil
329 tab-width: 4
330 End: