• Skip to content
  • Skip to link menu
KDE API Reference
  • KDE API Reference
  • applications API Reference
  • KDE Home
  • Contact Us
 

Konsole

  • kde-4.14
  • applications
  • konsole
  • src
SessionController.cpp
Go to the documentation of this file.
1 /*
2  Copyright 2006-2008 by Robert Knight <robertknight@gmail.com>
3  Copyright 2009 by Thomas Dreibholz <dreibh@iem.uni-due.de>
4 
5  This program is free software; you can redistribute it and/or modify
6  it under the terms of the GNU General Public License as published by
7  the Free Software Foundation; either version 2 of the License, or
8  (at your option) any later version.
9 
10  This program is distributed in the hope that it will be useful,
11  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  GNU General Public License for more details.
14 
15  You should have received a copy of the GNU General Public License
16  along with this program; if not, write to the Free Software
17  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
18  02110-1301 USA.
19 */
20 
21 // Own
22 #include "SessionController.h"
23 
24 // Qt
25 #include <QApplication>
26 #include <QMenu>
27 #include <QtGui/QKeyEvent>
28 #include <QPrinter>
29 #include <QPrintDialog>
30 #include <QPainter>
31 
32 // KDE
33 #include <KAction>
34 #include <KActionMenu>
35 #include <KActionCollection>
36 #include <KIcon>
37 #include <KLocalizedString>
38 #include <KMenu>
39 #include <KMessageBox>
40 #include <KRun>
41 #include <KShell>
42 #include <KToolInvocation>
43 #include <KStandardDirs>
44 #include <KToggleAction>
45 #include <KSelectAction>
46 #include <KUrl>
47 #include <KXmlGuiWindow>
48 #include <KXMLGUIFactory>
49 #include <KXMLGUIBuilder>
50 #include <KDebug>
51 #include <KUriFilter>
52 #include <KStringHandler>
53 #include <KConfigGroup>
54 #include <KGlobal>
55 
56 #include <kdeversion.h>
57 #if KDE_IS_VERSION(4, 9, 1)
58 #include <KCodecAction>
59 #else
60 #include <kcodecaction.h>
61 #endif
62 
63 // Konsole
64 #include "EditProfileDialog.h"
65 #include "CopyInputDialog.h"
66 #include "Emulation.h"
67 #include "Filter.h"
68 #include "History.h"
69 #include "HistorySizeDialog.h"
70 #include "IncrementalSearchBar.h"
71 #include "RenameTabDialog.h"
72 #include "ScreenWindow.h"
73 #include "Session.h"
74 #include "ProfileList.h"
75 #include "TerminalDisplay.h"
76 #include "SessionManager.h"
77 #include "Enumeration.h"
78 #include "PrintOptions.h"
79 
80 // for SaveHistoryTask
81 #include <KFileDialog>
82 #include <KIO/Job>
83 #include <KJob>
84 #include "TerminalCharacterDecoder.h"
85 
86 // For Unix signal names
87 #include <signal.h>
88 
89 using namespace Konsole;
90 
91 // TODO - Replace the icon choices below when suitable icons for silence and
92 // activity are available
93 const KIcon SessionController::_activityIcon("dialog-information");
94 const KIcon SessionController::_silenceIcon("dialog-information");
95 const KIcon SessionController::_broadcastIcon("emblem-important");
96 
97 QSet<SessionController*> SessionController::_allControllers;
98 int SessionController::_lastControllerId;
99 
100 SessionController::SessionController(Session* session , TerminalDisplay* view, QObject* parent)
101  : ViewProperties(parent)
102  , KXMLGUIClient()
103  , _session(session)
104  , _view(view)
105  , _copyToGroup(0)
106  , _profileList(0)
107  , _previousState(-1)
108  , _viewUrlFilter(0)
109  , _searchFilter(0)
110  , _copyInputToAllTabsAction(0)
111  , _findAction(0)
112  , _findNextAction(0)
113  , _findPreviousAction(0)
114  , _urlFilterUpdateRequired(false)
115  , _searchStartLine(0)
116  , _prevSearchResultLine(0)
117  , _searchBar(0)
118  , _codecAction(0)
119  , _switchProfileMenu(0)
120  , _webSearchMenu(0)
121  , _listenForScreenWindowUpdates(false)
122  , _preventClose(false)
123  , _keepIconUntilInteraction(false)
124  , _showMenuAction(0)
125  , _isSearchBarEnabled(false)
126 {
127  Q_ASSERT(session);
128  Q_ASSERT(view);
129 
130  // handle user interface related to session (menus etc.)
131  if (isKonsolePart()) {
132  setXMLFile("konsole/partui.rc");
133  setupCommonActions();
134  } else {
135  setXMLFile("konsole/sessionui.rc");
136  setupCommonActions();
137  setupExtraActions();
138  }
139 
140  actionCollection()->addAssociatedWidget(view);
141  foreach(QAction * action, actionCollection()->actions()) {
142  action->setShortcutContext(Qt::WidgetWithChildrenShortcut);
143  }
144 
145  setIdentifier(++_lastControllerId);
146  sessionTitleChanged();
147 
148  view->installEventFilter(this);
149  view->setSessionController(this);
150 
151  // listen for session resize requests
152  connect(_session, SIGNAL(resizeRequest(QSize)), this,
153  SLOT(sessionResizeRequest(QSize)));
154 
155  // listen for popup menu requests
156  connect(_view, SIGNAL(configureRequest(QPoint)), this,
157  SLOT(showDisplayContextMenu(QPoint)));
158 
159  // move view to newest output when keystrokes occur
160  connect(_view, SIGNAL(keyPressedSignal(QKeyEvent*)), this,
161  SLOT(trackOutput(QKeyEvent*)));
162 
163  // listen to activity / silence notifications from session
164  connect(_session, SIGNAL(stateChanged(int)), this,
165  SLOT(sessionStateChanged(int)));
166  // listen to title and icon changes
167  connect(_session, SIGNAL(titleChanged()), this, SLOT(sessionTitleChanged()));
168 
169  connect(_session , SIGNAL(currentDirectoryChanged(QString)) ,
170  this , SIGNAL(currentDirectoryChanged(QString)));
171 
172  // listen for color changes
173  connect(_session, SIGNAL(changeBackgroundColorRequest(QColor)), _view, SLOT(setBackgroundColor(QColor)));
174  connect(_session, SIGNAL(changeForegroundColorRequest(QColor)), _view, SLOT(setForegroundColor(QColor)));
175 
176  // update the title when the session starts
177  connect(_session, SIGNAL(started()), this, SLOT(snapshot()));
178 
179  // listen for output changes to set activity flag
180  connect(_session->emulation(), SIGNAL(outputChanged()), this,
181  SLOT(fireActivity()));
182 
183  // listen for detection of ZModem transfer
184  connect(_session, SIGNAL(zmodemDetected()), this, SLOT(zmodemDownload()));
185 
186  // listen for flow control status changes
187  connect(_session, SIGNAL(flowControlEnabledChanged(bool)), _view,
188  SLOT(setFlowControlWarningEnabled(bool)));
189  _view->setFlowControlWarningEnabled(_session->flowControlEnabled());
190 
191  // take a snapshot of the session state every so often when
192  // user activity occurs
193  //
194  // the timer is owned by the session so that it will be destroyed along
195  // with the session
196  _interactionTimer = new QTimer(_session);
197  _interactionTimer->setSingleShot(true);
198  _interactionTimer->setInterval(500);
199  connect(_interactionTimer, SIGNAL(timeout()), this, SLOT(snapshot()));
200  connect(_view, SIGNAL(keyPressedSignal(QKeyEvent*)), this, SLOT(interactionHandler()));
201 
202  // take a snapshot of the session state periodically in the background
203  QTimer* backgroundTimer = new QTimer(_session);
204  backgroundTimer->setSingleShot(false);
205  backgroundTimer->setInterval(2000);
206  connect(backgroundTimer, SIGNAL(timeout()), this, SLOT(snapshot()));
207  backgroundTimer->start();
208 
209  _allControllers.insert(this);
210 
211  // A list of programs that accept Ctrl+C to clear command line used
212  // before outputting bookmark.
213  _bookmarkValidProgramsToClear << "bash" << "fish" << "sh";
214  _bookmarkValidProgramsToClear << "tcsh" << "zsh";
215 }
216 
217 SessionController::~SessionController()
218 {
219  if (_view)
220  _view->setScreenWindow(0);
221 
222  _allControllers.remove(this);
223 
224  if (!_editProfileDialog.isNull()) {
225  delete _editProfileDialog.data();
226  }
227 }
228 void SessionController::trackOutput(QKeyEvent* event)
229 {
230  Q_ASSERT(_view->screenWindow());
231 
232  // jump to the end of the history buffer unless the key pressed
233  // is one of the three main modifiers, as these are used to select
234  // the selection mode (eg. Ctrl+Alt+<Left Click> for column/block selection)
235  switch (event->key()) {
236  case Qt::Key_Shift:
237  case Qt::Key_Control:
238  case Qt::Key_Alt:
239  break;
240  default:
241  _view->screenWindow()->setTrackOutput(true);
242  }
243 }
244 void SessionController::interactionHandler()
245 {
246  // This flag is used to make sure those special icons indicating interest
247  // events (activity/silence/bell?) remain in the tab until user interaction
248  // happens. Otherwise, those special icons will quickly be replaced by
249  // normal icon when ::snapshot() is triggered
250  _keepIconUntilInteraction = false;
251  _interactionTimer->start();
252 }
253 
254 void SessionController::requireUrlFilterUpdate()
255 {
256  // this method is called every time the screen window's output changes, so do not
257  // do anything expensive here.
258 
259  _urlFilterUpdateRequired = true;
260 }
261 void SessionController::snapshot()
262 {
263  Q_ASSERT(_session != 0);
264 
265  QString title = _session->getDynamicTitle();
266  title = title.simplified();
267 
268  // Visualize that the session is broadcasting to others
269  if (_copyToGroup && _copyToGroup->sessions().count() > 1) {
270  title.append('*');
271  }
272 
273  // use the fallback title if needed
274  if (title.isEmpty()) {
275  title = _session->title(Session::NameRole);
276  }
277 
278  // apply new title
279  _session->setTitle(Session::DisplayedTitleRole, title);
280 
281  // do not forget icon
282  updateSessionIcon();
283 }
284 
285 QString SessionController::currentDir() const
286 {
287  return _session->currentWorkingDirectory();
288 }
289 
290 KUrl SessionController::url() const
291 {
292  return _session->getUrl();
293 }
294 
295 void SessionController::rename()
296 {
297  renameSession();
298 }
299 
300 void SessionController::openUrl(const KUrl& url)
301 {
302  // Clear shell's command line
303  if (!_session->isForegroundProcessActive()
304  && _bookmarkValidProgramsToClear.contains(_session->foregroundProcessName())) {
305  _session->emulation()->sendText(QChar(0x03)); // Ctrl+C
306  _session->emulation()->sendText(QChar('\n'));
307  }
308 
309  // handle local paths
310  if (url.isLocalFile()) {
311  QString path = url.toLocalFile();
312  _session->emulation()->sendText("cd " + KShell::quoteArg(path) + '\r');
313  } else if (url.protocol().isEmpty()) {
314  // KUrl couldn't parse what the user entered into the URL field
315  // so just dump it to the shell
316  QString command = url.prettyUrl();
317  if (!command.isEmpty())
318  _session->emulation()->sendText(command + '\r');
319  } else if (url.protocol() == "ssh") {
320  QString sshCommand = "ssh ";
321 
322  if (url.port() > -1) {
323  sshCommand += QString("-p %1 ").arg(url.port());
324  }
325  if (url.hasUser()) {
326  sshCommand += (url.user() + '@');
327  }
328  if (url.hasHost()) {
329  sshCommand += url.host();
330  }
331 
332  _session->sendText(sshCommand + '\r');
333 
334  } else if (url.protocol() == "telnet") {
335  QString telnetCommand = "telnet ";
336 
337  if (url.hasUser()) {
338  telnetCommand += QString("-l %1 ").arg(url.user());
339  }
340  if (url.hasHost()) {
341  telnetCommand += (url.host() + ' ');
342  }
343  if (url.port() > -1) {
344  telnetCommand += QString::number(url.port());
345  }
346 
347  _session->sendText(telnetCommand + '\r');
348 
349  } else {
350  //TODO Implement handling for other Url types
351 
352  KMessageBox::sorry(_view->window(),
353  i18n("Konsole does not know how to open the bookmark: ") +
354  url.prettyUrl());
355 
356  kWarning() << "Unable to open bookmark at url" << url << ", I do not know"
357  << " how to handle the protocol " << url.protocol();
358  }
359 }
360 
361 void SessionController::setupPrimaryScreenSpecificActions(bool use)
362 {
363  KActionCollection* collection = actionCollection();
364  QAction* clearAction = collection->action("clear-history");
365  QAction* resetAction = collection->action("clear-history-and-reset");
366  QAction* selectAllAction = collection->action("select-all");
367  QAction* selectLineAction = collection->action("select-line");
368 
369  // these actions are meaningful only when primary screen is used.
370  clearAction->setEnabled(use);
371  resetAction->setEnabled(use);
372  selectAllAction->setEnabled(use);
373  selectLineAction->setEnabled(use);
374 }
375 
376 void SessionController::selectionChanged(const QString& selectedText)
377 {
378  _selectedText = selectedText;
379  updateCopyAction(selectedText);
380 }
381 
382 void SessionController::updateCopyAction(const QString& selectedText)
383 {
384  QAction* copyAction = actionCollection()->action("edit_copy");
385 
386  // copy action is meaningful only when some text is selected.
387  copyAction->setEnabled(!selectedText.isEmpty());
388 }
389 
390 void SessionController::updateWebSearchMenu()
391 {
392  // reset
393  _webSearchMenu->setVisible(false);
394  _webSearchMenu->menu()->clear();
395 
396  if (_selectedText.isEmpty())
397  return;
398 
399  QString searchText = _selectedText;
400  searchText = searchText.replace('\n', ' ').replace('\r', ' ').simplified();
401 
402  if (searchText.isEmpty())
403  return;
404 
405  KUriFilterData filterData(searchText);
406  filterData.setSearchFilteringOptions(KUriFilterData::RetrievePreferredSearchProvidersOnly);
407 
408  if (KUriFilter::self()->filterSearchUri(filterData, KUriFilter::NormalTextFilter)) {
409  const QStringList searchProviders = filterData.preferredSearchProviders();
410  if (!searchProviders.isEmpty()) {
411  _webSearchMenu->setText(i18n("Search for '%1' with", KStringHandler::rsqueeze(searchText, 16)));
412 
413  KAction* action = 0;
414 
415  foreach(const QString& searchProvider, searchProviders) {
416  action = new KAction(searchProvider, _webSearchMenu);
417  action->setIcon(KIcon(filterData.iconNameForPreferredSearchProvider(searchProvider)));
418  action->setData(filterData.queryForPreferredSearchProvider(searchProvider));
419  connect(action, SIGNAL(triggered()), this, SLOT(handleWebShortcutAction()));
420  _webSearchMenu->addAction(action);
421  }
422 
423  _webSearchMenu->addSeparator();
424 
425  action = new KAction(i18n("Configure Web Shortcuts..."), _webSearchMenu);
426  action->setIcon(KIcon("configure"));
427  connect(action, SIGNAL(triggered()), this, SLOT(configureWebShortcuts()));
428  _webSearchMenu->addAction(action);
429 
430  _webSearchMenu->setVisible(true);
431  }
432  }
433 }
434 
435 void SessionController::handleWebShortcutAction()
436 {
437  KAction* action = qobject_cast<KAction*>(sender());
438  if (!action)
439  return;
440 
441  KUriFilterData filterData(action->data().toString());
442 
443  if (KUriFilter::self()->filterUri(filterData, QStringList() << "kurisearchfilter")) {
444  const KUrl& url = filterData.uri();
445  new KRun(url, QApplication::activeWindow());
446  }
447 }
448 
449 void SessionController::configureWebShortcuts()
450 {
451  KToolInvocation::kdeinitExec("kcmshell4", QStringList() << "ebrowsing");
452 }
453 
454 void SessionController::sendSignal(QAction* action)
455 {
456  const int signal = action->data().value<int>();
457  _session->sendSignal(signal);
458 }
459 
460 bool SessionController::eventFilter(QObject* watched , QEvent* event)
461 {
462  if (watched == _view) {
463  if (event->type() == QEvent::FocusIn) {
464  // notify the world that the view associated with this session has been focused
465  // used by the view manager to update the title of the MainWindow widget containing the view
466  emit focused(this);
467 
468  // when the view is focused, set bell events from the associated session to be delivered
469  // by the focused view
470 
471  // first, disconnect any other views which are listening for bell signals from the session
472  disconnect(_session, SIGNAL(bellRequest(QString)), 0, 0);
473  // second, connect the newly focused view to listen for the session's bell signal
474  connect(_session, SIGNAL(bellRequest(QString)),
475  _view, SLOT(bell(QString)));
476 
477  if (_copyInputToAllTabsAction && _copyInputToAllTabsAction->isChecked()) {
478  // A session with "Copy To All Tabs" has come into focus:
479  // Ensure that newly created sessions are included in _copyToGroup!
480  copyInputToAllTabs();
481  }
482  }
483  // when a mouse move is received, create the URL filter and listen for output changes if
484  // it has not already been created. If it already exists, then update only if the output
485  // has changed since the last update ( _urlFilterUpdateRequired == true )
486  //
487  // also check that no mouse buttons are pressed since the URL filter only applies when
488  // the mouse is hovering over the view
489  if (event->type() == QEvent::MouseMove &&
490  (!_viewUrlFilter || _urlFilterUpdateRequired) &&
491  ((QMouseEvent*)event)->buttons() == Qt::NoButton) {
492  if (_view->screenWindow() && !_viewUrlFilter) {
493  connect(_view->screenWindow(), SIGNAL(scrolled(int)), this,
494  SLOT(requireUrlFilterUpdate()));
495  connect(_view->screenWindow(), SIGNAL(outputChanged()), this,
496  SLOT(requireUrlFilterUpdate()));
497 
498  // install filter on the view to highlight URLs
499  _viewUrlFilter = new UrlFilter();
500  _view->filterChain()->addFilter(_viewUrlFilter);
501  }
502 
503  _view->processFilters();
504  _urlFilterUpdateRequired = false;
505  }
506  }
507 
508  return false;
509 }
510 
511 void SessionController::removeSearchFilter()
512 {
513  if (!_searchFilter)
514  return;
515 
516  _view->filterChain()->removeFilter(_searchFilter);
517  delete _searchFilter;
518  _searchFilter = 0;
519 }
520 
521 void SessionController::setSearchBar(IncrementalSearchBar* searchBar)
522 {
523  // disconnect the existing search bar
524  if (_searchBar) {
525  disconnect(this, 0, _searchBar, 0);
526  disconnect(_searchBar, 0, this, 0);
527  }
528 
529  // connect new search bar
530  _searchBar = searchBar;
531  if (_searchBar) {
532  connect(_searchBar, SIGNAL(unhandledMovementKeyPressed(QKeyEvent*)), this, SLOT(movementKeyFromSearchBarReceived(QKeyEvent*)));
533  connect(_searchBar, SIGNAL(closeClicked()), this, SLOT(searchClosed()));
534  connect(_searchBar, SIGNAL(searchFromClicked()), this, SLOT(searchFrom()));
535  connect(_searchBar, SIGNAL(findNextClicked()), this, SLOT(findNextInHistory()));
536  connect(_searchBar, SIGNAL(findPreviousClicked()), this, SLOT(findPreviousInHistory()));
537  connect(_searchBar, SIGNAL(highlightMatchesToggled(bool)) , this , SLOT(highlightMatches(bool)));
538  connect(_searchBar, SIGNAL(matchCaseToggled(bool)), this, SLOT(changeSearchMatch()));
539 
540  // if the search bar was previously active
541  // then re-enter search mode
542  enableSearchBar(_isSearchBarEnabled);
543  }
544 }
545 IncrementalSearchBar* SessionController::searchBar() const
546 {
547  return _searchBar;
548 }
549 
550 void SessionController::setShowMenuAction(QAction* action)
551 {
552  _showMenuAction = action;
553 }
554 
555 void SessionController::setupCommonActions()
556 {
557  KAction* action = 0;
558  KActionCollection* collection = actionCollection();
559 
560  // Close Session
561  action = collection->addAction("close-session", this, SLOT(closeSession()));
562  if (isKonsolePart())
563  action->setText(i18n("&Close Session"));
564  else
565  action->setText(i18n("&Close Tab"));
566 
567  action->setIcon(KIcon("tab-close"));
568  action->setShortcut(QKeySequence(Qt::CTRL + Qt::SHIFT + Qt::Key_W));
569 
570  // Open Browser
571  action = collection->addAction("open-browser", this, SLOT(openBrowser()));
572  action->setText(i18n("Open File Manager"));
573  action->setIcon(KIcon("system-file-manager"));
574 
575  // Copy and Paste
576  action = KStandardAction::copy(this, SLOT(copy()), collection);
577  action->setShortcut(QKeySequence(Qt::CTRL + Qt::SHIFT + Qt::Key_C));
578  // disabled at first, since nothing has been selected now
579  action->setEnabled(false);
580 
581  action = KStandardAction::paste(this, SLOT(paste()), collection);
582  KShortcut pasteShortcut = action->shortcut();
583  pasteShortcut.setPrimary(QKeySequence(Qt::CTRL + Qt::SHIFT + Qt::Key_V));
584  pasteShortcut.setAlternate(QKeySequence(Qt::SHIFT + Qt::Key_Insert));
585  action->setShortcut(pasteShortcut);
586 
587  action = collection->addAction("paste-selection", this, SLOT(pasteFromX11Selection()));
588  action->setText(i18n("Paste Selection"));
589  action->setShortcut(QKeySequence(Qt::CTRL + Qt::SHIFT + Qt::Key_Insert));
590 
591  _webSearchMenu = new KActionMenu(i18n("Web Search"), this);
592  _webSearchMenu->setIcon(KIcon("preferences-web-browser-shortcuts"));
593  _webSearchMenu->setVisible(false);
594  collection->addAction("web-search", _webSearchMenu);
595 
596 
597  action = collection->addAction("select-all", this, SLOT(selectAll()));
598  action->setText(i18n("&Select All"));
599  action->setIcon(KIcon("edit-select-all"));
600 
601  action = collection->addAction("select-line", this, SLOT(selectLine()));
602  action->setText(i18n("Select &Line"));
603 
604  action = KStandardAction::saveAs(this, SLOT(saveHistory()), collection);
605  action->setText(i18n("Save Output &As..."));
606 
607  action = KStandardAction::print(this, SLOT(print_screen()), collection);
608  action->setText(i18n("&Print Screen..."));
609  action->setShortcut(QKeySequence(Qt::CTRL + Qt::SHIFT + Qt::Key_P));
610 
611  action = collection->addAction("adjust-history", this, SLOT(showHistoryOptions()));
612  action->setText(i18n("Adjust Scrollback..."));
613  action->setIcon(KIcon("configure"));
614 
615  action = collection->addAction("clear-history", this, SLOT(clearHistory()));
616  action->setText(i18n("Clear Scrollback"));
617  action->setIcon(KIcon("edit-clear-history"));
618 
619  action = collection->addAction("clear-history-and-reset", this, SLOT(clearHistoryAndReset()));
620  action->setText(i18n("Clear Scrollback and Reset"));
621  action->setIcon(KIcon("edit-clear-history"));
622  action->setShortcut(QKeySequence(Qt::CTRL + Qt::SHIFT + Qt::Key_K));
623 
624  // Profile Options
625  action = collection->addAction("edit-current-profile", this, SLOT(editCurrentProfile()));
626  action->setText(i18n("Edit Current Profile..."));
627  action->setIcon(KIcon("document-properties"));
628 
629  _switchProfileMenu = new KActionMenu(i18n("Switch Profile"), this);
630  collection->addAction("switch-profile", _switchProfileMenu);
631  connect(_switchProfileMenu->menu(), SIGNAL(aboutToShow()), this, SLOT(prepareSwitchProfileMenu()));
632 
633  // History
634  _findAction = KStandardAction::find(this, SLOT(searchBarEvent()), collection);
635  _findAction->setShortcut(QKeySequence());
636 
637  _findNextAction = KStandardAction::findNext(this, SLOT(findNextInHistory()), collection);
638  _findNextAction->setShortcut(QKeySequence());
639  _findNextAction->setEnabled(false);
640 
641  _findPreviousAction = KStandardAction::findPrev(this, SLOT(findPreviousInHistory()), collection);
642  _findPreviousAction->setShortcut(QKeySequence());
643  _findPreviousAction->setEnabled(false);
644 
645  // Character Encoding
646  _codecAction = new KCodecAction(i18n("Set &Encoding"), this);
647  _codecAction->setIcon(KIcon("character-set"));
648  collection->addAction("set-encoding", _codecAction);
649  connect(_codecAction->menu(), SIGNAL(aboutToShow()), this, SLOT(updateCodecAction()));
650  connect(_codecAction, SIGNAL(triggered(QTextCodec*)), this, SLOT(changeCodec(QTextCodec*)));
651 }
652 
653 void SessionController::setupExtraActions()
654 {
655  KAction* action = 0;
656  KToggleAction* toggleAction = 0;
657  KActionCollection* collection = actionCollection();
658 
659  // Rename Session
660  action = collection->addAction("rename-session", this, SLOT(renameSession()));
661  action->setText(i18n("&Rename Tab..."));
662  action->setIcon(KIcon("edit-rename"));
663  action->setShortcut(QKeySequence(Qt::CTRL + Qt::ALT + Qt::Key_S));
664 
665  // Copy input to ==> all tabs
666  KToggleAction* copyInputToAllTabsAction = collection->add<KToggleAction>("copy-input-to-all-tabs");
667  copyInputToAllTabsAction->setText(i18n("&All Tabs in Current Window"));
668  copyInputToAllTabsAction->setData(CopyInputToAllTabsMode);
669  // this action is also used in other place, so remember it
670  _copyInputToAllTabsAction = copyInputToAllTabsAction;
671 
672  // Copy input to ==> selected tabs
673  KToggleAction* copyInputToSelectedTabsAction = collection->add<KToggleAction>("copy-input-to-selected-tabs");
674  copyInputToSelectedTabsAction->setText(i18n("&Select Tabs..."));
675  copyInputToSelectedTabsAction->setShortcut(QKeySequence(Qt::CTRL + Qt::SHIFT + Qt::Key_Period));
676  copyInputToSelectedTabsAction->setData(CopyInputToSelectedTabsMode);
677 
678  // Copy input to ==> none
679  KToggleAction* copyInputToNoneAction = collection->add<KToggleAction>("copy-input-to-none");
680  copyInputToNoneAction->setText(i18nc("@action:inmenu Do not select any tabs", "&None"));
681  copyInputToNoneAction->setShortcut(QKeySequence(Qt::CTRL + Qt::SHIFT + Qt::Key_Slash));
682  copyInputToNoneAction->setData(CopyInputToNoneMode);
683  copyInputToNoneAction->setChecked(true); // the default state
684 
685  // The "Copy Input To" submenu
686  // The above three choices are represented as combo boxes
687  KSelectAction* copyInputActions = collection->add<KSelectAction>("copy-input-to");
688  copyInputActions->setText(i18n("Copy Input To"));
689  copyInputActions->addAction(copyInputToAllTabsAction);
690  copyInputActions->addAction(copyInputToSelectedTabsAction);
691  copyInputActions->addAction(copyInputToNoneAction);
692  connect(copyInputActions, SIGNAL(triggered(QAction*)), this, SLOT(copyInputActionsTriggered(QAction*)));
693 
694  action = collection->addAction("zmodem-upload", this, SLOT(zmodemUpload()));
695  action->setText(i18n("&ZModem Upload..."));
696  action->setIcon(KIcon("document-open"));
697  action->setShortcut(QKeySequence(Qt::CTRL + Qt::ALT + Qt::Key_U));
698 
699  // Monitor
700  toggleAction = new KToggleAction(i18n("Monitor for &Activity"), this);
701  toggleAction->setShortcut(QKeySequence(Qt::CTRL + Qt::SHIFT + Qt::Key_A));
702  action = collection->addAction("monitor-activity", toggleAction);
703  connect(action, SIGNAL(toggled(bool)), this, SLOT(monitorActivity(bool)));
704 
705  toggleAction = new KToggleAction(i18n("Monitor for &Silence"), this);
706  toggleAction->setShortcut(QKeySequence(Qt::CTRL + Qt::SHIFT + Qt::Key_I));
707  action = collection->addAction("monitor-silence", toggleAction);
708  connect(action, SIGNAL(toggled(bool)), this, SLOT(monitorSilence(bool)));
709 
710  // Text Size
711  action = collection->addAction("enlarge-font", this, SLOT(increaseFontSize()));
712  action->setText(i18n("Enlarge Font"));
713  action->setIcon(KIcon("format-font-size-more"));
714  KShortcut enlargeFontShortcut = action->shortcut();
715  enlargeFontShortcut.setPrimary(QKeySequence(Qt::CTRL + Qt::Key_Plus));
716  enlargeFontShortcut.setAlternate(QKeySequence(Qt::CTRL + Qt::Key_Equal));
717  action->setShortcut(enlargeFontShortcut);
718 
719  action = collection->addAction("shrink-font", this, SLOT(decreaseFontSize()));
720  action->setText(i18n("Shrink Font"));
721  action->setIcon(KIcon("format-font-size-less"));
722  action->setShortcut(KShortcut(Qt::CTRL | Qt::Key_Minus));
723 
724  // Send signal
725  KSelectAction* sendSignalActions = collection->add<KSelectAction>("send-signal");
726  sendSignalActions->setText(i18n("Send Signal"));
727  connect(sendSignalActions, SIGNAL(triggered(QAction*)), this, SLOT(sendSignal(QAction*)));
728 
729  action = collection->addAction("sigstop-signal");
730  action->setText(i18n("&Suspend Task") + " (STOP)");
731  action->setData(SIGSTOP);
732  sendSignalActions->addAction(action);
733 
734  action = collection->addAction("sigcont-signal");
735  action->setText(i18n("&Continue Task") + " (CONT)");
736  action->setData(SIGCONT);
737  sendSignalActions->addAction(action);
738 
739  action = collection->addAction("sighup-signal");
740  action->setText(i18n("&Hangup") + " (HUP)");
741  action->setData(SIGHUP);
742  sendSignalActions->addAction(action);
743 
744  action = collection->addAction("sigint-signal");
745  action->setText(i18n("&Interrupt Task") + " (INT)");
746  action->setData(SIGINT);
747  sendSignalActions->addAction(action);
748 
749  action = collection->addAction("sigterm-signal");
750  action->setText(i18n("&Terminate Task") + " (TERM)");
751  action->setData(SIGTERM);
752  sendSignalActions->addAction(action);
753 
754  action = collection->addAction("sigkill-signal");
755  action->setText(i18n("&Kill Task") + " (KILL)");
756  action->setData(SIGKILL);
757  sendSignalActions->addAction(action);
758 
759  action = collection->addAction("sigusr1-signal");
760  action->setText(i18n("User Signal &1") + " (USR1)");
761  action->setData(SIGUSR1);
762  sendSignalActions->addAction(action);
763 
764  action = collection->addAction("sigusr2-signal");
765  action->setText(i18n("User Signal &2") + " (USR2)");
766  action->setData(SIGUSR2);
767  sendSignalActions->addAction(action);
768 
769  _findAction->setShortcut(QKeySequence(Qt::CTRL + Qt::SHIFT + Qt::Key_F));
770  _findNextAction->setShortcut(QKeySequence(Qt::Key_F3));
771  _findPreviousAction->setShortcut(QKeySequence(Qt::SHIFT + Qt::Key_F3));
772 }
773 
774 void SessionController::switchProfile(Profile::Ptr profile)
775 {
776  SessionManager::instance()->setSessionProfile(_session, profile);
777 }
778 
779 void SessionController::prepareSwitchProfileMenu()
780 {
781  if (_switchProfileMenu->menu()->isEmpty()) {
782  _profileList = new ProfileList(false, this);
783  connect(_profileList, SIGNAL(profileSelected(Profile::Ptr)), this, SLOT(switchProfile(Profile::Ptr)));
784  }
785 
786  _switchProfileMenu->menu()->clear();
787  _switchProfileMenu->menu()->addActions(_profileList->actions());
788 }
789 void SessionController::updateCodecAction()
790 {
791  _codecAction->setCurrentCodec(QString(_session->codec()));
792 }
793 
794 void SessionController::changeCodec(QTextCodec* codec)
795 {
796  _session->setCodec(codec);
797 }
798 
799 EditProfileDialog* SessionController::profileDialogPointer()
800 {
801  return _editProfileDialog.data();
802 }
803 
804 void SessionController::editCurrentProfile()
805 {
806  // Searching for Edit profile dialog opened with the same profile
807  foreach (SessionController* session, _allControllers.values()) {
808  if (session->profileDialogPointer()
809  && session->profileDialogPointer()->isVisible()
810  && session->profileDialogPointer()->lookupProfile() == SessionManager::instance()->sessionProfile(_session)) {
811  session->profileDialogPointer()->close();
812  }
813  }
814 
815  // NOTE bug311270: For to prevent the crash, the profile must be reset.
816  if (!_editProfileDialog.isNull()) {
817  // exists but not visible
818  delete _editProfileDialog.data();
819  }
820 
821  _editProfileDialog = new EditProfileDialog(QApplication::activeWindow());
822  _editProfileDialog.data()->setProfile(SessionManager::instance()->sessionProfile(_session));
823  _editProfileDialog.data()->show();
824 }
825 
826 void SessionController::renameSession()
827 {
828  QScopedPointer<RenameTabDialog> dialog(new RenameTabDialog(QApplication::activeWindow()));
829  dialog->setTabTitleText(_session->tabTitleFormat(Session::LocalTabTitle));
830  dialog->setRemoteTabTitleText(_session->tabTitleFormat(Session::RemoteTabTitle));
831 
832  if (_session->isRemote()) {
833  dialog->focusRemoteTabTitleText();
834  } else {
835  dialog->focusTabTitleText();
836  }
837 
838  QPointer<Session> guard(_session);
839  int result = dialog->exec();
840  if (!guard)
841  return;
842 
843  if (result) {
844  QString tabTitle = dialog->tabTitleText();
845  QString remoteTabTitle = dialog->remoteTabTitleText();
846 
847  _session->setTabTitleFormat(Session::LocalTabTitle, tabTitle);
848  _session->setTabTitleFormat(Session::RemoteTabTitle, remoteTabTitle);
849 
850  // trigger an update of the tab text
851  snapshot();
852  }
853 }
854 
855 bool SessionController::confirmClose() const
856 {
857  if (_session->isForegroundProcessActive()) {
858  QString title = _session->foregroundProcessName();
859 
860  // hard coded for now. In future make it possible for the user to specify which programs
861  // are ignored when considering whether to display a confirmation
862  QStringList ignoreList;
863  ignoreList << QString(qgetenv("SHELL")).section('/', -1);
864  if (ignoreList.contains(title))
865  return true;
866 
867  QString question;
868  if (title.isEmpty())
869  question = i18n("A program is currently running in this session."
870  " Are you sure you want to close it?");
871  else
872  question = i18n("The program '%1' is currently running in this session."
873  " Are you sure you want to close it?", title);
874 
875  int result = KMessageBox::warningYesNo(_view->window(), question, i18n("Confirm Close"));
876  return (result == KMessageBox::Yes) ? true : false;
877  }
878  return true;
879 }
880 bool SessionController::confirmForceClose() const
881 {
882  if (_session->isRunning()) {
883  QString title = _session->program();
884 
885  // hard coded for now. In future make it possible for the user to specify which programs
886  // are ignored when considering whether to display a confirmation
887  QStringList ignoreList;
888  ignoreList << QString(qgetenv("SHELL")).section('/', -1);
889  if (ignoreList.contains(title))
890  return true;
891 
892  QString question;
893  if (title.isEmpty())
894  question = i18n("A program in this session would not die."
895  " Are you sure you want to kill it by force?");
896  else
897  question = i18n("The program '%1' is in this session would not die."
898  " Are you sure you want to kill it by force?", title);
899 
900  int result = KMessageBox::warningYesNo(_view->window(), question, i18n("Confirm Close"));
901  return (result == KMessageBox::Yes) ? true : false;
902  }
903  return true;
904 }
905 void SessionController::closeSession()
906 {
907  if (_preventClose)
908  return;
909 
910  if (confirmClose()) {
911  if (_session->closeInNormalWay()) {
912  return;
913  } else if (confirmForceClose()) {
914  if (_session->closeInForceWay())
915  return;
916  else
917  kWarning() << "Konsole failed to close a session in any way.";
918  }
919  }
920 }
921 
922 // Trying to open a remote Url may produce unexpected results.
923 // Therefore, if a remote url, open the user's home path.
924 // TODO consider: 1) disable menu upon remote session
925 // 2) transform url to get the desired result (ssh -> sftp, etc)
926 void SessionController::openBrowser()
927 {
928  KUrl currentUrl = url();
929 
930  if (currentUrl.isLocalFile())
931  new KRun(currentUrl, QApplication::activeWindow(), 0, true, true);
932  else
933  new KRun(KUrl(QDir::homePath()), QApplication::activeWindow(), 0, true, true);
934 }
935 
936 void SessionController::copy()
937 {
938  _view->copyToClipboard();
939 }
940 
941 void SessionController::paste()
942 {
943  _view->pasteFromClipboard();
944 }
945 void SessionController::pasteFromX11Selection()
946 {
947  _view->pasteFromX11Selection();
948 }
949 void SessionController::selectAll()
950 {
951  ScreenWindow * screenWindow = _view->screenWindow();
952  screenWindow->setSelectionByLineRange(0, _session->emulation()->lineCount());
953  _view->copyToX11Selection();
954 }
955 void SessionController::selectLine()
956 {
957  _view->selectCurrentLine();
958 }
959 static const KXmlGuiWindow* findWindow(const QObject* object)
960 {
961  // Walk up the QObject hierarchy to find a KXmlGuiWindow.
962  while (object != 0) {
963  const KXmlGuiWindow* window = qobject_cast<const KXmlGuiWindow*>(object);
964  if (window != 0) {
965  return(window);
966  }
967  object = object->parent();
968  }
969  return(0);
970 }
971 
972 static bool hasTerminalDisplayInSameWindow(const Session* session, const KXmlGuiWindow* window)
973 {
974  // Iterate all TerminalDisplays of this Session ...
975  foreach(const TerminalDisplay* terminalDisplay, session->views()) {
976  // ... and check whether a TerminalDisplay has the same
977  // window as given in the parameter
978  if (window == findWindow(terminalDisplay)) {
979  return(true);
980  }
981  }
982  return(false);
983 }
984 
985 void SessionController::copyInputActionsTriggered(QAction* action)
986 {
987  const int mode = action->data().value<int>();
988 
989  switch (mode) {
990  case CopyInputToAllTabsMode:
991  copyInputToAllTabs();
992  break;
993  case CopyInputToSelectedTabsMode:
994  copyInputToSelectedTabs();
995  break;
996  case CopyInputToNoneMode:
997  copyInputToNone();
998  break;
999  default:
1000  Q_ASSERT(false);
1001  }
1002 }
1003 
1004 void SessionController::copyInputToAllTabs()
1005 {
1006  if (!_copyToGroup) {
1007  _copyToGroup = new SessionGroup(this);
1008  }
1009 
1010  // Find our window ...
1011  const KXmlGuiWindow* myWindow = findWindow(_view);
1012 
1013  QSet<Session*> group =
1014  QSet<Session*>::fromList(SessionManager::instance()->sessions());
1015  for (QSet<Session*>::iterator iterator = group.begin();
1016  iterator != group.end(); ++iterator) {
1017  Session* session = *iterator;
1018 
1019  // First, ensure that the session is removed
1020  // (necessary to avoid duplicates on addSession()!)
1021  _copyToGroup->removeSession(session);
1022 
1023  // Add current session if it is displayed our window
1024  if (hasTerminalDisplayInSameWindow(session, myWindow)) {
1025  _copyToGroup->addSession(session);
1026  }
1027  }
1028  _copyToGroup->setMasterStatus(_session, true);
1029  _copyToGroup->setMasterMode(SessionGroup::CopyInputToAll);
1030 
1031  snapshot();
1032 }
1033 
1034 void SessionController::copyInputToSelectedTabs()
1035 {
1036  if (!_copyToGroup) {
1037  _copyToGroup = new SessionGroup(this);
1038  _copyToGroup->addSession(_session);
1039  _copyToGroup->setMasterStatus(_session, true);
1040  _copyToGroup->setMasterMode(SessionGroup::CopyInputToAll);
1041  }
1042 
1043  QPointer<CopyInputDialog> dialog = new CopyInputDialog(_view);
1044  dialog->setMasterSession(_session);
1045 
1046  QSet<Session*> currentGroup = QSet<Session*>::fromList(_copyToGroup->sessions());
1047  currentGroup.remove(_session);
1048 
1049  dialog->setChosenSessions(currentGroup);
1050 
1051  QPointer<Session> guard(_session);
1052  int result = dialog->exec();
1053  if (!guard)
1054  return;
1055 
1056  if (result == QDialog::Accepted) {
1057  QSet<Session*> newGroup = dialog->chosenSessions();
1058  newGroup.remove(_session);
1059 
1060  QSet<Session*> completeGroup = newGroup | currentGroup;
1061  foreach(Session * session, completeGroup) {
1062  if (newGroup.contains(session) && !currentGroup.contains(session))
1063  _copyToGroup->addSession(session);
1064  else if (!newGroup.contains(session) && currentGroup.contains(session))
1065  _copyToGroup->removeSession(session);
1066  }
1067 
1068  _copyToGroup->setMasterStatus(_session, true);
1069  _copyToGroup->setMasterMode(SessionGroup::CopyInputToAll);
1070  snapshot();
1071  }
1072 }
1073 
1074 void SessionController::copyInputToNone()
1075 {
1076  if (!_copyToGroup) // No 'Copy To' is active
1077  return;
1078 
1079  QSet<Session*> group =
1080  QSet<Session*>::fromList(SessionManager::instance()->sessions());
1081  for (QSet<Session*>::iterator iterator = group.begin();
1082  iterator != group.end(); ++iterator) {
1083  Session* session = *iterator;
1084 
1085  if (session != _session) {
1086  _copyToGroup->removeSession(*iterator);
1087  }
1088  }
1089  delete _copyToGroup;
1090  _copyToGroup = 0;
1091  snapshot();
1092 }
1093 
1094 void SessionController::searchClosed()
1095 {
1096  _isSearchBarEnabled = false;
1097  searchHistory(false);
1098 }
1099 
1100 void SessionController::setSearchStartToWindowCurrentLine()
1101 {
1102  setSearchStartTo(-1);
1103 }
1104 
1105 void SessionController::setSearchStartTo(int line)
1106 {
1107  _searchStartLine = line;
1108  _prevSearchResultLine = line;
1109 }
1110 
1111 void SessionController::listenForScreenWindowUpdates()
1112 {
1113  if (_listenForScreenWindowUpdates)
1114  return;
1115 
1116  connect(_view->screenWindow(), SIGNAL(outputChanged()), this,
1117  SLOT(updateSearchFilter()));
1118  connect(_view->screenWindow(), SIGNAL(scrolled(int)), this,
1119  SLOT(updateSearchFilter()));
1120  connect(_view->screenWindow(), SIGNAL(currentResultLineChanged()), _view,
1121  SLOT(update()));
1122 
1123  _listenForScreenWindowUpdates = true;
1124 }
1125 
1126 void SessionController::updateSearchFilter()
1127 {
1128  if (_searchFilter && _searchBar) {
1129  _view->processFilters();
1130  }
1131 }
1132 
1133 void SessionController::searchBarEvent()
1134 {
1135  QString selectedText = _view->screenWindow()->selectedText(true, true);
1136  if (!selectedText.isEmpty())
1137  _searchBar->setSearchText(selectedText);
1138 
1139  if (_searchBar->isVisible()) {
1140  _searchBar->focusLineEdit();
1141  } else {
1142  searchHistory(true);
1143  _isSearchBarEnabled = true;
1144  }
1145 }
1146 
1147 void SessionController::enableSearchBar(bool showSearchBar)
1148 {
1149  if (!_searchBar)
1150  return;
1151 
1152  if (showSearchBar && !_searchBar->isVisible()) {
1153  setSearchStartToWindowCurrentLine();
1154  }
1155 
1156  _searchBar->setVisible(showSearchBar);
1157  if (showSearchBar) {
1158  connect(_searchBar, SIGNAL(searchChanged(QString)), this,
1159  SLOT(searchTextChanged(QString)));
1160  connect(_searchBar, SIGNAL(searchReturnPressed(QString)), this,
1161  SLOT(findPreviousInHistory()));
1162  connect(_searchBar, SIGNAL(searchShiftPlusReturnPressed()), this,
1163  SLOT(findNextInHistory()));
1164  } else {
1165  disconnect(_searchBar, SIGNAL(searchChanged(QString)), this,
1166  SLOT(searchTextChanged(QString)));
1167  disconnect(_searchBar, SIGNAL(searchReturnPressed(QString)), this,
1168  SLOT(findPreviousInHistory()));
1169  disconnect(_searchBar, SIGNAL(searchShiftPlusReturnPressed()), this,
1170  SLOT(findNextInHistory()));
1171  if (_view && _view->screenWindow()) {
1172  _view->screenWindow()->setCurrentResultLine(-1);
1173  }
1174  }
1175 }
1176 
1177 
1178 bool SessionController::reverseSearchChecked() const
1179 {
1180  Q_ASSERT(_searchBar);
1181 
1182  QBitArray options = _searchBar->optionsChecked();
1183  return options.at(IncrementalSearchBar::ReverseSearch);
1184 }
1185 
1186 QRegExp SessionController::regexpFromSearchBarOptions()
1187 {
1188  QBitArray options = _searchBar->optionsChecked();
1189 
1190  Qt::CaseSensitivity caseHandling = options.at(IncrementalSearchBar::MatchCase) ? Qt::CaseSensitive : Qt::CaseInsensitive;
1191  QRegExp::PatternSyntax syntax = options.at(IncrementalSearchBar::RegExp) ? QRegExp::RegExp : QRegExp::FixedString;
1192 
1193  QRegExp regExp(_searchBar->searchText(), caseHandling , syntax);
1194  return regExp;
1195 }
1196 
1197 // searchHistory() may be called either as a result of clicking a menu item or
1198 // as a result of changing the search bar widget
1199 void SessionController::searchHistory(bool showSearchBar)
1200 {
1201  enableSearchBar(showSearchBar);
1202 
1203  if (_searchBar) {
1204  if (showSearchBar) {
1205  removeSearchFilter();
1206 
1207  listenForScreenWindowUpdates();
1208 
1209  _searchFilter = new RegExpFilter();
1210  _searchFilter->setRegExp(regexpFromSearchBarOptions());
1211  _view->filterChain()->addFilter(_searchFilter);
1212  _view->processFilters();
1213 
1214  setFindNextPrevEnabled(true);
1215  } else {
1216  setFindNextPrevEnabled(false);
1217 
1218  removeSearchFilter();
1219 
1220  _view->setFocus(Qt::ActiveWindowFocusReason);
1221  }
1222  }
1223 }
1224 
1225 void SessionController::setFindNextPrevEnabled(bool enabled)
1226 {
1227  _findNextAction->setEnabled(enabled);
1228  _findPreviousAction->setEnabled(enabled);
1229 }
1230 void SessionController::searchTextChanged(const QString& text)
1231 {
1232  Q_ASSERT(_view->screenWindow());
1233 
1234  if (_searchText == text)
1235  return;
1236 
1237  _searchText = text;
1238 
1239  if (text.isEmpty()) {
1240  _view->screenWindow()->clearSelection();
1241  _view->screenWindow()->scrollTo(_searchStartLine);
1242  }
1243 
1244  // update search. this is called even when the text is
1245  // empty to clear the view's filters
1246  beginSearch(text , reverseSearchChecked() ? SearchHistoryTask::BackwardsSearch : SearchHistoryTask::ForwardsSearch);
1247 }
1248 void SessionController::searchCompleted(bool success)
1249 {
1250  _prevSearchResultLine = _view->screenWindow()->currentResultLine();
1251 
1252  if (_searchBar)
1253  _searchBar->setFoundMatch(success);
1254 }
1255 
1256 void SessionController::beginSearch(const QString& text , int direction)
1257 {
1258  Q_ASSERT(_searchBar);
1259  Q_ASSERT(_searchFilter);
1260 
1261  QRegExp regExp = regexpFromSearchBarOptions();
1262  _searchFilter->setRegExp(regExp);
1263 
1264  if (_searchStartLine == -1) {
1265  if (direction == SearchHistoryTask::ForwardsSearch) {
1266  setSearchStartTo(_view->screenWindow()->currentLine());
1267  } else {
1268  setSearchStartTo(_view->screenWindow()->currentLine() + _view->screenWindow()->windowLines());
1269  }
1270  }
1271 
1272  if (!regExp.isEmpty()) {
1273  _view->screenWindow()->setCurrentResultLine(-1);
1274  SearchHistoryTask* task = new SearchHistoryTask(this);
1275 
1276  connect(task, SIGNAL(completed(bool)), this, SLOT(searchCompleted(bool)));
1277 
1278  task->setRegExp(regExp);
1279  task->setSearchDirection((SearchHistoryTask::SearchDirection)direction);
1280  task->setAutoDelete(true);
1281  task->setStartLine(_searchStartLine);
1282  task->addScreenWindow(_session , _view->screenWindow());
1283  task->execute();
1284  } else if (text.isEmpty()) {
1285  searchCompleted(false);
1286  }
1287 
1288  _view->processFilters();
1289 }
1290 void SessionController::highlightMatches(bool highlight)
1291 {
1292  if (highlight) {
1293  _view->filterChain()->addFilter(_searchFilter);
1294  _view->processFilters();
1295  } else {
1296  _view->filterChain()->removeFilter(_searchFilter);
1297  }
1298 
1299  _view->update();
1300 }
1301 
1302 void SessionController::searchFrom()
1303 {
1304  Q_ASSERT(_searchBar);
1305  Q_ASSERT(_searchFilter);
1306 
1307  if (reverseSearchChecked()) {
1308  setSearchStartTo(_view->screenWindow()->lineCount());
1309  } else {
1310  setSearchStartTo(0);
1311  }
1312 
1313 
1314  beginSearch(_searchBar->searchText(), reverseSearchChecked() ? SearchHistoryTask::BackwardsSearch : SearchHistoryTask::ForwardsSearch);
1315 }
1316 void SessionController::findNextInHistory()
1317 {
1318  Q_ASSERT(_searchBar);
1319  Q_ASSERT(_searchFilter);
1320 
1321  setSearchStartTo(_prevSearchResultLine);
1322 
1323  beginSearch(_searchBar->searchText(), reverseSearchChecked() ? SearchHistoryTask::BackwardsSearch : SearchHistoryTask::ForwardsSearch);
1324 }
1325 void SessionController::findPreviousInHistory()
1326 {
1327  Q_ASSERT(_searchBar);
1328  Q_ASSERT(_searchFilter);
1329 
1330  setSearchStartTo(_prevSearchResultLine);
1331 
1332  beginSearch(_searchBar->searchText(), reverseSearchChecked() ? SearchHistoryTask::ForwardsSearch : SearchHistoryTask::BackwardsSearch);
1333 }
1334 void SessionController::changeSearchMatch()
1335 {
1336  Q_ASSERT(_searchBar);
1337  Q_ASSERT(_searchFilter);
1338 
1339  // reset Selection for new case match
1340  _view->screenWindow()->clearSelection();
1341  beginSearch(_searchBar->searchText(), reverseSearchChecked() ? SearchHistoryTask::BackwardsSearch : SearchHistoryTask::ForwardsSearch);
1342 }
1343 void SessionController::showHistoryOptions()
1344 {
1345  QScopedPointer<HistorySizeDialog> dialog(new HistorySizeDialog(QApplication::activeWindow()));
1346  const HistoryType& currentHistory = _session->historyType();
1347 
1348  if (currentHistory.isEnabled()) {
1349  if (currentHistory.isUnlimited()) {
1350  dialog->setMode(Enum::UnlimitedHistory);
1351  } else {
1352  dialog->setMode(Enum::FixedSizeHistory);
1353  dialog->setLineCount(currentHistory.maximumLineCount());
1354  }
1355  } else {
1356  dialog->setMode(Enum::NoHistory);
1357  }
1358 
1359  QPointer<Session> guard(_session);
1360  int result = dialog->exec();
1361  if (!guard)
1362  return;
1363 
1364  if (result) {
1365  scrollBackOptionsChanged(dialog->mode(), dialog->lineCount());
1366  }
1367 }
1368 void SessionController::sessionResizeRequest(const QSize& size)
1369 {
1370  //kDebug() << "View resize requested to " << size;
1371  _view->setSize(size.width(), size.height());
1372 }
1373 void SessionController::scrollBackOptionsChanged(int mode, int lines)
1374 {
1375  switch (mode) {
1376  case Enum::NoHistory:
1377  _session->setHistoryType(HistoryTypeNone());
1378  break;
1379  case Enum::FixedSizeHistory:
1380  _session->setHistoryType(CompactHistoryType(lines));
1381  break;
1382  case Enum::UnlimitedHistory:
1383  _session->setHistoryType(HistoryTypeFile());
1384  break;
1385  }
1386 }
1387 
1388 void SessionController::print_screen()
1389 {
1390  QPrinter printer;
1391 
1392  QPointer<QPrintDialog> dialog = new QPrintDialog(&printer, _view);
1393  PrintOptions* options = new PrintOptions();
1394 
1395  dialog->setOptionTabs(QList<QWidget*>() << options);
1396  dialog->setWindowTitle(i18n("Print Shell"));
1397  connect(dialog, SIGNAL(accepted()), options, SLOT(saveSettings()));
1398  if (dialog->exec() != QDialog::Accepted)
1399  return;
1400 
1401  QPainter painter;
1402  painter.begin(&printer);
1403 
1404  KConfigGroup configGroup(KGlobal::config(), "PrintOptions");
1405 
1406  if (configGroup.readEntry("ScaleOutput", true)) {
1407  double scale = qMin(printer.pageRect().width() / static_cast<double>(_view->width()),
1408  printer.pageRect().height() / static_cast<double>(_view->height()));
1409  painter.scale(scale, scale);
1410  }
1411 
1412  _view->printContent(painter, configGroup.readEntry("PrinterFriendly", true));
1413 }
1414 
1415 void SessionController::saveHistory()
1416 {
1417  SessionTask* task = new SaveHistoryTask(this);
1418  task->setAutoDelete(true);
1419  task->addSession(_session);
1420  task->execute();
1421 }
1422 
1423 void SessionController::clearHistory()
1424 {
1425  _session->clearHistory();
1426  _view->updateImage(); // To reset view scrollbar
1427 }
1428 
1429 void SessionController::clearHistoryAndReset()
1430 {
1431  Profile::Ptr profile = SessionManager::instance()->sessionProfile(_session);
1432  QByteArray name = profile->defaultEncoding().toUtf8();
1433 
1434  Emulation* emulation = _session->emulation();
1435  emulation->reset();
1436  _session->refresh();
1437  _session->setCodec(QTextCodec::codecForName(name));
1438  clearHistory();
1439 }
1440 
1441 void SessionController::increaseFontSize()
1442 {
1443  _view->increaseFontSize();
1444 }
1445 
1446 void SessionController::decreaseFontSize()
1447 {
1448  _view->decreaseFontSize();
1449 }
1450 
1451 void SessionController::monitorActivity(bool monitor)
1452 {
1453  _session->setMonitorActivity(monitor);
1454 }
1455 void SessionController::monitorSilence(bool monitor)
1456 {
1457  _session->setMonitorSilence(monitor);
1458 }
1459 void SessionController::updateSessionIcon()
1460 {
1461  // Visualize that the session is broadcasting to others
1462  if (_copyToGroup && _copyToGroup->sessions().count() > 1) {
1463  // Master Mode: set different icon, to warn the user to be careful
1464  setIcon(_broadcastIcon);
1465  } else {
1466  if (!_keepIconUntilInteraction) {
1467  // Not in Master Mode: use normal icon
1468  setIcon(_sessionIcon);
1469  }
1470  }
1471 }
1472 void SessionController::sessionTitleChanged()
1473 {
1474  if (_sessionIconName != _session->iconName()) {
1475  _sessionIconName = _session->iconName();
1476  _sessionIcon = KIcon(_sessionIconName);
1477  updateSessionIcon();
1478  }
1479 
1480  QString title = _session->title(Session::DisplayedTitleRole);
1481 
1482  // special handling for the "%w" marker which is replaced with the
1483  // window title set by the shell
1484  title.replace("%w", _session->userTitle());
1485  // special handling for the "%#" marker which is replaced with the
1486  // number of the shell
1487  title.replace("%#", QString::number(_session->sessionId()));
1488 
1489  if (title.isEmpty())
1490  title = _session->title(Session::NameRole);
1491 
1492  setTitle(title);
1493  emit rawTitleChanged();
1494 }
1495 
1496 void SessionController::showDisplayContextMenu(const QPoint& position)
1497 {
1498  // needed to make sure the popup menu is available, even if a hosting
1499  // application did not merge our GUI.
1500  if (!factory()) {
1501  if (!clientBuilder()) {
1502  setClientBuilder(new KXMLGUIBuilder(_view));
1503  }
1504 
1505  KXMLGUIFactory* factory = new KXMLGUIFactory(clientBuilder(), this);
1506  factory->addClient(this);
1507  //kDebug() << "Created xmlgui factory" << factory;
1508  }
1509 
1510  QPointer<QMenu> popup = qobject_cast<QMenu*>(factory()->container("session-popup-menu", this));
1511  if (popup) {
1512  // prepend content-specific actions such as "Open Link", "Copy Email Address" etc.
1513  QList<QAction*> contentActions = _view->filterActions(position);
1514  QAction* contentSeparator = new QAction(popup);
1515  contentSeparator->setSeparator(true);
1516  contentActions << contentSeparator;
1517  popup->insertActions(popup->actions().value(0, 0), contentActions);
1518 
1519  // always update this submenu before showing the context menu,
1520  // because the available search services might have changed
1521  // since the context menu is shown last time
1522  updateWebSearchMenu();
1523 
1524  _preventClose = true;
1525 
1526  if (_showMenuAction) {
1527  if ( _showMenuAction->isChecked() ) {
1528  popup->removeAction( _showMenuAction);
1529  } else {
1530  popup->insertAction(_switchProfileMenu, _showMenuAction);
1531  }
1532  }
1533 
1534  QAction* chosen = popup->exec(_view->mapToGlobal(position));
1535 
1536  // check for validity of the pointer to the popup menu
1537  if (popup) {
1538  // Remove content-specific actions
1539  //
1540  // If the close action was chosen, the popup menu will be partially
1541  // destroyed at this point, and the rest will be destroyed later by
1542  // 'chosen->trigger()'
1543  foreach(QAction * action, contentActions) {
1544  popup->removeAction(action);
1545  }
1546 
1547  delete contentSeparator;
1548  }
1549 
1550  _preventClose = false;
1551 
1552  if (chosen && chosen->objectName() == "close-session")
1553  chosen->trigger();
1554  } else {
1555  kWarning() << "Unable to display popup menu for session"
1556  << _session->title(Session::NameRole)
1557  << ", no GUI factory available to build the popup.";
1558  }
1559 }
1560 
1561 void SessionController::movementKeyFromSearchBarReceived(QKeyEvent *event)
1562 {
1563  QCoreApplication::sendEvent(_view, event);
1564  setSearchStartToWindowCurrentLine();
1565 }
1566 
1567 void SessionController::sessionStateChanged(int state)
1568 {
1569  if (state == _previousState)
1570  return;
1571 
1572  if (state == NOTIFYACTIVITY) {
1573  setIcon(_activityIcon);
1574  _keepIconUntilInteraction = true;
1575  } else if (state == NOTIFYSILENCE) {
1576  setIcon(_silenceIcon);
1577  _keepIconUntilInteraction = true;
1578  } else if (state == NOTIFYNORMAL) {
1579  if (_sessionIconName != _session->iconName()) {
1580  _sessionIconName = _session->iconName();
1581  _sessionIcon = KIcon(_sessionIconName);
1582  }
1583 
1584  updateSessionIcon();
1585  }
1586 
1587  _previousState = state;
1588 }
1589 
1590 void SessionController::zmodemDownload()
1591 {
1592  QString zmodem = KStandardDirs::findExe("rz");
1593  if (zmodem.isEmpty()) {
1594  zmodem = KStandardDirs::findExe("lrz");
1595  }
1596  if (!zmodem.isEmpty()) {
1597  const QString path = KFileDialog::getExistingDirectory(
1598  QString(), _view,
1599  i18n("Save ZModem Download to..."));
1600 
1601  if (!path.isEmpty()) {
1602  _session->startZModem(zmodem, path, QStringList());
1603  return;
1604  }
1605  } else {
1606  KMessageBox::error(_view,
1607  i18n("<p>A ZModem file transfer attempt has been detected, "
1608  "but no suitable ZModem software was found on this system.</p>"
1609  "<p>You may wish to install the 'rzsz' or 'lrzsz' package.</p>"));
1610  }
1611  _session->cancelZModem();
1612  return;
1613 }
1614 
1615 void SessionController::zmodemUpload()
1616 {
1617  if (_session->isZModemBusy()) {
1618  KMessageBox::sorry(_view,
1619  i18n("<p>The current session already has a ZModem file transfer in progress.</p>"));
1620  return;
1621  }
1622  QString zmodem = KStandardDirs::findExe("sz");
1623  if (zmodem.isEmpty()) {
1624  zmodem = KStandardDirs::findExe("lsz");
1625  }
1626  if (zmodem.isEmpty()) {
1627  KMessageBox::sorry(_view,
1628  i18n("<p>No suitable ZModem software was found on this system.</p>"
1629  "<p>You may wish to install the 'rzsz' or 'lrzsz' package.</p>"));
1630  return;
1631  }
1632 
1633  QStringList files = KFileDialog::getOpenFileNames(KUrl(), QString(), _view,
1634  i18n("Select Files for ZModem Upload"));
1635  if (!files.isEmpty()) {
1636  _session->startZModem(zmodem, QString(), files);
1637  }
1638 }
1639 
1640 bool SessionController::isKonsolePart() const
1641 {
1642  // Check to see if we are being called from Konsole or a KPart
1643  if (QString(qApp->metaObject()->className()) == "Konsole::Application")
1644  return false;
1645  else
1646  return true;
1647 }
1648 
1649 SessionTask::SessionTask(QObject* parent)
1650  : QObject(parent)
1651  , _autoDelete(false)
1652 {
1653 }
1654 void SessionTask::setAutoDelete(bool enable)
1655 {
1656  _autoDelete = enable;
1657 }
1658 bool SessionTask::autoDelete() const
1659 {
1660  return _autoDelete;
1661 }
1662 void SessionTask::addSession(Session* session)
1663 {
1664  _sessions << session;
1665 }
1666 QList<SessionPtr> SessionTask::sessions() const
1667 {
1668  return _sessions;
1669 }
1670 
1671 SaveHistoryTask::SaveHistoryTask(QObject* parent)
1672  : SessionTask(parent)
1673 {
1674 }
1675 SaveHistoryTask::~SaveHistoryTask()
1676 {
1677 }
1678 
1679 void SaveHistoryTask::execute()
1680 {
1681  // TODO - think about the UI when saving multiple history sessions, if there are more than two or
1682  // three then providing a URL for each one will be tedious
1683 
1684  // TODO - show a warning ( preferably passive ) if saving the history output fails
1685  //
1686 
1687  KFileDialog* dialog = new KFileDialog(QString(":konsole") /* check this */,
1688  QString(), QApplication::activeWindow());
1689  dialog->setOperationMode(KFileDialog::Saving);
1690  dialog->setConfirmOverwrite(true);
1691 
1692  QStringList mimeTypes;
1693  mimeTypes << "text/plain";
1694  mimeTypes << "text/html";
1695  dialog->setMimeFilter(mimeTypes, "text/plain");
1696 
1697  // iterate over each session in the task and display a dialog to allow the user to choose where
1698  // to save that session's history.
1699  // then start a KIO job to transfer the data from the history to the chosen URL
1700  foreach(const SessionPtr& session, sessions()) {
1701  dialog->setCaption(i18n("Save Output From %1", session->title(Session::NameRole)));
1702 
1703  int result = dialog->exec();
1704 
1705  if (result != QDialog::Accepted)
1706  continue;
1707 
1708  KUrl url = dialog->selectedUrl();
1709 
1710  if (!url.isValid()) {
1711  // UI: Can we make this friendlier?
1712  KMessageBox::sorry(0 , i18n("%1 is an invalid URL, the output could not be saved.", url.url()));
1713  continue;
1714  }
1715 
1716  KIO::TransferJob* job = KIO::put(url,
1717  -1, // no special permissions
1718  // overwrite existing files
1719  // do not resume an existing transfer
1720  // show progress information only for remote
1721  // URLs
1722  KIO::Overwrite | (url.isLocalFile() ? KIO::HideProgressInfo : KIO::DefaultFlags)
1723  // a better solution would be to show progress
1724  // information after a certain period of time
1725  // instead, since the overall speed of transfer
1726  // depends on factors other than just the protocol
1727  // used
1728  );
1729 
1730  SaveJob jobInfo;
1731  jobInfo.session = session;
1732  jobInfo.lastLineFetched = -1; // when each request for data comes in from the KIO subsystem
1733  // lastLineFetched is used to keep track of how much of the history
1734  // has already been sent, and where the next request should continue
1735  // from.
1736  // this is set to -1 to indicate the job has just been started
1737 
1738  if (dialog->currentMimeFilter() == "text/html")
1739  jobInfo.decoder = new HTMLDecoder();
1740  else
1741  jobInfo.decoder = new PlainTextDecoder();
1742 
1743  _jobSession.insert(job, jobInfo);
1744 
1745  connect(job, SIGNAL(dataReq(KIO::Job*,QByteArray&)),
1746  this, SLOT(jobDataRequested(KIO::Job*,QByteArray&)));
1747  connect(job, SIGNAL(result(KJob*)),
1748  this, SLOT(jobResult(KJob*)));
1749  }
1750 
1751  dialog->deleteLater();
1752 }
1753 void SaveHistoryTask::jobDataRequested(KIO::Job* job , QByteArray& data)
1754 {
1755  // TODO - Report progress information for the job
1756 
1757  // PERFORMANCE: Do some tests and tweak this value to get faster saving
1758  const int LINES_PER_REQUEST = 500;
1759 
1760  SaveJob& info = _jobSession[job];
1761 
1762  // transfer LINES_PER_REQUEST lines from the session's history
1763  // to the save location
1764  if (info.session) {
1765  // note: when retrieving lines from the emulation,
1766  // the first line is at index 0.
1767 
1768  int sessionLines = info.session->emulation()->lineCount();
1769 
1770  if (sessionLines - 1 == info.lastLineFetched)
1771  return; // if there is no more data to transfer then stop the job
1772 
1773  int copyUpToLine = qMin(info.lastLineFetched + LINES_PER_REQUEST ,
1774  sessionLines - 1);
1775 
1776  QTextStream stream(&data, QIODevice::ReadWrite);
1777  info.decoder->begin(&stream);
1778  info.session->emulation()->writeToStream(info.decoder , info.lastLineFetched + 1 , copyUpToLine);
1779  info.decoder->end();
1780 
1781  info.lastLineFetched = copyUpToLine;
1782  }
1783 }
1784 void SaveHistoryTask::jobResult(KJob* job)
1785 {
1786  if (job->error()) {
1787  KMessageBox::sorry(0 , i18n("A problem occurred when saving the output.\n%1", job->errorString()));
1788  }
1789 
1790  TerminalCharacterDecoder * decoder = _jobSession[job].decoder;
1791 
1792  _jobSession.remove(job);
1793 
1794  delete decoder;
1795 
1796  // notify the world that the task is done
1797  emit completed(true);
1798 
1799  if (autoDelete())
1800  deleteLater();
1801 }
1802 void SearchHistoryTask::addScreenWindow(Session* session , ScreenWindow* searchWindow)
1803 {
1804  _windows.insert(session, searchWindow);
1805 }
1806 void SearchHistoryTask::execute()
1807 {
1808  QMapIterator< SessionPtr , ScreenWindowPtr > iter(_windows);
1809 
1810  while (iter.hasNext()) {
1811  iter.next();
1812  executeOnScreenWindow(iter.key() , iter.value());
1813  }
1814 }
1815 
1816 void SearchHistoryTask::executeOnScreenWindow(SessionPtr session , ScreenWindowPtr window)
1817 {
1818  Q_ASSERT(session);
1819  Q_ASSERT(window);
1820 
1821  Emulation* emulation = session->emulation();
1822 
1823  if (!_regExp.isEmpty()) {
1824  int pos = -1;
1825  const bool forwards = (_direction == ForwardsSearch);
1826  const int lastLine = window->lineCount() - 1;
1827 
1828  int startLine;
1829  if (forwards && (_startLine == lastLine)) {
1830  startLine = 0;
1831  } else if (!forwards && (_startLine == 0)) {
1832  startLine = lastLine;
1833  } else {
1834  startLine = _startLine + (forwards ? 1 : -1);
1835  }
1836 
1837  QString string;
1838 
1839  //text stream to read history into string for pattern or regular expression searching
1840  QTextStream searchStream(&string);
1841 
1842  PlainTextDecoder decoder;
1843  decoder.setRecordLinePositions(true);
1844 
1845  //setup first and last lines depending on search direction
1846  int line = startLine;
1847 
1848  //read through and search history in blocks of 10K lines.
1849  //this balances the need to retrieve lots of data from the history each time
1850  //(for efficient searching)
1851  //without using silly amounts of memory if the history is very large.
1852  const int maxDelta = qMin(window->lineCount(), 10000);
1853  int delta = forwards ? maxDelta : -maxDelta;
1854 
1855  int endLine = line;
1856  bool hasWrapped = false; // set to true when we reach the top/bottom
1857  // of the output and continue from the other
1858  // end
1859 
1860  //loop through history in blocks of <delta> lines.
1861  do {
1862  // ensure that application does not appear to hang
1863  // if searching through a lengthy output
1864  QApplication::processEvents();
1865 
1866  // calculate lines to search in this iteration
1867  if (hasWrapped) {
1868  if (endLine == lastLine)
1869  line = 0;
1870  else if (endLine == 0)
1871  line = lastLine;
1872 
1873  endLine += delta;
1874 
1875  if (forwards)
1876  endLine = qMin(startLine , endLine);
1877  else
1878  endLine = qMax(startLine , endLine);
1879  } else {
1880  endLine += delta;
1881 
1882  if (endLine > lastLine) {
1883  hasWrapped = true;
1884  endLine = lastLine;
1885  } else if (endLine < 0) {
1886  hasWrapped = true;
1887  endLine = 0;
1888  }
1889  }
1890 
1891  decoder.begin(&searchStream);
1892  emulation->writeToStream(&decoder, qMin(endLine, line) , qMax(endLine, line));
1893  decoder.end();
1894 
1895  // line number search below assumes that the buffer ends with a new-line
1896  string.append('\n');
1897 
1898  if (forwards)
1899  pos = string.indexOf(_regExp);
1900  else
1901  pos = string.lastIndexOf(_regExp);
1902 
1903  //if a match is found, position the cursor on that line and update the screen
1904  if (pos != -1) {
1905  int newLines = 0;
1906  QList<int> linePositions = decoder.linePositions();
1907  while (newLines < linePositions.count() && linePositions[newLines] <= pos)
1908  newLines++;
1909 
1910  // ignore the new line at the start of the buffer
1911  newLines--;
1912 
1913  int findPos = qMin(line, endLine) + newLines;
1914 
1915  highlightResult(window, findPos);
1916 
1917  emit completed(true);
1918 
1919  return;
1920  }
1921 
1922  //clear the current block of text and move to the next one
1923  string.clear();
1924  line = endLine;
1925  } while (startLine != endLine);
1926 
1927  // if no match was found, clear selection to indicate this
1928  window->clearSelection();
1929  window->notifyOutputChanged();
1930  }
1931 
1932  emit completed(false);
1933 }
1934 void SearchHistoryTask::highlightResult(ScreenWindowPtr window , int findPos)
1935 {
1936  //work out how many lines into the current block of text the search result was found
1937  //- looks a little painful, but it only has to be done once per search.
1938 
1939  //kDebug() << "Found result at line " << findPos;
1940 
1941  //update display to show area of history containing selection
1942  if ((findPos < window->currentLine()) ||
1943  (findPos >= (window->currentLine() + window->windowLines()))) {
1944  int centeredScrollPos = findPos - window->windowLines() / 2;
1945  if (centeredScrollPos < 0) {
1946  centeredScrollPos = 0;
1947  }
1948 
1949  window->scrollTo(centeredScrollPos);
1950  }
1951 
1952  window->setTrackOutput(false);
1953  window->notifyOutputChanged();
1954  window->setCurrentResultLine(findPos);
1955 }
1956 
1957 SearchHistoryTask::SearchHistoryTask(QObject* parent)
1958  : SessionTask(parent)
1959  , _direction(BackwardsSearch)
1960  , _startLine(0)
1961 {
1962 }
1963 void SearchHistoryTask::setSearchDirection(SearchDirection direction)
1964 {
1965  _direction = direction;
1966 }
1967 void SearchHistoryTask::setStartLine(int line)
1968 {
1969  _startLine = line;
1970 }
1971 SearchHistoryTask::SearchDirection SearchHistoryTask::searchDirection() const
1972 {
1973  return _direction;
1974 }
1975 void SearchHistoryTask::setRegExp(const QRegExp& expression)
1976 {
1977  _regExp = expression;
1978 }
1979 QRegExp SearchHistoryTask::regExp() const
1980 {
1981  return _regExp;
1982 }
1983 
1984 QString SessionController::userTitle() const
1985 {
1986  if (_session) {
1987  return _session->userTitle();
1988  } else {
1989  return QString();
1990  }
1991 }
1992 
1993 #include "SessionController.moc"
1994 
Konsole::HTMLDecoder
A terminal character decoder which produces pretty HTML markup.
Definition: TerminalCharacterDecoder.h:115
QTimer::setInterval
void setInterval(int msec)
Konsole::SaveHistoryTask::SaveHistoryTask
SaveHistoryTask(QObject *parent=0)
Constructs a new task to save session output to URLs.
Definition: SessionController.cpp:1671
Session.h
Konsole::SessionTask::SessionTask
SessionTask(QObject *parent=0)
Definition: SessionController.cpp:1649
Konsole::NOTIFYSILENCE
Definition: Emulation.h:65
Konsole::PlainTextDecoder::end
virtual void end()
End decoding.
Definition: TerminalCharacterDecoder.cpp:55
QEvent
Konsole::SessionManager::instance
static SessionManager * instance()
Returns the session manager instance.
Definition: SessionManager.cpp:69
Konsole::PlainTextDecoder::setRecordLinePositions
void setRecordLinePositions(bool record)
Enables recording of character positions at which new lines are added.
Definition: TerminalCharacterDecoder.cpp:60
Konsole::Session
Represents a terminal session consisting of a pseudo-teletype and a terminal emulation.
Definition: Session.h:78
Konsole::SessionController
Provides the menu actions to manipulate a single terminal session and view pair.
Definition: SessionController.h:85
Konsole::ViewProperties::title
QString title() const
Returns the title associated with a view.
Definition: ViewProperties.cpp:85
QString::append
QString & append(QChar ch)
QAction::setShortcutContext
void setShortcutContext(Qt::ShortcutContext context)
QEvent::type
Type type() const
Konsole::SessionManager::setSessionProfile
void setSessionProfile(Session *session, Profile::Ptr profile)
Sets the profile associated with a session.
Definition: SessionManager.cpp:145
QHash::insert
iterator insert(const Key &key, const T &value)
Konsole::IncrementalSearchBar::MatchCase
Searches are case-sensitive or not.
Definition: IncrementalSearchBar.h:68
PrintOptions.h
Konsole::SearchHistoryTask::setStartLine
void setStartLine(int startLine)
The line from which the search will be done.
Definition: SessionController.cpp:1967
QSize::width
int width() const
Konsole::SearchHistoryTask::BackwardsSearch
Searches backwards through the output, starting at the current selection.
Definition: SessionController.h:492
Konsole::ProfileList::actions
QList< QAction * > actions()
Returns a list of actions representing profiles.
Definition: ProfileList.cpp:167
Konsole::HistoryType::isEnabled
virtual bool isEnabled() const =0
Returns true if the history is enabled ( can store lines of output ) or false otherwise.
Konsole::IncrementalSearchBar::RegExp
Searches use regular expressions.
Definition: IncrementalSearchBar.h:70
QAction::setSeparator
void setSeparator(bool b)
KXMLGUIClient
Konsole::SessionController::setShowMenuAction
void setShowMenuAction(QAction *action)
Sets the action displayed in the session's context menu to hide or show the menu bar.
Definition: SessionController.cpp:550
Konsole::SessionController::url
virtual KUrl url() const
Returns the URL current associated with a view.
Definition: SessionController.cpp:290
QRegExp::isEmpty
bool isEmpty() const
Konsole::SearchHistoryTask::regExp
QRegExp regExp() const
Returns the regular expression which is searched for when execute() is called.
Definition: SessionController.cpp:1979
Konsole::ViewProperties::setIdentifier
void setIdentifier(int id)
Subclasses may call this method to change the identifier.
Definition: ViewProperties.cpp:76
Konsole::SessionTask
Abstract class representing a task which can be performed on a group of sessions. ...
Definition: SessionController.h:378
QByteArray
Konsole::HistorySizeDialog
Definition: HistorySizeDialog.h:37
QPrinter
Konsole::HistoryType::maximumLineCount
virtual int maximumLineCount() const =0
Returns the maximum number of lines which this history type can store or -1 if the history can store ...
Konsole::HistoryTypeNone
Definition: History.h:348
QObject::sender
QObject * sender() const
QChar
QAction::isChecked
bool isChecked() const
QAction::data
QVariant data() const
Emulation.h
HistorySizeDialog.h
QPainter::scale
void scale(qreal sx, qreal sy)
findWindow
static const KXmlGuiWindow * findWindow(const QObject *object)
Definition: SessionController.cpp:959
Konsole::SessionController::SessionController
SessionController(Session *session, TerminalDisplay *view, QObject *parent)
Constructs a new SessionController which operates on session and view.
Definition: SessionController.cpp:100
QPointer< Session >
QStringList::contains
bool contains(const QString &str, Qt::CaseSensitivity cs) const
Konsole::ProfileList
ProfileList provides a list of actions which represent session profiles that a SessionManager can cre...
Definition: ProfileList.h:51
Konsole::SessionGroup::sessions
QList< Session * > sessions() const
Returns the list of sessions currently in the group.
Definition: Session.cpp:1461
QString::simplified
QString simplified() const
Konsole::Session::DisplayedTitleRole
The title of the session which is displayed in tabs etc.
Definition: Session.h:255
Konsole::ViewProperties::setTitle
void setTitle(const QString &title)
Subclasses may call this method to change the title.
Definition: ViewProperties.cpp:59
QVariant::value
T value() const
Konsole::CompactHistoryType
Definition: History.h:373
QRect::height
int height() const
Konsole::SessionTask::execute
virtual void execute()=0
Executes the task on each of the sessions in the group.
Konsole::ViewProperties::setIcon
void setIcon(const QIcon &icon)
Subclasses may call this method to change the icon.
Definition: ViewProperties.cpp:66
QPoint
Konsole::RenameTabDialog
Definition: RenameTabDialog.h:33
QMouseEvent
Konsole::SearchHistoryTask::searchDirection
SearchDirection searchDirection() const
Returns the current search direction.
Definition: SessionController.cpp:1971
Konsole::ViewProperties::titleChanged
void titleChanged(ViewProperties *properties)
Emitted when the title for a view changes.
QObject::disconnect
bool disconnect(const QObject *sender, const char *signal, const QObject *receiver, const char *method)
Konsole::SaveHistoryTask::~SaveHistoryTask
virtual ~SaveHistoryTask()
Definition: SessionController.cpp:1675
QDir::homePath
QString homePath()
Konsole::Session::views
QList< TerminalDisplay * > views() const
Returns the views connected to this session.
Definition: Session.cpp:303
IncrementalSearchBar.h
Konsole::Emulation::reset
virtual void reset()=0
Resets the state of the terminal.
Konsole::SessionManager::sessionProfile
Profile::Ptr sessionProfile(Session *session) const
Returns the profile associated with a session.
Definition: SessionManager.cpp:141
Filter.h
hasTerminalDisplayInSameWindow
static bool hasTerminalDisplayInSameWindow(const Session *session, const KXmlGuiWindow *window)
Definition: SessionController.cpp:972
QTextStream
Konsole::Emulation::writeToStream
virtual void writeToStream(TerminalCharacterDecoder *decoder, int startLine, int endLine)
Copies the output history from startLine to endLine into stream, using decoder to convert the termina...
Definition: Emulation.cpp:296
Konsole::ScreenWindow::setSelectionByLineRange
void setSelectionByLineRange(int start, int end)
Sets the selection as the range specified by line start and line end in the whole history...
Definition: ScreenWindow.cpp:154
QAction::trigger
void trigger()
Konsole::EditProfileDialog
A dialog which allows the user to edit a profile.
Definition: EditProfileDialog.h:61
Konsole::SessionController::rename
virtual void rename()
Requests the renaming of this view.
Definition: SessionController.cpp:295
QObject::event
virtual bool event(QEvent *e)
Konsole::PlainTextDecoder
A terminal character decoder which produces plain text, ignoring colors and other appearance-related ...
Definition: TerminalCharacterDecoder.h:72
Konsole::SessionController::increaseFontSize
void increaseFontSize()
Increase font size.
Definition: SessionController.cpp:1441
Konsole::SessionController::focused
void focused(SessionController *controller)
Emitted when the view associated with the controller is focused.
Konsole::NOTIFYACTIVITY
The emulation is currently receiving data from its terminal input.
Definition: Emulation.h:62
Konsole::SessionController::profileDialogPointer
EditProfileDialog * profileDialogPointer()
Definition: SessionController.cpp:799
QRegExp
QObject::name
const char * name() const
Konsole::SessionController::CopyInputToNoneMode
Do not copy keyboard input to other tabs.
Definition: SessionController.h:98
History.h
QApplication::activeWindow
QWidget * activeWindow()
QString::number
QString number(int n, int base)
QList::count
int count(const T &value) const
Konsole::SearchHistoryTask::setSearchDirection
void setSearchDirection(SearchDirection direction)
Specifies the direction to search in when execute() is called.
Definition: SessionController.cpp:1963
CopyInputDialog.h
QCoreApplication::processEvents
void processEvents(QFlags< QEventLoop::ProcessEventsFlag > flags)
Konsole::TerminalCharacterDecoder
Base class for terminal character decoders.
Definition: TerminalCharacterDecoder.h:45
TerminalDisplay.h
QMapIterator
KXmlGuiWindow
Konsole::SessionController::setSearchStartToWindowCurrentLine
void setSearchStartToWindowCurrentLine()
set start line to the first or last line (depending on the reverse search setting) in the terminal di...
Definition: SessionController.cpp:1100
Konsole::SessionTask::sessions
QList< SessionPtr > sessions() const
Returns a list of sessions in the group.
Definition: SessionController.cpp:1666
QObject::installEventFilter
void installEventFilter(QObject *filterObj)
QTimer
Konsole::SessionGroup
Provides a group of sessions which is divided into master and slave sessions.
Definition: Session.h:770
ProfileList.h
Konsole::PrintOptions
Definition: PrintOptions.h:28
QPrintDialog
Konsole::SessionController::selectionChanged
void selectionChanged(const QString &selectedText)
update actions which are closely related with the selected text.
Definition: SessionController.cpp:376
Konsole::SessionController::confirmForceClose
virtual bool confirmForceClose() const
Definition: SessionController.cpp:880
QMapIterator::next
Item next()
QObject
Konsole::SearchHistoryTask::addScreenWindow
void addScreenWindow(Session *session, ScreenWindow *searchWindow)
Adds a screen window to the list to search when execute() is called.
Definition: SessionController.cpp:1802
Konsole::SessionTask::addSession
void addSession(Session *session)
Adds a new session to the group.
Definition: SessionController.cpp:1662
QScopedPointer
Konsole::ScreenWindow
Provides a window onto a section of a terminal screen.
Definition: ScreenWindow.h:52
QList::isEmpty
bool isEmpty() const
QPainter
Konsole::SearchHistoryTask::ForwardsSearch
Searches forwards through the output, starting at the current selection.
Definition: SessionController.h:490
QObject::objectName
objectName
QString::isEmpty
bool isEmpty() const
Konsole::SessionGroup::setMasterStatus
void setMasterStatus(Session *session, bool master)
Sets whether a particular session is a master within the group.
Definition: Session.cpp:1495
QCoreApplication::sendEvent
bool sendEvent(QObject *receiver, QEvent *event)
Konsole::SearchHistoryTask::SearchHistoryTask
SearchHistoryTask(QObject *parent=0)
Constructs a new search task.
Definition: SessionController.cpp:1957
Konsole::ViewProperties::fireActivity
void fireActivity()
Emits the activity() signal.
Definition: ViewProperties.cpp:50
Konsole::Emulation
Base class for terminal emulation back-ends.
Definition: Emulation.h:117
Konsole::NOTIFYNORMAL
The emulation is currently receiving user input.
Definition: Emulation.h:52
Konsole::SessionController::session
QPointer< Session > session()
Returns the session associated with this controller.
Definition: SessionController.h:108
Konsole::SessionController::setSearchStartTo
void setSearchStartTo(int line)
Set the start line from which the next search will be done.
Definition: SessionController.cpp:1105
EditProfileDialog.h
Konsole::Session::RemoteTabTitle
Tab title format used session currently contains a connection to a remote computer (via SSH) ...
Definition: Session.h:166
QSet
QObject::deleteLater
void deleteLater()
Konsole::SessionController::setupPrimaryScreenSpecificActions
void setupPrimaryScreenSpecificActions(bool use)
update actions which are meaningful only when primary screen is in use.
Definition: SessionController.cpp:361
QString
QList< QWidget * >
Enumeration.h
QColor
QHash::remove
int remove(const Key &key)
Konsole::Enum::NoHistory
No output is remembered.
Definition: Enumeration.h:42
QMapIterator::key
const Key & key() const
QTextCodec
Konsole::SearchHistoryTask
A task which searches through the output of sessions for matches for a given regular expression...
Definition: SessionController.h:479
Konsole::TerminalDisplay::setSessionController
void setSessionController(SessionController *controller)
Definition: TerminalDisplay.cpp:3230
QBitArray
QMapIterator::value
const T & value() const
QBitArray::at
bool at(int i) const
Konsole::SearchHistoryTask::execute
virtual void execute()
Performs a search through the session's history, starting at the position of the current selection...
Definition: SessionController.cpp:1806
Konsole::SessionController::eventFilter
virtual bool eventFilter(QObject *watched, QEvent *event)
Definition: SessionController.cpp:460
QStringList
Konsole::ViewProperties
Encapsulates user-visible information about the terminal session currently being displayed in a view...
Definition: ViewProperties.h:44
Konsole::SessionGroup::setMasterMode
void setMasterMode(int mode)
Specifies which activity in the group's master sessions is propagated to all sessions in the group...
Definition: Session.cpp:1487
Konsole::SessionGroup::removeSession
void removeSession(Session *session)
Removes a session from the group.
Definition: Session.cpp:1475
Konsole::IncrementalSearchBar
A widget which allows users to search incrementally through a document for a a text string or regular...
Definition: IncrementalSearchBar.h:56
Konsole::RegExpFilter::setRegExp
void setRegExp(const QRegExp &text)
Sets the regular expression which the filter searches for in blocks of text.
Definition: Filter.cpp:316
QKeyEvent::key
int key() const
Konsole::RegExpFilter
A filter which searches for sections of text matching a regular expression and creates a new RegExpFi...
Definition: Filter.h:182
QMenu
QSet::begin
iterator begin()
QSize
Konsole::SessionController::CopyInputToAllTabsMode
Copy keyboard input to all the other tabs in current window.
Definition: SessionController.h:92
Konsole::PlainTextDecoder::linePositions
QList< int > linePositions() const
Returns of character positions in the output stream at which new lines where added.
Definition: TerminalCharacterDecoder.cpp:64
Konsole::HistoryTypeFile
Definition: History.h:359
QSet::contains
bool contains(const T &value) const
Konsole::EditProfileDialog::lookupProfile
const Profile::Ptr lookupProfile() const
Definition: EditProfileDialog.cpp:197
Konsole::HistoryType
Definition: History.h:319
Konsole::Profile::Ptr
KSharedPtr< Profile > Ptr
Definition: Profile.h:67
QString::replace
QString & replace(int position, int n, QChar after)
QKeyEvent
Konsole::PlainTextDecoder::begin
virtual void begin(QTextStream *output)
Begin decoding characters.
Definition: TerminalCharacterDecoder.cpp:49
Konsole::SessionController::openUrl
void openUrl(const KUrl &url)
Issues a command to the session to navigate to the specified URL.
Definition: SessionController.cpp:300
TerminalCharacterDecoder.h
QRect::width
int width() const
Konsole::Session::NameRole
The name of the session.
Definition: Session.h:253
QSet::remove
bool remove(const T &value)
Konsole::SessionController::setSearchBar
void setSearchBar(IncrementalSearchBar *searchBar)
Sets the widget used for searches through the session's output.
Definition: SessionController.cpp:521
Konsole::Session::LocalTabTitle
Default tab title format.
Definition: Session.h:161
Konsole::UrlFilter
A filter which matches URLs in blocks of text.
Definition: Filter.h:239
Konsole::SaveHistoryTask::execute
virtual void execute()
Opens a save file dialog for each session in the group and begins saving each session's history to th...
Definition: SessionController.cpp:1679
QKeySequence
Konsole::SessionController::closeSession
void closeSession()
close the associated session.
Definition: SessionController.cpp:905
Konsole::SearchHistoryTask::SearchDirection
SearchDirection
This enum describes the strategies available for searching through the session's output.
Definition: SessionController.h:488
Konsole::IncrementalSearchBar::ReverseSearch
Search from the bottom and up.
Definition: IncrementalSearchBar.h:72
QSet::end
iterator end()
Konsole::Enum::UnlimitedHistory
All output is remembered for the duration of the session.
Definition: Enumeration.h:51
Konsole::SessionGroup::addSession
void addSession(Session *session)
Adds a session to the group.
Definition: Session.cpp:1470
QAction
QTextCodec::codecForName
QTextCodec * codecForName(const QByteArray &name)
QSize::height
int height() const
RenameTabDialog.h
QSet::fromList
QSet< T > fromList(const QList< T > &list)
Konsole::Enum::FixedSizeHistory
A fixed number of lines of output are remembered.
Definition: Enumeration.h:46
Konsole::HistoryType::isUnlimited
bool isUnlimited() const
Returns true if the history size is unlimited.
Definition: History.h:343
Konsole::SessionController::userTitle
QString userTitle() const
Returns the "window title" of the associated session.
Definition: SessionController.cpp:1984
QString::section
QString section(QChar sep, int start, int end, QFlags< QString::SectionFlag > flags) const
QPrinter::pageRect
QRect pageRect() const
Konsole::CopyInputDialog
Dialog which allows the user to mark a list of sessions to copy the input from the current session to...
Definition: CopyInputDialog.h:50
Konsole::SessionController::CopyInputToSelectedTabsMode
Copy keyboard input to user selected tabs in current window.
Definition: SessionController.h:95
QTimer::start
void start(int msec)
SessionManager.h
Konsole::SessionGroup::CopyInputToAll
Any input key presses in the master sessions are sent to all sessions in the group.
Definition: Session.h:809
Konsole::SaveHistoryTask
A task which prompts for a URL for each session and saves that session's output to the given URL...
Definition: SessionController.h:427
Konsole::SearchHistoryTask::setRegExp
void setRegExp(const QRegExp &regExp)
Sets the regular expression which is searched for when execute() is called.
Definition: SessionController.cpp:1975
QObject::connect
bool connect(const QObject *sender, const char *signal, const QObject *receiver, const char *method, Qt::ConnectionType type)
ScreenWindow.h
Konsole::SessionController::searchBar
IncrementalSearchBar * searchBar() const
see setSearchBar()
Definition: SessionController.cpp:545
QPainter::begin
bool begin(QPaintDevice *device)
Konsole::TerminalDisplay
A widget which displays output from a terminal emulation and sends input keypresses and mouse activit...
Definition: TerminalDisplay.h:63
Konsole::SessionController::~SessionController
~SessionController()
Definition: SessionController.cpp:217
Konsole::SessionTask::setAutoDelete
void setAutoDelete(bool enable)
Sets whether the task automatically deletes itself when the task has been finished.
Definition: SessionController.cpp:1654
Konsole::SessionTask::autoDelete
bool autoDelete() const
Returns true if the task automatically deletes itself.
Definition: SessionController.cpp:1658
Konsole::SessionController::confirmClose
virtual bool confirmClose() const
Sub-classes may re-implement this method to display a message to the user to allow them to confirm wh...
Definition: SessionController.cpp:855
Konsole::SessionTask::completed
void completed(bool success)
Emitted when the task has completed.
QString::arg
QString arg(qlonglong a, int fieldWidth, int base, const QChar &fillChar) const
Konsole::SessionController::decreaseFontSize
void decreaseFontSize()
Decrease font size.
Definition: SessionController.cpp:1446
QSet::iterator
Konsole::SessionController::currentDir
virtual QString currentDir() const
Returns the current directory associated with a view.
Definition: SessionController.cpp:285
SessionController.h
Konsole::SessionController::currentDirectoryChanged
void currentDirectoryChanged(const QString &dir)
Emitted when the current working directory of the session associated with the controller is changed...
QAction::setEnabled
void setEnabled(bool)
QMapIterator::hasNext
bool hasNext() const
Konsole::SessionController::rawTitleChanged
void rawTitleChanged()
QTimer::setSingleShot
void setSingleShot(bool singleShot)
This file is part of the KDE documentation.
Documentation copyright © 1996-2020 The KDE developers.
Generated on Sat May 9 2020 03:56:27 by doxygen 1.8.7 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.

Konsole

Skip menu "Konsole"
  • Main Page
  • Namespace List
  • Namespace Members
  • Alphabetical List
  • Class List
  • Class Hierarchy
  • Class Members
  • File List
  • File Members
  • Related Pages

applications API Reference

Skip menu "applications API Reference"
  •   kate
  •       kate
  •   KTextEditor
  •   Kate
  • Konsole

Search



Report problems with this website to our bug tracking system.
Contact the specific authors with questions and comments about the page contents.

KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal