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
20 #ifndef SESSIONCONTROLLER_H
21 #define SESSIONCONTROLLER_H
24 #include <QtGui/QIcon>
25 #include <QtCore/QList>
26 #include <QtCore/QPointer>
27 #include <QtCore/QString>
28 #include <QtCore/QThread>
29 #include <QtCore/QHash>
32 #include <KActionCollection>
34 #include <KXMLGUIClient>
37 #include "HistorySizeDialog.h"
38 #include "ViewProperties.h"
59 class TerminalDisplay
;
60 class IncrementalSearchBar
;
66 class TerminalCharacterDecoder
;
69 typedef QPointer
<Session
> SessionPtr
;
72 * Provides the menu actions to manipulate a single terminal session and view pair.
73 * The actions provided by this class are defined in the sessionui.rc XML file.
75 * SessionController monitors the session and provides access to basic information
76 * about the session such as title(), icon() and currentDir(). SessionController
77 * provides notifications of activity in the session via the activity() signal.
79 * When the controlled view receives the focus, the focused() signal is emitted
80 * with a pointer to the controller. This can be used by main application window
81 * which contains the view to plug the controller's actions into the menu when
82 * the view is focused.
84 class SessionController
: public ViewProperties
, public KXMLGUIClient
90 * Constructs a new SessionController which operates on @p session and @p view.
92 SessionController(Session
* session
, TerminalDisplay
* view
, QObject
* parent
);
95 /** Returns the session associated with this controller */
96 QPointer
<Session
> session() { return _session
; }
97 /** Returns the view associated with this controller */
98 QPointer
<TerminalDisplay
> view() { return _view
; }
101 * Returns true if the controller is valid.
102 * A valid controller is one which has a non-null session() and view().
104 * Equivalent to "!session().isNull() && !view().isNull()"
106 bool isValid() const;
109 * Sets the widget used for searches through the session's output.
111 * When the user clicks on the "Search Output" menu action the @p searchBar 's
112 * show() method will be called. The SessionController will then connect to the search
113 * bar's signals to update the search when the widget's controls are pressed.
115 void setSearchBar( IncrementalSearchBar
* searchBar
);
119 IncrementalSearchBar
* searchBar() const;
122 * Sets the action displayed in the session's context menu to hide or
125 void setShowMenuAction(QAction
* action
);
128 virtual KUrl
url() const;
129 virtual QString
currentDir() const;
130 virtual void rename();
131 virtual bool confirmClose() const;
133 // Reimplemented to watch for events happening to the view
134 virtual bool eventFilter(QObject
* watched
, QEvent
* event
);
136 /** Returns the set of all controllers that exist. */
137 static QSet
<SessionController
*> allControllers()
138 { return _allControllers
; }
142 * Emitted when the view associated with the controller is focused.
143 * This can be used by other classes to plug the controller's actions into a window's
146 void focused( SessionController
* controller
);
150 * Issues a command to the session to navigate to the specified URL.
151 * This may not succeed if the foreground program does not understand
152 * the command sent to it ( 'cd path' for local URLs ) or is not
153 * responding to input.
155 * openUrl() currently supports urls for local paths and those
156 * using the 'ssh' protocol ( eg. ssh://joebloggs@hostname )
158 void openUrl( const KUrl
& url
);
161 // menu item handlers
165 void pasteSelection(); // shortcut only
167 void clearAndReset();
169 void editCurrentProfile();
170 void changeCodec(QTextCodec
* codec
);
171 void searchHistory(bool showSearchBar
);
172 void findNextInHistory();
173 void findPreviousInHistory();
175 void showHistoryOptions();
177 void clearHistoryAndReset();
179 void monitorActivity(bool monitor
);
180 void monitorSilence(bool monitor
);
181 void increaseTextSize();
182 void decreaseTextSize();
183 void renameSession();
185 void changeProfile(Profile::Ptr profile
);
188 void prepareChangeProfileMenu();
189 void updateCodecAction();
190 void showDisplayContextMenu(const QPoint
& position
);
191 void sessionStateChanged(int state
);
192 void sessionTitleChanged();
193 void searchTextChanged(const QString
& text
);
194 void searchCompleted(bool success
);
195 void searchClosed(); // called when the user clicks on the
196 // history search bar's close button
198 void snapshot(); // called periodically as the user types
199 // to take a snapshot of the state of the
200 // foreground process in the terminal
202 void requireUrlFilterUpdate();
203 void highlightMatches(bool highlight
);
204 void scrollBackOptionsChanged(int mode
, int lines
);
205 void sessionResizeRequest(const QSize
& size
);
206 void trackOutput(QKeyEvent
* event
); // move view to end of current output
207 // when a key press occurs in the
210 void updateSearchFilter();
214 // text - pattern to search for
215 // direction - value from SearchHistoryTask::SearchDirection enum to specify
216 // the search direction
217 void beginSearch(const QString
& text
, int direction
);
219 void removeSearchFilter(); // remove and delete the current search filter if set
220 void setFindNextPrevEnabled(bool enabled
);
221 void listenForScreenWindowUpdates();
224 QPointer
<Session
> _session
;
225 QPointer
<TerminalDisplay
> _view
;
226 SessionGroup
* _copyToGroup
;
228 ProfileList
* _profileList
;
231 QString _sessionIconName
;
234 UrlFilter
* _viewUrlFilter
;
235 RegExpFilter
* _searchFilter
;
237 KAction
* _searchToggleAction
;
238 KAction
* _findNextAction
;
239 KAction
* _findPreviousAction
;
242 bool _urlFilterUpdateRequired
;
244 QPointer
<IncrementalSearchBar
> _searchBar
;
246 KCodecAction
* _codecAction
;
248 KMenu
* _changeProfileMenu
;
250 bool _listenForScreenWindowUpdates
;
253 static QSet
<SessionController
*> _allControllers
;
254 static int _lastControllerId
;
255 static KIcon _activityIcon
;
256 static KIcon _silenceIcon
;
258 inline bool SessionController::isValid() const
260 return !_session
.isNull() && !_view
.isNull();
264 * Abstract class representing a task which can be performed on a group of sessions.
266 * Create a new instance of the appropriate sub-class for the task you want to perform and
267 * call the addSession() method to add each session which needs to be processed.
269 * Finally, call the execute() method to perform the sub-class specific action on each
272 class SessionTask
: public QObject
277 SessionTask(QObject
* parent
= 0);
280 * Sets whether the task automatically deletes itself when the task has been finished.
281 * Depending on whether the task operates synchronously or asynchronously, the deletion
282 * may be scheduled immediately after execute() returns or it may happen some time later.
284 void setAutoDelete(bool enable
);
285 /** Returns true if the task automatically deletes itself. See setAutoDelete() */
286 bool autoDelete() const;
288 /** Adds a new session to the group */
289 void addSession(Session
* session
);
292 * Executes the task on each of the sessions in the group.
293 * The completed() signal is emitted when the task is finished, depending on the specific sub-class
294 * execute() may be synchronous or asynchronous
296 virtual void execute() = 0;
300 * Emitted when the task has completed.
301 * Depending on the task this may occur just before execute() returns, or it
304 * @param success Indicates whether the task completed successfully or not
306 void completed(bool success
);
310 /** Returns a list of sessions in the group */
311 QList
< SessionPtr
> sessions() const;
316 QList
< SessionPtr
> _sessions
;
320 * A task which prompts for a URL for each session and saves that session's output
323 class SaveHistoryTask
: public SessionTask
328 /** Constructs a new task to save session output to URLs */
329 SaveHistoryTask(QObject
* parent
= 0);
330 virtual ~SaveHistoryTask();
333 * Opens a save file dialog for each session in the group and begins saving
334 * each session's history to the given URL.
336 * The data transfer is performed asynchronously and will continue after execute() returns.
338 virtual void execute();
341 void jobDataRequested(KIO::Job
* job
, QByteArray
& data
);
342 void jobResult(KJob
* job
);
345 class SaveJob
// structure to keep information needed to process
346 // incoming data requests from jobs
349 SessionPtr session
; // the session associated with a history save job
350 int lastLineFetched
; // the last line processed in the previous data request
351 // set this to -1 at the start of the save job
353 TerminalCharacterDecoder
* decoder
; // decoder used to convert terminal characters
358 QHash
<KJob
*,SaveJob
> _jobSession
;
361 class SearchHistoryThread
;
363 * A task which searches through the output of sessions for matches for a given regular expression.
364 * SearchHistoryTask operates on ScreenWindow instances rather than sessions added by addSession().
365 * A screen window can be added to the list to search using addScreenWindow()
367 * When execute() is called, the search begins in the direction specified by searchDirection(),
368 * starting at the position of the current selection.
370 * FIXME - This is not a proper implementation of SessionTask, in that it ignores sessions specified
373 * TODO - Implementation requirements:
374 * May provide progress feedback to the user when searching very large output logs.
376 class SearchHistoryTask
: public SessionTask
382 * This enum describes the strategies available for searching through the
387 /** Searches forwards through the output, starting at the current selection. */
389 /** Searches backwars through the output, starting at the current selection. */
394 * Constructs a new search task.
396 explicit SearchHistoryTask(QObject
* parent
= 0);
398 /** Adds a screen window to the list to search when execute() is called. */
399 void addScreenWindow( Session
* session
, ScreenWindow
* searchWindow
);
401 /** Sets the regular expression which is searched for when execute() is called */
402 void setRegExp(const QRegExp
& regExp
);
403 /** Returns the regular expression which is searched for when execute() is called */
404 QRegExp
regExp() const;
406 /** Specifies the direction to search in when execute() is called. */
407 void setSearchDirection( SearchDirection direction
);
408 /** Returns the current search direction. See setSearchDirection(). */
409 SearchDirection
searchDirection() const;
412 * Performs a search through the session's history, starting at the position
413 * of the current selection, in the direction specified by setSearchDirection().
415 * If it finds a match, the ScreenWindow specified in the constructor is
416 * scrolled to the position where the match occurred and the selection
417 * is set to the matching text. execute() then returns immediately.
419 * To continue the search looking for further matches, call execute() again.
421 virtual void execute();
424 typedef QPointer
<ScreenWindow
> ScreenWindowPtr
;
426 void executeOnScreenWindow( SessionPtr session
, ScreenWindowPtr window
);
427 void highlightResult( ScreenWindowPtr window
, int position
);
429 QMap
< SessionPtr
, ScreenWindowPtr
> _windows
;
431 SearchDirection _direction
;
433 static QPointer
<SearchHistoryThread
> _thread
;
438 #endif //SESSIONCONTROLLER_H
443 c-file-style: "stroustrup"
444 indent-tabs-mode: nil