Moved the chat history into the libretroshare.

Now the history is saved encrypted. Please delete all files with "chat*.xml" in your profile folder.
Added new config p3HistoryMgr and interface p3History.
Added new option to limit the count of the saved history items.
Added new simple html optimizer "RsHtml::optimizeHtml" to reduce the size of the html strings.

git-svn-id: http://svn.code.sf.net/p/retroshare/code/trunk@4623 b45a01b8-16f6-495d-af2f-9b41ad6348cc
This commit is contained in:
thunder2 2011-09-29 09:20:09 +00:00
parent c6a68fe05e
commit 29c090fb44
45 changed files with 1721 additions and 1406 deletions

View file

@ -1,51 +0,0 @@
/****************************************************************
* RetroShare is distributed under the following license:
*
* Copyright (C) 2009 The RetroShare Team, Oleksiy Bilyanskyy
*
* This program is free 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 2
* 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
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301, USA.
****************************************************************/
#include "IMHistoryItem.h"
//============================================================================
IMHistoryItem::IMHistoryItem()
{
hiid = 0;
}
//============================================================================
IMHistoryItem::IMHistoryItem(int hiidIn, bool incomingIn, const std::string &idIn, const QString &nameIn, const QDateTime &sendTimeIn, const QDateTime &recvTimeIn, const QString &messageTextIn)
{
hiid = hiidIn;
incoming = incomingIn;
id = idIn;
name = nameIn;
sendTime = sendTimeIn;
recvTime = recvTimeIn;
messageText = messageTextIn;
}
//============================================================================
//! after qSort() older messages will become first
bool
IMHistoryItem::operator<(const IMHistoryItem& item) const
{
return (recvTime < item.recvTime) ;
}

View file

@ -1,47 +0,0 @@
/****************************************************************
* RetroShare is distributed under the following license:
*
* Copyright (C) 2009 The RetroShare Team, Oleksiy Bilyanskyy
*
* This program is free 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 2
* 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
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301, USA.
****************************************************************/
#ifndef __IM_history_item__
#define __IM_history_item__
#include <QDateTime>
#include <QString>
class IMHistoryItem
{
public:
IMHistoryItem();
IMHistoryItem(int hiid, bool incoming, const std::string &id, const QString &name, const QDateTime &sendTime, const QDateTime &recvTime, const QString &messageText);
int hiid;
bool incoming;
std::string id;
QString name;
QDateTime sendTime;
QDateTime recvTime;
QString messageText;
bool operator<(const IMHistoryItem& item) const;
} ;
#endif

View file

@ -26,8 +26,6 @@
#include <QString>
#include <QStyleOption>
#include "IMHistoryItem.h"
class QPainter;
class IMHistoryItemPainter

View file

@ -1,267 +0,0 @@
/****************************************************************
* RetroShare is distributed under the following license:
*
* Copyright (C) 2009 The RetroShare Team, Oleksiy Bilyanskyy
*
* This program is free 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 2
* 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
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301, USA.
****************************************************************/
#include "IMHistoryKeeper.h"
#include <iostream>
#include <QFile>
#include <QIODevice>
#include <QTimer>
#include <QtAlgorithms> //for qSort
#include <QXmlStreamReader>
#include "IMHistoryReader.h"
#include "IMHistoryWriter.h"
//=============================================================================
IMHistoryKeeper::IMHistoryKeeper()
{
historyChanged = false;
// save histroy every 10 seconds (when changed)
saveTimer = new QTimer(this);
saveTimer->connect(saveTimer, SIGNAL(timeout()), this, SLOT(saveHistory()));
saveTimer->setInterval(10000);
saveTimer->start();
lasthiid = 0;
};
//=============================================================================
IMHistoryKeeper::~IMHistoryKeeper()
{
saveHistory();
}
//=============================================================================
void IMHistoryKeeper::init(QString historyFileName)
{
lasthiid = 0;
hfName = historyFileName;
loadHistoryFile();
}
//=============================================================================
void IMHistoryKeeper::addMessage(bool incoming, const std::string &id, const QString &name, const QDateTime &sendTime, const QDateTime &recvTime, const QString &messageText)
{
IMHistoryItem item(++lasthiid, incoming, id, name, sendTime, recvTime, messageText);
hitems.append(item);
historyChanged = true;
emit historyAdd(item);
//std::cerr << "IMHistoryKeeper::addMessage "
// << messageText.toStdString() << "\n";
//std::cerr << "IMHistoryKeeper::addMessage count is" << hitems.count();
}
//=============================================================================
bool IMHistoryKeeper::loadHistoryFile()
{
qDebug() << " IMHistoryKeeper::loadHistoryFile is here";
if (hfName.isEmpty()) {
lastErrorMessage = "history file not set";
return false;
}
QFile fl(hfName);
if (!fl.exists()) {
lastErrorMessage = QString("history file not found (%1)").arg(hfName) ;
return false;
}
IMHistoryReader hreader;
if (!hreader.read(hitems, hfName, lasthiid)) {
lastErrorMessage = hreader.errorMessage();
return false;
}
qSort(hitems.begin(), hitems.end());
qDebug() << " IMHistoryKeeper::loadHistoryFile finished";
historyChanged = false;
return true;
}
//=============================================================================
QString IMHistoryKeeper::errorMessage()
{
QString errorMessage = lastErrorMessage;
lastErrorMessage.clear();
return errorMessage;
}
//=============================================================================
bool IMHistoryKeeper::getMessages(QList<IMHistoryItem> &historyItems, const int messagesCount)
{
int messFound = 0;
historyItems.clear();
QListIterator<IMHistoryItem> hii(hitems);
hii.toBack();
while (hii.hasPrevious()) {
IMHistoryItem hitem = hii.previous();
historyItems.insert(historyItems.begin(), hitem);
messFound++;
if (messagesCount && messFound >= messagesCount) {
break;
}
}
return true; // successful end
}
//=============================================================================
bool IMHistoryKeeper::getMessage(int hiid, IMHistoryItem &item)
{
QList<IMHistoryItem>::iterator it;
for (it = hitems.begin(); it != hitems.end(); it++) {
if (it->hiid == hiid) {
item = *it;
return true;
}
}
return false;
}
//=============================================================================
void IMHistoryKeeper::clear()
{
hitems.clear();
historyChanged = true;
lasthiid = 0;
emit historyClear();
}
//=============================================================================
/*static*/ bool IMHistoryKeeper::compareItem(const IMHistoryItem &item, bool incoming, const std::string &id, const QDateTime &sendTime, const QString &messageText)
{
// "\n" is not saved in xml
QString copyMessage1(messageText);
copyMessage1.replace("\n", "");
QString copyMessage2(item.messageText);
copyMessage2.replace("\n", "");
if (item.incoming == incoming && item.id == id && item.sendTime == sendTime && copyMessage1 == copyMessage2) {
return true;
}
return false;
}
//=============================================================================
bool IMHistoryKeeper::findMessage(bool incoming, const std::string &id, const QDateTime &sendTime, const QString &messageText, int &hiid)
{
hiid = 0;
QList<IMHistoryItem>::const_iterator it;
for (it = hitems.begin(); it != hitems.end(); it++) {
if (compareItem(*it, incoming, id, sendTime, messageText)) {
hiid = it->hiid;
return true;
}
}
return false;
}
//=============================================================================
void IMHistoryKeeper::removeMessage(int hiid)
{
QList<IMHistoryItem>::iterator it;
for (it = hitems.begin(); it != hitems.end(); it++) {
if (it->hiid == hiid) {
emit historyRemove(*it);
hitems.erase(it);
historyChanged = true;
break;
}
}
}
//=============================================================================
void IMHistoryKeeper::removeMessages(QList<int> &hiids)
{
bool changed = false;
QList<IMHistoryItem>::iterator it = hitems.begin();
while (it != hitems.end()) {
if (qFind(hiids, it->hiid) != hiids.end()) {
emit historyRemove(*it);
it = hitems.erase(it);
changed = true;
continue;
}
it++;
}
if (changed) {
historyChanged = true;
}
}
//=============================================================================
void IMHistoryKeeper::saveHistory()
{
if (historyChanged && hfName.isEmpty() == false) {
//=== we have to save all messages
qSort( hitems.begin(), hitems.end() ) ; // not nesessary, but just in case...
// it will not take a long time over ordered array
IMHistoryWriter wri;
wri.write(hitems, hfName);
historyChanged = false;
}
}

View file

@ -1,115 +0,0 @@
/****************************************************************
* RetroShare is distributed under the following license:
*
* Copyright (C) 2009 The RetroShare Team, Oleksiy Bilyanskyy
*
* This program is free 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 2
* 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
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301, USA.
****************************************************************/
#ifndef _HISTORY_KEEPER_H_
#define _HISTORY_KEEPER_H_
#include <QObject>
#include <QDebug>
#include <QString>
#include "IMHistoryItem.h"
class QTimer;
//! An engine for instant messaging history management
//! This class holds history for instant messages. It stores all messages
//! in xml file. Something like
//! <?xml version="1.0" encoding="UTF-8"?>
//! <!DOCTYPE history_file>
//! <history_file format_version="1.0">
//! <message sendTime="10000" id="id" name="Name">manual message</message>
//! ...
//! other messages in <message..> ... </message> tags
//! ...
//! </history_file>
//!
//! The class loads all messages from the file after creation, and saves them
//! at destruction. This means, the more history user has, the more memory
//! will be used. Maybe it's not good, but it isn't so large, I think
class IMHistoryKeeper : public QObject
{
Q_OBJECT
public:
IMHistoryKeeper();
//! A destructor
//! Warning: history messages will be saved to the file here. This means,
//! a IMHistoryKeeper object must be deleted properly.
virtual ~IMHistoryKeeper();
//! last error description
QString errorMessage();
//! initialize history keeper
void init(QString historyFileName);
//! Select messages from history
//! Fills given list with items
bool getMessages(QList<IMHistoryItem> &historyItems, const int messagesCount);
//! Get message
bool getMessage(int hiid, IMHistoryItem &item);
//! Adds new message to the history
//! Adds new message to the history, but the message will be saved to
//! file only after destroing the object
void addMessage(bool incoming, const std::string &id, const QString &name, const QDateTime &sendTime, const QDateTime &recvTime, const QString &messageText);
//! Clear the history
void clear();
//! Find message
static bool compareItem(const IMHistoryItem &item, bool incoming, const std::string &id, const QDateTime &sendTime, const QString &messageText);
bool findMessage(bool incoming, const std::string &id, const QDateTime &sendTime, const QString &messageText, int &hiid);
//! Remove item
void removeMessage(int hiid);
//! Remove items
void removeMessages(QList<int> &hiids);
private:
bool loadHistoryFile();
QList<IMHistoryItem> hitems;
QString hfName ; //! history file name
bool historyChanged;
QString lastErrorMessage;
QTimer *saveTimer;
int lasthiid;
private slots:
void saveHistory();
signals:
void historyAdd(IMHistoryItem item) const;
void historyRemove(IMHistoryItem item) const;
void historyClear() const;
};
#endif // _HISTORY_KEEPER_H_

View file

@ -1,206 +0,0 @@
/****************************************************************
* RetroShare is distributed under the following license:
*
* Copyright (C) 2009 The RetroShare Team, Oleksiy Bilyanskyy
*
* This program is free 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 2
* 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
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301, USA.
****************************************************************/
#include "IMHistoryReader.h"
#include <QFile>
#include <QDebug>
//=============================================================================
IMHistoryReader::IMHistoryReader()
:errMess("No error")
{
// nothing to do here
}
//=============================================================================
bool IMHistoryReader::read(QList<IMHistoryItem>& resultList, const QString fileName, int &lasthiid)
{
errMess = "No error";
resultList.clear();
//==== check for file and open it
QFile fl(fileName);
if (fl.exists()) {
fl.open(QIODevice::ReadOnly);
} else {
errMess = QString("file not found (%1)").arg(fileName);
return false ;
}
//==== set the file, and check it once more
setDevice(&fl);
if (atEnd()) {
errMess = "end of document reached before anything happened";
return false;
}
//==== now, read the first element (it should be document element)
while (!atEnd()) {
readNext();
if (isStartElement()) {
if (name() == "history_file" && attributes().value("format_version") == "1.0") {
readHistory(resultList, lasthiid);
break;
} else {
errMess = "The file is not a history file with format version 1.0";
return false ;
}
}
}
if (error()) {
errMess = errorString();
// } else {
// QList<IMHistoryItem>::const_iterator hii;//history items iterator
// for (hii = result.constBegin(); hii != result.constEnd(); ++hii) {
// resultList << *hii;
// }
}
return !error();
}
//=============================================================================
QString IMHistoryReader::errorMessage()
{
QString result = errMess;
errMess = "No error" ;
return result;
}
//=============================================================================
void IMHistoryReader::readUnknownElement()
{
Q_ASSERT(isStartElement());
qDebug()<< " " << "unknown node " << name().toString();
while (!atEnd()) {
readNext();
if (isEndElement()) {
break;
}
if (isStartElement()) {
readUnknownElement();
}
}
}
//=============================================================================
void IMHistoryReader::readHistory(QList<IMHistoryItem> &historyItems, int &lasthiid)
{
Q_ASSERT(isStartElement());
// qDebug()<< " " << "node with message " << name() ;
historyItems.clear();
lasthiid = 0;
bool recalculate = false;
while (!atEnd()) {
readNext();
if (isEndElement()) {
break;
}
if (isStartElement()) {
if ( name() == "message") {
IMHistoryItem item;
readMessage(item);
if (item.hiid == 0) {
recalculate = true;
} else {
if (item.hiid > lasthiid) {
lasthiid = item.hiid;
}
}
historyItems.append(item);
} else {
readUnknownElement();
}
}
}
if (recalculate) {
// calculate hiid
QList<IMHistoryItem>::iterator item = historyItems.begin();
for (item = historyItems.begin(); item != historyItems.end(); item++) {
if (item->hiid == 0) {
item->hiid = ++lasthiid;
}
}
}
}
//=============================================================================
void IMHistoryReader::readMessage(IMHistoryItem &historyItem)
{
// Q_ASSERT(isStartElement() );
if (isStartElement() && (name() == "message")) {
//=== process attributes
historyItem.hiid = attributes().value("hiid").toString().toInt();
historyItem.incoming = (attributes().value("incoming").toString().toInt() == 1);
historyItem.id = attributes().value("id").toString().toStdString();
historyItem.name = attributes().value("name").toString();
int ti = attributes().value("sendTime").toString().toInt();
historyItem.sendTime = QDateTime::fromTime_t(ti);
ti = attributes().value("recvTime").toString().toInt();
if (ti) {
historyItem.recvTime = QDateTime::fromTime_t(ti);
} else {
historyItem.recvTime = historyItem.sendTime;
}
//=== after processing attributes, read the message text
QString tstr = readElementText();
//=== remove '\0' chars from the string. Is it a QXmlStuff bug,
// if they appear?
for (int i = 0; i< tstr.length(); i++) {
if (tstr.at(i) == '\n') {
tstr.remove(i, 1);
}
}
historyItem.messageText = tstr;
//qDebug() << QString(" readMessage: %1, %2, %3, %4" )
// .arg(rez.text()).arg(rez.sender())
// .arg(rez.receiver()).arg(ti) ;
}
}

View file

@ -1,50 +0,0 @@
/****************************************************************
* RetroShare is distributed under the following license:
*
* Copyright (C) 2009 The RetroShare Team, Oleksiy Bilyanskyy
*
* This program is free 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 2
* 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
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301, USA.
****************************************************************/
#ifndef __IM_History_reader__
#define __IM_History_reader__
#include <QXmlStreamReader>
#include <QString>
#include <QStringList>
#include "IMHistoryItem.h"
class IMHistoryReader : public QXmlStreamReader
{
public:
IMHistoryReader();
bool read(QList<IMHistoryItem>& resultList, const QString fileName, int &lasthiid);
QString errorMessage();
private:
void readUnknownElement();
void readHistory(QList<IMHistoryItem> &historyItems, int &lasthiid);
void readMessage(IMHistoryItem &historyItem);
QString errMess;
} ;
#endif

View file

@ -1,93 +0,0 @@
/****************************************************************
* RetroShare is distributed under the following license:
*
* Copyright (C) 2009 The RetroShare Team, Oleksiy Bilyanskyy
*
* This program is free 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 2
* 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
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301, USA.
****************************************************************/
#include "IMHistoryWriter.h"
#include <QFile>
#include <QDebug>
#include <QDateTime>
//=============================================================================
IMHistoryWriter::IMHistoryWriter()
:errMess("No error")
{
// nothing to do here
}
//=============================================================================
bool IMHistoryWriter::write(QList<IMHistoryItem>& itemList, const QString fileName)
{
qDebug() << " IMHistoryWriter::write is here" ;
errMess = "No error";
if (itemList.size() == 0) {
return remove(fileName);
}
//==== check for file and open it
QFile fl(fileName);
if (fl.open(QIODevice::WriteOnly | QIODevice::Truncate) == false) {
errMess = QString("error opening file %1 (code %2)")
.arg(fileName).arg( fl.error() );
return false;
}
//==== set the file, and check it once more
setDevice(&fl);
writeStartDocument();
writeDTD("<!DOCTYPE history_file>");
writeStartElement("history_file");
writeAttribute("format_version", "1.0");
foreach(IMHistoryItem item, itemList) {
writeStartElement("message");
writeAttribute("hiid", QString::number(item.hiid));
writeAttribute("incoming", QString::number(item.incoming ? 1 : 0));
writeAttribute("id", QString::fromStdString(item.id));
writeAttribute("name", item.name);
writeAttribute("sendTime", QString::number(item.sendTime.toTime_t()));
writeAttribute("recvTime", QString::number(item.recvTime.toTime_t()));
writeCDATA(item.messageText);
writeEndElement();
}
writeEndDocument() ;
fl.close();
qDebug() << " IMHistoryWriter::write done" ;
return true;
}
bool IMHistoryWriter::remove(const QString &fileName)
{
if (!QFile::remove(fileName)) {
qDebug() << " IMHistoryWriter::remove Failed to remove history file";
return false;
}
return true;
}

View file

@ -1,53 +0,0 @@
/****************************************************************
* RetroShare is distributed under the following license:
*
* Copyright (C) 2009 The RetroShare Team, Oleksiy Bilyanskyy
*
* This program is free 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 2
* 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
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301, USA.
****************************************************************/
#ifndef __IM_History_writer__
#define __IM_History_writer__
#include <QXmlStreamWriter>
#include <QString>
//#include <QStringList>
#include "IMHistoryItem.h"
class IMHistoryWriter : public QXmlStreamWriter
{
public:
IMHistoryWriter();
bool write(QList<IMHistoryItem>& itemList,
const QString fileName );
//! remove history file
bool remove(const QString& fileName);
QString errorMessage();
private:
QString errMess;
} ;
#endif

View file

@ -34,16 +34,18 @@
#include "IMHistoryItemPainter.h"
#include "rshare.h"
#include <retroshare/rshistory.h>
#include "gui/settings/rsharesettings.h"
#include "gui/notifyqt.h"
#define ROLE_HIID Qt::UserRole
#define ROLE_MSGID Qt::UserRole
#define ROLE_PLAINTEXT Qt::UserRole + 1
#define ROLE_OFFLINE Qt::UserRole + 2
ImHistoryBrowserCreateItemsThread::ImHistoryBrowserCreateItemsThread(ImHistoryBrowser *parent, IMHistoryKeeper &histKeeper)
: QThread(parent), m_historyKeeper(histKeeper)
ImHistoryBrowserCreateItemsThread::ImHistoryBrowserCreateItemsThread(ImHistoryBrowser *parent, const std::string& peerId)
: QThread(parent)
{
m_peerId = peerId;
m_historyBrowser = parent;
stopped = false;
}
@ -68,17 +70,18 @@ void ImHistoryBrowserCreateItemsThread::stop()
void ImHistoryBrowserCreateItemsThread::run()
{
QList<IMHistoryItem> historyItems;
m_historyKeeper.getMessages(historyItems, 0);
std::list<HistoryMsg> historyMsgs;
rsHistory->getMessages(m_peerId, historyMsgs, 0);
int count = historyItems.count();
int count = historyMsgs.size();
int current = 0;
foreach(IMHistoryItem item, historyItems) {
std::list<HistoryMsg>::iterator it;
for (it = historyMsgs.begin(); it != historyMsgs.end(); it++) {
if (stopped) {
break;
}
QListWidgetItem *itemWidget = m_historyBrowser->createItem(item);
QListWidgetItem *itemWidget = m_historyBrowser->createItem(*it);
if (itemWidget) {
m_items.push_back(itemWidget);
emit progress(++current, count);
@ -87,8 +90,8 @@ void ImHistoryBrowserCreateItemsThread::run()
}
/** Default constructor */
ImHistoryBrowser::ImHistoryBrowser(const std::string &peerId, IMHistoryKeeper &histKeeper, QTextEdit *edit, QWidget *parent, Qt::WFlags flags)
: QDialog(parent, flags), historyKeeper(histKeeper)
ImHistoryBrowser::ImHistoryBrowser(const std::string &peerId, QTextEdit *edit, QWidget *parent, Qt::WFlags flags)
: QDialog(parent, flags)
{
/* Invoke Qt Designer generated QObject setup routine */
ui.setupUi(this);
@ -97,9 +100,7 @@ ImHistoryBrowser::ImHistoryBrowser(const std::string &peerId, IMHistoryKeeper &h
m_isPrivateChat = !m_peerId.empty();
textEdit = edit;
connect(&historyKeeper, SIGNAL(historyAdd(IMHistoryItem)), this, SLOT(historyAdd(IMHistoryItem)));
connect(&historyKeeper, SIGNAL(historyRemove(IMHistoryItem)), this, SLOT(historyRemove(IMHistoryItem)));
connect(&historyKeeper, SIGNAL(historyClear()), this, SLOT(historyClear()));
connect(NotifyQt::getInstance(), SIGNAL(historyChanged(uint, int)), this, SLOT(historyChanged(uint, int)));
connect(ui.clearFilterButton, SIGNAL(clicked()), this, SLOT(clearFilter()));
connect(ui.filterPatternLineEdit, SIGNAL(textChanged(const QString &)), this, SLOT(filterRegExpChanged()));
@ -110,8 +111,6 @@ ImHistoryBrowser::ImHistoryBrowser(const std::string &peerId, IMHistoryKeeper &h
connect(ui.listWidget, SIGNAL(itemSelectionChanged()), this, SLOT(itemSelectionChanged()));
connect(ui.listWidget, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(customContextMenuRequested(QPoint)));
connect(NotifyQt::getInstance(), SIGNAL(privateChatChanged(int,int)), this, SLOT(privateChatChanged(int,int)));
ui.clearFilterButton->hide();
// embed smileys ?
@ -125,9 +124,6 @@ ImHistoryBrowser::ImHistoryBrowser(const std::string &peerId, IMHistoryKeeper &h
ui.listWidget->setItemDelegate(new IMHistoryItemDelegate);
// call once
privateChatChanged(NOTIFY_LIST_PRIVATE_OUTGOING_CHAT, NOTIFY_TYPE_ADD);
QByteArray geometry = Settings->valueFromGroup("HistorieBrowser", "Geometry", QByteArray()).toByteArray();
if (geometry.isEmpty() == false) {
restoreGeometry(geometry);
@ -138,7 +134,7 @@ ImHistoryBrowser::ImHistoryBrowser(const std::string &peerId, IMHistoryKeeper &h
ui.listWidget->installEventFilter(this);
m_createThread = new ImHistoryBrowserCreateItemsThread(this, historyKeeper);
m_createThread = new ImHistoryBrowserCreateItemsThread(this, m_peerId);
connect(m_createThread, SIGNAL(finished()), this, SLOT(createThreadFinished()));
connect(m_createThread, SIGNAL(progress(int,int)), this, SLOT(createThreadProgress(int,int)));
m_createThread->start();
@ -178,11 +174,11 @@ void ImHistoryBrowser::createThreadFinished()
m_createThread->deleteLater();
m_createThread = NULL;
QList<IMHistoryItem>::iterator histIt;
for (histIt = m_itemsAddedOnLoad.begin(); histIt != m_itemsAddedOnLoad.end(); histIt++) {
QList<HistoryMsg>::iterator histIt;
for (histIt = itemsAddedOnLoad.begin(); histIt != itemsAddedOnLoad.end(); histIt++) {
historyAdd(*histIt);
}
m_itemsAddedOnLoad.clear();
itemsAddedOnLoad.clear();
}
}
}
@ -210,39 +206,56 @@ bool ImHistoryBrowser::eventFilter(QObject *obj, QEvent *event)
return QDialog::eventFilter(obj, event);
}
void ImHistoryBrowser::historyAdd(IMHistoryItem item)
void ImHistoryBrowser::historyAdd(HistoryMsg& msg)
{
if (m_createThread) {
// create later
m_itemsAddedOnLoad.push_back(item);
itemsAddedOnLoad.push_back(msg);
return;
}
QListWidgetItem *itemWidget = createItem(item);
QListWidgetItem *itemWidget = createItem(msg);
if (itemWidget) {
ui.listWidget->addItem(itemWidget);
filterItems(itemWidget);
}
}
void ImHistoryBrowser::historyRemove(IMHistoryItem item)
void ImHistoryBrowser::historyChanged(uint msgId, int type)
{
int count = ui.listWidget->count();
for (int i = 0; i < count; i++) {
QListWidgetItem *itemWidget = ui.listWidget->item(i);
if (itemWidget->data(ROLE_HIID).toString().toInt() == item.hiid) {
delete(ui.listWidget->takeItem(i));
break;
if (type == NOTIFY_TYPE_ADD) {
/* history message added */
HistoryMsg msg;
if (rsHistory->getMessage(msgId, msg) == false) {
return;
}
historyAdd(msg);
return;
}
if (type == NOTIFY_TYPE_DEL) {
/* history message removed */
int count = ui.listWidget->count();
for (int i = 0; i < count; i++) {
QListWidgetItem *itemWidget = ui.listWidget->item(i);
if (itemWidget->data(ROLE_MSGID).toString().toUInt() == msgId) {
delete(ui.listWidget->takeItem(i));
break;
}
}
return;
}
if (type == NOTIFY_TYPE_MOD) {
/* clear history */
ui.listWidget->clear();
return;
}
}
void ImHistoryBrowser::historyClear()
{
ui.listWidget->clear();
}
void ImHistoryBrowser::fillItem(QListWidgetItem *itemWidget, IMHistoryItem &item)
void ImHistoryBrowser::fillItem(QListWidgetItem *itemWidget, HistoryMsg& msg)
{
unsigned int formatFlag = CHAT_FORMATMSG_EMBED_LINKS;
@ -250,49 +263,30 @@ void ImHistoryBrowser::fillItem(QListWidgetItem *itemWidget, IMHistoryItem &item
formatFlag |= CHAT_FORMATMSG_EMBED_SMILEYS;
}
std::list<ChatInfo>::iterator offineChatIt;
for(offineChatIt = m_savedOfflineChat.begin(); offineChatIt != m_savedOfflineChat.end(); offineChatIt++) {
/* are they public? */
if ((offineChatIt->chatflags & RS_CHAT_PRIVATE) == 0) {
/* this should not happen */
continue;
}
QDateTime sendTime = QDateTime::fromTime_t(offineChatIt->sendTime);
QString message = QString::fromStdWString(offineChatIt->msg);
if (IMHistoryKeeper::compareItem(item, false, offineChatIt->rsid, sendTime, message)) {
break;
}
}
ChatStyle::enumFormatMessage type;
if (offineChatIt == m_savedOfflineChat.end()) {
if (item.incoming) {
type = ChatStyle::FORMATMSG_INCOMING;
} else {
type = ChatStyle::FORMATMSG_OUTGOING;
}
if (msg.incoming) {
type = ChatStyle::FORMATMSG_INCOMING;
} else {
type = ChatStyle::FORMATMSG_OOUTGOING;
type = ChatStyle::FORMATMSG_OUTGOING;
}
QString formatMsg = style.formatMessage(type, item.name, item.sendTime, item.messageText, formatFlag);
QString messageText = QString::fromUtf8(msg.message.c_str());
QString formatMsg = style.formatMessage(type, QString::fromUtf8(msg.peerName.c_str()), QDateTime::fromTime_t(msg.sendTime), messageText, formatFlag);
itemWidget->setData(Qt::DisplayRole, qVariantFromValue(IMHistoryItemPainter(formatMsg)));
itemWidget->setData(ROLE_HIID, item.hiid);
itemWidget->setData(ROLE_MSGID, msg.msgId);
itemWidget->setData(ROLE_OFFLINE, (type == ChatStyle::FORMATMSG_OOUTGOING) ? true : false);
/* calculate plain text */
QTextDocument doc;
doc.setHtml(item.messageText);
doc.setHtml(messageText);
itemWidget->setData(ROLE_PLAINTEXT, doc.toPlainText());
}
QListWidgetItem *ImHistoryBrowser::createItem(IMHistoryItem &item)
QListWidgetItem *ImHistoryBrowser::createItem(HistoryMsg& msg)
{
QListWidgetItem *itemWidget = new QListWidgetItem;
fillItem(itemWidget, item);
fillItem(itemWidget, msg);
return itemWidget;
}
@ -346,7 +340,7 @@ void ImHistoryBrowser::filterItems(QListWidgetItem *item)
}
}
void ImHistoryBrowser::getSelectedItems(QList<int> &items)
void ImHistoryBrowser::getSelectedItems(std::list<uint32_t> &items)
{
QList<QListWidgetItem*> itemWidgets = ui.listWidget->selectedItems();
@ -356,16 +350,16 @@ void ImHistoryBrowser::getSelectedItems(QList<int> &items)
if (item->isHidden()) {
continue;
}
items.append(item->data(ROLE_HIID).toString().toInt());
items.push_back(item->data(ROLE_MSGID).toString().toInt());
}
}
void ImHistoryBrowser::itemSelectionChanged()
{
QList<int> hiids;
getSelectedItems(hiids);
std::list<uint32_t> msgIds;
getSelectedItems(msgIds);
if (hiids.size()) {
if (msgIds.size()) {
// activate buttons
ui.copyButton->setEnabled(true);
ui.removeButton->setEnabled(true);
@ -378,8 +372,8 @@ void ImHistoryBrowser::itemSelectionChanged()
void ImHistoryBrowser::customContextMenuRequested(QPoint /*pos*/)
{
QList<int> hiids;
getSelectedItems(hiids);
std::list<uint32_t> msgIds;
getSelectedItems(msgIds);
QListWidgetItem *currentItem = ui.listWidget->currentItem();
@ -400,7 +394,7 @@ void ImHistoryBrowser::customContextMenuRequested(QPoint /*pos*/)
}
}
if (hiids.size()) {
if (msgIds.size()) {
connect(selectAll, SIGNAL(triggered()), ui.listWidget, SLOT(selectAll()));
connect(copyMessage, SIGNAL(triggered()), this, SLOT(copyMessage()));
connect(removeMessages, SIGNAL(triggered()), this, SLOT(removeMessages()));
@ -429,11 +423,11 @@ void ImHistoryBrowser::copyMessage()
{
QListWidgetItem *currentItem = ui.listWidget->currentItem();
if (currentItem) {
int hiid = currentItem->data(ROLE_HIID).toString().toInt();
IMHistoryItem item;
if (historyKeeper.getMessage(hiid, item)) {
uint32_t msgId = currentItem->data(ROLE_MSGID).toString().toInt();
HistoryMsg msg;
if (rsHistory->getMessage(msgId, msg)) {
QTextDocument doc;
doc.setHtml(item.messageText);
doc.setHtml(QString::fromUtf8(msg.message.c_str()));
QApplication::clipboard()->setText(doc.toPlainText());
}
}
@ -441,15 +435,15 @@ void ImHistoryBrowser::copyMessage()
void ImHistoryBrowser::removeMessages()
{
QList<int> hiids;
getSelectedItems(hiids);
std::list<uint32_t> msgIds;
getSelectedItems(msgIds);
historyKeeper.removeMessages(hiids);
rsHistory->removeMessages(msgIds);
}
void ImHistoryBrowser::clearHistory()
{
historyKeeper.clear();
rsHistory->clear(m_peerId);
}
void ImHistoryBrowser::sendMessage()
@ -457,11 +451,11 @@ void ImHistoryBrowser::sendMessage()
if (textEdit) {
QListWidgetItem *currentItem = ui.listWidget->currentItem();
if (currentItem) {
int hiid = currentItem->data(ROLE_HIID).toString().toInt();
IMHistoryItem item;
if (historyKeeper.getMessage(hiid, item)) {
uint32_t msgId = currentItem->data(ROLE_MSGID).toString().toInt();
HistoryMsg msg;
if (rsHistory->getMessage(msgId, msg)) {
textEdit->clear();
textEdit->setText(item.messageText);
textEdit->setText(QString::fromUtf8(msg.message.c_str()));
textEdit->setFocus();
QTextCursor cursor = textEdit->textCursor();
cursor.movePosition(QTextCursor::End);
@ -471,45 +465,3 @@ void ImHistoryBrowser::sendMessage()
}
}
}
void ImHistoryBrowser::privateChatChanged(int list, int type)
{
if (m_isPrivateChat == false) {
return;
}
if (list == NOTIFY_LIST_PRIVATE_OUTGOING_CHAT) {
switch (type) {
case NOTIFY_TYPE_ADD:
{
m_savedOfflineChat.clear();
rsMsgs->getPrivateChatQueueCount(false) && rsMsgs->getPrivateChatQueue(false, m_peerId, m_savedOfflineChat);
}
break;
case NOTIFY_TYPE_DEL:
{
m_savedOfflineChat.clear();
}
break;
}
// recalculate items in history
int count = ui.listWidget->count();
for (int i = 0; i < count; i++) {
QListWidgetItem *itemWidget = ui.listWidget->item(i);
if (itemWidget->data(ROLE_OFFLINE).toBool()) {
int hiid = itemWidget->data(ROLE_HIID).toInt();
IMHistoryItem item;
if (historyKeeper.getMessage(hiid, item) == false) {
continue;
}
fillItem(itemWidget, item);
}
}
filterRegExpChanged();
}
}

View file

@ -27,13 +27,13 @@
#include <QThread>
#include <retroshare/rsmsgs.h>
#include "IMHistoryKeeper.h"
#include "gui/chat/ChatStyle.h"
#include "ui_ImHistoryBrowser.h"
class QTextEdit;
class ImHistoryBrowserCreateItemsThread;
class HistoryMsg;
class ImHistoryBrowser : public QDialog
{
@ -43,7 +43,7 @@ class ImHistoryBrowser : public QDialog
public:
/** Default constructor */
ImHistoryBrowser(const std::string &peerId, IMHistoryKeeper &histKeeper, QTextEdit *edit, QWidget *parent = 0, Qt::WFlags flags = 0);
ImHistoryBrowser(const std::string &peerId, QTextEdit *edit, QWidget *parent = 0, Qt::WFlags flags = 0);
/** Default destructor */
virtual ~ImHistoryBrowser();
@ -54,9 +54,7 @@ private slots:
void createThreadFinished();
void createThreadProgress(int current, int count);
void historyAdd(IMHistoryItem item);
void historyRemove(IMHistoryItem item);
void historyClear();
void historyChanged(uint msgId, int type);
void filterRegExpChanged();
void clearFilter();
@ -69,14 +67,15 @@ private slots:
void clearHistory();
void sendMessage();
void privateChatChanged(int list, int type);
private:
QListWidgetItem *createItem(IMHistoryItem &item);
void fillItem(QListWidgetItem *itemWidget, IMHistoryItem &item);
void historyAdd(HistoryMsg& msg);
QListWidgetItem *createItem(HistoryMsg& msg);
void fillItem(QListWidgetItem *itemWidget, HistoryMsg& msg);
void filterItems(QListWidgetItem *item = NULL);
void getSelectedItems(QList<int> &items);
void getSelectedItems(std::list<uint32_t> &items);
ImHistoryBrowserCreateItemsThread *m_createThread;
@ -84,11 +83,9 @@ private:
bool m_isPrivateChat;
QTextEdit *textEdit;
bool embedSmileys;
IMHistoryKeeper &historyKeeper;
ChatStyle style;
std::list<ChatInfo> m_savedOfflineChat;
QList<IMHistoryItem> m_itemsAddedOnLoad;
QList<HistoryMsg> itemsAddedOnLoad;
/** Qt Designer generated object */
Ui::ImHistoryBrowser ui;
@ -99,7 +96,7 @@ class ImHistoryBrowserCreateItemsThread : public QThread
Q_OBJECT
public:
ImHistoryBrowserCreateItemsThread(ImHistoryBrowser *parent, IMHistoryKeeper &histKeeper);
ImHistoryBrowserCreateItemsThread(ImHistoryBrowser *parent, const std::string& peerId);
~ImHistoryBrowserCreateItemsThread();
void run();
@ -113,8 +110,8 @@ public:
QList<QListWidgetItem*> m_items;
private:
IMHistoryKeeper &m_historyKeeper;
ImHistoryBrowser *m_historyBrowser;
std::string m_peerId;
volatile bool stopped;
};