[prev in list] [next in list] [prev in thread] [next in thread] 

List:       kopete-devel
Subject:    Re: [kopete-devel] History Import extension
From:       Timo_Schlüßler <timo () schluessler ! org>
Date:       2008-12-22 17:07:06
Message-ID: 494FC93A.3080902 () schluessler ! org
[Download RAW message or body]

[Attachment #2 (multipart/alternative)]


attached is a version where i changed the things you mentioned in irc ...

regards

Olivier Goffart wrote:
> Le mercredi 3 décembre 2008, Timo Schlüßler a écrit :
>   
>> Hello,
>>
>> attached is a patch and the two files which add the ability to import
>> logs from pidgin to kopete. The source-code files belong to
>> kdenetwork/kopete/plugins/history.
>> I changed HistoryLogger slightly so that appendMessage() uses the
>> timestamp from the message that is to be imported  but not
>> QDate::currentDate().
>>
>> I don't know what happens if you want to import multiuser chatlogs
>> because i haven't got any ... i would be glad if you can check that.
>> For me it works just fine, but the logs from pidgin are very unsteady.
>> anyway i hope it works for all pidgin logs.
>>     
>
> Hi,
>
> sorry for answering so late.
>
> You shouldn't change the reference date in the getDocument() function.
>
> You should understand that by definition, the 'int month' passed to the 
> getDocument function is the difference between the _current_ month and the 
> month of the document you ask.
>
> So you should not change the reference.
>
> What you should do instead is, in appendMessage, call the overloaded
> getDocument, that take a QDate instead.
> BUT then move the cache from the function that take an integer to this one.
>
>   
> ------------------------------------------------------------------------
>
> _______________________________________________
> kopete-devel mailing list
> kopete-devel@kde.org
> https://mail.kde.org/mailman/listinfo/kopete-devel
>   

[Attachment #5 (text/html)]

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
  <meta content="text/html;charset=ISO-8859-1" http-equiv="Content-Type">
  <title></title>
</head>
<body bgcolor="#ffffff" text="#000000">
attached is a version where i changed the things you mentioned in irc
...<br>
<br>
regards<br>
<br>
Olivier Goffart wrote:
<blockquote cite="mid:200812202242.48214.ogoffart@kde.org" type="cite">
  <pre wrap="">Le mercredi 3 d&eacute;cembre 2008, Timo Schl&uuml;&szlig;ler a \
&eacute;crit&nbsp;:  </pre>
  <blockquote type="cite">
    <pre wrap="">Hello,

attached is a patch and the two files which add the ability to import
logs from pidgin to kopete. The source-code files belong to
kdenetwork/kopete/plugins/history.
I changed HistoryLogger slightly so that appendMessage() uses the
timestamp from the message that is to be imported  but not
QDate::currentDate().

I don't know what happens if you want to import multiuser chatlogs
because i haven't got any ... i would be glad if you can check that.
For me it works just fine, but the logs from pidgin are very unsteady.
anyway i hope it works for all pidgin logs.
    </pre>
  </blockquote>
  <pre wrap=""><!---->
Hi,

sorry for answering so late.

You shouldn't change the reference date in the getDocument() function.

You should understand that by definition, the 'int month' passed to the 
getDocument function is the difference between the _current_ month and the 
month of the document you ask.

So you should not change the reference.

What you should do instead is, in appendMessage, call the overloaded
getDocument, that take a QDate instead.
BUT then move the cache from the function that take an integer to this one.

  </pre>
  <pre wrap="">
<hr size="4" width="90%">
_______________________________________________
kopete-devel mailing list
<a class="moz-txt-link-abbreviated" \
href="mailto:kopete-devel@kde.org">kopete-devel@kde.org</a> <a \
class="moz-txt-link-freetext" \
href="https://mail.kde.org/mailman/listinfo/kopete-devel">https://mail.kde.org/mailman/listinfo/kopete-devel</a>
  </pre>
</blockquote>
</body>
</html>


["historyimport.cpp" (text/plain)]

/*
    historyimport.cpp

    Copyright (c) 2008 by Timo Schluessler

    Kopete    (c) 2008 by the Kopete developers  <kopete-devel@kde.org>

    *************************************************************************
    *                                                                       *
    * 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.                                   *
    *                                                                       *
    *************************************************************************
*/


#include "historyimport.h"

#include "historylogger.h"

#include <kdebug.h>
#include <klocale.h>

#include <kopetecontactlist.h>
#include <kopetemetacontact.h>
#include <kopeteprotocol.h>
#include <kopeteaccount.h>

HistoryImport::HistoryImport(QWidget *parent)
	: KDialog(parent)
{

	// set dialog settings
	setButtons(KDialog::Ok | KDialog::Details | KDialog::Cancel);
	setWindowTitle(KDialog::makeStandardCaption(i18n("Import History")));
	setButtonText(KDialog::Ok, i18n("Import listed logs"));

	// create widgets
	QWidget *w = new QWidget(this);
	QGridLayout *l = new QGridLayout(w);

	display = new QTextEdit(w);
	display->setReadOnly(true);
	treeView = new QTreeView(w);

	QPushButton *fromPidgin = new QPushButton(i18n("Get history from &Pidgin"), w);
	
	l->addWidget(treeView, 0, 0, 1, 3);
	l->addWidget(display, 0, 4, 1, 10);
	l->addWidget(fromPidgin, 1, 0);

	setMainWidget(w);


	// create details widget
	QWidget *details = new QWidget(w);
	QVBoxLayout *dL = new QVBoxLayout(w);

	QTextEdit *detailsEdit = new QTextEdit(details);
	detailsEdit->setReadOnly(true);
	selectByHand = new QCheckBox(i18n("Select log directory by hand"), details);
	
	dL->addWidget(selectByHand);
	dL->addWidget(detailsEdit);
	details->setLayout(dL);

	setDetailsWidget(details);
	detailsCursor = QTextCursor(detailsEdit->document());

	// create model for treeView
	QStandardItemModel *model = new QStandardItemModel(treeView);
	treeView->setModel(model);
	model->setHorizontalHeaderLabels(QStringList(i18n("Parsed History")));

	// connect everything
	connect(treeView, SIGNAL(clicked(const QModelIndex &)), this, SLOT(itemClicked(const \
QModelIndex &)));  connect(fromPidgin, SIGNAL(clicked()), this, \
SLOT(importPidgin()));  connect(this, SIGNAL(okClicked()), this, SLOT(save()));

	// define variables
	amount = 0;
	cancel = false;
	pidginImported = false;

	timeFormats << "(MM/dd/yyyy hh:mm:ss)" << "(MM/dd/yyyy hh:mm:ss AP)" << "(MM/dd/yy \
hh:mm:ss)" << "(MM/dd/yy hh:mm:ss AP)" << "(dd.MM.yyyy hh:mm:ss)" << "(dd.MM.yyyy \
hh:mm:ss AP)" << "(dd.MM.yy hh:mm:ss)" << "(dd.MM.yyyy hh:mm:ss AP)" << "(dd/MM/yyyy \
hh:mm:ss)" << "(dd/MM/yyyy hh:mm:ss AP)" << "(dd/MM/yy hh:mm:ss)" << "(dd/MM/yy \
hh:mm:ss AP)";

	show();
}

HistoryImport::~HistoryImport(void)
{
}

void HistoryImport::save(void)
{
	QProgressDialog progress(i18n("Saving logs to disk ..."), i18n("Abort Saving"), 0, \
amount, this);  progress.setWindowTitle(i18n("Saving"));

	Log log;

	foreach (log, logs) {
		HistoryLogger logger(log.other, this);
		Message message;
		foreach (message, log.messages) {
			Kopete::Message kMessage;
			if (message.incoming) {
				kMessage = Kopete::Message(log.other, log.me);
				kMessage.setDirection(Kopete::Message::Inbound);
			} else {
				kMessage = Kopete::Message(log.me, log.other);
				kMessage.setDirection(Kopete::Message::Outbound);
			}
			kMessage.setPlainBody(message.text);
			kMessage.setTimestamp(message.timestamp);
			logger.appendMessage(kMessage, log.other);
			
			progress.setValue(progress.value()+1);
			qApp->processEvents();
			if (progress.wasCanceled()) {
				cancel = true;
				break;
			}
		}
		if (cancel)
			break;
	}
}

void HistoryImport::displayLog(struct Log *log)
{
	Message message;

	QList<QStandardItem*> items;
	QStringList strings;

	items << static_cast<QStandardItemModel*>(treeView->model())->invisibleRootItem();
	items << NULL << NULL << NULL;
	strings << "" << "" << "";

	foreach(message, log->messages) {
		amount++; // for QProgressDialog in save()

		strings[0] = log->other->protocol()->pluginId() + " (" + \
log->other->account()->accountId() + ')';  strings[1] = log->other->nickName();
		strings[2] = message.timestamp.toString("yyyy-MM-dd");

		bool update = false;
		int i;
		for (i=1; i<4; i++) {
			if (update || !items.at(i) || items.at(i)->data(Qt::DisplayRole) != \
strings.at(i-1)) {  items[i] = findItem(strings.at(i-1), items.at(i-1));
				update = true;
			} //else
				//kDebug(14310) << "using cached item";
		}

		if (!items.at(3)->data(Qt::UserRole).isValid())
			items[3]->setData((int)logs.indexOf(*log), Qt::UserRole);
	}

}

QStandardItem * HistoryImport::findItem(const QString &text, QStandardItem *parent)
{
	int i;
	bool found = false;
	QStandardItem *child = 0L;

	for (i=0; i < parent->rowCount(); i++) {
		child = parent->child(i, 0);
		if (child->data(Qt::DisplayRole) == text) {
			found = true;
			break;
		}
	}
	if (!found) {
		child = new QStandardItem(text);
		parent->appendRow(child);
	}

	return child;
}
		
void HistoryImport::itemClicked(const QModelIndex &index)
{
	QVariant id = index.data(Qt::UserRole);

	if (id.canConvert<int>()) {
		Log log = logs.at(id.toInt());
		display->document()->clear();
		QTextCursor cursor(display->document());

		Message message;
		QDate date = QDate::fromString(index.data(Qt::DisplayRole).toString(), \
"yyyy-MM-dd");  foreach (message, log.messages) {
			if (date != message.timestamp.date())
				continue;
			cursor.insertText(message.timestamp.toString("hh:mm:ss "));
			if (message.incoming)
				cursor.insertText(log.other->nickName().append(": "));
			else
				cursor.insertText(log.me->nickName().append(": "));
			cursor.insertText(message.text);
			cursor.insertBlock();
		}
	}
}

int HistoryImport::countLogs(QDir dir, int depth)
{
	int res = 0;
	QStack<int> pos;
	QStringList files;
	pos.push(0);

	depth++;

	forever {
		files = dir.entryList(QDir::Dirs | QDir::NoDotAndDotDot);

		if (pos.size() == depth) {
			res += dir.entryList(QDir::Files).size();
		}
		if (files.isEmpty() || files.size() <= pos.top() || pos.size() == depth) {
			dir.cdUp();
			pos.pop();
			if (pos.isEmpty())
				break;
			pos.top()++;
		}
		else if (pos.size() != depth) {
			dir.cd(files.at(pos.top()));
			pos.push(0);
		}
	}

	return res;
}

void HistoryImport::importPidgin()
{
	if (pidginImported) {
		if (QMessageBox::question(this,
		 i18n("Are you sure?"),
		 i18n("You already imported logs from pidgin. If you do it twice, each message is \
imported twice!\nAre you sure you want to continue?"),  QMessageBox::Yes | \
QMessageBox::No,  QMessageBox::No) != QMessageBox::Yes)
			return;
	}
	pidginImported = true;

	QDir logDir = QDir::homePath();
	if (selectByHand->isChecked() || !logDir.cd(".purple/logs"))
		logDir = QFileDialog::getExistingDirectory(mainWidget(), i18n("Select log \
directory"), QDir::homePath());

	int total = countLogs(logDir, 3);
	QProgressDialog progress(i18n("Parsing history from pidgin ..."), i18n("Abort \
parsing"), 0, total, mainWidget());  progress.setWindowTitle(i18n("Parsing \
history"));  progress.show();
	cancel = false;

	QString protocolFolder;
	foreach (protocolFolder, logDir.entryList(QDir::Dirs | QDir::NoDotAndDotDot)) {
		logDir.cd(protocolFolder);

		QString accountFolder;
		foreach (accountFolder, logDir.entryList(QDir::Dirs | QDir::NoDotAndDotDot)) {
			logDir.cd(accountFolder);

			// TODO use findContact?
			Kopete::ContactList * cList = Kopete::ContactList::self();
			QList<Kopete::Contact *> meList = cList->myself()->contacts();
			Kopete::Contact *me;
			bool found = false;
			foreach (me, meList) {
				if (me->protocol()->pluginId().contains(protocolFolder, Qt::CaseInsensitive) &&
				 me->account()->accountId().contains(accountFolder, Qt::CaseInsensitive)) {
					found = true;
					break;
				}
			}
			if (!found) {
				detailsCursor.insertText(i18n("WARNING: Can't find matching account for %1 \
(%2)!\n").arg(accountFolder).arg(protocolFolder));  logDir.cdUp();
				continue;
			}

			QString chatPartner;
			foreach (chatPartner, logDir.entryList(QDir::Dirs | QDir::NoDotAndDotDot)) {
				logDir.cd(chatPartner);

				Kopete::Contact *other = cList->findContact(me->protocol()->pluginId(), \
me->account()->accountId(), chatPartner);  struct Log log;
				if (!other) {
					detailsCursor.insertText(i18n("WARNING: Can't find %1 (%2) in your contact list. \
Found logs will not be imported!\n").arg(chatPartner).arg(protocolFolder));  \
logDir.cdUp();  continue;
				}
				else {
					log.me = me;
					log.other = other;
				}

				QString logFile;
				QStringList filter;
				filter << "*.html" << "*.txt";
				foreach(logFile, logDir.entryList(filter, QDir::Files)) {
					QFile file(logDir.filePath(logFile));
					if (!file.open(QIODevice::ReadOnly)) {
						detailsCursor.insertText(i18n("WARNING: Can't open file %1. \
Skipping.\n").arg(logDir.filePath(logFile)));  continue;
					}

					if (logFile.endsWith(".html"))
						parsePidginXml(file, &log, QDate::fromString(logFile.left(10), "yyyy-MM-dd"));
					else if (logFile.endsWith(".txt"))
						parsePidginTxt(file, &log, QDate::fromString(logFile.left(10), "yyyy-MM-dd"));

					file.close();

					progress.setValue(progress.value()+1);
					qApp->processEvents();
					if (cancel || progress.wasCanceled()) {
						cancel = true;
						break;
					}
				}

				logs.append(log);
				displayLog(&log);

				if (cancel)
					break;
				logDir.cdUp();
			}
			if (cancel)
				break;
			logDir.cdUp();
		}	
		if (cancel)
			break;
		logDir.cdUp();
	}

}

bool HistoryImport::isNickIncoming(const QString &nick, struct Log *log)
{
	bool incoming;

	if (nick == log->me->nickName())
		incoming = false;
	else if (nick == log->other->nickName())
		incoming = true;
	else if (knownNicks.contains(nick)) 
		incoming = knownNicks.value(nick);
	else {
		int r = QMessageBox::question(NULL,
			i18n("Can't map nickname to account"),
			i18n("Did you use \"%1\" as nickname in history?").arg(nick),
			QMessageBox::Yes | QMessageBox::No | QMessageBox::Abort);

		if (r == QMessageBox::Yes) {
			knownNicks.insert(nick, true);
			incoming = true;
		}
		else if (r == QMessageBox::No) {
			knownNicks.insert(nick, false);
			incoming = false;
		}
		else {
			cancel = true;
			return false;
		}
	}
	return incoming;
}

QDateTime HistoryImport::extractTime(const QString &string, QDate ref)
{
	QDateTime dateTime;
	QTime time;

	// try some formats used by pidgin
	if      ((time = QTime::fromString(string, "(hh:mm:ss)"))    .isValid());
	else if ((time = QTime::fromString(string, "(hh:mm:ss AP)")) .isValid());
	else {
		QString format;
		foreach (format, timeFormats) {
			if ((dateTime = QDateTime::fromString(string, format)).isValid())
				break;
		}
	}

	// check if the century in dateTime is equal to that of our date reference
	if (dateTime.isValid()) {
		int diff = ref.year() - dateTime.date().year();
		dateTime = dateTime.addYears(diff - (diff % 100));
	}

	// if string contains only a time we use ref as date
	if (time.isValid())
		dateTime = QDateTime(ref, time);

	// inform the user about the date problems
	if (!dateTime.isValid())
		detailsCursor.insertText(i18n("WARNING: can't parse date \"%1\". You may want to \
edit the file containing this date manually. (example for recognized date strings: \
\"05/31/2008 15:24:30\")\n").arg(string, dateTime.toString("yyyy-MM-dd hh:mm:ss")));


	return dateTime;
}

void HistoryImport::parsePidginTxt(QFile &file, struct Log *log, QDate date)
{
	QByteArray line;
	QTime time;
	QDateTime dateTime;
	QString messageText, nick;
	bool incoming = false; // =false to make the compiler not complain

	while (!file.atEnd()) {
		line = file.readLine();

		if (line[0] == '(') {
			if (!messageText.isEmpty()) {
				// messageText contains an unwished newline at the end
				if (messageText.endsWith("\n"))
					messageText.remove(-1, 1);
				struct Message message;
				message.incoming = incoming;
				message.text = messageText;
				message.timestamp = dateTime;
				log->messages.append(message);
				messageText.clear();
			}

			int endTime = line.indexOf(')')+1;
			dateTime = extractTime(line.left(endTime), date);

			int nickEnd = QRegExp("\\s").indexIn(line, endTime + 1);
			// TODO what if a nickname consists of two words? is this possible?
			// the following while can't be used because in status logs there is no : after \
the nickname :(  //while (line[nickEnd-1] != ':')
			//	nickEnd = QRegExp("\\").indexIn(line, nickEnd);
			if (line[nickEnd -1] != ':') // this line is a status message
				continue;

			nick = line.mid(endTime+1, nickEnd - endTime - 2); // -2 to delete the colon

			incoming = isNickIncoming(nick, log);
			if (cancel)
				return;

			messageText = line.mid(nickEnd + 1);
		}
		else if (line[0] == ' ') {
			// an already started message is continued in this line
			int start = QRegExp("\\S").indexIn(line);
			messageText.append('\n' + line.mid(start));
		}
	}
	if (!messageText.isEmpty()) {
		struct Message message;
		message.incoming = incoming;
		message.text = messageText;
		message.timestamp = dateTime;
		log->messages.append(message);
		messageText.clear();
	}
}
			

void HistoryImport::parsePidginXml(QFile &file, struct Log * log, QDate date)
{
	bool incoming = false, inMessage = false, textComes = false;
	QString messageText, status;
	QTime time;
	QDateTime dateTime;

	// unfortunately pidgin doesn't write <... /> for the <meta> tag
	QByteArray data = file.readAll();
	if (data.contains("<meta")) {
		int metaEnd = data.indexOf(">", data.indexOf("<meta"));
		if (data.at(metaEnd-1) != '/')
			data.insert(metaEnd, '/');
	}

	QXmlStreamReader reader(data);

	while (!reader.atEnd()) {
		reader.readNext();

		if (reader.isStartElement() && reader.name() == "font" && \
!reader.attributes().value("color").isEmpty()) {  if \
(reader.attributes().value("color") == "#A82F2F")  incoming = true;
			else
				incoming = false;

			while (reader.readNext() != QXmlStreamReader::Characters);

			dateTime = extractTime(reader.text().toString(), date);
			inMessage = true;
		}
		if (inMessage && reader.isStartElement() && reader.name() == "b") {
			reader.readNext();
			status = reader.text().toString();
			textComes = true;
		}
		else if (textComes && reader.isCharacters()) {
			messageText += reader.text().toString();
		}
		else if (reader.isStartElement() && reader.name() == "br" && \
!messageText.isEmpty()) {  messageText.remove(0, 1); // remove the leading blank
		
			struct Message message;
			message.incoming = incoming;
			message.text = messageText;
			message.timestamp = dateTime;
			log->messages.append(message);

			messageText.clear();
			textComes = false;
			inMessage = false;
		}
			 
	}
	if (reader.hasError()) {
		// we ignore error 4: premature end of document
		if (reader.error() != 4) {
			int i, pos = 0;
			for (i=1;i<reader.lineNumber();i++)
				pos = data.indexOf('\n', pos) + 1;
			detailsCursor.insertText(i18n("WARNING: XML parser error in %1 at line %2, \
character %3: %4").  \
arg(file.fileName()).arg(reader.lineNumber()).arg(reader.columnNumber()).arg(reader.errorString()));
  detailsCursor.insertBlock();
			detailsCursor.insertText(i18n("\t%1").arg(QString(data.mid(pos, data.indexOf('\n', \
pos) - pos))));  detailsCursor.insertBlock();
		}
	}
}

#include "historyimport.moc"


["historyimport.h" (text/plain)]

/*
    historylogger.cpp

    Copyright (c) 2008 by Timo Schluessler       <timo@schluessler.org>

    Kopete    (c) 2008 by the Kopete developers  <kopete-devel@kde.org>

    *************************************************************************
    *                                                                       *
    * 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.                                   *
    *                                                                       *
    *************************************************************************
*/


#ifndef HISTORYIMPORT_H
#define HISTORYIMPORT_H

#include <QtGui>

#include <kdialog.h>

#include "kopeteglobal.h"
#include "kopetecontact.h"
#include "kopetemessage.h"

/**
 * @author Timo Schluessler <timo@schluessler.org>
 */
class HistoryImport : public KDialog
{
Q_OBJECT
public:

	HistoryImport(QWidget *parent);
	~HistoryImport();

private:

	/**
	 * Used for internal storage of a message.
	 */
	struct Message {
		bool incoming;
		QString text;
		QDateTime timestamp;
	};
		
	/**
	 * Holds the messages sent and received between two specified contacts.
	 */
	struct Log {
		Kopete::Contact *me;
		Kopete::Contact *other;
		QList<Message> messages;
		/**
		 * Comparison between the Message lists is not neccessary because we need this operator
		 * only in displayLog() to get the index of this log in logs.
		 */
		bool operator==(const struct Log & cmp) {
			if (cmp.me == me && cmp.other == other/* && other.messages == messages*/)
				return true;
			else
				return false;
		}
	};
		
	/**
	 * Parses @param file and appends the found messages to @param log.
	 */
	void parsePidginXml(QFile &file, struct Log *log, QDate date);

	/**
	 * Parses @param file and appends the found messages to @param log.
	 */
	void parsePidginTxt(QFile &file, struct Log *log, QDate date);


	/**
	 * Inserts @param log into treeView and prepares to display it when clicking on it.
	 */
	void displayLog(struct Log *log);

	/**
	 * Looks up if an item with @param text exists already as child of @param parent.
	 * If not, it creates one.
	 */
	QStandardItem * findItem(const QString &text, QStandardItem *parent);

	/**
	 * @return the number of files found in @param depth th subdir of @param dir.
	 */
	int countLogs(QDir dir, int depth);

	/**
	 * Checks if nickname @param nick can be mapped to either @param log ->me or @param log ->other.
	 * If not it asks the user if it is his nickname or someone elses.
	 */
	bool isNickIncoming(const QString &nick, struct Log *log);

	/**
	 * Trys to extract the time from @param string using formats specified in timeFormats.
	 * @param ref is used when @param string doesn't contain a date or to adjust a found date.
	 * @param ref is taken from the filename of the log.
	 */
	QDateTime extractTime(const QString &string, QDate ref);

	QStringList timeFormats;

	QTreeView *treeView;
	QTextEdit *display;

	/**
	 * Used for adding details to the details widget.
	 */
	QTextCursor detailsCursor;

	/**
	 * Enables/disables auto search for log dirs.
	 */
	QCheckBox *selectByHand;

	/**
	 * Contains all already parsed logs.
	 */
	QList<Log> logs;

	/**
	 * Used for mapping nickname to account. See isNickIncoming().
	 */
	QHash<QString, bool> knownNicks;

	/**
	 * To warn the user when importing logs twice
	 */
	bool pidginImported;

	int amount;
	bool cancel;

private slots:
	/**
	 * Starts parsing history from pidgin.
	 * Default path is ~/.purple/logs.
	 */
	void importPidgin(void);

	void save(void);
	void itemClicked(const QModelIndex & index);
};

#endif

["kopete-history-import-1.0.patch" (text/plain)]

Index: historylogger.cpp
===================================================================
--- historylogger.cpp	(revision 900154)
+++ historylogger.cpp	(working copy)
@@ -255,7 +255,9 @@
 		return;
 	}
 
-	QDomDocument doc=getDocument(c,0);
+	QDate date = msg.timestamp().date();
+		
+	QDomDocument doc=getDocument(c, QDate::currentDate().month() - date.month() - \
(QDate::currentDate().year() - date.year()) * 12);  QDomElement docElem = \
doc.documentElement();  
 	if(docElem.isNull())
@@ -266,8 +268,8 @@
 		QDomElement headElem = doc.createElement( "head" );
 		docElem.appendChild( headElem );
 		QDomElement dateElem = doc.createElement( "date" );
-		dateElem.setAttribute( "year",  QString::number(QDate::currentDate().year()) );
-		dateElem.setAttribute( "month", QString::number(QDate::currentDate().month()) );
+		dateElem.setAttribute( "year",  QString::number(date.year()) );
+		dateElem.setAttribute( "month", QString::number(date.month()) );
 		headElem.appendChild(dateElem);
 		QDomElement myselfElem = doc.createElement( "contact" );
 		myselfElem.setAttribute( "type",  "myself" );
@@ -293,7 +295,7 @@
 	// On hight-traffic channel, saving can take lots of CPU. (because the file is big)
 	// So i wait a time proportional to the time needed to save..
 
-	const QString filename=getFileName(c,QDate::currentDate());
+	const QString filename=getFileName(c, date);
 	if(!m_toSaveFileName.isEmpty() && m_toSaveFileName != filename)
 	{ //that mean the contact or the month has changed, save it now.
 		saveToDisk();
Index: historyviewer.ui
===================================================================
--- historyviewer.ui	(revision 900154)
+++ historyviewer.ui	(working copy)
@@ -57,6 +57,13 @@
       </widget>
      </item>
      <item>
+      <widget class="QPushButton" name="importHistory" >
+       <property name="text" >
+        <string>Import History</string>
+       </property>
+      </widget>
+     </item>
+     <item>
       <widget class="QLabel" name="textLabel1_2" >
        <property name="text" >
         <string>Message Filter:</string>
@@ -73,7 +80,7 @@
        </property>
        <property name="minimumSize" >
         <size>
-         <width>200</width>
+         <width>140</width>
          <height>0</height>
         </size>
        </property>
Index: historydialog.cpp
===================================================================
--- historydialog.cpp	(revision 900154)
+++ historydialog.cpp	(working copy)
@@ -18,6 +18,7 @@
 
 #include "historydialog.h"
 #include "historylogger.h"
+#include "historyimport.h"
 #include "ui_historyviewer.h"
 #include "kopetemetacontact.h"
 #include "kopeteprotocol.h"
@@ -161,6 +162,7 @@
 	connect(mMainWidget->searchLine, SIGNAL(textChanged(const QString&)), this, \
SLOT(slotSearchTextChanged(const QString&)));  connect(mMainWidget->contactComboBox, \
SIGNAL(activated(int)), this, SLOT(slotContactChanged(int)));  \
connect(mMainWidget->messageFilterBox, SIGNAL(activated(int)), this, \
SLOT(slotFilterChanged(int ))); +	connect(mMainWidget->importHistory, \
SIGNAL(clicked()), this, SLOT(slotImportHistory()));  connect(mHtmlPart, \
SIGNAL(popupMenu(const QString &, const QPoint &)), this, SLOT(slotRightClick(const \
QString &, const QPoint &)));  
 	//initActions
@@ -614,4 +616,10 @@
 	connect( QApplication::clipboard(), SIGNAL( selectionChanged()), mHtmlPart, \
SLOT(slotClearSelection()));  }
 
+void HistoryDialog::slotImportHistory(void)
+{
+	HistoryImport importer(this);
+	importer.exec();
+}
+
 #include "historydialog.moc"
Index: historydialog.h
===================================================================
--- historydialog.h	(revision 900154)
+++ historydialog.h	(working copy)
@@ -96,6 +96,8 @@
 		void slotCopy();
 		void slotCopyURL();
 
+		void slotImportHistory();
+
 	private:
 		enum Disabled { Prev=1, Next=2 };
 		void refreshEnabled( /*Disabled*/ uint disabled );
Index: CMakeLists.txt
===================================================================
--- CMakeLists.txt	(revision 900154)
+++ CMakeLists.txt	(working copy)
@@ -11,7 +11,8 @@
    historydialog.cpp 
    historylogger.cpp 
    converter.cpp 
-   historyguiclient.cpp )
+   historyguiclient.cpp
+	historyimport.cpp )
 
 kde4_add_ui_files(kopete_history_PART_SRCS historyviewer.ui )
 



_______________________________________________
kopete-devel mailing list
kopete-devel@kde.org
https://mail.kde.org/mailman/listinfo/kopete-devel


[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic