+#include "network.h"
+#include "signalproxy.h"
+#include "ircchannel.h"
+
+#include <QTextCodec>
+#include <QDebug>
+
+INIT_SYNCABLE_OBJECT(IrcUser)
+IrcUser::IrcUser(const QString &hostmask, Network *network) : SyncableObject(network),
+ _initialized(false),
+ _nick(nickFromMask(hostmask)),
+ _user(userFromMask(hostmask)),
+ _host(hostFromMask(hostmask)),
+ _realName(),
+ _awayMessage(),
+ _away(false),
+ _server(),
+ // _idleTime(QDateTime::currentDateTime()),
+ _ircOperator(),
+ _lastAwayMessageTime(),
+ _whoisServiceReply(),
+ _encrypted(false),
+ _network(network),
+ _codecForEncoding(0),
+ _codecForDecoding(0)
+{
+ updateObjectName();
+ _lastAwayMessageTime.setTimeSpec(Qt::UTC);
+ _lastAwayMessageTime.setMSecsSinceEpoch(0);
+}
+
+
+IrcUser::~IrcUser()
+{
+}
+
+
+// ====================
+// PUBLIC:
+// ====================
+
+QString IrcUser::hostmask() const
+{
+ return QString("%1!%2@%3").arg(nick()).arg(user()).arg(host());
+}
+
+
+QDateTime IrcUser::idleTime()
+{
+ if ((QDateTime::currentDateTime().toMSecsSinceEpoch() - _idleTimeSet.toMSecsSinceEpoch())
+ > 1200000) {
+ // 20 * 60 * 1000 = 1200000
+ // 20 minutes have elapsed, clear the known idle time as it's likely inaccurate by now
+ _idleTime = QDateTime();
+ }
+ return _idleTime;
+}
+
+
+QStringList IrcUser::channels() const
+{
+ QStringList chanList;
+ IrcChannel *channel;
+ foreach(channel, _channels) {
+ chanList << channel->name();
+ }
+ return chanList;
+}
+
+
+void IrcUser::setCodecForEncoding(const QString &name)
+{
+ setCodecForEncoding(QTextCodec::codecForName(name.toLatin1()));
+}
+
+
+void IrcUser::setCodecForEncoding(QTextCodec *codec)
+{
+ _codecForEncoding = codec;
+}
+
+
+void IrcUser::setCodecForDecoding(const QString &name)
+{
+ setCodecForDecoding(QTextCodec::codecForName(name.toLatin1()));
+}
+
+
+void IrcUser::setCodecForDecoding(QTextCodec *codec)
+{
+ _codecForDecoding = codec;
+}
+
+
+QString IrcUser::decodeString(const QByteArray &text) const
+{
+ if (!codecForDecoding()) return network()->decodeString(text);
+ return ::decodeString(text, codecForDecoding());
+}
+
+
+QByteArray IrcUser::encodeString(const QString &string) const
+{
+ if (codecForEncoding()) {
+ return codecForEncoding()->fromUnicode(string);
+ }
+ return network()->encodeString(string);
+}
+
+
+// ====================
+// PUBLIC SLOTS:
+// ====================
+void IrcUser::setUser(const QString &user)
+{
+ if (!user.isEmpty() && _user != user) {
+ _user = user;
+ SYNC(ARG(user));
+ }
+}
+
+
+void IrcUser::setRealName(const QString &realName)
+{
+ if (!realName.isEmpty() && _realName != realName) {
+ _realName = realName;
+ SYNC(ARG(realName))
+ }
+}
+
+
+void IrcUser::setAccount(const QString &account)
+{
+ if (_account != account) {
+ _account = account;
+ SYNC(ARG(account))
+ }
+}
+
+
+void IrcUser::setAway(bool away)
+{
+ if (away != _away) {
+ _away = away;
+ markAwayChanged();
+ SYNC(ARG(away))
+ emit awaySet(away);
+ }
+}
+
+
+void IrcUser::setAwayMessage(const QString &awayMessage)
+{
+ if (!awayMessage.isEmpty() && _awayMessage != awayMessage) {
+ _awayMessage = awayMessage;
+ markAwayChanged();
+ SYNC(ARG(awayMessage))
+ }
+}
+
+
+void IrcUser::setIdleTime(const QDateTime &idleTime)
+{
+ if (idleTime.isValid() && _idleTime != idleTime) {
+ _idleTime = idleTime;
+ _idleTimeSet = QDateTime::currentDateTime();
+ SYNC(ARG(idleTime))
+ }
+}
+
+
+void IrcUser::setLoginTime(const QDateTime &loginTime)
+{
+ if (loginTime.isValid() && _loginTime != loginTime) {
+ _loginTime = loginTime;
+ SYNC(ARG(loginTime))
+ }
+}
+
+
+void IrcUser::setServer(const QString &server)
+{
+ if (!server.isEmpty() && _server != server) {
+ _server = server;
+ SYNC(ARG(server))
+ }
+}
+
+
+void IrcUser::setIrcOperator(const QString &ircOperator)
+{
+ if (!ircOperator.isEmpty() && _ircOperator != ircOperator) {
+ _ircOperator = ircOperator;
+ SYNC(ARG(ircOperator))
+ }
+}
+
+
+// This function is only ever called by SYNC calls from legacy cores (pre-0.13).
+// Therefore, no SYNC call is needed here.
+void IrcUser::setLastAwayMessage(int lastAwayMessage)
+{
+#if QT_VERSION >= 0x050800
+ QDateTime lastAwayMessageTime = QDateTime::fromSecsSinceEpoch(lastAwayMessage);
+#else
+ // toSecsSinceEpoch() was added in Qt 5.8. Manually downconvert to seconds for now.
+ // See https://doc.qt.io/qt-5/qdatetime.html#toMSecsSinceEpoch
+ QDateTime lastAwayMessageTime = QDateTime::fromMSecsSinceEpoch(lastAwayMessage * 1000);
+#endif
+ lastAwayMessageTime.setTimeSpec(Qt::UTC);
+ setLastAwayMessageTime(lastAwayMessageTime);
+}
+
+
+void IrcUser::setLastAwayMessageTime(const QDateTime &lastAwayMessageTime)
+{
+ if (lastAwayMessageTime > _lastAwayMessageTime) {
+ _lastAwayMessageTime = lastAwayMessageTime;
+ SYNC(ARG(lastAwayMessageTime))
+ }