1/*
2 This file is part of Konsole, an X terminal.
3
4 Copyright (C) 2007 by Robert Knight <robertknight@gmail.com>
5 Copyright (C) 1997,1998 by Lars Doelle <lars.doelle@on-line.de>
6
7 Rewritten for QT4 by e_k <e_k at users.sourceforge.net>, Copyright (C)2008
8
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2 of the License, or
12 (at your option) any later version.
13
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
18
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
22 02110-1301 USA.
23*/
24
25#ifndef SESSION_H
26#define SESSION_H
27
28#include <QStringList>
29#include <QWidget>
30
31#include "Emulation.h"
32#include "History.h"
33
34class KProcess;
35
36namespace Konsole {
37
38class Emulation;
39class Pty;
40class TerminalDisplay;
41//class ZModemDialog;
42
43/**
44 * Represents a terminal session consisting of a pseudo-teletype and a terminal emulation.
45 * The pseudo-teletype (or PTY) handles I/O between the terminal process and Konsole.
46 * The terminal emulation ( Emulation and subclasses ) processes the output stream from the
47 * PTY and produces a character image which is then shown on views connected to the session.
48 *
49 * Each Session can be connected to one or more views by using the addView() method.
50 * The attached views can then display output from the program running in the terminal
51 * or send input to the program in the terminal in the form of keypresses and mouse
52 * activity.
53 */
54class Session : public QObject {
55 Q_OBJECT
56
57public:
58 Q_PROPERTY(QString name READ nameTitle)
59 Q_PROPERTY(int processId READ processId)
60 Q_PROPERTY(QString keyBindings READ keyBindings WRITE setKeyBindings)
61 Q_PROPERTY(QSize size READ size WRITE setSize)
62
63 /**
64 * Constructs a new session.
65 *
66 * To start the terminal process, call the run() method,
67 * after specifying the program and arguments
68 * using setProgram() and setArguments()
69 *
70 * If no program or arguments are specified explicitly, the Session
71 * falls back to using the program specified in the SHELL environment
72 * variable.
73 */
74 Session(QObject* parent = 0);
75 virtual ~Session();
76
77 /**
78 * Returns true if the session is currently running. This will be true
79 * after run() has been called successfully.
80 */
81 bool isRunning() const;
82
83 /**
84 * Sets the profile associated with this session.
85 *
86 * @param profileKey A key which can be used to obtain the current
87 * profile settings from the SessionManager
88 */
89 void setProfileKey(const QString & profileKey);
90 /**
91 * Returns the profile key associated with this session.
92 * This can be passed to the SessionManager to obtain the current
93 * profile settings.
94 */
95 QString profileKey() const;
96
97 /**
98 * Adds a new view for this session.
99 *
100 * The viewing widget will display the output from the terminal and
101 * input from the viewing widget (key presses, mouse activity etc.)
102 * will be sent to the terminal.
103 *
104 * Views can be removed using removeView(). The session is automatically
105 * closed when the last view is removed.
106 */
107 void addView(TerminalDisplay * widget);
108 /**
109 * Removes a view from this session. When the last view is removed,
110 * the session will be closed automatically.
111 *
112 * @p widget will no longer display output from or send input
113 * to the terminal
114 */
115 void removeView(TerminalDisplay * widget);
116
117 /**
118 * Returns the views connected to this session
119 */
120 QList<TerminalDisplay *> views() const;
121
122 /**
123 * Returns the terminal emulation instance being used to encode / decode
124 * characters to / from the process.
125 */
126 Emulation * emulation() const;
127
128 /**
129 * Returns the environment of this session as a list of strings like
130 * VARIABLE=VALUE
131 */
132 QStringList environment() const;
133 /**
134 * Sets the environment for this session.
135 * @p environment should be a list of strings like
136 * VARIABLE=VALUE
137 */
138 void setEnvironment(const QStringList & environment);
139
140 /** Returns the unique ID for this session. */
141 int sessionId() const;
142
143 /**
144 * Return the session title set by the user (ie. the program running
145 * in the terminal), or an empty string if the user has not set a custom title
146 */
147 QString userTitle() const;
148
149 /**
150 * This enum describes the contexts for which separate
151 * tab title formats may be specified.
152 */
153 enum TabTitleContext {
154 /** Default tab title format */
155 LocalTabTitle,
156 /**
157 * Tab title format used session currently contains
158 * a connection to a remote computer (via SSH)
159 */
160 RemoteTabTitle
161 };
162 /**
163 * Sets the format used by this session for tab titles.
164 *
165 * @param context The context whoose format should be set.
166 * @param format The tab title format. This may be a mixture
167 * of plain text and dynamic elements denoted by a '%' character
168 * followed by a letter. (eg. %d for directory). The dynamic
169 * elements available depend on the @p context
170 */
171 void setTabTitleFormat(TabTitleContext context , const QString & format);
172 /** Returns the format used by this session for tab titles. */
173 QString tabTitleFormat(TabTitleContext context) const;
174
175
176 /** Returns the arguments passed to the shell process when run() is called. */
177 QStringList arguments() const;
178 /** Returns the program name of the shell process started when run() is called. */
179 QString program() const;
180
181 /**
182 * Sets the command line arguments which the session's program will be passed when
183 * run() is called.
184 */
185 void setArguments(const QStringList & arguments);
186 /** Sets the program to be executed when run() is called. */
187 void setProgram(const QString & program);
188
189 /** Returns the session's current working directory. */
190 QString initialWorkingDirectory() {
191 return _initialWorkingDir;
192 }
193
194 /**
195 * Sets the initial working directory for the session when it is run
196 * This has no effect once the session has been started.
197 */
198 void setInitialWorkingDirectory( const QString & dir );
199
200 /**
201 * Sets the type of history store used by this session.
202 * Lines of output produced by the terminal are added
203 * to the history store. The type of history store
204 * used affects the number of lines which can be
205 * remembered before they are lost and the storage
206 * (in memory, on-disk etc.) used.
207 */
208 void setHistoryType(const HistoryType & type);
209 /**
210 * Returns the type of history store used by this session.
211 */
212 const HistoryType & historyType() const;
213 /**
214 * Clears the history store used by this session.
215 */
216 void clearHistory();
217
218 /**
219 * Enables monitoring for activity in the session.
220 * This will cause notifySessionState() to be emitted
221 * with the NOTIFYACTIVITY state flag when output is
222 * received from the terminal.
223 */
224 void setMonitorActivity(bool);
225 /** Returns true if monitoring for activity is enabled. */
226 bool isMonitorActivity() const;
227
228 /**
229 * Enables monitoring for silence in the session.
230 * This will cause notifySessionState() to be emitted
231 * with the NOTIFYSILENCE state flag when output is not
232 * received from the terminal for a certain period of
233 * time, specified with setMonitorSilenceSeconds()
234 */
235 void setMonitorSilence(bool);
236 /**
237 * Returns true if monitoring for inactivity (silence)
238 * in the session is enabled.
239 */
240 bool isMonitorSilence() const;
241 /** See setMonitorSilence() */
242 void setMonitorSilenceSeconds(int seconds);
243
244 /**
245 * Sets the key bindings used by this session. The bindings
246 * specify how input key sequences are translated into
247 * the character stream which is sent to the terminal.
248 *
249 * @param id The name of the key bindings to use. The
250 * names of available key bindings can be determined using the
251 * KeyboardTranslatorManager class.
252 */
253 void setKeyBindings(const QString & id);
254 /** Returns the name of the key bindings used by this session. */
255 QString keyBindings() const;
256
257 /**
258 * This enum describes the available title roles.
259 */
260 enum TitleRole {
261 /** The name of the session. */
262 NameRole,
263 /** The title of the session which is displayed in tabs etc. */
264 DisplayedTitleRole
265 };
266
267 /** Sets the session's title for the specified @p role to @p title. */
268 void setTitle(TitleRole role , const QString & title);
269 /** Returns the session's title for the specified @p role. */
270 QString title(TitleRole role) const;
271 /** Convenience method used to read the name property. Returns title(Session::NameRole). */
272 QString nameTitle() const {
273 return title(Session::NameRole);
274 }
275
276 /** Sets the name of the icon associated with this session. */
277 void setIconName(const QString & iconName);
278 /** Returns the name of the icon associated with this session. */
279 QString iconName() const;
280
281 /** Sets the text of the icon associated with this session. */
282 void setIconText(const QString & iconText);
283 /** Returns the text of the icon associated with this session. */
284 QString iconText() const;
285
286 /** Flag if the title/icon was changed by user/shell. */
287 bool isTitleChanged() const;
288
289 /** Specifies whether a utmp entry should be created for the pty used by this session. */
290 void setAddToUtmp(bool);
291
292 /** Sends the specified @p signal to the terminal process. */
293 bool sendSignal(int signal);
294
295 /**
296 * Specifies whether to close the session automatically when the terminal
297 * process terminates.
298 */
299 void setAutoClose(bool b) {
300 _autoClose = b;
301 }
302
303 /**
304 * Sets whether flow control is enabled for this terminal
305 * session.
306 */
307 void setFlowControlEnabled(bool enabled);
308
309 /** Returns whether flow control is enabled for this terminal session. */
310 bool flowControlEnabled() const;
311
312 /**
313 * Sends @p text to the current foreground terminal program.
314 */
315 void sendText(const QString & text) const;
316
317 /**
318 * Returns the process id of the terminal process.
319 * This is the id used by the system API to refer to the process.
320 */
321 int processId() const;
322
323 /**
324 * Returns the process id of the terminal's foreground process.
325 * This is initially the same as processId() but can change
326 * as the user starts other programs inside the terminal.
327 */
328 int foregroundProcessId() const;
329
330 /** Returns the terminal session's window size in lines and columns. */
331 QSize size();
332 /**
333 * Emits a request to resize the session to accommodate
334 * the specified window size.
335 *
336 * @param size The size in lines and columns to request.
337 */
338 void setSize(const QSize & size);
339
340 /** Sets the text codec used by this session's terminal emulation. */
341 void setCodec(QTextCodec * codec);
342
343 /**
344 * Sets whether the session has a dark background or not. The session
345 * uses this information to set the COLORFGBG variable in the process's
346 * environment, which allows the programs running in the terminal to determine
347 * whether the background is light or dark and use appropriate colors by default.
348 *
349 * This has no effect once the session is running.
350 */
351 void setDarkBackground(bool darkBackground);
352 /**
353 * Returns true if the session has a dark background.
354 * See setDarkBackground()
355 */
356 bool hasDarkBackground() const;
357
358 /**
359 * Attempts to get the shell program to redraw the current display area.
360 * This can be used after clearing the screen, for example, to get the
361 * shell to redraw the prompt line.
362 */
363 void refresh();
364
365// void startZModem(const QString &rz, const QString &dir, const QStringList &list);
366// void cancelZModem();
367// bool isZModemBusy() { return _zmodemBusy; }
368
369 /**
370 * Returns a pty slave file descriptor.
371 * This can be used for display and control
372 * a remote terminal.
373 */
374 int getPtySlaveFd() const;
375
376public slots:
377
378 /**
379 * Starts the terminal session.
380 *
381 * This creates the terminal process and connects the teletype to it.
382 */
383 void run();
384
385 /**
386 * Starts the terminal session for "as is" PTY
387 * (without the direction a data to internal terminal process).
388 * It can be used for control or display a remote/external terminal.
389 */
390 void runEmptyPTY();
391
392 /**
393 * Closes the terminal session. This sends a hangup signal
394 * (SIGHUP) to the terminal process and causes the done(Session*)
395 * signal to be emitted.
396 */
397 void close();
398
399 /**
400 * Changes the session title or other customizable aspects of the terminal
401 * emulation display. For a list of what may be changed see the
402 * Emulation::titleChanged() signal.
403 */
404 void setUserTitle( int, const QString & caption );
405
406signals:
407
408 /** Emitted when the terminal process starts. */
409 void started();
410
411 /**
412 * Emitted when the terminal process exits.
413 */
414 void finished();
415
416 /**
417 * Emitted when output is received from the terminal process.
418 */
419 void receivedData( const QString & text );
420
421 /** Emitted when the session's title has changed. */
422 void titleChanged();
423
424 /** Emitted when the session's profile has changed. */
425 void profileChanged(const QString & profile);
426
427 /**
428 * Emitted when the activity state of this session changes.
429 *
430 * @param state The new state of the session. This may be one
431 * of NOTIFYNORMAL, NOTIFYSILENCE or NOTIFYACTIVITY
432 */
433 void stateChanged(int state);
434
435 /** Emitted when a bell event occurs in the session. */
436 void bellRequest( const QString & message );
437
438 /**
439 * Requests that the color the text for any tabs associated with
440 * this session should be changed;
441 *
442 * TODO: Document what the parameter does
443 */
444 void changeTabTextColorRequest(int);
445
446 /**
447 * Requests that the background color of views on this session
448 * should be changed.
449 */
450 void changeBackgroundColorRequest(const QColor &);
451
452 /** TODO: Document me. */
453 void openUrlRequest(const QString & url);
454
455 /** TODO: Document me. */
456// void zmodemDetected();
457
458 /**
459 * Emitted when the terminal process requests a change
460 * in the size of the terminal window.
461 *
462 * @param size The requested window size in terms of lines and columns.
463 */
464 void resizeRequest(const QSize & size);
465
466 /**
467 * Emitted when a profile change command is received from the terminal.
468 *
469 * @param text The text of the command. This is a string of the form
470 * "PropertyName=Value;PropertyName=Value ..."
471 */
472 void profileChangeCommandReceived(const QString & text);
473
474 /**
475 * Emitted when the flow control state changes.
476 *
477 * @param enabled True if flow control is enabled or false otherwise.
478 */
479 void flowControlEnabledChanged(bool enabled);
480
481 /**
482 * Broker for Emulation::cursorChanged() signal
483 */
484 void cursorChanged(Emulation::KeyboardCursorShape cursorShape, bool blinkingCursorEnabled);
485
486 void silence();
487 void activity();
488
489private slots:
490 void done(int);
491
492// void fireZModemDetected();
493
494 void onReceiveBlock( const char * buffer, int len );
495 void monitorTimerDone();
496
497 void onViewSizeChange(int height, int width);
498 void onEmulationSizeChange(QSize);
499
500 void activityStateSet(int);
501
502 //automatically detach views from sessions when view is destroyed
503 void viewDestroyed(QObject * view);
504
505// void zmodemReadStatus();
506// void zmodemReadAndSendBlock();
507// void zmodemRcvBlock(const char *data, int len);
508// void zmodemFinished();
509
510private:
511
512 void updateTerminalSize();
513 WId windowId() const;
514
515 int _uniqueIdentifier;
516
517 Pty *_shellProcess;
518 Emulation * _emulation;
519
520 QList<TerminalDisplay *> _views;
521
522 bool _monitorActivity;
523 bool _monitorSilence;
524 bool _notifiedActivity;
525 bool _masterMode;
526 bool _autoClose;
527 bool _wantedClose;
528 QTimer * _monitorTimer;
529
530 int _silenceSeconds;
531
532 QString _nameTitle;
533 QString _displayTitle;
534 QString _userTitle;
535
536 QString _localTabTitleFormat;
537 QString _remoteTabTitleFormat;
538
539 QString _iconName;
540 QString _iconText; // as set by: echo -en '\033]1;IconText\007
541 bool _isTitleChanged; ///< flag if the title/icon was changed by user
542 bool _addToUtmp;
543 bool _flowControl;
544 bool _fullScripting;
545
546 QString _program;
547 QStringList _arguments;
548
549 QStringList _environment;
550 int _sessionId;
551
552 QString _initialWorkingDir;
553
554 // ZModem
555// bool _zmodemBusy;
556// KProcess* _zmodemProc;
557// ZModemDialog* _zmodemProgress;
558
559 // Color/Font Changes by ESC Sequences
560
561 QColor _modifiedBackground; // as set by: echo -en '\033]11;Color\007
562
563 QString _profileKey;
564
565 bool _hasDarkBackground;
566
567 static int lastSessionId;
568
569 int ptySlaveFd;
570
571};
572
573/**
574 * Provides a group of sessions which is divided into master and slave sessions.
575 * Activity in master sessions can be propagated to all sessions within the group.
576 * The type of activity which is propagated and method of propagation is controlled
577 * by the masterMode() flags.
578 */
579class SessionGroup : public QObject {
580 Q_OBJECT
581
582public:
583 /** Constructs an empty session group. */
584 SessionGroup();
585 /** Destroys the session group and removes all connections between master and slave sessions. */
586 ~SessionGroup();
587
588 /** Adds a session to the group. */
589 void addSession( Session * session );
590 /** Removes a session from the group. */
591 void removeSession( Session * session );
592
593 /** Returns the list of sessions currently in the group. */
594 QList<Session *> sessions() const;
595
596 /**
597 * Sets whether a particular session is a master within the group.
598 * Changes or activity in the group's master sessions may be propagated
599 * to all the sessions in the group, depending on the current masterMode()
600 *
601 * @param session The session whoose master status should be changed.
602 * @param master True to make this session a master or false otherwise
603 */
604 void setMasterStatus( Session * session , bool master );
605 /** Returns the master status of a session. See setMasterStatus() */
606 bool masterStatus( Session * session ) const;
607
608 /**
609 * This enum describes the options for propagating certain activity or
610 * changes in the group's master sessions to all sessions in the group.
611 */
612 enum MasterMode {
613 /**
614 * Any input key presses in the master sessions are sent to all
615 * sessions in the group.
616 */
617 CopyInputToAll = 1
618 };
619
620 /**
621 * Specifies which activity in the group's master sessions is propagated
622 * to all sessions in the group.
623 *
624 * @param mode A bitwise OR of MasterMode flags.
625 */
626 void setMasterMode( int mode );
627 /**
628 * Returns a bitwise OR of the active MasterMode flags for this group.
629 * See setMasterMode()
630 */
631 int masterMode() const;
632
633private:
634 void connectPair(Session * master , Session * other);
635 void disconnectPair(Session * master , Session * other);
636 void connectAll(bool connect);
637 QList<Session *> masters() const;
638
639 // maps sessions to their master status
640 QHash<Session *,bool> _sessions;
641
642 int _masterMode;
643};
644
645}
646
647#endif
648