Commit 9855b2c1 authored by Mariusz Glebocki's avatar Mariusz Glebocki Committed by Kurt Hindenburg
Browse files

Use flags for each session notification type

Replaces single-value session state with separate flags for each
possible notification (silence, activity, bell). This will allow for
more flexible control over how specific notifications are displayed.
parent 9ee21b9c
......@@ -205,7 +205,7 @@ void Emulation::receiveChar(uint c)
_currentScreen->toStartOfLine();
break;
case 0x07:
emit stateSet(NOTIFYBELL);
emit bell();
break;
default:
_currentScreen->displayCharacter(c);
......@@ -215,8 +215,6 @@ void Emulation::receiveChar(uint c)
void Emulation::sendKeyEvent(QKeyEvent *ev)
{
emit stateSet(NOTIFYNORMAL);
if (!ev->text().isEmpty()) {
// A block of text
// Note that the text is proper unicode.
......@@ -236,8 +234,6 @@ void Emulation::sendMouseEvent(int /*buttons*/, int /*column*/, int /*row*/, int
void Emulation::receiveData(const char *text, int length)
{
emit stateSet(NOTIFYACTIVITY);
bufferedUpdate();
QVector<uint> unicodeText = _decoder->toUnicode(text, length).toUcs4();
......
......@@ -41,30 +41,6 @@ class Screen;
class ScreenWindow;
class TerminalCharacterDecoder;
/**
* This enum describes the available states which
* the terminal emulation may be set to.
*
* These are the values used by Emulation::stateChanged()
*/
enum {
/** The emulation is currently receiving user input. */
NOTIFYNORMAL = 0,
/**
* The terminal program has triggered a bell event
* to get the user's attention.
*/
NOTIFYBELL = 1,
/**
* The emulation is currently receiving data from its
* terminal input.
*/
NOTIFYACTIVITY = 2,
// unused here?
NOTIFYSILENCE = 3
};
/**
* Base class for terminal emulation back-ends.
*
......@@ -289,12 +265,9 @@ Q_SIGNALS:
void useUtf8Request(bool);
/**
* Emitted when the activity state of the emulation is set.
*
* @param state The new activity state, one of NOTIFYNORMAL, NOTIFYACTIVITY
* or NOTIFYBELL
* Emitted when bell appeared
*/
void stateSet(int state);
void bell();
/**
* Emitted when the special sequence indicating the request for data
......
......@@ -393,13 +393,13 @@ void Part::setMonitorSilenceEnabled(bool enabled)
if (enabled) {
activeSession()->setMonitorSilence(true);
connect(activeSession(), &Konsole::Session::stateChanged,
this, &Konsole::Part::sessionStateChanged,
connect(activeSession(), &Konsole::Session::notificationsChanged,
this, &Konsole::Part::notificationChanged,
Qt::UniqueConnection);
} else {
activeSession()->setMonitorSilence(false);
disconnect(activeSession(), &Konsole::Session::stateChanged,
this, &Konsole::Part::sessionStateChanged);
disconnect(activeSession(), &Konsole::Session::notificationsChanged,
this, &Konsole::Part::notificationChanged);
}
}
......@@ -409,14 +409,14 @@ void Part::setMonitorActivityEnabled(bool enabled)
if (enabled) {
activeSession()->setMonitorActivity(true);
connect(activeSession(), &Konsole::Session::stateChanged,
this, &Konsole::Part::sessionStateChanged,
connect(activeSession(), &Konsole::Session::notificationsChanged,
this, &Konsole::Part::notificationChanged,
Qt::UniqueConnection);
} else {
activeSession()->setMonitorActivity(false);
disconnect(activeSession(), &Konsole::Session::stateChanged,
disconnect(activeSession(), &Konsole::Session::notificationsChanged,
this,
&Konsole::Part::sessionStateChanged);
&Konsole::Part::notificationChanged);
}
}
......@@ -425,11 +425,11 @@ bool Part::isBlurEnabled()
return ViewManager::profileHasBlurEnabled(SessionManager::instance()->sessionProfile(activeSession()));
}
void Part::sessionStateChanged(int state)
void Part::notificationChanged(Session::Notification notification, bool enabled)
{
if (state == NOTIFYSILENCE) {
if (notification == Session::Notification::Silence && enabled) {
emit silenceDetected();
} else if (state == NOTIFYACTIVITY) {
} else if (notification == Session::Notification::Activity && enabled) {
emit activityDetected();
}
}
......
......@@ -28,6 +28,7 @@
#include <QVariantList>
// Konsole
#include "Session.h"
#include "config-konsole.h"
class QStringList;
......@@ -208,7 +209,7 @@ private Q_SLOTS:
void terminalExited();
void newTab();
void overrideTerminalShortcut(QKeyEvent *, bool &override);
void sessionStateChanged(int state);
void notificationChanged(Session::Notification notification, bool enabled);
private:
Session *activeSession() const;
......
......@@ -121,7 +121,10 @@ Session::Session(QObject* parent) :
_emulation = new Vt102Emulation();
connect(_emulation, &Konsole::Emulation::sessionAttributeChanged, this, &Konsole::Session::setSessionAttribute);
connect(_emulation, &Konsole::Emulation::stateSet, this, &Konsole::Session::activityStateSet);
connect(_emulation, &Konsole::Emulation::bell, this, [this]() {
emit bellRequest(i18n("Bell in session '%1'", _nameTitle));
this->setPendingNotification(Notification::Bell);
});
connect(_emulation, &Konsole::Emulation::zmodemDownloadDetected, this, &Konsole::Session::fireZModemDownloadDetected);
connect(_emulation, &Konsole::Emulation::zmodemUploadDetected, this, &Konsole::Session::fireZModemUploadDetected);
connect(_emulation, &Konsole::Emulation::changeTabTextColorRequest, this, &Konsole::Session::changeTabTextColor);
......@@ -333,6 +336,8 @@ void Session::addView(TerminalDisplay* widget)
connect(_emulation, &Konsole::Emulation::setCursorStyleRequest, widget, &Konsole::TerminalDisplay::setCursorStyle);
connect(_emulation, &Konsole::Emulation::resetCursorStyleRequest, widget, &Konsole::TerminalDisplay::resetCursorStyle);
connect(widget, &Konsole::TerminalDisplay::keyPressedSignal, this, &Konsole::Session::resetNotifications);
}
void Session::viewDestroyed(QObject* view)
......@@ -617,7 +622,7 @@ void Session::silenceTimerDone()
//FIXME: Make message text for this notification and the activity notification more descriptive.
if (!_monitorSilence) {
emit stateChanged(NOTIFYNORMAL);
setPendingNotification(Notification::Silence, false);
return;
}
......@@ -633,7 +638,7 @@ void Session::silenceTimerDone()
i18n("Silence in session '%1'", _nameTitle), QPixmap(),
QApplication::activeWindow(),
KNotification::CloseWhenWidgetActivated);
emit stateChanged(NOTIFYSILENCE);
setPendingNotification(Notification::Silence);
}
void Session::activityTimerDone()
......@@ -641,6 +646,14 @@ void Session::activityTimerDone()
_notifiedActivity = false;
}
void Session::resetNotifications()
{
static const Notification availableNotifications[] = {Activity, Silence, Bell};
for (auto notification: availableNotifications) {
setPendingNotification(notification, false);
}
}
void Session::updateFlowControlState(bool suspended)
{
if (suspended) {
......@@ -688,50 +701,6 @@ void Session::sessionAttributeRequest(int id)
}
}
void Session::activityStateSet(int state)
{
// TODO: should this hardcoded interval be user configurable?
const int activityMaskInSeconds = 15;
if (state == NOTIFYBELL) {
emit bellRequest(i18n("Bell in session '%1'", _nameTitle));
} else if (state == NOTIFYACTIVITY) {
// Don't notify if the terminal is active
bool hasFocus = false;
for (const TerminalDisplay *display : qAsConst(_views)) {
if (display->hasFocus()) {
hasFocus = true;
break;
}
}
if (_monitorActivity && !_notifiedActivity) {
KNotification::event(hasFocus ? QStringLiteral("Activity") : QStringLiteral("ActivityHidden"),
i18n("Activity in session '%1'", _nameTitle), QPixmap(),
QApplication::activeWindow(),
KNotification::CloseWhenWidgetActivated);
// mask activity notification for a while to avoid flooding
_notifiedActivity = true;
_activityTimer->start(activityMaskInSeconds * 1000);
}
// reset the counter for monitoring continuous silence since there is activity
if (_monitorSilence) {
_silenceTimer->start(_silenceSeconds * 1000);
}
}
if (state == NOTIFYACTIVITY && !_monitorActivity) {
state = NOTIFYNORMAL;
}
if (state == NOTIFYSILENCE && !_monitorSilence) {
state = NOTIFYNORMAL;
}
emit stateChanged(state);
}
void Session::onViewSizeChange(int /*height*/, int /*width*/)
{
updateTerminalSize();
......@@ -1305,7 +1274,7 @@ void Session::setMonitorActivity(bool monitor)
// This timer is meaningful only after activity has been notified
_activityTimer->stop();
activityStateSet(NOTIFYNORMAL);
setPendingNotification(Notification::Activity, false);
}
void Session::setMonitorSilence(bool monitor)
......@@ -1321,7 +1290,7 @@ void Session::setMonitorSilence(bool monitor)
_silenceTimer->stop();
}
activityStateSet(NOTIFYNORMAL);
setPendingNotification(Notification::Silence, false);
}
void Session::setMonitorSilenceSeconds(int seconds)
......@@ -1495,6 +1464,7 @@ void Session::zmodemFinished()
void Session::onReceiveBlock(const char* buf, int len)
{
handleActivity();
_emulation->receiveData(buf, len);
}
......@@ -1710,6 +1680,50 @@ QString Session::validDirectory(const QString& dir) const
return validDir;
}
void Session::setPendingNotification(Session::Notification notification, bool enable)
{
if(enable != _activeNotifications.testFlag(notification)) {
_activeNotifications.setFlag(notification, enable);
emit notificationsChanged(notification, enable);
}
}
void Session::handleActivity()
{
// TODO: should this hardcoded interval be user configurable?
const int activityMaskInSeconds = 15;
bool hasFocus = false;
// Don't notify if the terminal is active
const auto &displays = _views;
for (const TerminalDisplay *display: displays) {
if (display->hasFocus()) {
hasFocus = true;
break;
}
}
if (_monitorActivity && !_notifiedActivity) {
KNotification::event(hasFocus ? QStringLiteral("Activity") : QStringLiteral("ActivityHidden"),
i18n("Activity in session '%1'", _nameTitle), QPixmap(),
QApplication::activeWindow(),
KNotification::CloseWhenWidgetActivated);
// mask activity notification for a while to avoid flooding
_notifiedActivity = true;
_activityTimer->start(activityMaskInSeconds * 1000);
}
// reset the counter for monitoring continuous silence since there is activity
if (_monitorSilence) {
_silenceTimer->start(_silenceSeconds * 1000);
}
if (_monitorActivity) {
setPendingNotification(Notification::Activity);
}
}
bool Session::isReadOnly() const
{
return _readOnly;
......
......@@ -384,6 +384,17 @@ public:
bool isPrimaryScreen();
void tabTitleSetByUser(bool set);
enum Notification {
NoNotification = 0,
Activity = 1,
Silence = 2,
Bell = 4,
};
Q_DECLARE_FLAGS(Notifications, Notification)
/** Returns active notifications. */
Notifications activeNotifications() const { return _activeNotifications; }
public Q_SLOTS:
/**
......@@ -619,14 +630,6 @@ Q_SIGNALS:
/** Emitted when the session gets locked / unlocked. */
void readOnlyChanged();
/**
* 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 the current working directory of this session changes.
*
......@@ -637,6 +640,8 @@ Q_SIGNALS:
/** Emitted when a bell event occurs in the session. */
void bellRequest(const QString &message);
/** Emitted when @p notification state changed to @p enabled */
void notificationsChanged(Notification notification, bool enabled);
/**
* Requests that the background color of views on this session
......@@ -723,11 +728,10 @@ private Q_SLOTS:
void onReceiveBlock(const char *buf, int len);
void silenceTimerDone();
void activityTimerDone();
void resetNotifications();
void onViewSizeChange(int height, int width);
void activityStateSet(int);
//automatically detach views from sessions when view is destroyed
void viewDestroyed(QObject *view);
......@@ -788,6 +792,11 @@ private:
QTimer *_silenceTimer;
QTimer *_activityTimer;
void setPendingNotification(Notification notification, bool enable = true);
void handleActivity();
Notifications _activeNotifications;
bool _autoClose;
bool _closePerUserRequest;
......
......@@ -167,7 +167,7 @@ SessionController::SessionController(Session* session , TerminalDisplay* view, Q
connect(_view.data(), &Konsole::TerminalDisplay::keyPressedSignal, this, &Konsole::SessionController::trackOutput);
// listen to activity / silence notifications from session
connect(_session.data(), &Konsole::Session::stateChanged, this, &Konsole::SessionController::sessionStateChanged);
connect(_session.data(), &Konsole::Session::notificationsChanged, this, &Konsole::SessionController::sessionNotificationsChanged);
// listen to title and icon changes
connect(_session.data(), &Konsole::Session::sessionAttributeChanged, this, &Konsole::SessionController::sessionAttributeChanged);
connect(_session.data(), &Konsole::Session::readOnlyChanged, this, &Konsole::SessionController::sessionReadOnlyChanged);
......@@ -1741,26 +1741,21 @@ void SessionController::movementKeyFromSearchBarReceived(QKeyEvent *event)
setSearchStartToWindowCurrentLine();
}
void SessionController::sessionStateChanged(int state)
void SessionController::sessionNotificationsChanged(Session::Notification notification, bool enabled)
{
if (state == _previousState) {
return;
}
if (state == NOTIFYACTIVITY) {
if (notification == Session::Notification::Activity && enabled) {
setIcon(*_activityIcon);
_keepIconUntilInteraction = true;
} else if (state == NOTIFYSILENCE) {
} else if (notification == Session::Notification::Silence && enabled) {
setIcon(*_silenceIcon);
_keepIconUntilInteraction = true;
} else if (state == NOTIFYBELL) {
} else if (notification == Session::Notification::Bell && enabled) {
setIcon(*_bellIcon);
_keepIconUntilInteraction = true;
} else if (state == NOTIFYNORMAL) {
} else {
updateSessionIcon();
}
_previousState = state;
emit notificationChanged(this, notification, enabled);
}
void SessionController::zmodemDownload()
......
......@@ -34,6 +34,7 @@
#include "ViewProperties.h"
#include "Profile.h"
#include "Enumeration.h"
#include "Session.h"
class QAction;
class QTextCodec;
......@@ -255,7 +256,7 @@ private Q_SLOTS:
void updateCodecAction();
void showDisplayContextMenu(const QPoint &position);
void movementKeyFromSearchBarReceived(QKeyEvent *event);
void sessionStateChanged(int state);
void sessionNotificationsChanged(Session::Notification notification, bool enabled);
void sessionAttributeChanged();
void sessionReadOnlyChanged();
void searchTextChanged(const QString &text);
......
......@@ -28,6 +28,7 @@
// Konsole
#include "konsoleprivate_export.h"
#include "Session.h"
namespace Konsole {
/**
......@@ -89,6 +90,8 @@ Q_SIGNALS:
void titleChanged(ViewProperties *properties);
/** Emitted when activity has occurred in this view. */
void activity(ViewProperties *item);
/** Emitted when notification for a view changes */
void notificationChanged(ViewProperties *item, Session::Notification notification, bool enabled);
public Q_SLOTS:
/**
......
......@@ -564,7 +564,7 @@ void Vt102Emulation::processToken(int token, int p, int q)
case token_ctl('D' ) : /* EOT: ignored */ break;
case token_ctl('E' ) : reportAnswerBack ( ); break; //VT100
case token_ctl('F' ) : /* ACK: ignored */ break;
case token_ctl('G' ) : emit stateSet(NOTIFYBELL);
case token_ctl('G' ) : emit bell();
break; //VT100
case token_ctl('H' ) : _currentScreen->backspace ( ); break; //VT100
case token_ctl('I' ) : _currentScreen->tab ( ); break; //VT100
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment