mirror of
https://github.com/KDE/konsole.git
synced 2026-02-05 12:51:44 -05:00
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:
@@ -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 );
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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*)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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();
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user