Allow multiple views to be connected to a terminal emulation. Looking at this as a model-view combination, the terminal image (TEScreen) becomes the model, and the terminal display (TEWidget) becomes the view.

svn path=/trunk/KDE/kdebase/apps/konsole/; revision=582300
This commit is contained in:
Robert Knight
2006-09-08 23:39:28 +00:00
parent d7af9edabf
commit 9f6569394b
11 changed files with 356 additions and 99 deletions

View File

@@ -94,6 +94,9 @@ HistoryFile::~HistoryFile()
unmap();
}
//TODO: Mapping the entire file in will cause problems if the history file becomes exceedingly large,
//(ie. larger than available memory). HistoryFile::map() should only map in sections of the file at a time,
//to avoid this.
void HistoryFile::map()
{
assert( fileMap == 0 );

View File

@@ -65,7 +65,7 @@ private:
//incremented whenver 'add' is called and decremented whenever
//'get' is called.
//this is used to detect when a large number of lines are being read and processed from the history
//and automatically mmap the file for better performance
//and automatically mmap the file for better performance (saves the overhead of many lseek-read calls).
int readWriteBalance;
//when readWriteBalance goes below this threshold, the file will be mmap'ed automatically

View File

@@ -1007,7 +1007,8 @@ void TEWidget::setImage(const ca* const newimg, int lines, int columns)
//both the top and bottom halves of double height lines must always be redrawn
//although both top and bottom halves contain the same characters, only the top one is actually
//drawn.
updateLine |= (lineProperties[y] & LINE_DOUBLEHEIGHT);
if (lineProperties.count() > y)
updateLine |= (lineProperties[y] & LINE_DOUBLEHEIGHT);
if (updateLine)
{

View File

@@ -56,12 +56,17 @@ class QTimer;
class QFrame;
class QGridLayout;
/**
* A widget which displays output from a terminal emulation and sends input keypresses and mouse activity
* to the terminal.
*
* TEWidget does not know anything about the emulations to which it is connected. When the emulation receives new
* output from the program running in the terminal, it will update the display by calling setImage().
*/
class TEWidget : public QFrame
// a widget representing attributed text
{
Q_OBJECT
friend class Konsole;
public:
TEWidget(QWidget *parent=0);

View File

@@ -91,26 +91,52 @@ TEmuVt102::TEmuVt102(TEWidget* gui) : TEmulation(gui)
{
titleUpdateTimer.setSingleShot(true);
//kDebug(1211)<<"TEmuVt102 ctor() connecting"<<endl;
QObject::connect(gui,SIGNAL(mouseSignal(int,int,int,int)),
this,SLOT(onMouse(int,int,int,int)));
QObject::connect(gui, SIGNAL(sendStringToEmu(const char*)),
this, SLOT(sendString(const char*)));
setReceiveViewInput(gui,true);
QObject::connect(&titleUpdateTimer , SIGNAL(timeout()) , this , SLOT(updateTitle()));
//kDebug(1211)<<"TEmuVt102 ctor() initToken..."<<endl;
initTokenizer();
//kDebug(1211)<<"TEmuVt102 ctor() reset()"<<endl;
reset();
//kDebug(1211)<<"TEmuVt102 ctor() ctor done"<<endl;
}
void TEmuVt102::setReceiveViewInput(TEWidget* view , bool enable)
{
if (enable)
{
QObject::connect(view,SIGNAL(mouseSignal(int,int,int,int)),
this,SLOT(onMouse(int,int,int,int)));
QObject::connect(view, SIGNAL(sendStringToEmu(const char*)),
this, SLOT(sendString(const char*)));
}
else
{
QObject::disconnect(view,SIGNAL(mouseSignal(int,int,int,int)),
this,SLOT(onMouse(int,int,int,int)));
QObject::disconnect(view, SIGNAL(sendStringToEmu(const char*)),
this, SLOT(sendString(const char*)));
}
}
void TEmuVt102::addView(TEWidget* view)
{
kDebug() << __FUNCTION__ << endl;
TEmulation::addView(view);
setReceiveViewInput(view,true);
}
void TEmuVt102::removeView(TEWidget* view)
{
TEmulation::removeView(view);
setReceiveViewInput(view,false);
}
/*!
*/
void TEmuVt102::changeGUI(TEWidget* newgui)
void TEmuVt102::changeGUI(TEWidget* /*newgui*/)
{
if (static_cast<TEWidget *>( gui )==newgui) return;
Q_ASSERT(0); //Not implemented yet
/* if (static_cast<TEWidget *>( gui )==newgui) return;
if ( gui ) {
QObject::disconnect(gui,SIGNAL(mouseSignal(int,int,int,int)),
@@ -122,7 +148,7 @@ void TEmuVt102::changeGUI(TEWidget* newgui)
QObject::connect(gui,SIGNAL(mouseSignal(int,int,int,int)),
this,SLOT(onMouse(int,int,int,int)));
QObject::connect(gui, SIGNAL(sendStringToEmu(const char*)),
this, SLOT(sendString(const char*)));
this, SLOT(sendString(const char*)));*/
}
/*!
@@ -981,6 +1007,26 @@ void TEmuVt102::onScrollLock()
scrollLock(switchlock);
}
void TEmuVt102::scrollView( int lines )
{
QListIterator<QPointer<TEWidget> > viewIter(_views);
while (viewIter.hasNext())
viewIter.next()->doScroll( lines );
}
void TEmuVt102::scrollViewPages( int pages )
{
QListIterator< QPointer<TEWidget> > viewIter(_views);
while (viewIter.hasNext())
{
TEWidget* display = viewIter.next();
display->doScroll( pages * (display->Lines() / 2) );
}
}
#define encodeMode(M,B) BITS(B,getMode(M))
#define encodeStat(M,B) BITS(B,((ev->modifiers() & (M)) == (M)))
@@ -1013,10 +1059,10 @@ void TEmuVt102::onKeyPress( QKeyEvent* ev )
{
switch(cmd) // ... and execute if found.
{
case CMD_scrollPageUp : gui->doScroll(-gui->Lines()/2); return;
case CMD_scrollPageDown : gui->doScroll(+gui->Lines()/2); return;
case CMD_scrollLineUp : gui->doScroll(-1 ); return;
case CMD_scrollLineDown : gui->doScroll(+1 ); return;
case CMD_scrollPageUp : scrollViewPages(-1); return;
case CMD_scrollPageDown : scrollViewPages(+1); return;
case CMD_scrollLineUp : scrollView(-1 ); return;
case CMD_scrollLineDown : scrollView(+1 ); return;
case CMD_scrollLock : onScrollLock( ); return;
}
}
@@ -1024,10 +1070,10 @@ void TEmuVt102::onKeyPress( QKeyEvent* ev )
{
switch(ev->key())
{
case Qt::Key_Down : gui->doScroll(+1); return;
case Qt::Key_Up : gui->doScroll(-1); return;
case Qt::Key_PageUp : gui->doScroll(-gui->Lines()/2); return;
case Qt::Key_PageDown : gui->doScroll(gui->Lines()/2); return;
case Qt::Key_Down : scrollView(+1); return;
case Qt::Key_Up : scrollView(-1); return;
case Qt::Key_PageUp : scrollViewPages(-1); return;
case Qt::Key_PageDown : scrollViewPages(+1); return;
}
}
@@ -1208,6 +1254,13 @@ void TEmuVt102::resetModes()
holdScreen = false;
}
void TEmuVt102::setViewMouseMarks(bool marks)
{
QListIterator< QPointer<TEWidget> > viewIter(_views);
while (viewIter.hasNext())
viewIter.next()->setMouseMarks(marks);
}
void TEmuVt102::setMode(int m)
{
currParm.mode[m] = true;
@@ -1217,7 +1270,7 @@ void TEmuVt102::setMode(int m)
case MODE_Mouse1001:
case MODE_Mouse1002:
case MODE_Mouse1003:
if (connected) gui->setMouseMarks(false);
if (connected) setViewMouseMarks(false);
break;
case MODE_AppScreen : screen[1]->clearSelection();
@@ -1240,7 +1293,7 @@ void TEmuVt102::resetMode(int m)
case MODE_Mouse1001 :
case MODE_Mouse1002 :
case MODE_Mouse1003 :
if (connected) gui->setMouseMarks(true);
if (connected) setViewMouseMarks(true);
break;
case MODE_AppScreen : screen[0]->clearSelection();
@@ -1272,9 +1325,12 @@ bool TEmuVt102::getMode(int m)
void TEmuVt102::setConnect(bool c)
{
TEmulation::setConnect(c);
if (gui)
QListIterator< QPointer<TEWidget> > viewIter(_views);
while (viewIter.hasNext())
{
QObject::disconnect(gui, SIGNAL(sendStringToEmu(const char*)),
QObject::disconnect(viewIter.next(), SIGNAL(sendStringToEmu(const char*)),
this, SLOT(sendString(const char*)));
}
if (c)
@@ -1293,8 +1349,14 @@ void TEmuVt102::setConnect(bool c)
else
scrolllock_set_off();
#endif
QObject::connect(gui, SIGNAL(sendStringToEmu(const char*)),
this, SLOT(sendString(const char*)));
QListIterator< QPointer<TEWidget> > viewIter2(_views);
while (viewIter2.hasNext())
{
QObject::connect(viewIter2.next(), SIGNAL(sendStringToEmu(const char*)),
this, SLOT(sendString(const char*)));
}
}
}

View File

@@ -64,9 +64,15 @@ class TEmuVt102 : public TEmulation
public:
TEmuVt102(TEWidget* gui);
void changeGUI(TEWidget* newgui);
~TEmuVt102();
/** Reimplemented to enable handling of mouse input from the view */
virtual void addView(TEWidget* view);
/** Reimplemented to disconnect mouse input signals from the view */
virtual void removeView(TEWidget* view);
void changeGUI(TEWidget* newgui);
virtual void onKeyPress(QKeyEvent*);
public Q_SLOTS: // signals incoming from TEWidget
@@ -101,6 +107,23 @@ public:
private:
//Scrolls the all views on this emulation.
//Lines may be positive (to scroll down) or negative (to scroll up)
void scrollView( int lines );
//Scrolls all the views on this emulation by a given number of pages - where a page
//is half the number of visible lines. Page Up and Page Down scroll by -1 and +1 pages
//respectively.
void scrollViewPages( int pages );
//Enables or disables mouse marking in all the views on this emulation
void setViewMouseMarks( bool marks );
//Enables or disables Vt102 specific handling of input from the view
//(including xterm-style mouse input for example)
//
//See also - TEmulation::connectView()
void setReceiveViewInput( TEWidget* view , bool enable );
void resetToken();
#define MAXPBUF 80
void pushToToken(int cc);

View File

@@ -101,7 +101,8 @@
*/
TEmulation::TEmulation(TEWidget* w)
: gui(w),
: //gui(w),
//gui(0),
scr(0),
connected(false),
listenToKeyPress(false),
@@ -111,38 +112,42 @@ TEmulation::TEmulation(TEWidget* w)
m_findPos(-1)
{
screen[0] = new TEScreen(gui->Lines(),gui->Columns());
screen[1] = new TEScreen(gui->Lines(),gui->Columns());
screen[0] = new TEScreen(w->Lines(),w->Columns());
screen[1] = new TEScreen(w->Lines(),w->Columns());
scr = screen[0];
QObject::connect(&bulk_timer1, SIGNAL(timeout()), this, SLOT(showBulk()) );
QObject::connect(&bulk_timer2, SIGNAL(timeout()), this, SLOT(showBulk()) );
connectGUI();
addView(w);
//connectGUI();
setKeymap(0); // Default keymap
}
/*!
*/
void TEmulation::connectGUI()
void TEmulation::connectView(TEWidget* view)
{
QObject::connect(gui,SIGNAL(changedHistoryCursor(int)),
QObject::connect(view,SIGNAL(changedHistoryCursor(int)),
this,SLOT(onHistoryCursorChange(int)));
QObject::connect(gui,SIGNAL(keyPressedSignal(QKeyEvent*)),
QObject::connect(view,SIGNAL(keyPressedSignal(QKeyEvent*)),
this,SLOT(onKeyPress(QKeyEvent*)));
QObject::connect(gui,SIGNAL(beginSelectionSignal(const int,const int,const bool)),
QObject::connect(view,SIGNAL(beginSelectionSignal(const int,const int,const bool)),
this,SLOT(onSelectionBegin(const int,const int,const bool)) );
QObject::connect(gui,SIGNAL(extendSelectionSignal(const int,const int)),
QObject::connect(view,SIGNAL(extendSelectionSignal(const int,const int)),
this,SLOT(onSelectionExtend(const int,const int)) );
QObject::connect(gui,SIGNAL(endSelectionSignal(const bool)),
QObject::connect(view,SIGNAL(endSelectionSignal(const bool)),
this,SLOT(setSelection(const bool)) );
QObject::connect(gui,SIGNAL(copySelectionSignal()),
QObject::connect(view,SIGNAL(copySelectionSignal()),
this,SLOT(copySelection()) );
QObject::connect(gui,SIGNAL(clearSelectionSignal()),
QObject::connect(view,SIGNAL(clearSelectionSignal()),
this,SLOT(clearSelection()) );
QObject::connect(gui,SIGNAL(isBusySelecting(bool)),
QObject::connect(view,SIGNAL(isBusySelecting(bool)),
this,SLOT(isBusySelecting(bool)) );
QObject::connect(gui,SIGNAL(testIsSelected(const int, const int, bool &)),
QObject::connect(view,SIGNAL(testIsSelected(const int, const int, bool &)),
this,SLOT(testIsSelected(const int, const int, bool &)) );
}
@@ -151,7 +156,9 @@ void TEmulation::connectGUI()
void TEmulation::changeGUI(TEWidget* newgui)
{
if (static_cast<TEWidget *>( gui )==newgui) return;
Q_ASSERT( 0 ); //Not yet implemented
/*if (static_cast<TEWidget *>( gui )==newgui) return;
if ( gui ) {
QObject::disconnect(gui,SIGNAL(changedHistoryCursor(int)),
@@ -174,7 +181,8 @@ void TEmulation::changeGUI(TEWidget* newgui)
this,SLOT(testIsSelected(const int, const int, bool &)) );
}
gui=newgui;
connectGUI();
connectView(gui);
//connectGUI();*/
}
/*!
@@ -405,7 +413,13 @@ void TEmulation::onSelectionExtend(const int x, const int y) {
void TEmulation::setSelection(const bool preserve_line_breaks) {
if (!connected) return;
QString t = scr->getSelText(preserve_line_breaks);
if (!t.isNull()) gui->setSelection(t);
if (!t.isNull())
{
QListIterator< QPointer<TEWidget> > viewIter(_views);
while (viewIter.hasNext())
viewIter.next()->setSelection(t);
}
}
void TEmulation::isBusySelecting(bool busy)
@@ -540,12 +554,47 @@ bool TEmulation::findTextNext( const QString &str, bool forward, bool isCaseSens
/*!
*/
void TEmulation::addView(TEWidget* widget)
{
Q_ASSERT( !_views.contains(widget) );
_views << widget;
connectView(widget);
}
void TEmulation::removeView(TEWidget* widget)
{
Q_ASSERT(0); // Not implemented yet
_views.removeAll(widget);
}
void TEmulation::showBulk()
{
bulk_timer1.stop();
bulk_timer2.stop();
if (connected)
{
ca* image = scr->getCookedImage();
QVector<LineProperty> lineProperties = scr->getCookedLineProperties();
QListIterator< QPointer<TEWidget> > viewIter(_views);
while (viewIter.hasNext())
{
QPointer<TEWidget> view = viewIter.next();
view->setLineProperties( lineProperties );
view->setImage(image,
scr->getLines(),
scr->getColumns()); // actual refresh
view->setCursorPos(scr->getCursorX(), scr->getCursorY()); // set XIM position
view->setScroll(scr->getHistCursor(),scr->getHistLines());
}
free(image);
}
/*if (connected)
{
ca* image = scr->getCookedImage(); // get the image
@@ -559,7 +608,7 @@ void TEmulation::showBulk()
free(image);
gui->setScroll(scr->getHistCursor(),scr->getHistLines());
}
}*/
}
void TEmulation::bulkStart()

View File

@@ -40,9 +40,23 @@ class TEmulation : public QObject
public:
TEmulation(TEWidget* gui);
virtual void changeGUI(TEWidget* newgui);
~TEmulation();
virtual void changeGUI(TEWidget* newgui);
/**
* Adds a new view for this emulation.
*
* When the emulation output changes, the view will be updated to display the new output.
*/
virtual void addView(TEWidget* widget);
/**
* Removes a view from this emulation.
*
* @p widget will no longer be updated when the emulation output changes.
*/
virtual void removeView(TEWidget* widget);
public:
QSize imageSize();
virtual void setHistory(const HistoryType&);
@@ -114,7 +128,10 @@ public:
protected:
QPointer<TEWidget> gui;
QList< QPointer<TEWidget> > _views;
//QPointer<TEWidget> gui;
TEScreen* scr; // referes to one `screen'
TEScreen* screen[2]; // 0 = primary, 1 = alternate
void setScreen(int n); // set `scr' to `screen[n]'
@@ -139,7 +156,8 @@ private Q_SLOTS: // triggered by timer
private:
void connectGUI();
void connectView(TEWidget* widget);
//void connectGUI();
void bulkStart();

View File

@@ -24,12 +24,10 @@
/*! \class Konsole
\brief Konsole's main class and program
\brief The Konsole main window which hosts the terminal emulator displays.
The class Konsole handles the application level. Mainly, it is responsible
for the configuration, taken from several files, from the command line
and from the user. It hardly does anything interesting.
Everything is created as late as possible to make it startup fast.
This class is also responsible for setting up Konsole's menus, managing
terminal sessions and applying settings.
*/
/*TODO:
@@ -75,9 +73,6 @@ Time to start a requirement list.
should be rebalanced. Much more material now comes from configuration
files and the overall routines should better respect this.
- Font+Size list should go to a configuration file, too.
- Controlling the widget is currently done by individual attributes.
This lead to quite some amount of flicker when a whole bunch of
attributes has to be set, e.g. in session swapping.
*/
#include <stdio.h>
@@ -2919,7 +2914,7 @@ QString Konsole::newSession(KSimpleConfig *co, QString program, const QStringLis
QString sessionId="session_"+QString::number(++sessionIdCounter);
TESession* s = new TESession(te, QFile::encodeName(program),cmdArgs,emu,winId(),sessionId,cwd);
if ( co )
sessionConfigMap[s] = co;
@@ -4435,7 +4430,7 @@ void Konsole::setupTabContextMenu()
QString paletteName;
QStringList availablePalettes = KPalette::getPaletteList();
if (availablePalettes.contains("40.colors")) //FIXME: Should this be translated?
if (availablePalettes.contains("40.colors"))
paletteName = "40.colors";
KPalette palette(paletteName);

View File

@@ -18,29 +18,33 @@
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.
*/
#include "session.h"
#include "zmodem_dialog.h"
#include <assert.h>
#include <stdlib.h>
#include <QApplication>
#include <QByteArray>
#include <QDir>
#include <QFile>
#include <QRegExp>
#include <QStringList>
#include <QtDBus/QtDBus>
#include <config-konsole.h>
#include <kdebug.h>
#include <klocale.h>
#include <kmessagebox.h>
#include <knotification.h>
#include <klocale.h>
#include <kprocio.h>
#include <krun.h>
#include <kshell.h>
#include <kstandarddirs.h>
#include <stdlib.h>
#include <QFile>
#include <QDir>
#include <QRegExp>
#include <QStringList>
#include <QByteArray>
#include "sessionadaptor.h"
#include "sessionscriptingadaptor.h"
#include <QtDBus/QtDBus>
#include <assert.h>
#include "zmodem_dialog.h"
#include "session.h"
/*! \class TESession
@@ -53,7 +57,10 @@
*/
TESession::TESession(TEWidget* _te, const QString &_pgm, const QStringList & _args, const QString &_term, ulong _winId, const QString &_sessionId, const QString &_initial_cwd)
: connected(true)
: sh(0)
, te(0)
, em(0)
, connected(true)
, monitorActivity(false)
, monitorSilence(false)
, notifiedActivity(false)
@@ -81,14 +88,15 @@ TESession::TESession(TEWidget* _te, const QString &_pgm, const QStringList & _ar
QDBusConnection::sessionBus().registerService("org.kde.konsole");
//kDebug(1211)<<"TESession ctor() new TEPty"<<endl;
sh = new TEPty();
te = _te;
//kDebug(1211)<<"TESession ctor() new TEmuVt102"<<endl;
em = new TEmuVt102(te);
font_h = te-> fontHeight();
font_w = te-> fontWidth();
QObject::connect(te,SIGNAL(changedContentSizeSignal(int,int)),
addView(_te);
em = new TEmuVt102( primaryView() );
font_h = primaryView()-> fontHeight();
font_w = primaryView()-> fontWidth();
QObject::connect(primaryView(),SIGNAL(changedContentSizeSignal(int,int)),
this,SLOT(onContentSizeChange(int,int)));
QObject::connect(te,SIGNAL(changedFontMetricSignal(int,int)),
QObject::connect(primaryView(),SIGNAL(changedFontMetricSignal(int,int)),
this,SLOT(onFontMetricChange(int,int)));
term = _term;
@@ -96,7 +104,7 @@ TESession::TESession(TEWidget* _te, const QString &_pgm, const QStringList & _ar
iconName = "konsole";
//kDebug(1211)<<"TESession ctor() sh->setSize()"<<endl;
sh->setSize(te->Lines(),te->Columns()); // not absolutely necessary
sh->setSize(primaryView()->Lines(),primaryView()->Columns()); // not absolutely necessary
sh->useUtf8(em->utf8());
//kDebug(1211)<<"TESession ctor() connecting"<<endl;
connect( sh,SIGNAL(block_in(const char*,int)),this,SLOT(onRcvBlock(const char*,int)) );
@@ -128,17 +136,45 @@ void TESession::ptyError()
{
// FIXME: sh->error() is always empty
if ( sh->error().isEmpty() )
KMessageBox::error( te->topLevelWidget(),
KMessageBox::error( QApplication::activeWindow() ,
i18n("Konsole is unable to open a PTY (pseudo teletype). It is likely that this is due to an incorrect configuration of the PTY devices. Konsole needs to have read/write access to the PTY devices."),
i18n("A Fatal Error Has Occurred") );
else
KMessageBox::error(te->topLevelWidget(), sh->error());
KMessageBox::error(QApplication::activeWindow(), sh->error());
emit done(this);
}
TEWidget* TESession::primaryView()
{
if (!_views.isEmpty())
return _views.first();
else
return 0;
}
void TESession::addView(TEWidget* widget)
{
Q_ASSERT( !_views.contains(widget) );
_views.append(widget);
if ( em != 0 )
em->addView(widget);
}
void TESession::removeView(TEWidget* widget)
{
_views.removeAll(widget);
if ( em != 0 )
em->removeView(widget);
}
void TESession::changeWidget(TEWidget* w)
{
QObject::disconnect(te,SIGNAL(changedContentSizeSignal(int,int)),
Q_ASSERT(0); //Method not updated yet to handle multiple views
/* QObject::disconnect(te,SIGNAL(changedContentSizeSignal(int,int)),
this,SLOT(onContentSizeChange(int,int)));
QObject::disconnect(te,SIGNAL(changedFontMetricSignal(int,int)),
this,SLOT(onFontMetricChange(int,int)));
@@ -153,7 +189,7 @@ void TESession::changeWidget(TEWidget* w)
QObject::connect(te,SIGNAL(changedContentSizeSignal(int,int)),
this,SLOT(onContentSizeChange(int,int)));
QObject::connect(te,SIGNAL(changedFontMetricSignal(int,int)),
this,SLOT(onFontMetricChange(int,int)));
this,SLOT(onFontMetricChange(int,int)));*/
}
void TESession::run()
@@ -296,7 +332,10 @@ void TESession::setUserTitle( int what, const QString &caption )
if (backColor.isValid()){// change color via \033]11;Color\007
if (backColor != modifiedBackground) {
modifiedBackground = backColor;
te->setDefaultBackColor(backColor);
QListIterator<TEWidget*> viewIter(_views);
while (viewIter.hasNext())
viewIter.next()->setDefaultBackColor(backColor);
}
}
}
@@ -317,7 +356,10 @@ void TESession::setUserTitle( int what, const QString &caption )
if (what == 32) { // change icon via \033]32;Icon\007
if ( iconName != caption ) {
iconName = caption;
te->update();
QListIterator< TEWidget* > viewIter(_views);
while (viewIter.hasNext())
viewIter.next()->update();
modified = true;
}
}
@@ -349,8 +391,14 @@ QString TESession::displayTitle() const
void TESession::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
if (monitorSilence) {
KNotification::event("Silence", i18n("Silence in session '%1'", title), QPixmap(), te,
KNotification::event("Silence", i18n("Silence in session '%1'", title), QPixmap(),
QApplication::activeWindow(),
KNotification::CloseWhenWidgetActivated);
emit notifySessionState(this,NOTIFYSILENCE);
}
@@ -364,9 +412,11 @@ void TESession::monitorTimerDone()
void TESession::notifySessionState(int state)
{
Q_ASSERT( primaryView() );
if (state==NOTIFYBELL)
{
te->Bell(em->isConnected(),i18n("Bell in session '%1'", title));
primaryView()->Bell(em->isConnected(),i18n("Bell in session '%1'", title));
}
else if (state==NOTIFYACTIVITY)
{
@@ -375,8 +425,11 @@ void TESession::notifySessionState(int state)
monitorTimer->start(silence_seconds*1000);
}
//FIXME: See comments in TESession::monitorTimerDone()
if (!notifiedActivity) {
KNotification::event("Activity", i18n("Activity in session '%1'", title), QPixmap(), te, KNotification::CloseWhenWidgetActivated);
KNotification::event("Activity", i18n("Activity in session '%1'", title), QPixmap(),
QApplication::activeWindow(),
KNotification::CloseWhenWidgetActivated);
notifiedActivity=true;
}
monitorTimer->setSingleShot(true);
@@ -426,9 +479,11 @@ bool TESession::closeSession()
void TESession::feedSession(const QString &text)
{
Q_ASSERT( primaryView() );
emit disableMasterModeConnections();
setListenToKeyPress(true);
te->emitText(text);
primaryView()->emitText(text);
setListenToKeyPress(false);
emit enableMasterModeConnections();
}
@@ -495,7 +550,10 @@ void TESession::done(int exitStatus)
else
message = i18n("Session '%1' exited unexpectedly.", title);
KNotification::event("Finished", message , QPixmap(), te , KNotification::CloseWhenWidgetActivated);
//FIXME: See comments in TESession::monitorTimerDone()
KNotification::event("Finished", message , QPixmap(),
QApplication::activeWindow(),
KNotification::CloseWhenWidgetActivated);
}
emit processExited();
emit done(this);
@@ -757,7 +815,7 @@ void TESession::startZModem(const QString &zmodem, const QString &dir, const QSt
connect( sh,SIGNAL(block_in(const char*,int)), this, SLOT(zmodemRcvBlock(const char*,int)) );
connect( sh,SIGNAL(buffer_empty()), this, SLOT(zmodemContinue()));
zmodemProgress = new ZModemDialog(te->topLevelWidget(), false,
zmodemProgress = new ZModemDialog(QApplication::activeWindow(), false,
i18n("ZModem Progress"));
connect(zmodemProgress, SIGNAL(user1Clicked()),
@@ -850,7 +908,9 @@ void TESession::onRcvBlock( const char* buf, int len )
void TESession::print( QPainter &paint, bool friendly, bool exact )
{
te->print(paint, friendly, exact);
Q_ASSERT( primaryView() );
primaryView()->print(paint, friendly, exact);
}
QString TESession::schema()
@@ -867,14 +927,18 @@ void TESession::setSchema(const QString &schema)
QString TESession::font()
{
return te->getVTFont().toString();
Q_ASSERT( primaryView() );
return primaryView()->getVTFont().toString();
}
void TESession::setFont(const QString &font)
{
Q_ASSERT( primaryView() );
QFont tmp;
if (tmp.fromString(font))
te->setVTFont(tmp);
primaryView()->setVTFont(tmp);
else
kWarning()<<"unknown font: "<<font<<endl;
}

View File

@@ -44,15 +44,48 @@ public:
const QString &pgm, const QStringList & _args,
const QString &term, ulong winId, const QString &sessionId="session-1",
const QString &initial_cwd = QString());
void changeWidget(TEWidget* w);
TEWidget* widget() { return te; }
~TESession();
TEWidget* widget() { Q_ASSERT( primaryView() ) ; return primaryView(); }
void changeWidget(TEWidget* w);
/**
* 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.
*
* Currently each view on the session is required to be the same size. ie. They must all display
* the same number of lines and columns.
*/
void addView(TEWidget* widget);
/**
* Removes a view from this session.
*
* @p widget will no longer display output from or send input
* to the terminal
*/
void removeView(TEWidget* widget);
/**
* Returns the primary view for this session.
*
* The primary view is the first view added to the session, which is used by the emulation
* if it needs to determine the size of the view - ie. the number of lines and columns which
* the view can display.
*
* If the primary view is removed from the session using removeView(), the next view which is still
* attached will become the primary view.
*/
TEWidget* primaryView();
/**
* Returns true if the session has created child processes which have not yet terminated
* This call may be expensive if there are a large number of processes running.
*/
bool hasChildren();
void setConnect(bool r); // calls setListenToKeyPress(r)
void setListenToKeyPress(bool l);
TEmulation* getEmulation(); // to control emulation
@@ -83,6 +116,8 @@ public:
QString keymap();
QStringList getArgs();
QString getPgm();
/** Returns the session's current working directory. */
QString getCwd();
QString getInitial_cwd() { return initial_cwd; }
void setInitial_cwd(const QString& _cwd) { initial_cwd=_cwd; }
@@ -189,6 +224,8 @@ private:
TEWidget* te;
TEmulation* em;
QList<TEWidget*> _views;
bool connected;
bool monitorActivity;
bool monitorSilence;