IrcUser: Use QDateTime for lastAwayMessage, not int
authorMichael Marley <michael@michaelmarley.com>
Thu, 10 May 2018 18:32:31 +0000 (14:32 -0400)
committerManuel Nickschas <sputnick@quassel-irc.org>
Wed, 23 May 2018 22:33:28 +0000 (00:33 +0200)
This converts the lastAwayTime to a 64-bit time.  Backwards-
compatibility is also included in Network to convert back and forth
between the old 32-bit type for legacy peers.  No backwards-
compatibility is provided for the SYNC call because the value is
never actually used in any existing clients.  New clients that want
to implement this functionality would need to implement the
LongTime feature.

src/common/ircuser.cpp
src/common/ircuser.h
src/common/network.cpp
src/core/eventstringifier.cpp

index 6c10cf4..3cde7e7 100644 (file)
@@ -40,7 +40,7 @@ IrcUser::IrcUser(const QString &hostmask, Network *network) : SyncableObject(net
     _server(),
     // _idleTime(QDateTime::currentDateTime()),
     _ircOperator(),
-    _lastAwayMessage(0),
+    _lastAwayMessage(),
     _whoisServiceReply(),
     _encrypted(false),
     _network(network),
@@ -48,6 +48,8 @@ IrcUser::IrcUser(const QString &hostmask, Network *network) : SyncableObject(net
     _codecForDecoding(0)
 {
     updateObjectName();
+    _lastAwayMessage.setTimeSpec(Qt::UTC);
+    _lastAwayMessage.setMSecsSinceEpoch(0);
 }
 
 
@@ -215,7 +217,7 @@ void IrcUser::setIrcOperator(const QString &ircOperator)
 }
 
 
-void IrcUser::setLastAwayMessage(const int &lastAwayMessage)
+void IrcUser::setLastAwayMessage(const QDateTime &lastAwayMessage)
 {
     if (lastAwayMessage > _lastAwayMessage) {
         _lastAwayMessage = lastAwayMessage;
index 4aa2bf5..25d32a3 100644 (file)
@@ -50,7 +50,7 @@ class IrcUser : public SyncableObject
     Q_PROPERTY(QDateTime loginTime READ loginTime WRITE setLoginTime)
     Q_PROPERTY(QString server READ server WRITE setServer)
     Q_PROPERTY(QString ircOperator READ ircOperator WRITE setIrcOperator)
-    Q_PROPERTY(int lastAwayMessage READ lastAwayMessage WRITE setLastAwayMessage)
+    Q_PROPERTY(QDateTime lastAwayMessage READ lastAwayMessage WRITE setLastAwayMessage)
     Q_PROPERTY(QString whoisServiceReply READ whoisServiceReply WRITE setWhoisServiceReply)
     Q_PROPERTY(QString suserHost READ suserHost WRITE setSuserHost)
     Q_PROPERTY(bool encrypted READ encrypted WRITE setEncrypted)
@@ -79,7 +79,7 @@ public :
     inline QDateTime loginTime() const { return _loginTime; }
     inline QString server() const { return _server; }
     inline QString ircOperator() const { return _ircOperator; }
-    inline int lastAwayMessage() const { return _lastAwayMessage; }
+    inline QDateTime lastAwayMessage() const { return _lastAwayMessage; }
     inline QString whoisServiceReply() const { return _whoisServiceReply; }
     inline QString suserHost() const { return _suserHost; }
     inline bool encrypted() const { return _encrypted; }
@@ -123,7 +123,7 @@ public slots:
     void setLoginTime(const QDateTime &loginTime);
     void setServer(const QString &server);
     void setIrcOperator(const QString &ircOperator);
-    void setLastAwayMessage(const int &lastAwayMessage);
+    void setLastAwayMessage(const QDateTime &lastAwayMessage);
     void setWhoisServiceReply(const QString &whoisServiceReply);
     void setSuserHost(const QString &suserHost);
     void setEncrypted(bool encrypted);
@@ -156,7 +156,7 @@ signals:
 //   void loginTimeSet(QDateTime loginTime);
 //   void serverSet(QString server);
 //   void ircOperatorSet(QString ircOperator);
-//   void lastAwayMessageSet(int lastAwayMessage);
+//   void lastAwayMessageSet(QDateTime lastAwayMessage);
 //   void whoisServiceReplySet(QString whoisServiceReply);
 //   void suserHostSet(QString suserHost);
     void encryptedSet(bool encrypted);
@@ -203,7 +203,7 @@ private:
     QDateTime _idleTimeSet;
     QDateTime _loginTime;
     QString _ircOperator;
-    int _lastAwayMessage;
+    QDateTime _lastAwayMessage;
     QString _whoisServiceReply;
     QString _suserHost;
     bool _encrypted;
index 40040af..c4019cc 100644 (file)
@@ -21,6 +21,7 @@
 #include <QTextCodec>
 
 #include "network.h"
+#include "peer.h"
 
 QTextCodec *Network::_defaultCodecForServer = 0;
 QTextCodec *Network::_defaultCodecForEncoding = 0;
@@ -881,6 +882,8 @@ QVariantMap Network::initCaps() const
 // (without compression) with a decent amount of IrcUsers.
 QVariantMap Network::initIrcUsersAndChannels() const
 {
+    Q_ASSERT(proxy());
+    Q_ASSERT(proxy()->targetPeer());
     QVariantMap usersAndChannels;
 
     if (_ircUsers.count()) {
@@ -888,7 +891,20 @@ QVariantMap Network::initIrcUsersAndChannels() const
         QHash<QString, IrcUser *>::const_iterator it = _ircUsers.begin();
         QHash<QString, IrcUser *>::const_iterator end = _ircUsers.end();
         while (it != end) {
-            const QVariantMap &map = it.value()->toVariantMap();
+            QVariantMap map = it.value()->toVariantMap();
+            // If the peer doesn't support LongTime, replace the lastAwayMessage field
+            // with the 32-bit numerical seconds value used in older versions
+            if (!proxy()->targetPeer()->hasFeature(Quassel::Feature::LongTime)) {
+#if QT_VERSION >= 0x050800
+                int lastAwayMessage = it.value()->lastAwayMessage().toSecsSinceEpoch();
+#else
+                // toSecsSinceEpoch() was added in Qt 5.8.  Manually downconvert to seconds for now.
+                // See https://doc.qt.io/qt-5/qdatetime.html#toMSecsSinceEpoch
+                int lastAwayMessage = it.value()->lastAwayMessage().toMSecsSinceEpoch() / 1000;
+#endif
+                map["lastAwayMessage"] = lastAwayMessage;
+            }
+
             QVariantMap::const_iterator mapiter = map.begin();
             while (mapiter != map.end()) {
                 users[mapiter.key()] << mapiter.value();
@@ -930,6 +946,7 @@ QVariantMap Network::initIrcUsersAndChannels() const
 void Network::initSetIrcUsersAndChannels(const QVariantMap &usersAndChannels)
 {
     Q_ASSERT(proxy());
+    Q_ASSERT(proxy()->sourcePeer());
     if (isInitialized()) {
         qWarning() << "Network" << networkId() << "received init data for users and channels although there already are known users or channels!";
         return;
@@ -954,6 +971,22 @@ void Network::initSetIrcUsersAndChannels(const QVariantMap &usersAndChannels)
         QVariantMap map;
         foreach(const QString &key, users.keys())
             map[key] = users[key].toList().at(i);
+
+        // If the peer doesn't support LongTime, upconvert the lastAwayMessage field
+        // from the 32-bit numerical seconds value used in older versions to QDateTime
+        if (!proxy()->sourcePeer()->hasFeature(Quassel::Feature::LongTime)) {
+            QDateTime lastAwayMessage = QDateTime();
+            lastAwayMessage.setTimeSpec(Qt::UTC);
+#if QT_VERSION >= 0x050800
+            lastAwayMessage.fromSecsSinceEpoch(map["lastAwayMessage"].toInt());
+#else
+            // toSecsSinceEpoch() was added in Qt 5.8.  Manually downconvert to seconds for now.
+            // See https://doc.qt.io/qt-5/qdatetime.html#toMSecsSinceEpoch
+            lastAwayMessage.fromMSecsSinceEpoch(map["lastAwayMessage"].toInt() * 1000);
+#endif
+            map["lastAwayMessage"] = lastAwayMessage;
+        }
+
         newIrcUser(map["nick"].toString(), map); // newIrcUser() properly handles the hostmask being just the nick
     }
 
index c1279ff..725268c 100644 (file)
@@ -449,13 +449,11 @@ void EventStringifier::processIrcEvent301(IrcEvent *e)
         target = nick;
         IrcUser *ircuser = e->network()->ircUser(nick);
         if (ircuser) {
-            // FIXME: This needs converted to 64-bit time.
-            // For legacy protocol, keep the 32-bit signed int time.  For modern protocol, just send
-            // the actual QDateTime() instead, don't bother converting it.
-            int now = QDateTime::currentDateTime().toTime_t();
-            // FIXME: Convert to millisecond comparison, comment the constant value as needed
+            QDateTime now = QDateTime::currentDateTime();
+            now.setTimeSpec(Qt::UTC);
+            // Don't print "user is away" messages more often than this
             const int silenceTime = 60;
-            if (ircuser->lastAwayMessage() + silenceTime >= now)
+            if (ircuser->lastAwayMessage().addSecs(silenceTime) >= now)
                 send = false;
             ircuser->setLastAwayMessage(now);
         }