Mercurial > hg > octave-nkf
changeset 15647:a044a259c423
Renamed SessionModel in TerminalModel.
author | Jacob Dawid <jacob.dawid@googlemail.com> |
---|---|
date | Fri, 27 Jan 2012 23:28:55 +0100 |
parents | f570d3baa6fb |
children | d49e99269c0b |
files | libqterminal/QTerminal.cpp libqterminal/QTerminal.h libqterminal/SessionModel.cpp libqterminal/SessionModel.h libqterminal/TerminalModel.cpp libqterminal/TerminalModel.h libqterminal/libqterminal.pro |
diffstat | 7 files changed, 793 insertions(+), 790 deletions(-) [+] |
line wrap: on
line diff
--- a/libqterminal/QTerminal.cpp +++ b/libqterminal/QTerminal.cpp @@ -42,7 +42,7 @@ dup2 (fds, 1); dup2 (fds, 2); - m_sessionModel = new SessionModel(kpty); + m_sessionModel = new TerminalModel(kpty); m_sessionModel->setAutoClose(true); m_sessionModel->setCodec(QTextCodec::codecForName("UTF-8"));
--- a/libqterminal/QTerminal.h +++ b/libqterminal/QTerminal.h @@ -1,5 +1,6 @@ /* Copyright (C) 2008 e_k (e_k@users.sourceforge.net) - + Copyright (C) 2012 Jacob Dawid <jacob.dawid@googlemail.com> + This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either @@ -21,7 +22,7 @@ #define Q_TERMINAL #include <QtGui> -#include "SessionModel.h" +#include "TerminalModel.h" #include "SessionView.h" class QTerminal : public QWidget @@ -55,7 +56,7 @@ private: void init(); SessionView *m_sessionView; - SessionModel *m_sessionModel; + TerminalModel *m_sessionModel; }; #endif // Q_TERMINAL
deleted file mode 100644 --- a/libqterminal/SessionModel.cpp +++ /dev/null @@ -1,412 +0,0 @@ -/* - This file is part of Konsole - - Copyright (C) 2006-2007 by Robert Knight <robertknight@gmail.com> - Copyright (C) 1997,1998 by Lars Doelle <lars.doelle@on-line.de> - - Rewritten for QT4 by e_k <e_k at users.sourceforge.net>, Copyright (C)2008 - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - 02110-1301 USA. -*/ - -// Own -#include "SessionModel.h" - -// Standard -#include <assert.h> -#include <stdlib.h> - -// Qt -#include <QtGui/QApplication> -#include <QtCore/QByteRef> -#include <QtCore/QDir> -#include <QtCore/QFile> -#include <QtCore/QRegExp> -#include <QtCore/QStringList> -#include <QtCore> - -#include "SessionView.h" -#include "Vt102Emulation.h" - -SessionModel::SessionModel(KPty *kpty) : - _shellProcess(0) - , _emulation(0) - , _monitorActivity(false) - , _monitorSilence(false) - , _notifiedActivity(false) - , _autoClose(true) - , _wantedClose(false) - , _silenceSeconds(10) - , _addToUtmp(false) - , _fullScripting(false) - , _hasDarkBackground(false) -{ - _kpty = kpty; - - //create emulation backend - _emulation = new Vt102Emulation(); - connect( _emulation, SIGNAL( stateSet(int) ), - this, SLOT( activityStateSet(int) ) ); - connect( _emulation, SIGNAL( changeTabTextColorRequest( int ) ), - this, SIGNAL( changeTabTextColorRequest( int ) ) ); - connect( _emulation, SIGNAL(profileChangeCommandReceived(const QString&)), - this, SIGNAL( profileChangeCommandReceived(const QString&)) ); - // TODO - // connect( _emulation,SIGNAL(imageSizeChanged(int,int)) , this , - // SLOT(onEmulationSizeChange(int,int)) ); - - _selfListener = new SelfListener(kpty->masterFd()); - _selfListener->start(); - connect( _selfListener, SIGNAL(recvData(const char*,int)), - this, SLOT(onReceiveBlock(const char*,int)), Qt::BlockingQueuedConnection); - - connect( _emulation, SIGNAL(sendData(const char*,int)) - ,this,SLOT(sendData(const char*,int))); - - //connect( _emulation,SIGNAL(lockPtyRequest(bool)),_shellProcess,SLOT(lockPty(bool)) ); - //connect( _emulation,SIGNAL(useUtf8Request(bool)),_shellProcess,SLOT(setUtf8Mode(bool)) ); - - - //connect( _shellProcess,SIGNAL(done(int)), this, SLOT(done(int)) ); - - //setup timer for monitoring session activity - _monitorTimer = new QTimer(this); - _monitorTimer->setSingleShot(true); - connect(_monitorTimer, SIGNAL(timeout()), this, SLOT(monitorTimerDone())); -} - -void SessionModel::setDarkBackground(bool darkBackground) -{ - _hasDarkBackground = darkBackground; -} -bool SessionModel::hasDarkBackground() const -{ - return _hasDarkBackground; -} - -void SessionModel::setCodec(QTextCodec* codec) -{ - emulation()->setCodec(codec); -} - -QList<SessionView*> SessionModel::views() const -{ - return _views; -} - -void SessionModel::addView(SessionView* widget) -{ - Q_ASSERT( !_views.contains(widget) ); - - _views.append(widget); - - if ( _emulation != 0 ) - { - // connect emulation - view signals and slots - connect( widget , SIGNAL(keyPressedSignal(QKeyEvent*)) , _emulation , - SLOT(sendKeyEvent(QKeyEvent*)) ); - connect( widget , SIGNAL(mouseSignal(int,int,int,int)) , _emulation , - SLOT(sendMouseEvent(int,int,int,int)) ); - connect( widget , SIGNAL(sendStringToEmu(const char*)) , _emulation , - SLOT(sendString(const char*)) ); - - // allow emulation to notify view when the foreground process - // indicates whether or not it is interested in mouse signals - connect( _emulation , SIGNAL(programUsesMouseChanged(bool)) , widget , - SLOT(setUsesMouse(bool)) ); - - widget->setUsesMouse( _emulation->programUsesMouse() ); - - widget->setScreenWindow(_emulation->createWindow()); - } - - //connect view signals and slots - QObject::connect( widget ,SIGNAL(changedContentSizeSignal(int,int)),this, - SLOT(onViewSizeChange(int,int))); - - QObject::connect( widget ,SIGNAL(destroyed(QObject*)) , this , - SLOT(viewDestroyed(QObject*)) ); - //slot for close - //QObject::connect(this, SIGNAL(finished()), widget, SLOT(close())); -} - -void SessionModel::viewDestroyed(QObject* view) -{ - SessionView* display = (SessionView*)view; - - Q_ASSERT( _views.contains(display) ); - - removeView(display); -} - -void SessionModel::sendData(const char *buf, int len) -{ - ssize_t bytesWritten = ::write(_kpty->masterFd(), buf, len); - (void)bytesWritten; -} - -void SessionModel::removeView(SessionView* widget) -{ - _views.removeAll(widget); - - disconnect(widget,0,this,0); - - if ( _emulation != 0 ) - { - // disconnect - // - key presses signals from widget - // - mouse activity signals from widget - // - string sending signals from widget - // - // ... and any other signals connected in addView() - disconnect( widget, 0, _emulation, 0); - - // disconnect state change signals emitted by emulation - disconnect( _emulation , 0 , widget , 0); - } - - // close the session automatically when the last view is removed - if ( _views.count() == 0 ) - { - close(); - } -} - -void SessionModel::run() -{ - emit started(); -} - -void SessionModel::monitorTimerDone() -{ - //FIXME: The idea here is that the notification popup will appear to tell the user than output from - //the terminal has stopped and the popup will disappear when the user activates the session. - // - //This breaks with the addition of multiple views of a session. The popup should disappear - //when any of the views of the session becomes active - - - //FIXME: Make message text for this notification and the activity notification more descriptive. - if (_monitorSilence) { - // KNotification::event("Silence", ("Silence in session '%1'", _nameTitle), QPixmap(), - // QApplication::activeWindow(), - // KNotification::CloseWhenWidgetActivated); - emit stateChanged(NOTIFYSILENCE); - } - else - { - emit stateChanged(NOTIFYNORMAL); - } - - _notifiedActivity=false; -} - -void SessionModel::activityStateSet(int state) -{ - if (state==NOTIFYBELL) - { - emit bellRequest(""); - } - else if (state==NOTIFYACTIVITY) - { - if (_monitorSilence) { - _monitorTimer->start(_silenceSeconds*1000); - } - - if ( _monitorActivity ) { - //FIXME: See comments in Session::monitorTimerDone() - if (!_notifiedActivity) { - // KNotification::event("Activity", ("Activity in session '%1'", _nameTitle), QPixmap(), - // QApplication::activeWindow(), - // KNotification::CloseWhenWidgetActivated); - _notifiedActivity=true; - } - } - } - - if ( state==NOTIFYACTIVITY && !_monitorActivity ) - state = NOTIFYNORMAL; - if ( state==NOTIFYSILENCE && !_monitorSilence ) - state = NOTIFYNORMAL; - - emit stateChanged(state); -} - -void SessionModel::onViewSizeChange(int /*height*/, int /*width*/) -{ - updateTerminalSize(); -} -void SessionModel::onEmulationSizeChange(int lines , int columns) -{ - setSize( QSize(lines,columns) ); -} - -void SessionModel::updateTerminalSize() -{ - QListIterator<SessionView*> viewIter(_views); - - int minLines = -1; - int minColumns = -1; - - // minimum number of lines and columns that views require for - // their size to be taken into consideration ( to avoid problems - // with new view widgets which haven't yet been set to their correct size ) - const int VIEW_LINES_THRESHOLD = 2; - const int VIEW_COLUMNS_THRESHOLD = 2; - - //select largest number of lines and columns that will fit in all visible views - while ( viewIter.hasNext() ) - { - SessionView* view = viewIter.next(); - if ( view->isHidden() == false && - view->lines() >= VIEW_LINES_THRESHOLD && - view->columns() >= VIEW_COLUMNS_THRESHOLD ) - { - minLines = (minLines == -1) ? view->lines() : qMin( minLines , view->lines() ); - minColumns = (minColumns == -1) ? view->columns() : qMin( minColumns , view->columns() ); - } - } - - // backend emulation must have a _terminal of at least 1 column x 1 line in size - if ( minLines > 0 && minColumns > 0 ) - { - _emulation->setImageSize( minLines , minColumns ); - //_shellProcess->setWindowSize( minLines , minColumns ); - } -} - -void SessionModel::refresh() -{ -} - -void SessionModel::close() -{ - _autoClose = true; - _wantedClose = true; -} - -void SessionModel::sendText(const QString &text) const -{ - _emulation->sendText(text); -} - -SessionModel::~SessionModel() -{ - delete _emulation; -} - -void SessionModel::setProfileKey(const QString& key) -{ - _profileKey = key; - emit profileChanged(key); -} -QString SessionModel::profileKey() const { return _profileKey; } - -void SessionModel::done(int) -{ - emit finished(); -} - -Emulation* SessionModel::emulation() const -{ - return _emulation; -} - -QString SessionModel::keyBindings() const -{ - return _emulation->keyBindings(); -} - -void SessionModel::setKeyBindings(const QString &id) -{ - _emulation->setKeyBindings(id); -} - -void SessionModel::setHistoryType(const HistoryType &hType) -{ - _emulation->setHistory(hType); -} - -const HistoryType& SessionModel::historyType() const -{ - return _emulation->history(); -} - -void SessionModel::clearHistory() -{ - _emulation->clearHistory(); -} - -// unused currently -bool SessionModel::isMonitorActivity() const { return _monitorActivity; } -// unused currently -bool SessionModel::isMonitorSilence() const { return _monitorSilence; } - -void SessionModel::setMonitorActivity(bool _monitor) -{ - _monitorActivity=_monitor; - _notifiedActivity=false; - - activityStateSet(NOTIFYNORMAL); -} - -void SessionModel::setMonitorSilence(bool _monitor) -{ - if (_monitorSilence==_monitor) - return; - - _monitorSilence=_monitor; - if (_monitorSilence) - { - _monitorTimer->start(_silenceSeconds*1000); - } - else - _monitorTimer->stop(); - - activityStateSet(NOTIFYNORMAL); -} - -void SessionModel::setMonitorSilenceSeconds(int seconds) -{ - _silenceSeconds=seconds; - if (_monitorSilence) { - _monitorTimer->start(_silenceSeconds*1000); - } -} - -void SessionModel::setAddToUtmp(bool set) -{ - _addToUtmp = set; -} - -void SessionModel::onReceiveBlock( const char* buf, int len ) -{ - _emulation->receiveData( buf, len ); - emit receivedData( QString::fromLatin1( buf, len ) ); -} - -QSize SessionModel::size() -{ - return _emulation->imageSize(); -} - -void SessionModel::setSize(const QSize& size) -{ - if ((size.width() <= 1) || (size.height() <= 1)) - return; - - emit resizeRequest(size); -}
deleted file mode 100644 --- a/libqterminal/SessionModel.h +++ /dev/null @@ -1,370 +0,0 @@ -/* - This file is part of Konsole, an X terminal. - - Copyright (C) 2007 by Robert Knight <robertknight@gmail.com> - Copyright (C) 1997,1998 by Lars Doelle <lars.doelle@on-line.de> - - Rewritten for QT4 by e_k <e_k at users.sourceforge.net>, Copyright (C)2008 - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - 02110-1301 USA. -*/ - -#ifndef SESSION_H -#define SESSION_H - -// Qt -#include <QtCore/QStringList> -#include <QtCore> -#include <QWidget> - -#include "SelfListener.h" - -// Konsole -#include "History.h" -#include "kpty.h" - -class KProcess; - -class Emulation; -class PseudoTerminal; -class SessionView; - -/** - * Represents a terminal session consisting of a pseudo-teletype and a terminal emulation. - * The pseudo-teletype (or PTY) handles I/O between the terminal process and Konsole. - * The terminal emulation ( Emulation and subclasses ) processes the output stream from the - * PTY and produces a character image which is then shown on views connected to the session. - * - * Each Session can be connected to one or more views by using the addView() method. - * The attached views can then display output from the program running in the terminal - * or send input to the program in the terminal in the form of keypresses and mouse - * activity. - */ -class SessionModel : public QObject { -Q_OBJECT - -public: - Q_PROPERTY(QString keyBindings READ keyBindings WRITE setKeyBindings) - Q_PROPERTY(QSize size READ size WRITE setSize) - - /** - * Constructs a new session. - * - * To start the terminal process, call the run() method, - * after specifying the program and arguments - * using setProgram() and setArguments() - * - * If no program or arguments are specified explicitly, the Session - * falls back to using the program specified in the SHELL environment - * variable. - */ - SessionModel(KPty *kpty); - ~SessionModel(); - - - /** - * Sets the profile associated with this session. - * - * @param profileKey A key which can be used to obtain the current - * profile settings from the SessionManager - */ - void setProfileKey(const QString& profileKey); - /** - * Returns the profile key associated with this session. - * This can be passed to the SessionManager to obtain the current - * profile settings. - */ - QString profileKey() const; - - /** - * Adds a new view for this session. - * - * The viewing widget will display the output from the terminal and - * input from the viewing widget (key presses, mouse activity etc.) - * will be sent to the terminal. - * - * Views can be removed using removeView(). The session is automatically - * closed when the last view is removed. - */ - void addView(SessionView* widget); - /** - * Removes a view from this session. When the last view is removed, - * the session will be closed automatically. - * - * @p widget will no longer display output from or send input - * to the terminal - */ - void removeView(SessionView* widget); - - /** - * Returns the views connected to this session - */ - QList<SessionView*> views() const; - - /** - * Returns the terminal emulation instance being used to encode / decode - * characters to / from the process. - */ - Emulation* emulation() const; - - - - /** - * Sets the type of history store used by this session. - * Lines of output produced by the terminal are added - * to the history store. The type of history store - * used affects the number of lines which can be - * remembered before they are lost and the storage - * (in memory, on-disk etc.) used. - */ - void setHistoryType(const HistoryType& type); - /** - * Returns the type of history store used by this session. - */ - const HistoryType& historyType() const; - /** - * Clears the history store used by this session. - */ - void clearHistory(); - - /** - * Enables monitoring for activity in the session. - * This will cause notifySessionState() to be emitted - * with the NOTIFYACTIVITY state flag when output is - * received from the terminal. - */ - void setMonitorActivity(bool); - /** Returns true if monitoring for activity is enabled. */ - bool isMonitorActivity() const; - - /** - * Enables monitoring for silence in the session. - * This will cause notifySessionState() to be emitted - * with the NOTIFYSILENCE state flag when output is not - * received from the terminal for a certain period of - * time, specified with setMonitorSilenceSeconds() - */ - void setMonitorSilence(bool); - /** - * Returns true if monitoring for inactivity (silence) - * in the session is enabled. - */ - bool isMonitorSilence() const; - /** See setMonitorSilence() */ - void setMonitorSilenceSeconds(int seconds); - - /** - * Sets the key bindings used by this session. The bindings - * specify how input key sequences are translated into - * the character stream which is sent to the terminal. - * - * @param id The name of the key bindings to use. The - * names of available key bindings can be determined using the - * KeyboardTranslatorManager class. - */ - void setKeyBindings(const QString& id); - /** Returns the name of the key bindings used by this session. */ - QString keyBindings() const; - - - /** Specifies whether a utmp entry should be created for the pty used by this session. */ - void setAddToUtmp(bool); - - /** - * Specifies whether to close the session automatically when the terminal - * process terminates. - */ - void setAutoClose(bool b) { _autoClose = b; } - - /** - * Sends @p text to the current foreground terminal program. - */ - void sendText(const QString& text) const; - - - /** Returns the terminal session's window size in lines and columns. */ - QSize size(); - /** - * Emits a request to resize the session to accommodate - * the specified window size. - * - * @param size The size in lines and columns to request. - */ - void setSize(const QSize& size); - - /** Sets the text codec used by this session's terminal emulation. */ - void setCodec(QTextCodec* codec); - - /** - * Sets whether the session has a dark background or not. The session - * uses this information to set the COLORFGBG variable in the process's - * environment, which allows the programs running in the terminal to determine - * whether the background is light or dark and use appropriate colors by default. - * - * This has no effect once the session is running. - */ - void setDarkBackground(bool darkBackground); - /** - * Returns true if the session has a dark background. - * See setDarkBackground() - */ - bool hasDarkBackground() const; - - /** - * Attempts to get the shell program to redraw the current display area. - * This can be used after clearing the screen, for example, to get the - * shell to redraw the prompt line. - */ - void refresh(); - -public slots: - - /** - * Starts the terminal session. - * - * This creates the terminal process and connects the teletype to it. - */ - void run(); - - /** - * Closes the terminal session. This sends a hangup signal - * (SIGHUP) to the terminal process and causes the done(Session*) - * signal to be emitted. - */ - void close(); - -signals: - - /** Emitted when the terminal process starts. */ - void started(); - - /** - * Emitted when the terminal process exits. - */ - void finished(); - - /** - * Emitted when output is received from the terminal process. - */ - void receivedData( const QString& text ); - - /** Emitted when the session's title has changed. */ - void titleChanged(); - - /** Emitted when the session's profile has changed. */ - void profileChanged(const QString& profile); - - /** - * Emitted when the activity state of this session changes. - * - * @param state The new state of the session. This may be one - * of NOTIFYNORMAL, NOTIFYSILENCE or NOTIFYACTIVITY - */ - void stateChanged(int state); - - /** Emitted when a bell event occurs in the session. */ - void bellRequest( const QString& message ); - - /** - * Requests that the color the text for any tabs associated with - * this session should be changed; - * - * TODO: Document what the parameter does - */ - void changeTabTextColorRequest(int); - - /** - * Requests that the background color of views on this session - * should be changed. - */ - void changeBackgroundColorRequest(const QColor&); - - /** TODO: Document me. */ - void openUrlRequest(const QString& url); - - /** - * Emitted when the terminal process requests a change - * in the size of the terminal window. - * - * @param size The requested window size in terms of lines and columns. - */ - void resizeRequest(const QSize& size); - - /** - * Emitted when a profile change command is received from the terminal. - * - * @param text The text of the command. This is a string of the form - * "PropertyName=Value;PropertyName=Value ..." - */ - void profileChangeCommandReceived(const QString& text); - -private slots: - void done(int); - - void onReceiveBlock( const char* buffer, int len ); - void monitorTimerDone(); - - void onViewSizeChange(int height, int width); - void onEmulationSizeChange(int lines , int columns); - - void activityStateSet(int); - - //automatically detach views from sessions when view is destroyed - void viewDestroyed(QObject* view); - - void sendData(const char* buf, int len); - -private: - - void updateTerminalSize(); - WId windowId() const; - - int _uniqueIdentifier; - - PseudoTerminal* _shellProcess; - Emulation* _emulation; - - QList<SessionView*> _views; - - bool _monitorActivity; - bool _monitorSilence; - bool _notifiedActivity; - bool _masterMode; - bool _autoClose; - bool _wantedClose; - QTimer* _monitorTimer; - - int _silenceSeconds; - - bool _addToUtmp; - bool _fullScripting; - - int _masterFd; - int _slaveFd; - - SelfListener *_selfListener; - KPty * _kpty; - - - QColor _modifiedBackground; // as set by: echo -en '\033]11;Color\007 - - QString _profileKey; - - bool _hasDarkBackground; -}; - - -#endif
new file mode 100644 --- /dev/null +++ b/libqterminal/TerminalModel.cpp @@ -0,0 +1,413 @@ +/* + This file is part of Konsole + + Copyright (C) 2006-2007 by Robert Knight <robertknight@gmail.com> + Copyright (C) 1997,1998 by Lars Doelle <lars.doelle@on-line.de> + + Rewritten for QT4 by e_k <e_k at users.sourceforge.net>, Copyright (C)2008 + Copyright (C) 2012 Jacob Dawid <jacob.dawid@googlemail.com> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + 02110-1301 USA. +*/ + +// Own +#include "TerminalModel.h" + +// Standard +#include <assert.h> +#include <stdlib.h> + +// Qt +#include <QtGui/QApplication> +#include <QtCore/QByteRef> +#include <QtCore/QDir> +#include <QtCore/QFile> +#include <QtCore/QRegExp> +#include <QtCore/QStringList> +#include <QtCore> + +#include "SessionView.h" +#include "Vt102Emulation.h" + +TerminalModel::TerminalModel(KPty *kpty) : + _shellProcess(0) + , _emulation(0) + , _monitorActivity(false) + , _monitorSilence(false) + , _notifiedActivity(false) + , _autoClose(true) + , _wantedClose(false) + , _silenceSeconds(10) + , _addToUtmp(false) + , _fullScripting(false) + , _hasDarkBackground(false) +{ + _kpty = kpty; + + //create emulation backend + _emulation = new Vt102Emulation(); + connect( _emulation, SIGNAL( stateSet(int) ), + this, SLOT( activityStateSet(int) ) ); + connect( _emulation, SIGNAL( changeTabTextColorRequest( int ) ), + this, SIGNAL( changeTabTextColorRequest( int ) ) ); + connect( _emulation, SIGNAL(profileChangeCommandReceived(const QString&)), + this, SIGNAL( profileChangeCommandReceived(const QString&)) ); + // TODO + // connect( _emulation,SIGNAL(imageSizeChanged(int,int)) , this , + // SLOT(onEmulationSizeChange(int,int)) ); + + _selfListener = new SelfListener(kpty->masterFd()); + _selfListener->start(); + connect( _selfListener, SIGNAL(recvData(const char*,int)), + this, SLOT(onReceiveBlock(const char*,int)), Qt::BlockingQueuedConnection); + + connect( _emulation, SIGNAL(sendData(const char*,int)) + ,this,SLOT(sendData(const char*,int))); + + //connect( _emulation,SIGNAL(lockPtyRequest(bool)),_shellProcess,SLOT(lockPty(bool)) ); + //connect( _emulation,SIGNAL(useUtf8Request(bool)),_shellProcess,SLOT(setUtf8Mode(bool)) ); + + + //connect( _shellProcess,SIGNAL(done(int)), this, SLOT(done(int)) ); + + //setup timer for monitoring session activity + _monitorTimer = new QTimer(this); + _monitorTimer->setSingleShot(true); + connect(_monitorTimer, SIGNAL(timeout()), this, SLOT(monitorTimerDone())); +} + +void TerminalModel::setDarkBackground(bool darkBackground) +{ + _hasDarkBackground = darkBackground; +} +bool TerminalModel::hasDarkBackground() const +{ + return _hasDarkBackground; +} + +void TerminalModel::setCodec(QTextCodec* codec) +{ + emulation()->setCodec(codec); +} + +QList<SessionView*> TerminalModel::views() const +{ + return _views; +} + +void TerminalModel::addView(SessionView* widget) +{ + Q_ASSERT( !_views.contains(widget) ); + + _views.append(widget); + + if ( _emulation != 0 ) + { + // connect emulation - view signals and slots + connect( widget , SIGNAL(keyPressedSignal(QKeyEvent*)) , _emulation , + SLOT(sendKeyEvent(QKeyEvent*)) ); + connect( widget , SIGNAL(mouseSignal(int,int,int,int)) , _emulation , + SLOT(sendMouseEvent(int,int,int,int)) ); + connect( widget , SIGNAL(sendStringToEmu(const char*)) , _emulation , + SLOT(sendString(const char*)) ); + + // allow emulation to notify view when the foreground process + // indicates whether or not it is interested in mouse signals + connect( _emulation , SIGNAL(programUsesMouseChanged(bool)) , widget , + SLOT(setUsesMouse(bool)) ); + + widget->setUsesMouse( _emulation->programUsesMouse() ); + + widget->setScreenWindow(_emulation->createWindow()); + } + + //connect view signals and slots + QObject::connect( widget ,SIGNAL(changedContentSizeSignal(int,int)),this, + SLOT(onViewSizeChange(int,int))); + + QObject::connect( widget ,SIGNAL(destroyed(QObject*)) , this , + SLOT(viewDestroyed(QObject*)) ); + //slot for close + //QObject::connect(this, SIGNAL(finished()), widget, SLOT(close())); +} + +void TerminalModel::viewDestroyed(QObject* view) +{ + SessionView* display = (SessionView*)view; + + Q_ASSERT( _views.contains(display) ); + + removeView(display); +} + +void TerminalModel::sendData(const char *buf, int len) +{ + ssize_t bytesWritten = ::write(_kpty->masterFd(), buf, len); + (void)bytesWritten; +} + +void TerminalModel::removeView(SessionView* widget) +{ + _views.removeAll(widget); + + disconnect(widget,0,this,0); + + if ( _emulation != 0 ) + { + // disconnect + // - key presses signals from widget + // - mouse activity signals from widget + // - string sending signals from widget + // + // ... and any other signals connected in addView() + disconnect( widget, 0, _emulation, 0); + + // disconnect state change signals emitted by emulation + disconnect( _emulation , 0 , widget , 0); + } + + // close the session automatically when the last view is removed + if ( _views.count() == 0 ) + { + close(); + } +} + +void TerminalModel::run() +{ + emit started(); +} + +void TerminalModel::monitorTimerDone() +{ + //FIXME: The idea here is that the notification popup will appear to tell the user than output from + //the terminal has stopped and the popup will disappear when the user activates the session. + // + //This breaks with the addition of multiple views of a session. The popup should disappear + //when any of the views of the session becomes active + + + //FIXME: Make message text for this notification and the activity notification more descriptive. + if (_monitorSilence) { + // KNotification::event("Silence", ("Silence in session '%1'", _nameTitle), QPixmap(), + // QApplication::activeWindow(), + // KNotification::CloseWhenWidgetActivated); + emit stateChanged(NOTIFYSILENCE); + } + else + { + emit stateChanged(NOTIFYNORMAL); + } + + _notifiedActivity=false; +} + +void TerminalModel::activityStateSet(int state) +{ + if (state==NOTIFYBELL) + { + emit bellRequest(""); + } + else if (state==NOTIFYACTIVITY) + { + if (_monitorSilence) { + _monitorTimer->start(_silenceSeconds*1000); + } + + if ( _monitorActivity ) { + //FIXME: See comments in Session::monitorTimerDone() + if (!_notifiedActivity) { + // KNotification::event("Activity", ("Activity in session '%1'", _nameTitle), QPixmap(), + // QApplication::activeWindow(), + // KNotification::CloseWhenWidgetActivated); + _notifiedActivity=true; + } + } + } + + if ( state==NOTIFYACTIVITY && !_monitorActivity ) + state = NOTIFYNORMAL; + if ( state==NOTIFYSILENCE && !_monitorSilence ) + state = NOTIFYNORMAL; + + emit stateChanged(state); +} + +void TerminalModel::onViewSizeChange(int /*height*/, int /*width*/) +{ + updateTerminalSize(); +} +void TerminalModel::onEmulationSizeChange(int lines , int columns) +{ + setSize( QSize(lines,columns) ); +} + +void TerminalModel::updateTerminalSize() +{ + QListIterator<SessionView*> viewIter(_views); + + int minLines = -1; + int minColumns = -1; + + // minimum number of lines and columns that views require for + // their size to be taken into consideration ( to avoid problems + // with new view widgets which haven't yet been set to their correct size ) + const int VIEW_LINES_THRESHOLD = 2; + const int VIEW_COLUMNS_THRESHOLD = 2; + + //select largest number of lines and columns that will fit in all visible views + while ( viewIter.hasNext() ) + { + SessionView* view = viewIter.next(); + if ( view->isHidden() == false && + view->lines() >= VIEW_LINES_THRESHOLD && + view->columns() >= VIEW_COLUMNS_THRESHOLD ) + { + minLines = (minLines == -1) ? view->lines() : qMin( minLines , view->lines() ); + minColumns = (minColumns == -1) ? view->columns() : qMin( minColumns , view->columns() ); + } + } + + // backend emulation must have a _terminal of at least 1 column x 1 line in size + if ( minLines > 0 && minColumns > 0 ) + { + _emulation->setImageSize( minLines , minColumns ); + //_shellProcess->setWindowSize( minLines , minColumns ); + } +} + +void TerminalModel::refresh() +{ +} + +void TerminalModel::close() +{ + _autoClose = true; + _wantedClose = true; +} + +void TerminalModel::sendText(const QString &text) const +{ + _emulation->sendText(text); +} + +TerminalModel::~TerminalModel() +{ + delete _emulation; +} + +void TerminalModel::setProfileKey(const QString& key) +{ + _profileKey = key; + emit profileChanged(key); +} +QString TerminalModel::profileKey() const { return _profileKey; } + +void TerminalModel::done(int) +{ + emit finished(); +} + +Emulation* TerminalModel::emulation() const +{ + return _emulation; +} + +QString TerminalModel::keyBindings() const +{ + return _emulation->keyBindings(); +} + +void TerminalModel::setKeyBindings(const QString &id) +{ + _emulation->setKeyBindings(id); +} + +void TerminalModel::setHistoryType(const HistoryType &hType) +{ + _emulation->setHistory(hType); +} + +const HistoryType& TerminalModel::historyType() const +{ + return _emulation->history(); +} + +void TerminalModel::clearHistory() +{ + _emulation->clearHistory(); +} + +// unused currently +bool TerminalModel::isMonitorActivity() const { return _monitorActivity; } +// unused currently +bool TerminalModel::isMonitorSilence() const { return _monitorSilence; } + +void TerminalModel::setMonitorActivity(bool _monitor) +{ + _monitorActivity=_monitor; + _notifiedActivity=false; + + activityStateSet(NOTIFYNORMAL); +} + +void TerminalModel::setMonitorSilence(bool _monitor) +{ + if (_monitorSilence==_monitor) + return; + + _monitorSilence=_monitor; + if (_monitorSilence) + { + _monitorTimer->start(_silenceSeconds*1000); + } + else + _monitorTimer->stop(); + + activityStateSet(NOTIFYNORMAL); +} + +void TerminalModel::setMonitorSilenceSeconds(int seconds) +{ + _silenceSeconds=seconds; + if (_monitorSilence) { + _monitorTimer->start(_silenceSeconds*1000); + } +} + +void TerminalModel::setAddToUtmp(bool set) +{ + _addToUtmp = set; +} + +void TerminalModel::onReceiveBlock( const char* buf, int len ) +{ + _emulation->receiveData( buf, len ); + emit receivedData( QString::fromLatin1( buf, len ) ); +} + +QSize TerminalModel::size() +{ + return _emulation->imageSize(); +} + +void TerminalModel::setSize(const QSize& size) +{ + if ((size.width() <= 1) || (size.height() <= 1)) + return; + + emit resizeRequest(size); +}
new file mode 100644 --- /dev/null +++ b/libqterminal/TerminalModel.h @@ -0,0 +1,371 @@ +/* + This file is part of Konsole, an X terminal. + + Copyright (C) 2007 by Robert Knight <robertknight@gmail.com> + Copyright (C) 1997,1998 by Lars Doelle <lars.doelle@on-line.de> + + Rewritten for QT4 by e_k <e_k at users.sourceforge.net>, Copyright (C)2008 + Copyright (C) 2012 Jacob Dawid <jacob.dawid@googlemail.com> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + 02110-1301 USA. +*/ + +#ifndef TERMINALMODEL_H +#define TERMINALMODEL_H + +// Qt +#include <QtCore/QStringList> +#include <QtCore> +#include <QWidget> + +#include "SelfListener.h" + +// Konsole +#include "History.h" +#include "kpty.h" + +class KProcess; + +class Emulation; +class PseudoTerminal; +class SessionView; + +/** + * Represents a terminal session consisting of a pseudo-teletype and a terminal emulation. + * The pseudo-teletype (or PTY) handles I/O between the terminal process and Konsole. + * The terminal emulation ( Emulation and subclasses ) processes the output stream from the + * PTY and produces a character image which is then shown on views connected to the session. + * + * Each Session can be connected to one or more views by using the addView() method. + * The attached views can then display output from the program running in the terminal + * or send input to the program in the terminal in the form of keypresses and mouse + * activity. + */ +class TerminalModel : public QObject { +Q_OBJECT + +public: + Q_PROPERTY(QString keyBindings READ keyBindings WRITE setKeyBindings) + Q_PROPERTY(QSize size READ size WRITE setSize) + + /** + * Constructs a new session. + * + * To start the terminal process, call the run() method, + * after specifying the program and arguments + * using setProgram() and setArguments() + * + * If no program or arguments are specified explicitly, the Session + * falls back to using the program specified in the SHELL environment + * variable. + */ + TerminalModel(KPty *kpty); + ~TerminalModel(); + + + /** + * Sets the profile associated with this session. + * + * @param profileKey A key which can be used to obtain the current + * profile settings from the SessionManager + */ + void setProfileKey(const QString& profileKey); + /** + * Returns the profile key associated with this session. + * This can be passed to the SessionManager to obtain the current + * profile settings. + */ + QString profileKey() const; + + /** + * Adds a new view for this session. + * + * The viewing widget will display the output from the terminal and + * input from the viewing widget (key presses, mouse activity etc.) + * will be sent to the terminal. + * + * Views can be removed using removeView(). The session is automatically + * closed when the last view is removed. + */ + void addView(SessionView* widget); + /** + * Removes a view from this session. When the last view is removed, + * the session will be closed automatically. + * + * @p widget will no longer display output from or send input + * to the terminal + */ + void removeView(SessionView* widget); + + /** + * Returns the views connected to this session + */ + QList<SessionView*> views() const; + + /** + * Returns the terminal emulation instance being used to encode / decode + * characters to / from the process. + */ + Emulation* emulation() const; + + + + /** + * Sets the type of history store used by this session. + * Lines of output produced by the terminal are added + * to the history store. The type of history store + * used affects the number of lines which can be + * remembered before they are lost and the storage + * (in memory, on-disk etc.) used. + */ + void setHistoryType(const HistoryType& type); + /** + * Returns the type of history store used by this session. + */ + const HistoryType& historyType() const; + /** + * Clears the history store used by this session. + */ + void clearHistory(); + + /** + * Enables monitoring for activity in the session. + * This will cause notifySessionState() to be emitted + * with the NOTIFYACTIVITY state flag when output is + * received from the terminal. + */ + void setMonitorActivity(bool); + /** Returns true if monitoring for activity is enabled. */ + bool isMonitorActivity() const; + + /** + * Enables monitoring for silence in the session. + * This will cause notifySessionState() to be emitted + * with the NOTIFYSILENCE state flag when output is not + * received from the terminal for a certain period of + * time, specified with setMonitorSilenceSeconds() + */ + void setMonitorSilence(bool); + /** + * Returns true if monitoring for inactivity (silence) + * in the session is enabled. + */ + bool isMonitorSilence() const; + /** See setMonitorSilence() */ + void setMonitorSilenceSeconds(int seconds); + + /** + * Sets the key bindings used by this session. The bindings + * specify how input key sequences are translated into + * the character stream which is sent to the terminal. + * + * @param id The name of the key bindings to use. The + * names of available key bindings can be determined using the + * KeyboardTranslatorManager class. + */ + void setKeyBindings(const QString& id); + /** Returns the name of the key bindings used by this session. */ + QString keyBindings() const; + + + /** Specifies whether a utmp entry should be created for the pty used by this session. */ + void setAddToUtmp(bool); + + /** + * Specifies whether to close the session automatically when the terminal + * process terminates. + */ + void setAutoClose(bool b) { _autoClose = b; } + + /** + * Sends @p text to the current foreground terminal program. + */ + void sendText(const QString& text) const; + + + /** Returns the terminal session's window size in lines and columns. */ + QSize size(); + /** + * Emits a request to resize the session to accommodate + * the specified window size. + * + * @param size The size in lines and columns to request. + */ + void setSize(const QSize& size); + + /** Sets the text codec used by this session's terminal emulation. */ + void setCodec(QTextCodec* codec); + + /** + * Sets whether the session has a dark background or not. The session + * uses this information to set the COLORFGBG variable in the process's + * environment, which allows the programs running in the terminal to determine + * whether the background is light or dark and use appropriate colors by default. + * + * This has no effect once the session is running. + */ + void setDarkBackground(bool darkBackground); + /** + * Returns true if the session has a dark background. + * See setDarkBackground() + */ + bool hasDarkBackground() const; + + /** + * Attempts to get the shell program to redraw the current display area. + * This can be used after clearing the screen, for example, to get the + * shell to redraw the prompt line. + */ + void refresh(); + +public slots: + + /** + * Starts the terminal session. + * + * This creates the terminal process and connects the teletype to it. + */ + void run(); + + /** + * Closes the terminal session. This sends a hangup signal + * (SIGHUP) to the terminal process and causes the done(Session*) + * signal to be emitted. + */ + void close(); + +signals: + + /** Emitted when the terminal process starts. */ + void started(); + + /** + * Emitted when the terminal process exits. + */ + void finished(); + + /** + * Emitted when output is received from the terminal process. + */ + void receivedData( const QString& text ); + + /** Emitted when the session's title has changed. */ + void titleChanged(); + + /** Emitted when the session's profile has changed. */ + void profileChanged(const QString& profile); + + /** + * Emitted when the activity state of this session changes. + * + * @param state The new state of the session. This may be one + * of NOTIFYNORMAL, NOTIFYSILENCE or NOTIFYACTIVITY + */ + void stateChanged(int state); + + /** Emitted when a bell event occurs in the session. */ + void bellRequest( const QString& message ); + + /** + * Requests that the color the text for any tabs associated with + * this session should be changed; + * + * TODO: Document what the parameter does + */ + void changeTabTextColorRequest(int); + + /** + * Requests that the background color of views on this session + * should be changed. + */ + void changeBackgroundColorRequest(const QColor&); + + /** TODO: Document me. */ + void openUrlRequest(const QString& url); + + /** + * Emitted when the terminal process requests a change + * in the size of the terminal window. + * + * @param size The requested window size in terms of lines and columns. + */ + void resizeRequest(const QSize& size); + + /** + * Emitted when a profile change command is received from the terminal. + * + * @param text The text of the command. This is a string of the form + * "PropertyName=Value;PropertyName=Value ..." + */ + void profileChangeCommandReceived(const QString& text); + +private slots: + void done(int); + + void onReceiveBlock( const char* buffer, int len ); + void monitorTimerDone(); + + void onViewSizeChange(int height, int width); + void onEmulationSizeChange(int lines , int columns); + + void activityStateSet(int); + + //automatically detach views from sessions when view is destroyed + void viewDestroyed(QObject* view); + + void sendData(const char* buf, int len); + +private: + + void updateTerminalSize(); + WId windowId() const; + + int _uniqueIdentifier; + + PseudoTerminal* _shellProcess; + Emulation* _emulation; + + QList<SessionView*> _views; + + bool _monitorActivity; + bool _monitorSilence; + bool _notifiedActivity; + bool _masterMode; + bool _autoClose; + bool _wantedClose; + QTimer* _monitorTimer; + + int _silenceSeconds; + + bool _addToUtmp; + bool _fullScripting; + + int _masterFd; + int _slaveFd; + + SelfListener *_selfListener; + KPty * _kpty; + + + QColor _modifiedBackground; // as set by: echo -en '\033]11;Color\007 + + QString _profileKey; + + bool _hasDarkBackground; +}; + + +#endif // TERMINALMODEL_H
--- a/libqterminal/libqterminal.pro +++ b/libqterminal/libqterminal.pro @@ -27,9 +27,9 @@ ScreenWindow.h \ TerminalCharacterDecoder.h \ Vt102Emulation.h \ - SessionModel.h \ SessionView.h \ - SelfListener.h + SelfListener.h \ + TerminalModel.h SOURCES = BlockArray.cpp \ Emulation.cpp \ Filter.cpp \ @@ -42,6 +42,6 @@ ScreenWindow.cpp \ TerminalCharacterDecoder.cpp \ Vt102Emulation.cpp \ - SessionModel.cpp \ SessionView.cpp \ - SelfListener.cpp + SelfListener.cpp \ + TerminalModel.cpp