1
0
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:
Tux3 / Mlkj / !Lev.uXFMLA 2015-02-07 18:09:58 +01:00
commit 94e30b9e2d
No known key found for this signature in database
GPG Key ID: 7E086DD661263264
7 changed files with 209 additions and 64 deletions

View File

@ -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
View 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 &timestamp)
{
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
View 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 &timestamp = 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

View File

@ -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;
}

View File

@ -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();
};

View File

@ -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();
}
}

View File

@ -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;