From 52db452aa4455ff18ba29c10eaa10b80fcd6eb69 Mon Sep 17 00:00:00 2001 From: Robert Knight Date: Mon, 11 Jun 2007 20:44:04 +0000 Subject: [PATCH] Don't switch tabs when a non-active session finishes ( Bug #146639 ). Begin implementation of Send Input to All in new front-end. svn path=/trunk/KDE/kdebase/apps/konsole/; revision=674139 --- src/Emulation.cpp | 2 +- src/Emulation.h | 8 ++- src/Session.cpp | 115 +++++++++++++++++++++++++++++++++++++++++ src/Session.h | 74 ++++++++++++++++++++++++++ src/ViewManager.cpp | 32 +++++++++--- src/ViewManager.h | 3 ++ src/Vt102Emulation.cpp | 7 ++- src/Vt102Emulation.h | 2 +- 8 files changed, 231 insertions(+), 12 deletions(-) diff --git a/src/Emulation.cpp b/src/Emulation.cpp index 77c98b0cc..e01e728dc 100644 --- a/src/Emulation.cpp +++ b/src/Emulation.cpp @@ -274,7 +274,7 @@ void Emulation::sendKeyEvent( QKeyEvent* ev ) } } -void Emulation::sendString(const char*) +void Emulation::sendString(const char*,int) { // default implementation does nothing } diff --git a/src/Emulation.h b/src/Emulation.h index 11c57892d..6aedb08d5 100644 --- a/src/Emulation.h +++ b/src/Emulation.h @@ -230,9 +230,13 @@ public slots: virtual void sendMouseEvent(int buttons, int column, int line, int eventType); /** - * Sends a string of characters to the foreground terminal process + * Sends a string of characters to the foreground terminal process. + * + * @param string The characters to send. + * @param length Length of @p string or if set to a negative value, @p string will + * be treated as a null-terminated string and its length will be determined automatically. */ - virtual void sendString(const char *) = 0; + virtual void sendString(const char* string, int length = -1) = 0; /** Processes an incoming block of text. */ void receiveData(const char* txt,int len); diff --git a/src/Session.cpp b/src/Session.cpp index 5403e4c84..cdc65abfe 100644 --- a/src/Session.cpp +++ b/src/Session.cpp @@ -855,4 +855,119 @@ int Session::processId() const return _shellProcess->pid(); } +SessionGroup::SessionGroup() + : _masterMode(0) +{ +} +SessionGroup::~SessionGroup() +{ + // disconnect all + connectAll(false); +} +int SessionGroup::masterMode() const { return _masterMode; } +QList SessionGroup::sessions() const { return _sessions.keys(); } +bool SessionGroup::masterStatus(Session* session) const { return _sessions[session]; } + +void SessionGroup::addSession(Session* session) +{ + _sessions.insert(session,false); + + QListIterator masterIter(masters()); + + while ( masterIter.hasNext() ) + connectPair(masterIter.next(),session); +} +void SessionGroup::removeSession(Session* session) +{ + setMasterStatus(session,false); + + QListIterator masterIter(masters()); + + while ( masterIter.hasNext() ) + disconnectPair(masterIter.next(),session); + + _sessions.remove(session); +} +void SessionGroup::setMasterMode(int mode) +{ + _masterMode = mode; + + connectAll(false); + connectAll(true); +} +QList SessionGroup::masters() const +{ + return _sessions.keys(true); +} +void SessionGroup::connectAll(bool connect) +{ + QListIterator masterIter(masters()); + + while ( masterIter.hasNext() ) + { + Session* master = masterIter.next(); + + QListIterator otherIter(_sessions.keys()); + while ( otherIter.hasNext() ) + { + Session* other = otherIter.next(); + + if ( other != master ) + { + if ( connect ) + connectPair(master,other); + else + disconnectPair(master,other); + } + } + } +} +void SessionGroup::setMasterStatus(Session* session , bool master) +{ + bool wasMaster = _sessions[session]; + _sessions[session] = master; + + if ( !wasMaster && !master + || wasMaster && master ) + return; + + QListIterator iter(_sessions.keys()); + while ( iter.hasNext() ) + { + Session* other = iter.next(); + + if ( other != session ) + { + if ( master ) + connectPair(session,other); + else + disconnectPair(session,other); + } + } +} +void SessionGroup::connectPair(Session* master , Session* other) +{ + qDebug() << __FUNCTION__; + + if ( _masterMode & CopyInputToAll ) + { + qDebug() << "Connection session " << master->nameTitle() << "to" << other->nameTitle(); + + connect( master->emulation() , SIGNAL(sendData(const char*,int)) , other->emulation() , + SLOT(sendString(const char*,int)) ); + } +} +void SessionGroup::disconnectPair(Session* master , Session* other) +{ + qDebug() << __FUNCTION__; + + if ( _masterMode & CopyInputToAll ) + { + qDebug() << "Disconnecting session " << master->nameTitle() << "from" << other->nameTitle(); + + disconnect( master->emulation() , SIGNAL(sendData(const char*,int)) , other->emulation() , + SLOT(sendString(const char*,int)) ); + } +} + #include "Session.moc" diff --git a/src/Session.h b/src/Session.h index fa86379fc..244a62e9a 100644 --- a/src/Session.h +++ b/src/Session.h @@ -508,6 +508,80 @@ private: }; +/** + * Provides a group of sessions which is divided into master and slave sessions. + * Activity in master sessions can be propagated to all sessions within the group. + * The type of activity which is propagated and method of propagation is controlled + * by the masterMode() flags. + */ +class SessionGroup : public QObject +{ +Q_OBJECT + +public: + /** Constructs an empty session group. */ + SessionGroup(); + /** Destroys the session group and removes all connections between master and slave sessions. */ + ~SessionGroup(); + + /** Adds a session to the group. */ + void addSession( Session* session ); + /** Removes a session from the group. */ + void removeSession( Session* session ); + + /** Returns the list of sessions currently in the group. */ + QList sessions() const; + + /** + * Sets whether a particular session is a master within the group. + * Changes or activity in the group's master sessions may be propagated + * to all the sessions in the group, depending on the current masterMode() + * + * @param session The session whoose master status should be changed. + * @param master True to make this session a master or false otherwise + */ + void setMasterStatus( Session* session , bool master ); + /** Returns the master status of a session. See setMasterStatus() */ + bool masterStatus( Session* session ) const; + + /** + * This enum describes the options for propagating certain activity or + * changes in the group's master sessions to all sessions in the group. + */ + enum MasterMode + { + /** + * Any input key presses in the master sessions are sent to all + * sessions in the group. + */ + CopyInputToAll = 1 + }; + + /** + * Specifies which activity in the group's master sessions is propagated + * to all sessions in the group. + * + * @param mode A bitwise OR of MasterMode flags. + */ + void setMasterMode( int mode ); + /** + * Returns a bitwise OR of the active MasterMode flags for this group. + * See setMasterMode() + */ + int masterMode() const; + +private: + void connectPair(Session* master , Session* other); + void disconnectPair(Session* master , Session* other); + void connectAll(bool connect); + QList masters() const; + + // maps sessions to their master status + QHash _sessions; + + int _masterMode; +}; + } #endif diff --git a/src/ViewManager.cpp b/src/ViewManager.cpp index d3e363c1c..1ba02e030 100644 --- a/src/ViewManager.cpp +++ b/src/ViewManager.cpp @@ -254,13 +254,16 @@ void ViewManager::detachActiveView() void ViewManager::sessionFinished() { - // switch to the previous view before deleting the session views to prevent flicker - // occurring as a result of an interval between removing the active view and switching - // to the previous view - previousView(); - Session* session = qobject_cast(sender()); + if ( _sessionMap[qobject_cast(activeView())] == session ) + { + // switch to the previous view before deleting the session views to prevent flicker + // occurring as a result of an interval between removing the active view and switching + // to the previous view + previousView(); + } + Q_ASSERT(session); QList children = _viewSplitter->findChildren(); @@ -406,7 +409,8 @@ SessionController* ViewManager::createController(Session* session , TerminalDisp connect( controller , SIGNAL(focused(SessionController*)) , this , SIGNAL(activeViewChanged(SessionController*)) ); connect( session , SIGNAL(destroyed()) , controller , SLOT(deleteLater()) ); connect( view , SIGNAL(destroyed()) , controller , SLOT(deleteLater()) ); - + connect( controller , SIGNAL(sendInputToAll(bool)) , this , SLOT(sendInputToAll()) ); + return controller; } @@ -644,6 +648,22 @@ QList ViewManager::viewProperties() const return list; } +void ViewManager::sendInputToAll() +{ + SessionGroup* group = new SessionGroup(); + group->setMasterMode( SessionGroup::CopyInputToAll ); + + Session* activeSession = _sessionMap[qobject_cast(activeView())]; + if ( activeSession != 0 ) + { + QListIterator iter( SessionManager::instance()->sessions() ); + while ( iter.hasNext() ) + group->addSession(iter.next()); + + group->setMasterStatus(activeSession,true); + } +} + uint qHash(QPointer display) { return qHash((TerminalDisplay*)display); diff --git a/src/ViewManager.h b/src/ViewManager.h index e81ff7d6d..987d14e29 100644 --- a/src/ViewManager.h +++ b/src/ViewManager.h @@ -175,6 +175,9 @@ private slots: void updateViewsForSession(Session* session); + // sends input from active view to all sessions + void sendInputToAll(); + private: void setupActions(); void focusActiveView(); diff --git a/src/Vt102Emulation.cpp b/src/Vt102Emulation.cpp index 494b5f673..3a05b127b 100644 --- a/src/Vt102Emulation.cpp +++ b/src/Vt102Emulation.cpp @@ -808,9 +808,12 @@ void Vt102Emulation::clearScreenAndSetColumns(int columnCount) /*! */ -void Vt102Emulation::sendString(const char* s) +void Vt102Emulation::sendString(const char* s , int length) { - emit sendData(s,strlen(s)); + if ( length >= 0 ) + emit sendData(s,length); + else + emit sendData(s,strlen(s)); } // Replies ----------------------------------------------------------------- -- diff --git a/src/Vt102Emulation.h b/src/Vt102Emulation.h index a3eac7592..01d84dd68 100644 --- a/src/Vt102Emulation.h +++ b/src/Vt102Emulation.h @@ -94,7 +94,7 @@ public: public slots: // reimplemented - virtual void sendString(const char*); + virtual void sendString(const char*,int length = -1); virtual void sendText(const QString& text); virtual void sendKeyEvent(QKeyEvent*); virtual void sendMouseEvent( int buttons, int column, int line , int eventType );