useSsl = _account.useSsl();
#endif
- _peer->dispatch(RegisterClient(Quassel::buildInfo().fancyVersionString, Quassel::buildInfo().commitDate, useSsl));
+ _peer->dispatch(RegisterClient(Quassel::buildInfo().fancyVersionString, Quassel::buildInfo().commitDate, useSsl, Quassel::features()));
}
_backendInfo = msg.backendInfo;
_authenticatorInfo = msg.authenticatorInfo;
- Client::setCoreFeatures(static_cast<Quassel::Features>(msg.coreFeatures));
+ Client::setCoreFeatures(Quassel::Features(msg.coreFeatures));
+ SignalProxy::current()->sourcePeer()->setFeatures(Quassel::Features(msg.coreFeatures));
// The legacy protocol enables SSL at this point
if(_legacy && _account.useSsl())
#include "message.h"
#include "util.h"
+#include "signalproxy.h"
+#include "peer.h"
#include <QDataStream>
QDataStream &operator<<(QDataStream &out, const Message &msg)
{
// We do not serialize the sender prefixes until we have a new protocol or client-features implemented
- out << msg.msgId() << (quint32)msg.timestamp().toTime_t() << (quint32)msg.type() << (quint8)msg.flags()
- << msg.bufferInfo() << msg.sender().toUtf8() << msg.contents().toUtf8();
+ out << msg.msgId()
+ << (quint32) msg.timestamp().toTime_t()
+ << (quint32) msg.type()
+ << (quint8) msg.flags()
+ << msg.bufferInfo()
+ << msg.sender().toUtf8();
+
+ if (SignalProxy::current()->targetPeer()->features().testFlag(Quassel::Feature::SenderPrefixes))
+ out << msg.senderPrefixes().toUtf8();
+
+ out << msg.contents().toUtf8();
return out;
}
QDataStream &operator>>(QDataStream &in, Message &msg)
{
- quint8 f;
- quint32 t;
- quint32 ts;
- QByteArray s, m;
- BufferInfo buf;
- in >> msg._msgId >> ts >> t >> f >> buf >> s >> m;
- msg._type = (Message::Type)t;
- msg._flags = (Message::Flags)f;
- msg._bufferInfo = buf;
- msg._timestamp = QDateTime::fromTime_t(ts);
- msg._sender = QString::fromUtf8(s);
- // We do not serialize the sender prefixes until we have a new protocol or client-features implemented
- msg._senderPrefixes = QString("");
- msg._contents = QString::fromUtf8(m);
+ in >> msg._msgId;
+
+ quint32 timeStamp;
+ in >> timeStamp;
+ msg._timestamp = QDateTime::fromTime_t(timeStamp);
+
+ quint32 type;
+ in >> type;
+ msg._type = Message::Type(type);
+
+ quint8 flags;
+ in >> flags;
+ msg._flags = Message::Flags(flags);
+
+ in >> msg._bufferInfo;
+
+ QByteArray sender;
+ in >> sender;
+ msg._sender = QString::fromUtf8(sender);
+
+ QByteArray senderPrefixes;
+ if (SignalProxy::current()->sourcePeer()->features().testFlag(Quassel::Feature::SenderPrefixes))
+ in >> senderPrefixes;
+ msg._senderPrefixes = QString::fromUtf8(senderPrefixes);
+
+ QByteArray contents;
+ in >> contents;
+ msg._contents = QString::fromUtf8(contents);
+
return in;
}
_clientVersion = clientVersion;
}
+Quassel::Features Peer::features() const {
+ return _features;
+}
+
+void Peer::setFeatures(Quassel::Features features) {
+ _features = features;
+}
+
int Peer::id() const {
return _id;
}
#include "authhandler.h"
#include "protocol.h"
#include "signalproxy.h"
+#include "quassel.h"
class Peer : public QObject
{
QString clientVersion() const;
void setClientVersion(const QString &clientVersion);
+ Quassel::Features features() const;
+ void setFeatures(Quassel::Features features);
+
int id() const;
void setId(int id);
QString _buildDate;
QString _clientVersion;
+ Quassel::Features _features;
int _id = -1;
};
struct RegisterClient : public HandshakeMessage
{
- inline RegisterClient(const QString &clientVersion, const QString &buildDate, bool sslSupported = false)
+ inline RegisterClient(const QString &clientVersion, const QString &buildDate, bool sslSupported = false, int32_t features = 0)
: clientVersion(clientVersion)
, buildDate(buildDate)
- , sslSupported(sslSupported) {}
+ , sslSupported(sslSupported)
+ , clientFeatures(features) {}
QString clientVersion;
QString buildDate;
// this is only used by the LegacyProtocol in compat mode
bool sslSupported;
+ int32_t clientFeatures;
};
}
if (msgType == "ClientInit") {
- handle(RegisterClient(m["ClientVersion"].toString(), m["ClientDate"].toString(), false)); // UseSsl obsolete
+ handle(RegisterClient(m["ClientVersion"].toString(), m["ClientDate"].toString(), false, m["Features"].toInt())); // UseSsl obsolete
}
else if (msgType == "ClientInitReject") {
m["MsgType"] = "ClientInit";
m["ClientVersion"] = msg.clientVersion;
m["ClientDate"] = msg.buildDate;
+ m["Features"] = msg.clientFeatures;
writeMessage(m);
}
socket()->setProperty("UseCompression", true);
}
#endif
- handle(RegisterClient(m["ClientVersion"].toString(), m["ClientDate"].toString(), m["UseSsl"].toBool()));
+ handle(RegisterClient(m["ClientVersion"].toString(), m["ClientDate"].toString(), m["UseSsl"].toBool(), m["Features"].toInt()));
}
else if (msgType == "ClientInitReject") {
m["MsgType"] = "ClientInit";
m["ClientVersion"] = msg.clientVersion;
m["ClientDate"] = msg.buildDate;
+ m["Features"] = msg.clientFeatures;
// FIXME only in compat mode
m["ProtocolVersion"] = protocolVersion;
Authenticators = 0x0400, /// Whether or not the core supports auth backends.
BufferActivitySync = 0x0800, /// Sync buffer activity status
CoreSideHighlights = 0x1000, /// Core-Side highlight configuration and matching
+ SenderPrefixes = 0x2000, /// Show prefixes for senders in backlog
- NumFeatures = 0x1000
+ NumFeatures = 0x2000
};
Q_DECLARE_FLAGS(Features, Feature)
void RemotePeer::onReadyRead()
{
QByteArray msg;
- while (readMessage(msg))
+ while (readMessage(msg)) {
+ if (SignalProxy::current())
+ SignalProxy::current()->setSourcePeer(this);
+
processMessage(msg);
+
+
+ if (SignalProxy::current())
+ SignalProxy::current()->setSourcePeer(nullptr);
+ }
}
initClient();
}
+thread_local SignalProxy *SignalProxy::_current;
+
void SignalProxy::init()
{
setHeartBeatInterval(30);
setMaxHeartBeatCount(2);
_secure = false;
+ _current = this;
updateSecureState();
}
void SignalProxy::dispatch(const T &protoMessage)
{
for (auto peer : _peerMap.values()) {
+ _targetPeer = peer;
+
if (peer->isOpen())
peer->dispatch(protoMessage);
else
QCoreApplication::postEvent(this, new ::RemovePeerEvent(peer));
}
+ _targetPeer = nullptr;
}
template<class T>
void SignalProxy::dispatch(Peer *peer, const T &protoMessage)
{
+ _targetPeer = peer;
+
if (peer && peer->isOpen())
peer->dispatch(protoMessage);
else
QCoreApplication::postEvent(this, new ::RemovePeerEvent(peer));
+
+ _targetPeer = nullptr;
}
if (eMeta->argTypes(receiverId).count() > 1)
returnParams << syncMessage.params;
returnParams << returnValue;
+ _targetPeer = peer;
peer->dispatch(SyncMessage(syncMessage.className, syncMessage.objectName, eMeta->methodName(receiverId), returnParams));
+ _targetPeer = nullptr;
}
// send emit update signal
}
SyncableObject *obj = _syncSlave[initRequest.className][initRequest.objectName];
+ _targetPeer = peer;
peer->dispatch(InitData(initRequest.className, initRequest.objectName, initData(obj)));
+ _targetPeer = nullptr;
}
_restrictedTargets = previousRestrictedTargets;
}
+Peer *SignalProxy::sourcePeer() {
+ return _sourcePeer;
+}
+
+void SignalProxy::setSourcePeer(Peer *sourcePeer) {
+ _sourcePeer = sourcePeer;
+}
+
+Peer *SignalProxy::targetPeer() {
+ return _targetPeer;
+}
+
+void SignalProxy::setTargetPeer(Peer *targetPeer) {
+ _targetPeer = targetPeer;
+}
+
// ==================================================
// ExtendedMetaObject
// ==================================================
#include <QEvent>
#include <QSet>
+#include <QThreadStorage>
#include <functional>
+#include <memory>
#include "protocol.h"
void dumpProxyStats();
void dumpSyncMap(SyncableObject *object);
+ static SignalProxy *current() {
+ return _current;
+ }
+
/**@{*/
/**
* This method allows to send a signal only to a limited set of peers
/**
* @return If handling a signal, the Peer from which the current signal originates
*/
- Peer *sourcePeer() { return _sourcePeer; }
+ Peer *sourcePeer();
+ void setSourcePeer(Peer *sourcePeer);
+
+ /**
+ * @return If sending a signal, the Peer to which the current signal is directed
+ */
+ Peer *targetPeer();
+ void setTargetPeer(Peer *targetPeer);
public slots:
void detachObject(QObject *obj);
bool _restrictMessageTarget = false;
Peer *_sourcePeer = nullptr;
+ Peer *_targetPeer = nullptr;
+
+ thread_local static SignalProxy *_current;
friend class SignalRelay;
friend class SyncableObject;
_peer->setBuildDate(msg.buildDate);
_peer->setClientVersion(msg.clientVersion);
+ _peer->setFeatures(Quassel::Features(msg.clientFeatures));
if (_legacy && useSsl)
startSsl();
*/
inline void setTimestampFormatString(const QString &format) { setLocalValue("TimestampFormat", format); }
+ /**
+ * Gets if prefixmodes are shown before sender names
+ *
+ * @returns True if sender prefixmodes enabled, otherwise false
+ */
+ inline bool showSenderPrefixes() { return localValue("ShowSenderPrefixes", false).toBool(); }
+
/**
* Gets if brackets are shown around sender names
*
updateUseCustomTimestampFormat();
s.notify("TimestampFormat", this, SLOT(updateTimestampFormatString()));
updateTimestampFormatString();
+ s.notify("ShowSenderPrefixes", this, SLOT(updateShowSenderPrefixes()));
+ updateShowSenderPrefixes();
s.notify("ShowSenderBrackets", this, SLOT(updateShowSenderBrackets()));
updateShowSenderBrackets();
setTimestampFormatString(s.timestampFormatString());
}
+void QtUiStyle::updateShowSenderPrefixes()
+{
+ ChatViewSettings s;
+ enableSenderPrefixes(s.showSenderPrefixes());
+}
+
void QtUiStyle::updateShowSenderBrackets()
{
ChatViewSettings s;
* Updates knowledge of the current timestamp format
*/
void updateTimestampFormatString();
+
+ /**
+ * Updates knowledge of whether or not to show sender prefixmodes
+ */
+ void updateShowSenderPrefixes();
/**
* Updates knowledge of whether or not to show sender brackets
</property>
</widget>
</item>
+ <item>
+ <widget class="QCheckBox" name="showSenderPrefixes">
+ <property name="toolTip">
+ <string>Shows the modes of senders before their name (e.g. @, +)</string>
+ </property>
+ <property name="text">
+ <string>Show sendermodes in front of nicknames:</string>
+ </property>
+ <property name="checked">
+ <bool>true</bool>
+ </property>
+ <property name="defaultValue" stdset="0">
+ <bool>true</bool>
+ </property>
+ <property name="settingsKey" stdset="0">
+ <string notr="true">ShowSenderPrefixes</string>
+ </property>
+ </widget>
+ </item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_3">
<item>
bool UiStyle::_useCustomTimestampFormat; /// If true, use the custom timestamp format
QString UiStyle::_timestampFormatString; /// Timestamp format
QString UiStyle::_systemTimestampFormatString; /// Cached copy of system locale timestamp format
+bool UiStyle::_showSenderPrefixes; /// If true, show prefixmodes before sender names
bool UiStyle::_showSenderBrackets; /// If true, show brackets around sender names
UiStyle::UiStyle(QObject *parent)
// in there.
setUseCustomTimestampFormat(false);
setTimestampFormatString(" hh:mm:ss");
+ enableSenderPrefixes(false);
enableSenderBrackets(true);
// BufferView / NickView settings
}
}
+void UiStyle::enableSenderPrefixes(bool enabled)
+{
+ if (_showSenderPrefixes != enabled) {
+ _showSenderPrefixes = enabled;
+ }
+}
+
void UiStyle::enableSenderBrackets(bool enabled)
{
if (_showSenderBrackets != enabled) {
QString UiStyle::StyledMessage::decoratedSender() const
{
+ QString _senderPrefixes;
+ if (_showSenderPrefixes) {
+ _senderPrefixes = senderPrefixes();
+ }
+
switch (type()) {
case Message::Plain:
if (_showSenderBrackets)
- return QString("<%1>").arg(plainSender());
+ return QString("<%1%2>").arg(_senderPrefixes, plainSender());
else
- return QString("%1").arg(plainSender());
+ return QString("%1%2").arg(_senderPrefixes, plainSender());
break;
case Message::Notice:
- return QString("[%1]").arg(plainSender()); break;
+ return QString("[%1%2]").arg(_senderPrefixes, plainSender()); break;
case Message::Action:
return "-*-"; break;
case Message::Nick:
case Message::Invite:
return "->"; break;
default:
- return QString("%1").arg(plainSender());
+ return QString("%1%2").arg(_senderPrefixes, plainSender());
}
}
* @param[in] format Timestamp format string
*/
static void setTimestampFormatString(const QString &format);
+ /**
+ * Updates the local setting cache of whether or not to show sender prefixmodes
+ *
+ * @param[in] enabled If true, sender prefixmodes are enabled, otherwise false.
+ */
+ static void enableSenderPrefixes(bool enabled);
/**
* Updates the local setting cache of whether or not to show sender brackets
static bool _useCustomTimestampFormat; /// If true, use the custom timestamp format
static QString _systemTimestampFormatString; /// Cached copy of system locale timestamp format
static QString _timestampFormatString; /// Timestamp format string
+ static bool _showSenderPrefixes; /// If true, show prefixmodes before sender names
static bool _showSenderBrackets; /// If true, show brackets around sender names
QIcon _channelJoinedIcon;