Verified Commit 25ee8500 authored by Phobos D'thorga's avatar Phobos D'thorga 🐲
Browse files

* Sorting of message history for the XMPP side-of-things now works...

* Sorting of message history for the XMPP side-of-things now works more-or-less correctly now! I'm so happy :)
parent ac79a787
Pipeline #994 passed with stages
in 35 minutes and 3 seconds
......@@ -741,6 +741,27 @@ QDateTime GkXmppClient::calcMaxTimestampForXmppMsgHistory(const QString &bareJid
return QDateTime::currentDateTimeUtc();
}
/**
* @brief GkXmppClient::compareTimestamps compares a given QList() of timestamps and returns the closet
* matching value to the given input reference.
* @author Phobos A. D'thorga <phobos.gekko@gekkofyre.io>
* @param data The QList of data for making comparisons.
* @param value The reference value in which to make the comparison against.
* @return The closest, compared, value which has been found.
*/
qint64 GkXmppClient::compareTimestamps(const std::vector<GekkoFyre::Network::GkXmpp::GkRecvMsgsTableViewModel> &data,
const qint64 &value)
{
std::vector<qint64> timestamps;
for (const auto &stanza: data) {
timestamps.push_back(stanza.timestamp.toMSecsSinceEpoch());
}
auto const it = std::lower_bound(timestamps.begin(), timestamps.end(), value);
if (it == timestamps.end()) { return -1; }
return *it;
}
/**
* @brief GkXmppClient::getRegistrationMgr
* @author Phobos A. D'thorga <phobos.gekko@gekkofyre.io>
......
......@@ -132,6 +132,7 @@ public:
// Date & Time Management
[[nodiscard]] QDateTime calcMinTimestampForXmppMsgHistory(const QString &bareJid, const QList<GekkoFyre::Network::GkXmpp::GkXmppCallsign> &msg_history);
[[nodiscard]] QDateTime calcMaxTimestampForXmppMsgHistory(const QString &bareJid, const QList<GekkoFyre::Network::GkXmpp::GkXmppCallsign> &msg_history);
[[nodiscard]] qint64 compareTimestamps(const std::vector<GekkoFyre::Network::GkXmpp::GkRecvMsgsTableViewModel> &data, const qint64 &value);
//
// User, roster and presence details
......
......@@ -104,23 +104,44 @@ void GkXmppRecvMsgsTableViewModel::populateData(const QList<GkRecvMsgsTableViewM
* @param bareJid The identity of the user, as it should appear on the XMPP server.
* @param msg The message data to be inserted.
* @param timestamp The date/time to be inserted.
* @param doNotAddToTable As the variable name suggests, do not make any modifications to the QTableView itself. Only
* modify `m_data` instead.
*/
void GkXmppRecvMsgsTableViewModel::insertData(const QString &bareJid, const QString &msg, const QDateTime &timestamp)
{
try {
std::lock_guard<std::mutex> lock_guard(m_dataBatchMutex);
beginInsertRows(QModelIndex(), m_data.count(), m_data.count());
qint32 idx = -1;
if (!m_data.isEmpty()) {
//
// Find the nearest timestamp to the one provided!
const auto comp_timestamp = m_xmppClient->compareTimestamps(std::vector<GkRecvMsgsTableViewModel>(m_data.begin(), m_data.end()),
timestamp.toMSecsSinceEpoch());
for (qint32 i = 0; i < m_data.size(); ++i) {
if (m_data.at(i).timestamp.toMSecsSinceEpoch() == comp_timestamp) {
idx = i;
}
}
}
GkRecvMsgsTableViewModel recvMsg;
recvMsg.timestamp = timestamp;
recvMsg.bareJid = bareJid;
recvMsg.message = msg;
recvMsg.nickName = m_xmppClient->getJidNickname(recvMsg.bareJid);
m_data.append(recvMsg);
endInsertRows();
//
// Insert the data into the QTableView itself!
beginInsertRows(QModelIndex(), m_data.count(), m_data.count());
if (!m_data.isEmpty() && idx >= 0) {
m_data.insert(m_data.begin() + idx, recvMsg);
} else {
m_data.push_back(recvMsg);
}
endInsertRows();
auto top = this->createIndex((m_data.count() + 1), 0, nullptr);
auto bottom = this->createIndex((m_data.count() + 1), GK_XMPP_RECV_MSGS_TABLEVIEW_MODEL_TOTAL_IDX, nullptr);
emit dataChanged(top, bottom);
} catch (const std::exception &e) {
std::throw_with_nested(std::runtime_error(e.what()));
......
......@@ -90,5 +90,6 @@ private:
// Multithreading, mutexes, etc.
//
std::mutex m_dataBatchMutex;
};
};
......@@ -46,6 +46,7 @@
#include <utility>
#include <iterator>
#include <iostream>
#include <algorithm>
#include <QMap>
#include <QIcon>
#include <QPixmap>
......@@ -118,8 +119,8 @@ GkXmppMessageDialog::GkXmppMessageDialog(QPointer<GekkoFyre::StringFuncs> string
QObject::connect(m_xmppClient, SIGNAL(xmppMsgUpdate(const QXmppMessage &)), this, SLOT(recvXmppMsg(const QXmppMessage &)));
QObject::connect(m_xmppClient, SIGNAL(updateMsgHistory()), this, SLOT(updateMsgHistory()));
QObject::connect(m_xmppClient, SIGNAL(msgArchiveSuccReceived()), this, SLOT(msgArchiveSuccReceived()));
QObject::connect(this, SIGNAL(updateMamArchive(const QString &, const bool &, const bool &)),
this, SLOT(procMamArchive(const QString &, const bool &, const bool &)));
QObject::connect(this, SIGNAL(updateMamArchive(const bool &, const bool &)),
this, SLOT(procMamArchive(const bool &, const bool &)));
//
// Setup and initialize QTableView's...
......@@ -484,9 +485,9 @@ QXmppMessage GkXmppMessageDialog::createXmppMessageIq(const QString &to, const Q
void GkXmppMessageDialog::msgArchiveSuccReceived()
{
if (!startupSucc) {
emit updateMamArchive(gkConnDetails.jid, true, true);
emit updateMamArchive(true, true);
for (const auto &bareJid: m_bareJids) {
emit updateMamArchive(bareJid, false, true);
emit updateMamArchive(false, true);
}
startupSucc = true;
......@@ -499,17 +500,16 @@ void GkXmppMessageDialog::msgArchiveSuccReceived()
* @brief GkXmppMessageDialog::procMamArchive is a helper class for dealing with the processing of recorded messages that
* have been archived to a given XMPP server, according to specification, XEP-0313 (Message Archive Management).
* @author Phobos A. D'thorga <phobos.gekko@gekkofyre.io>
* @param bareJid The user we are in communiqué with!
* @param wipeExistingHistory Whether to wipe the pre-existing chat history or not, specifically from the given QTableView
* object, GekkoFyre::GkXmppRecvMsgsTableViewModel().
* @param presented Should we update the fact that these messages are now already 'presented' (and thereby inserted into
* the QTableView) or not?
*/
void GkXmppMessageDialog::procMamArchive(const QString &bareJid, const bool &wipeExistingHistory, const bool &presented)
void GkXmppMessageDialog::procMamArchive(const bool &wipeExistingHistory, const bool &presented)
{
try {
if (!startupSucc) {
getArchivedMessagesFromDb(bareJid, true, wipeExistingHistory, presented);
getArchivedMessagesFromDb(true, wipeExistingHistory, presented);
}
} catch (const std::exception &e) {
gkStringFuncs->print_exception(e);
......@@ -538,7 +538,6 @@ void GkXmppMessageDialog::getArchivedMessages()
* again.
* NOTE: The Google LevelDB functionality is currently disabled!
* @author Phobos A. D'thorga <phobos.gekko@gekkofyre.io>
* @param bareJid The user we are in communiqué with!
* @param insertData Whether to insert the archived messages into the given QTableView or not.
* @param wipeExistingHistory Whether to wipe the pre-existing chat history or not, specifically from the given QTableView
* object, GekkoFyre::GkXmppRecvMsgsTableViewModel().
......@@ -547,39 +546,40 @@ void GkXmppMessageDialog::getArchivedMessages()
* @param presented Should we update the fact that these messages are now already 'presented' (and thereby inserted into
* the QTableView) or not?
*/
void GkXmppMessageDialog::getArchivedMessagesFromDb(const QString &bareJid, const bool &insertData, const bool &wipeExistingHistory,
void GkXmppMessageDialog::getArchivedMessagesFromDb(const bool &insertData, const bool &wipeExistingHistory,
const bool &updateSortFilterProxy, const bool &presented)
{
try {
if (!bareJid.isEmpty()) {
auto rosterMap = m_xmppClient->getRosterMap(); // Grab the `GkXmppCallsign()` object and temporarily store it in memory for just use in this function!
if (!rosterMap.isEmpty()) {
std::lock_guard<std::mutex> lock_guard(m_archivedMsgsFromDbMtx);
if (wipeExistingHistory) {
gkXmppRecvMsgsTableViewModel->removeData();
}
auto rosterMap = m_xmppClient->getRosterMap(); // Grab the `GkXmppCallsign()` object and temporarily store it in memory for just use in this function!
if (!rosterMap.isEmpty()) {
std::lock_guard<std::mutex> lock_guard(m_archivedMsgsFromDbMtx);
if (wipeExistingHistory) {
gkXmppRecvMsgsTableViewModel->removeData();
}
for (auto roster = rosterMap.begin(); roster != rosterMap.end(); ++roster) {
if (roster->bareJid == bareJid) {
gkEventLogger->publishEvent(tr("Gathering archived messages for XMPP user, \"%1\", from the database!").arg(roster->bareJid), GkSeverity::Debug,
"", false, true, false, false, false);
if (!roster->messages.isEmpty()) {
for (auto iter = roster->messages.begin(); iter != roster->messages.end(); ++iter) {
if (!iter->presented && insertData) {
gkXmppRecvMsgsTableViewModel->insertData(bareJid, iter->message.body(), iter->message.stamp());
iter->presented = true;
} else {
iter->presented = presented;
}
}
m_xmppClient->updateRosterMap(rosterMap);
for (auto roster = rosterMap.begin(); roster != rosterMap.end(); ++roster) {
gkEventLogger->publishEvent(tr("Gathering archived messages for XMPP user, \"%1\", from the database!").arg(roster->bareJid), GkSeverity::Debug,
"", false, true, false, false, false);
if (!roster->messages.isEmpty()) {
//
// Performs a comparison between two, QDateTime objects, and sorts the QList accordingly!
// std::sort(roster->messages.begin(), roster->messages.end(), [](const GkXmppMamMsg &left, const GkXmppMamMsg &right)->bool{ return left.message.stamp().toMSecsSinceEpoch() < right.message.stamp().toMSecsSinceEpoch(); });
//
// Insert the archived messages, now downloaded from the given XMPP server and then sorted, into the QTableView provided!
for (auto iter = roster->messages.begin(); iter != roster->messages.end(); ++iter) {
if (!iter->presented && insertData) {
gkXmppRecvMsgsTableViewModel->insertData(roster->bareJid, iter->message.body(), iter->message.stamp());
iter->presented = true;
} else {
iter->presented = presented;
}
ui->tableView_recv_msg_dlg->scrollToBottom();
break;
}
m_xmppClient->updateRosterMap(rosterMap);
}
ui->tableView_recv_msg_dlg->scrollToBottom();
}
}
} catch (const std::exception &e) {
......
......@@ -110,9 +110,9 @@ private slots:
//
// QXmppMamManager handling
void msgArchiveSuccReceived();
void procMamArchive(const QString &bareJid, const bool &wipeExistingHistory = false, const bool &presented = false);
void procMamArchive(const bool &wipeExistingHistory = false, const bool &presented = false);
void getArchivedMessages();
void getArchivedMessagesFromDb(const QString &bareJid, const bool &insertData, const bool &wipeExistingHistory = false,
void getArchivedMessagesFromDb(const bool &insertData, const bool &wipeExistingHistory = false,
const bool &updateSortFilterProxy = false, const bool &presented = false);
signals:
......@@ -124,7 +124,8 @@ signals:
//
// QXmppMamManager handling
void updateMamArchive(const QString &bareJid, const bool &wipeExistingHistory = false, const bool &presented = false);
void updateMamArchive(const bool &wipeExistingHistory = false, const bool &presented = false);
void updateTableModel();
private:
Ui::GkXmppMessageDialog *ui;
......@@ -161,5 +162,6 @@ private:
GekkoFyre::Network::GkXmpp::GkNetworkState m_netState;
QStringList m_bareJids;
QString m_clientNickname;
};
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment