mirror of
https://github.com/qTox/qTox.git
synced 2024-03-22 14:00:36 +08:00
Merge branch 'pr1117'
This commit is contained in:
commit
94e30b9e2d
6
qtox.pro
6
qtox.pro
|
@ -234,7 +234,8 @@ HEADERS += src/widget/form/addfriendform.h \
|
|||
src/widget/systemtrayicon_private.h \
|
||||
src/nexus.h \
|
||||
src/widget/gui.h \
|
||||
src/widget/androidgui.h
|
||||
src/widget/androidgui.h \
|
||||
src/offlinemsgengine.h
|
||||
|
||||
SOURCES += \
|
||||
src/widget/form/addfriendform.cpp \
|
||||
|
@ -306,7 +307,8 @@ SOURCES += \
|
|||
src/widget/systemtrayicon.cpp \
|
||||
src/nexus.cpp \
|
||||
src/widget/gui.cpp \
|
||||
src/widget/androidgui.cpp
|
||||
src/widget/androidgui.cpp \
|
||||
src/offlinemsgengine.cpp
|
||||
|
||||
contains(DEFINES, QTOX_FILTER_AUDIO) {
|
||||
HEADERS += src/audiofilterer.h
|
||||
|
|
121
src/offlinemsgengine.cpp
Normal file
121
src/offlinemsgengine.cpp
Normal file
|
@ -0,0 +1,121 @@
|
|||
/*
|
||||
Copyright (C) 2015 by Project Tox <https://tox.im>
|
||||
|
||||
This file is part of qTox, a Qt-based graphical interface for Tox.
|
||||
|
||||
This program is libre software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
|
||||
See the COPYING file for more details.
|
||||
*/
|
||||
|
||||
#include "offlinemsgengine.h"
|
||||
#include "src/friend.h"
|
||||
#include "src/historykeeper.h"
|
||||
#include "src/misc/settings.h"
|
||||
#include "src/core.h"
|
||||
#include <QMutexLocker>
|
||||
#include <QTimer>
|
||||
|
||||
const int OfflineMsgEngine::offlineTimeout = 2000;
|
||||
QSet<OfflineMsgEngine*> OfflineMsgEngine::engines;
|
||||
QMutex OfflineMsgEngine::globalMutex;
|
||||
|
||||
OfflineMsgEngine::OfflineMsgEngine(Friend *frnd) :
|
||||
mutex(QMutex::Recursive),
|
||||
f(frnd)
|
||||
{
|
||||
engines.insert(this);
|
||||
}
|
||||
|
||||
OfflineMsgEngine::~OfflineMsgEngine()
|
||||
{
|
||||
engines.remove(this);
|
||||
}
|
||||
|
||||
void OfflineMsgEngine::dischargeReceipt(int receipt)
|
||||
{
|
||||
QMutexLocker ml(&mutex);
|
||||
|
||||
auto it = receipts.find(receipt);
|
||||
if (it != receipts.end())
|
||||
{
|
||||
int mID = it.value();
|
||||
auto msgIt = undeliveredMsgs.find(mID);
|
||||
if (msgIt != undeliveredMsgs.end())
|
||||
{
|
||||
HistoryKeeper::getInstance()->markAsSent(mID);
|
||||
msgIt.value().msg->markAsSent();
|
||||
msgIt.value().msg->featureUpdate();
|
||||
undeliveredMsgs.erase(msgIt);
|
||||
}
|
||||
receipts.erase(it);
|
||||
}
|
||||
}
|
||||
|
||||
void OfflineMsgEngine::registerReceipt(int receipt, int messageID, MessageActionPtr msg, const QDateTime ×tamp)
|
||||
{
|
||||
QMutexLocker ml(&mutex);
|
||||
|
||||
receipts[receipt] = messageID;
|
||||
undeliveredMsgs[messageID] = {msg, timestamp, receipt};
|
||||
}
|
||||
|
||||
void OfflineMsgEngine::deliverOfflineMsgs()
|
||||
{
|
||||
QMutexLocker ml(&mutex);
|
||||
|
||||
if (!Settings::getInstance().getFauxOfflineMessaging())
|
||||
return;
|
||||
|
||||
if (f->getStatus() == Status::Offline)
|
||||
return;
|
||||
|
||||
if (undeliveredMsgs.size() == 0)
|
||||
return;
|
||||
|
||||
QMap<int, MsgPtr> msgs = undeliveredMsgs;
|
||||
removeAllReciepts();
|
||||
|
||||
for (auto iter = msgs.begin(); iter != msgs.end(); iter++)
|
||||
{
|
||||
if (iter.value().timestamp.msecsTo(QDateTime::currentDateTime()) < offlineTimeout)
|
||||
{
|
||||
registerReceipt(iter.value().receipt, iter.key(), iter.value().msg, iter.value().timestamp);
|
||||
continue;
|
||||
}
|
||||
QString messageText = iter.value().msg->getRawMessage();
|
||||
int rec;
|
||||
if (iter.value().msg->isAction())
|
||||
rec = Core::getInstance()->sendAction(f->getFriendID(), messageText);
|
||||
else
|
||||
rec = Core::getInstance()->sendMessage(f->getFriendID(), messageText);
|
||||
registerReceipt(rec, iter.key(), iter.value().msg);
|
||||
}
|
||||
}
|
||||
|
||||
void OfflineMsgEngine::removeAllReciepts()
|
||||
{
|
||||
QMutexLocker ml(&mutex);
|
||||
|
||||
receipts.clear();
|
||||
undeliveredMsgs.clear();
|
||||
}
|
||||
|
||||
void OfflineMsgEngine::processAllMsgs()
|
||||
{
|
||||
if (globalMutex.tryLock())
|
||||
{
|
||||
for (auto &it : engines)
|
||||
{
|
||||
it->deliverOfflineMsgs();
|
||||
}
|
||||
|
||||
globalMutex.unlock();
|
||||
}
|
||||
}
|
61
src/offlinemsgengine.h
Normal file
61
src/offlinemsgengine.h
Normal file
|
@ -0,0 +1,61 @@
|
|||
/*
|
||||
Copyright (C) 2015 by Project Tox <https://tox.im>
|
||||
|
||||
This file is part of qTox, a Qt-based graphical interface for Tox.
|
||||
|
||||
This program is libre software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
|
||||
See the COPYING file for more details.
|
||||
*/
|
||||
|
||||
#ifndef OFFLINEMSGENGINE_H
|
||||
#define OFFLINEMSGENGINE_H
|
||||
|
||||
#include <QObject>
|
||||
#include <QSet>
|
||||
#include <QMutex>
|
||||
#include <QDateTime>
|
||||
#include "src/widget/tool/chatactions/messageaction.h"
|
||||
|
||||
struct Friend;
|
||||
class QTimer;
|
||||
|
||||
class OfflineMsgEngine : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
OfflineMsgEngine(Friend *);
|
||||
virtual ~OfflineMsgEngine();
|
||||
|
||||
void dischargeReceipt(int receipt);
|
||||
void registerReceipt(int receipt, int messageID, MessageActionPtr msg, const QDateTime ×tamp = QDateTime::currentDateTime());
|
||||
|
||||
public slots:
|
||||
void deliverOfflineMsgs();
|
||||
void removeAllReciepts();
|
||||
static void processAllMsgs();
|
||||
|
||||
private:
|
||||
struct MsgPtr {
|
||||
MessageActionPtr msg;
|
||||
QDateTime timestamp;
|
||||
int receipt;
|
||||
};
|
||||
|
||||
QMutex mutex;
|
||||
Friend* f;
|
||||
QHash<int, int> receipts;
|
||||
QMap<int, MsgPtr> undeliveredMsgs;
|
||||
|
||||
static QSet<OfflineMsgEngine*> engines;
|
||||
static const int offlineTimeout;
|
||||
static QMutex globalMutex;
|
||||
};
|
||||
|
||||
#endif // OFFLINEMSGENGINE_H
|
|
@ -41,6 +41,7 @@
|
|||
#include "src/widget/widget.h"
|
||||
#include "src/widget/maskablepixmapwidget.h"
|
||||
#include "src/widget/croppinglabel.h"
|
||||
#include "src/offlinemsgengine.h"
|
||||
|
||||
ChatForm::ChatForm(Friend* chatFriend)
|
||||
: f(chatFriend)
|
||||
|
@ -57,6 +58,8 @@ ChatForm::ChatForm(Friend* chatFriend)
|
|||
|
||||
callConfirm = nullptr;
|
||||
|
||||
offlineEngine = new OfflineMsgEngine(f);
|
||||
|
||||
isTypingLabel = new QLabel();
|
||||
QFont font = isTypingLabel->font();
|
||||
font.setItalic(true);
|
||||
|
@ -90,7 +93,7 @@ ChatForm::ChatForm(Friend* chatFriend)
|
|||
connect(volButton, SIGNAL(clicked()), this, SLOT(onVolMuteToggle()));
|
||||
connect(chatWidget, &ChatAreaWidget::onFileTranfertInterract, this, &ChatForm::onFileTansBtnClicked);
|
||||
connect(Core::getInstance(), &Core::fileSendFailed, this, &ChatForm::onFileSendFailed);
|
||||
connect(this, SIGNAL(chatAreaCleared()), this, SLOT(clearReciepts()));
|
||||
connect(this, SIGNAL(chatAreaCleared()), getOfflineMsgEngine(), SLOT(removeAllReciepts()));
|
||||
connect(nameLabel, &CroppingLabel::textChanged, this, [=](QString text, QString orig)
|
||||
{if (text != orig) emit aliasChanged(text);} );
|
||||
connect(&typingTimer, &QTimer::timeout, this, [=]{Core::getInstance()->sendTyping(f->getFriendID(), false);});
|
||||
|
@ -143,7 +146,7 @@ void ChatForm::onSendTriggered()
|
|||
else
|
||||
rec = Core::getInstance()->sendMessage(f->getFriendID(), qt_msg);
|
||||
|
||||
registerReceipt(rec, id, ma);
|
||||
getOfflineMsgEngine()->registerReceipt(rec, id, ma);
|
||||
|
||||
msgEdit->setLastMessage(msg); //set last message only when sending it
|
||||
}
|
||||
|
@ -821,7 +824,7 @@ void ChatForm::loadHistory(QDateTime since, bool processUndelivered)
|
|||
rec = Core::getInstance()->sendAction(f->getFriendID(), ca->getRawMessage());
|
||||
else
|
||||
rec = Core::getInstance()->sendMessage(f->getFriendID(), ca->getRawMessage());
|
||||
registerReceipt(rec, it.id, ca);
|
||||
getOfflineMsgEngine()->registerReceipt(rec, it.id, ca);
|
||||
}
|
||||
}
|
||||
historyMessages.append(ca);
|
||||
|
@ -906,30 +909,6 @@ QString ChatForm::secondsToDHMS(quint32 duration)
|
|||
return cD + res.sprintf("%dd%02dh %02dm %02ds", days, hours, minutes, seconds);
|
||||
}
|
||||
|
||||
void ChatForm::registerReceipt(int receipt, int messageID, MessageActionPtr msg)
|
||||
{
|
||||
receipts[receipt] = messageID;
|
||||
undeliveredMsgs[messageID] = msg;
|
||||
}
|
||||
|
||||
void ChatForm::dischargeReceipt(int receipt)
|
||||
{
|
||||
auto it = receipts.find(receipt);
|
||||
if (it != receipts.end())
|
||||
{
|
||||
int mID = it.value();
|
||||
auto msgIt = undeliveredMsgs.find(mID);
|
||||
if (msgIt != undeliveredMsgs.end())
|
||||
{
|
||||
HistoryKeeper::getInstance()->markAsSent(mID);
|
||||
msgIt.value()->markAsSent();
|
||||
msgIt.value()->featureUpdate();
|
||||
undeliveredMsgs.erase(msgIt);
|
||||
}
|
||||
receipts.erase(it);
|
||||
}
|
||||
}
|
||||
|
||||
void ChatForm::setFriendTyping(bool isTyping)
|
||||
{
|
||||
if (isTyping)
|
||||
|
@ -938,32 +917,6 @@ void ChatForm::setFriendTyping(bool isTyping)
|
|||
isTypingLabel->clear();
|
||||
}
|
||||
|
||||
void ChatForm::clearReciepts()
|
||||
{
|
||||
receipts.clear();
|
||||
undeliveredMsgs.clear();
|
||||
}
|
||||
|
||||
void ChatForm::deliverOfflineMsgs()
|
||||
{
|
||||
if (!Settings::getInstance().getFauxOfflineMessaging())
|
||||
return;
|
||||
|
||||
QMap<int, MessageActionPtr> msgs = undeliveredMsgs;
|
||||
clearReciepts();
|
||||
|
||||
for (auto iter = msgs.begin(); iter != msgs.end(); iter++)
|
||||
{
|
||||
QString messageText = iter.value()->getRawMessage();
|
||||
int rec;
|
||||
if (iter.value()->isAction())
|
||||
rec = Core::getInstance()->sendAction(f->getFriendID(), messageText);
|
||||
else
|
||||
rec = Core::getInstance()->sendMessage(f->getFriendID(), messageText);
|
||||
registerReceipt(rec, iter.key(), iter.value());
|
||||
}
|
||||
}
|
||||
|
||||
void ChatForm::show(Ui::MainWindow &ui)
|
||||
{
|
||||
GenericChatForm::show(ui);
|
||||
|
@ -977,3 +930,8 @@ void ChatForm::hideEvent(QHideEvent*)
|
|||
if (callConfirm)
|
||||
callConfirm->hide();
|
||||
}
|
||||
|
||||
OfflineMsgEngine *ChatForm::getOfflineMsgEngine()
|
||||
{
|
||||
return offlineEngine;
|
||||
}
|
||||
|
|
|
@ -32,6 +32,7 @@ class QPixmap;
|
|||
class CallConfirmWidget;
|
||||
class QHideEvent;
|
||||
class QMoveEvent;
|
||||
class OfflineMsgEngine;
|
||||
|
||||
class ChatForm : public GenericChatForm
|
||||
{
|
||||
|
@ -44,6 +45,7 @@ public:
|
|||
|
||||
void dischargeReceipt(int receipt);
|
||||
void setFriendTyping(bool isTyping);
|
||||
OfflineMsgEngine* getOfflineMsgEngine();
|
||||
|
||||
virtual void show(Ui::MainWindow &ui);
|
||||
|
||||
|
@ -60,8 +62,6 @@ signals:
|
|||
void aliasChanged(const QString& alias);
|
||||
|
||||
public slots:
|
||||
void deliverOfflineMsgs();
|
||||
void clearReciepts();
|
||||
void startFileSend(ToxFile file);
|
||||
void onFileRecvRequest(ToxFile file);
|
||||
void onAvInvite(int FriendId, int CallId, bool video);
|
||||
|
@ -102,7 +102,6 @@ protected:
|
|||
void dragEnterEvent(QDragEnterEvent* ev);
|
||||
void dropEvent(QDropEvent* ev);
|
||||
virtual void hideEvent(QHideEvent* event);
|
||||
void registerReceipt(int receipt, int messageID, MessageActionPtr msg);
|
||||
|
||||
private:
|
||||
Friend* f;
|
||||
|
@ -115,13 +114,12 @@ private:
|
|||
QTimer *disableCallButtonsTimer;
|
||||
QElapsedTimer timeElapsed;
|
||||
QLabel *isTypingLabel;
|
||||
OfflineMsgEngine *offlineEngine;
|
||||
|
||||
QHash<uint, FileTransferInstance*> ftransWidgets;
|
||||
void startCounter();
|
||||
void stopCounter();
|
||||
QString secondsToDHMS(quint32 duration);
|
||||
QHash<int, int> receipts;
|
||||
QMap<int, MessageActionPtr> undeliveredMsgs;
|
||||
CallConfirmWidget *callConfirm;
|
||||
void enableCallButtons();
|
||||
};
|
||||
|
|
|
@ -37,6 +37,7 @@
|
|||
#include "src/platform/timer.h"
|
||||
#include "systemtrayicon.h"
|
||||
#include "src/nexus.h"
|
||||
#include "src/offlinemsgengine.h"
|
||||
#include <cassert>
|
||||
#include <QMessageBox>
|
||||
#include <QDebug>
|
||||
|
@ -88,6 +89,8 @@ void Widget::init()
|
|||
|
||||
timer = new QTimer();
|
||||
timer->start(1000);
|
||||
offlineMsgTimer = new QTimer();
|
||||
offlineMsgTimer->start(15000);
|
||||
|
||||
//restore window state
|
||||
restoreGeometry(Settings::getInstance().getWindowGeometry());
|
||||
|
@ -222,6 +225,7 @@ void Widget::init()
|
|||
connect(addFriendForm, SIGNAL(friendRequested(QString, QString)), this, SIGNAL(friendRequested(QString, QString)));
|
||||
connect(timer, &QTimer::timeout, this, &Widget::onUserAwayCheck);
|
||||
connect(timer, &QTimer::timeout, this, &Widget::onEventIconTick);
|
||||
connect(offlineMsgTimer, &QTimer::timeout, &OfflineMsgEngine::processAllMsgs);
|
||||
|
||||
addFriendForm->show(*ui);
|
||||
|
||||
|
@ -276,6 +280,7 @@ Widget::~Widget()
|
|||
delete addFriendForm;
|
||||
delete filesForm;
|
||||
delete timer;
|
||||
delete offlineMsgTimer;
|
||||
|
||||
FriendList::clear();
|
||||
GroupList::clear();
|
||||
|
@ -684,7 +689,7 @@ void Widget::onFriendStatusChanged(int friendId, Status status)
|
|||
|
||||
if (isActualChange && status != Status::Offline)
|
||||
{ // wait a little
|
||||
QTimer::singleShot(250, f->getChatForm(), SLOT(deliverOfflineMsgs()));
|
||||
QTimer::singleShot(250, f->getChatForm()->getOfflineMsgEngine(), SLOT(deliverOfflineMsgs()));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -748,7 +753,7 @@ void Widget::onReceiptRecieved(int friendId, int receipt)
|
|||
if (!f)
|
||||
return;
|
||||
|
||||
f->getChatForm()->dischargeReceipt(receipt);
|
||||
f->getChatForm()->getOfflineMsgEngine()->dischargeReceipt(receipt);
|
||||
}
|
||||
|
||||
void Widget::newMessageAlert(GenericChatroomWidget* chat)
|
||||
|
@ -1125,7 +1130,7 @@ void Widget::clearAllReceipts()
|
|||
QList<Friend*> frnds = FriendList::getAllFriends();
|
||||
for (Friend *f : frnds)
|
||||
{
|
||||
f->getChatForm()->clearReciepts();
|
||||
f->getChatForm()->getOfflineMsgEngine()->removeAllReciepts();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -162,7 +162,7 @@ private:
|
|||
bool notify(QObject *receiver, QEvent *event);
|
||||
bool autoAwayActive = false;
|
||||
Status beforeDisconnect = Status::Offline;
|
||||
QTimer* timer;
|
||||
QTimer* timer, *offlineMsgTimer;
|
||||
QTranslator* translator;
|
||||
QRegExp nameMention, sanitizedNameMention;
|
||||
bool eventFlag;
|
||||
|
|
Loading…
Reference in New Issue
Block a user