|
|
|
/*
|
|
|
|
kopetehistorydialog.cpp - Kopete History Dialog
|
|
|
|
|
|
|
|
Copyright (c) 2002 by Richard Stellingwerff <remenic@linuxfromscratch.org>
|
|
|
|
Copyright (c) 2004 by Stefan Gehn <metz AT gehn.net>
|
|
|
|
|
|
|
|
Kopete (c) 2002-2004 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 "historydialog.h"
|
|
|
|
#include "historylogger.h"
|
|
|
|
#include "historyviewer.h"
|
|
|
|
#include "kopetemetacontact.h"
|
|
|
|
#include "kopeteprotocol.h"
|
|
|
|
#include "kopeteaccount.h"
|
|
|
|
#include "kopetecontactlist.h"
|
|
|
|
#include "kopeteprefs.h"
|
|
|
|
|
|
|
|
#include <dom/dom_doc.h>
|
|
|
|
#include <dom/dom_element.h>
|
|
|
|
#include <dom/html_document.h>
|
|
|
|
#include <dom/html_element.h>
|
|
|
|
#include <khtml_part.h>
|
|
|
|
#include <khtmlview.h>
|
|
|
|
|
|
|
|
#include <tqpushbutton.h>
|
|
|
|
#include <tqlineedit.h>
|
|
|
|
#include <tqcheckbox.h>
|
|
|
|
#include <tqlayout.h>
|
|
|
|
#include <tqdir.h>
|
|
|
|
#include <tqdatetime.h>
|
|
|
|
#include <tqheader.h>
|
|
|
|
#include <tqlabel.h>
|
|
|
|
#include <tqclipboard.h>
|
|
|
|
|
|
|
|
#include <kapplication.h>
|
|
|
|
#include <kdebug.h>
|
|
|
|
#include <kiconloader.h>
|
|
|
|
#include <klocale.h>
|
|
|
|
#include <krun.h>
|
|
|
|
#include <kstandarddirs.h>
|
|
|
|
#include <klistview.h>
|
|
|
|
#include <klistviewsearchline.h>
|
|
|
|
#include <kprogress.h>
|
|
|
|
#include <kiconloader.h>
|
|
|
|
#include <kcombobox.h>
|
|
|
|
#include <kpopupmenu.h>
|
|
|
|
#include <kstdaction.h>
|
|
|
|
#include <kaction.h>
|
|
|
|
|
|
|
|
class KListViewDateItem : public KListViewItem
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
KListViewDateItem(KListView* parent, TQDate date, Kopete::MetaContact *mc);
|
|
|
|
TQDate date() { return mDate; }
|
|
|
|
Kopete::MetaContact *metaContact() { return mMetaContact; }
|
|
|
|
|
|
|
|
public:
|
|
|
|
int compare(TQListViewItem *i, int col, bool ascending) const;
|
|
|
|
private:
|
|
|
|
TQDate mDate;
|
|
|
|
Kopete::MetaContact *mMetaContact;
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
KListViewDateItem::KListViewDateItem(KListView* parent, TQDate date, Kopete::MetaContact *mc)
|
|
|
|
: KListViewItem(parent, date.toString(Qt::ISODate), mc->displayName())
|
|
|
|
{
|
|
|
|
mDate = date;
|
|
|
|
mMetaContact = mc;
|
|
|
|
}
|
|
|
|
|
|
|
|
int KListViewDateItem::compare(TQListViewItem *i, int col, bool ascending) const
|
|
|
|
{
|
|
|
|
if (col)
|
|
|
|
return TQListViewItem::compare(i, col, ascending);
|
|
|
|
|
|
|
|
//compare dates - do NOT use ascending var here
|
|
|
|
KListViewDateItem* item = static_cast<KListViewDateItem*>(i);
|
|
|
|
if ( mDate < item->date() )
|
|
|
|
return -1;
|
|
|
|
return ( mDate > item->date() );
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
HistoryDialog::HistoryDialog(Kopete::MetaContact *mc, TQWidget* parent,
|
|
|
|
const char* name) : KDialogBase(parent, name, false,
|
|
|
|
i18n("History for %1").arg(mc->displayName()), 0), mSearching(false)
|
|
|
|
{
|
|
|
|
TQString fontSize;
|
|
|
|
TQString htmlCode;
|
|
|
|
TQString fontStyle;
|
|
|
|
|
|
|
|
kdDebug(14310) << k_funcinfo << "called." << endl;
|
|
|
|
setWFlags(TQt::WDestructiveClose); // send TQT_SIGNAL(closing()) on quit
|
|
|
|
|
|
|
|
// FIXME: Allow to show this dialog for only one contact
|
|
|
|
mMetaContact = mc;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Widgets initializations
|
|
|
|
mMainWidget = new HistoryViewer(this, "HistoryDialog::mMainWidget");
|
|
|
|
mMainWidget->searchLine->setFocus();
|
|
|
|
mMainWidget->searchLine->setTrapReturnKey (true);
|
|
|
|
mMainWidget->searchLine->setTrapReturnKey(true);
|
|
|
|
mMainWidget->searchErase->setPixmap(BarIcon("locationbar_erase"));
|
|
|
|
|
|
|
|
mMainWidget->contactComboBox->insertItem(i18n("All"));
|
|
|
|
mMetaContactList = Kopete::ContactList::self()->metaContacts();
|
|
|
|
TQPtrListIterator<Kopete::MetaContact> it(mMetaContactList);
|
|
|
|
for(; it.current(); ++it)
|
|
|
|
{
|
|
|
|
mMainWidget->contactComboBox->insertItem((*it)->displayName());
|
|
|
|
}
|
|
|
|
|
|
|
|
if (mMetaContact)
|
|
|
|
mMainWidget->contactComboBox->setCurrentItem(mMetaContactList.find(mMetaContact)+1);
|
|
|
|
|
|
|
|
mMainWidget->dateSearchLine->setListView(mMainWidget->dateListView);
|
|
|
|
mMainWidget->dateListView->setSorting(0, 0); //newest-first
|
|
|
|
|
|
|
|
setMainWidget(mMainWidget);
|
|
|
|
|
|
|
|
// Initializing HTML Part
|
|
|
|
mMainWidget->htmlFrame->setFrameStyle(TQFrame::WinPanel | TQFrame::Sunken);
|
|
|
|
TQVBoxLayout *l = new TQVBoxLayout(mMainWidget->htmlFrame);
|
|
|
|
mHtmlPart = new KHTMLPart(mMainWidget->htmlFrame, "htmlHistoryView");
|
|
|
|
|
|
|
|
//Security settings, we don't need this stuff
|
|
|
|
mHtmlPart->setJScriptEnabled(false);
|
|
|
|
mHtmlPart->setJavaEnabled(false);
|
|
|
|
mHtmlPart->setPluginsEnabled(false);
|
|
|
|
mHtmlPart->setMetaRefreshEnabled(false);
|
|
|
|
mHtmlPart->setOnlyLocalReferences(true);
|
|
|
|
|
|
|
|
mHtmlView = mHtmlPart->view();
|
|
|
|
mHtmlView->setMarginWidth(4);
|
|
|
|
mHtmlView->setMarginHeight(4);
|
|
|
|
mHtmlView->setFocusPolicy(TQ_NoFocus);
|
|
|
|
mHtmlView->setSizePolicy(
|
|
|
|
TQSizePolicy(TQSizePolicy::Expanding, TQSizePolicy::Expanding));
|
|
|
|
l->addWidget(mHtmlView);
|
|
|
|
|
|
|
|
TQTextOStream( &fontSize ) << KopetePrefs::prefs()->fontFace().pointSize();
|
|
|
|
fontStyle = "<style>.hf { font-size:" + fontSize + ".0pt; font-family:" + KopetePrefs::prefs()->fontFace().family() + "; color: " + KopetePrefs::prefs()->textColor().name() + "; }</style>";
|
|
|
|
|
|
|
|
mHtmlPart->begin();
|
|
|
|
htmlCode = "<html><head>" + fontStyle + "</head><body class=\"hf\"></body></html>";
|
|
|
|
mHtmlPart->write( TQString::fromLatin1( htmlCode.latin1() ) );
|
|
|
|
mHtmlPart->end();
|
|
|
|
|
|
|
|
|
|
|
|
connect(mHtmlPart->browserExtension(), TQT_SIGNAL(openURLRequestDelayed(const KURL &, const KParts::URLArgs &)),
|
|
|
|
this, TQT_SLOT(slotOpenURLRequest(const KURL &, const KParts::URLArgs &)));
|
|
|
|
connect(mMainWidget->dateListView, TQT_SIGNAL(clicked(TQListViewItem*)), this, TQT_SLOT(dateSelected(TQListViewItem*)));
|
|
|
|
connect(mMainWidget->searchButton, TQT_SIGNAL(clicked()), this, TQT_SLOT(slotSearch()));
|
|
|
|
connect(mMainWidget->searchLine, TQT_SIGNAL(returnPressed()), this, TQT_SLOT(slotSearch()));
|
|
|
|
connect(mMainWidget->searchLine, TQT_SIGNAL(textChanged(const TQString&)), this, TQT_SLOT(slotSearchTextChanged(const TQString&)));
|
|
|
|
connect(mMainWidget->searchErase, TQT_SIGNAL(clicked()), this, TQT_SLOT(slotSearchErase()));
|
|
|
|
connect(mMainWidget->contactComboBox, TQT_SIGNAL(activated(int)), this, TQT_SLOT(slotContactChanged(int)));
|
|
|
|
connect(mMainWidget->messageFilterBox, TQT_SIGNAL(activated(int)), this, TQT_SLOT(slotFilterChanged(int )));
|
|
|
|
connect(mHtmlPart, TQT_SIGNAL(popupMenu(const TQString &, const TQPoint &)), this, TQT_SLOT(slotRightClick(const TQString &, const TQPoint &)));
|
|
|
|
|
|
|
|
//initActions
|
|
|
|
KActionCollection* ac = new KActionCollection(this);
|
|
|
|
mCopyAct = KStdAction::copy( TQT_TQOBJECT(this), TQT_SLOT(slotCopy()), ac );
|
|
|
|
mCopyURLAct = new KAction( i18n( "Copy Link Address" ), TQString::fromLatin1( "editcopy" ), 0, TQT_TQOBJECT(this), TQT_SLOT( slotCopyURL() ), ac );
|
|
|
|
|
|
|
|
resize(650, 700);
|
|
|
|
centerOnScreen(this);
|
|
|
|
|
|
|
|
// show the dialog before people get impatient
|
|
|
|
show();
|
|
|
|
|
|
|
|
// Load history dates in the listview
|
|
|
|
init();
|
|
|
|
}
|
|
|
|
|
|
|
|
HistoryDialog::~HistoryDialog()
|
|
|
|
{
|
|
|
|
mSearching = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
void HistoryDialog::init()
|
|
|
|
{
|
|
|
|
if(mMetaContact)
|
|
|
|
{
|
|
|
|
HistoryLogger logger(mMetaContact, TQT_TQOBJECT(this));
|
|
|
|
init(mMetaContact);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
TQPtrListIterator<Kopete::MetaContact> it(mMetaContactList);
|
|
|
|
for(; it.current(); ++it)
|
|
|
|
{
|
|
|
|
HistoryLogger logger(*it, TQT_TQOBJECT(this));
|
|
|
|
init(*it);
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
initProgressBar(i18n("Loading..."),mInit.dateMCList.count());
|
|
|
|
TQTimer::singleShot(0,this,TQT_SLOT(slotLoadDays()));
|
|
|
|
}
|
|
|
|
|
|
|
|
void HistoryDialog::slotLoadDays()
|
|
|
|
{
|
|
|
|
if(mInit.dateMCList.isEmpty())
|
|
|
|
{
|
|
|
|
if (!mMainWidget->searchLine->text().isEmpty())
|
|
|
|
TQTimer::singleShot(0, this, TQT_SLOT(slotSearch()));
|
|
|
|
doneProgressBar();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
DMPair pair(mInit.dateMCList.first());
|
|
|
|
mInit.dateMCList.pop_front();
|
|
|
|
HistoryLogger logger(pair.metaContact(), TQT_TQOBJECT(this));
|
|
|
|
TQValueList<int> dayList = logger.getDaysForMonth(pair.date());
|
|
|
|
for (unsigned int i=0; i<dayList.count(); i++)
|
|
|
|
{
|
|
|
|
TQDate c2Date(pair.date().year(),pair.date().month(),dayList[i]);
|
|
|
|
if (mInit.dateMCList.find(pair) == mInit.dateMCList.end())
|
|
|
|
new KListViewDateItem(mMainWidget->dateListView, c2Date, pair.metaContact());
|
|
|
|
}
|
|
|
|
mMainWidget->searchProgress->advance(1);
|
|
|
|
TQTimer::singleShot(0,this,TQT_SLOT(slotLoadDays()));
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
void HistoryDialog::init(Kopete::MetaContact *mc)
|
|
|
|
{
|
|
|
|
TQPtrList<Kopete::Contact> contacts=mc->contacts();
|
|
|
|
TQPtrListIterator<Kopete::Contact> it( contacts );
|
|
|
|
|
|
|
|
for( ; it.current(); ++it )
|
|
|
|
{
|
|
|
|
init(*it);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void HistoryDialog::init(Kopete::Contact *c)
|
|
|
|
{
|
|
|
|
// Get year and month list
|
|
|
|
TQRegExp rx( "\\.(\\d\\d\\d\\d)(\\d\\d)" );
|
|
|
|
const TQString contact_in_filename=c->contactId().replace( TQRegExp( TQString::fromLatin1( "[./~?*]" ) ), TQString::fromLatin1( "-" ) );
|
|
|
|
TQFileInfo *fi;
|
|
|
|
|
|
|
|
|
|
|
|
// BEGIN check if there are Kopete 0.7.x
|
|
|
|
TQDir d1(locateLocal("data",TQString("kopete/logs/")+
|
|
|
|
c->protocol()->pluginId().replace( TQRegExp(TQString::fromLatin1("[./~?*]")),TQString::fromLatin1("-"))
|
|
|
|
));
|
|
|
|
d1.setFilter( TQDir::Files | TQDir::NoSymLinks );
|
|
|
|
d1.setSorting( TQDir::Name );
|
|
|
|
|
|
|
|
const TQFileInfoList *list1 = d1.entryInfoList();
|
|
|
|
if ( list1 != 0 )
|
|
|
|
{
|
|
|
|
TQFileInfoListIterator it1( *list1 );
|
|
|
|
while ( (fi = it1.current()) != 0 )
|
|
|
|
{
|
|
|
|
if(fi->fileName().contains(contact_in_filename))
|
|
|
|
{
|
|
|
|
rx.search(fi->fileName());
|
|
|
|
|
|
|
|
TQDate cDate = TQDate(rx.cap(1).toInt(), rx.cap(2).toInt(), 1);
|
|
|
|
|
|
|
|
DMPair pair(cDate, c->metaContact());
|
|
|
|
mInit.dateMCList.append(pair);
|
|
|
|
|
|
|
|
}
|
|
|
|
++it1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// END of kopete 0.7.x check
|
|
|
|
|
|
|
|
TQString logDir = locateLocal("data",TQString("kopete/logs/")+
|
|
|
|
c->protocol()->pluginId().replace( TQRegExp(TQString::fromLatin1("[./~?*]")),TQString::fromLatin1("-")) +
|
|
|
|
TQString::fromLatin1( "/" ) +
|
|
|
|
c->account()->accountId().replace( TQRegExp( TQString::fromLatin1( "[./~?*]" ) ), TQString::fromLatin1( "-" ) )
|
|
|
|
);
|
|
|
|
TQDir d(logDir);
|
|
|
|
d.setFilter( TQDir::Files | TQDir::NoSymLinks );
|
|
|
|
d.setSorting( TQDir::Name );
|
|
|
|
const TQFileInfoList *list = d.entryInfoList();
|
|
|
|
if ( list != 0 )
|
|
|
|
{
|
|
|
|
TQFileInfoListIterator it( *list );
|
|
|
|
while ( (fi = it.current()) != 0 )
|
|
|
|
{
|
|
|
|
if(fi->fileName().contains(contact_in_filename))
|
|
|
|
{
|
|
|
|
|
|
|
|
rx.search(fi->fileName());
|
|
|
|
|
|
|
|
// We search for an item in the list view with the same year. If then we add the month
|
|
|
|
TQDate cDate = TQDate(rx.cap(1).toInt(), rx.cap(2).toInt(), 1);
|
|
|
|
|
|
|
|
DMPair pair(cDate, c->metaContact());
|
|
|
|
mInit.dateMCList.append(pair);
|
|
|
|
}
|
|
|
|
++it;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void HistoryDialog::dateSelected(TQListViewItem* it)
|
|
|
|
{
|
|
|
|
KListViewDateItem *item = static_cast<KListViewDateItem*>(it);
|
|
|
|
|
|
|
|
if (!item) return;
|
|
|
|
|
|
|
|
TQDate chosenDate = item->date();
|
|
|
|
|
|
|
|
HistoryLogger logger(item->metaContact(), TQT_TQOBJECT(this));
|
|
|
|
TQValueList<Kopete::Message> msgs=logger.readMessages(chosenDate);
|
|
|
|
|
|
|
|
setMessages(msgs);
|
|
|
|
}
|
|
|
|
|
|
|
|
void HistoryDialog::setMessages(TQValueList<Kopete::Message> msgs)
|
|
|
|
{
|
|
|
|
// Clear View
|
|
|
|
DOM::HTMLElement htmlBody = mHtmlPart->htmlDocument().body();
|
|
|
|
while(htmlBody.hasChildNodes())
|
|
|
|
htmlBody.removeChild(htmlBody.childNodes().item(htmlBody.childNodes().length() - 1));
|
|
|
|
// ----
|
|
|
|
|
|
|
|
TQString dir = (TQApplication::reverseLayout() ? TQString::fromLatin1("rtl") :
|
|
|
|
TQString::fromLatin1("ltr"));
|
|
|
|
|
|
|
|
TQValueList<Kopete::Message>::iterator it = msgs.begin();
|
|
|
|
|
|
|
|
|
|
|
|
TQString accountLabel;
|
|
|
|
TQString resultHTML = "<b><font color=\"red\">" + (*it).timestamp().date().toString() + "</font></b><br/>";
|
|
|
|
DOM::HTMLElement newNode = mHtmlPart->document().createElement(TQString::fromLatin1("span"));
|
|
|
|
newNode.setAttribute(TQString::fromLatin1("dir"), dir);
|
|
|
|
newNode.setInnerHTML(resultHTML);
|
|
|
|
mHtmlPart->htmlDocument().body().appendChild(newNode);
|
|
|
|
|
|
|
|
// Populating HTML Part with messages
|
|
|
|
for ( it = msgs.begin(); it != msgs.end(); ++it )
|
|
|
|
{
|
|
|
|
if ( mMainWidget->messageFilterBox->currentItem() == 0
|
|
|
|
|| ( mMainWidget->messageFilterBox->currentItem() == 1 && (*it).direction() == Kopete::Message::Inbound )
|
|
|
|
|| ( mMainWidget->messageFilterBox->currentItem() == 2 && (*it).direction() == Kopete::Message::Outbound ) )
|
|
|
|
{
|
|
|
|
resultHTML = "";
|
|
|
|
|
|
|
|
if (accountLabel.isEmpty() || accountLabel != (*it).from()->account()->accountLabel())
|
|
|
|
// If the message's account is new, just specify it to the user
|
|
|
|
{
|
|
|
|
if (!accountLabel.isEmpty())
|
|
|
|
resultHTML += "<br/><br/><br/>";
|
|
|
|
resultHTML += "<b><font color=\"blue\">" + (*it).from()->account()->accountLabel() + "</font></b><br/>";
|
|
|
|
}
|
|
|
|
accountLabel = (*it).from()->account()->accountLabel();
|
|
|
|
|
|
|
|
TQString body = (*it).parsedBody();
|
|
|
|
|
|
|
|
if (!mMainWidget->searchLine->text().isEmpty())
|
|
|
|
// If there is a search, then we hightlight the keywords
|
|
|
|
{
|
|
|
|
body = body.replace(mMainWidget->searchLine->text(), "<span style=\"background-color:yellow\">" + mMainWidget->searchLine->text() + "</span>", false);
|
|
|
|
}
|
|
|
|
|
|
|
|
resultHTML += "(<b>" + (*it).timestamp().time().toString() + "</b>) "
|
|
|
|
+ ((*it).direction() == Kopete::Message::Outbound ?
|
|
|
|
"<font color=\"" + KopetePrefs::prefs()->textColor().dark().name() + "\"><b>></b></font> "
|
|
|
|
: "<font color=\"" + KopetePrefs::prefs()->textColor().light(200).name() + "\"><b><</b></font> ")
|
|
|
|
+ body + "<br/>";
|
|
|
|
|
|
|
|
newNode = mHtmlPart->document().createElement(TQString::fromLatin1("span"));
|
|
|
|
newNode.setAttribute(TQString::fromLatin1("dir"), dir);
|
|
|
|
newNode.setInnerHTML(resultHTML);
|
|
|
|
|
|
|
|
mHtmlPart->htmlDocument().body().appendChild(newNode);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void HistoryDialog::slotFilterChanged(int /* index */)
|
|
|
|
{
|
|
|
|
dateSelected(mMainWidget->dateListView->currentItem());
|
|
|
|
}
|
|
|
|
|
|
|
|
void HistoryDialog::slotOpenURLRequest(const KURL &url, const KParts::URLArgs &/*args*/)
|
|
|
|
{
|
|
|
|
kdDebug(14310) << k_funcinfo << "url=" << url.url() << endl;
|
|
|
|
new KRun(url, 0, false); // false = non-local files
|
|
|
|
}
|
|
|
|
|
|
|
|
// Disable search button if there is no search text
|
|
|
|
void HistoryDialog::slotSearchTextChanged(const TQString& searchText)
|
|
|
|
{
|
|
|
|
if (searchText.isEmpty())
|
|
|
|
{
|
|
|
|
mMainWidget->searchButton->setEnabled(false);
|
|
|
|
slotSearchErase();
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
mMainWidget->searchButton->setEnabled(true);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void HistoryDialog::listViewShowElements(bool s)
|
|
|
|
{
|
|
|
|
KListViewDateItem* item = static_cast<KListViewDateItem*>(mMainWidget->dateListView->firstChild());
|
|
|
|
while (item != 0)
|
|
|
|
{
|
|
|
|
item->setVisible(s);
|
|
|
|
item = static_cast<KListViewDateItem*>(item->nextSibling());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Erase the search line, show all date/metacontacts items in the list (accordint to the
|
|
|
|
// metacontact selected in the combobox)
|
|
|
|
void HistoryDialog::slotSearchErase()
|
|
|
|
{
|
|
|
|
mMainWidget->searchLine->clear();
|
|
|
|
listViewShowElements(true);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* How does the search work
|
|
|
|
* ------------------------
|
|
|
|
* We do the search respecting the current metacontact filter item. To do this, we iterate over the
|
|
|
|
* elements in the KListView (KListViewDateItems) and, for each one, we iterate over its subcontacts,
|
|
|
|
* manually searching the log files of each one. To avoid searching files twice, the months that have
|
|
|
|
* been searched already are stored in searchedMonths. The matches are placed in the matches TQMap.
|
|
|
|
* Finally, the current date item is checked in the matches TQMap, and if it is present, it is shown.
|
|
|
|
*
|
|
|
|
* Keyword highlighting is done in setMessages() : if the search field isn't empty, we highlight the
|
|
|
|
* search keyword.
|
|
|
|
*
|
|
|
|
* The search is _not_ case sensitive
|
|
|
|
*/
|
|
|
|
void HistoryDialog::slotSearch()
|
|
|
|
{
|
|
|
|
if (mMainWidget->dateListView->childCount() == 0) return;
|
|
|
|
|
|
|
|
TQRegExp rx("^ <msg.*time=\"(\\d+) \\d+:\\d+:\\d+\" >([^<]*)<");
|
|
|
|
TQMap<TQDate, TQValueList<Kopete::MetaContact*> > monthsSearched;
|
|
|
|
TQMap<TQDate, TQValueList<Kopete::MetaContact*> > matches;
|
|
|
|
|
|
|
|
// cancel button pressed
|
|
|
|
if (mSearching)
|
|
|
|
{
|
|
|
|
listViewShowElements(true);
|
|
|
|
goto searchFinished;
|
|
|
|
}
|
|
|
|
|
|
|
|
listViewShowElements(false);
|
|
|
|
|
|
|
|
initProgressBar(i18n("Searching..."), mMainWidget->dateListView->childCount());
|
|
|
|
mMainWidget->searchButton->setText(i18n("&Cancel"));
|
|
|
|
mSearching = true;
|
|
|
|
|
|
|
|
// iterate over items in the date list widget
|
|
|
|
for(KListViewDateItem *curItem = static_cast<KListViewDateItem*>(mMainWidget->dateListView->firstChild());
|
|
|
|
curItem != 0;
|
|
|
|
curItem = static_cast<KListViewDateItem *>(curItem->nextSibling())
|
|
|
|
)
|
|
|
|
{
|
|
|
|
tqApp->processEvents();
|
|
|
|
if (!mSearching) return;
|
|
|
|
|
|
|
|
TQDate month(curItem->date().year(),curItem->date().month(),1);
|
|
|
|
// if we haven't searched the relevant history logs, search them now
|
|
|
|
if (!monthsSearched[month].contains(curItem->metaContact()))
|
|
|
|
{
|
|
|
|
monthsSearched[month].push_back(curItem->metaContact());
|
|
|
|
TQPtrList<Kopete::Contact> contacts = curItem->metaContact()->contacts();
|
|
|
|
for(TQPtrListIterator<Kopete::Contact> it( contacts ); it.current(); ++it)
|
|
|
|
{
|
|
|
|
// get filename and open file
|
|
|
|
TQString filename(HistoryLogger::getFileName(*it, curItem->date()));
|
|
|
|
if (!TQFile::exists(filename)) continue;
|
|
|
|
TQFile file(filename);
|
|
|
|
file.open(IO_ReadOnly);
|
|
|
|
if (!file.isOpen())
|
|
|
|
{
|
|
|
|
kdWarning(14310) << k_funcinfo << "Error opening " <<
|
|
|
|
file.name() << ": " << TQString(file.errorString()).ascii() << endl;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
TQTextStream stream(&file);
|
|
|
|
TQString textLine;
|
|
|
|
while(!stream.atEnd())
|
|
|
|
{
|
|
|
|
textLine = stream.readLine();
|
|
|
|
if (textLine.contains(mMainWidget->searchLine->text(), false))
|
|
|
|
{
|
|
|
|
if(rx.search(textLine) != -1)
|
|
|
|
{
|
|
|
|
// only match message body
|
|
|
|
if (rx.cap(2).contains(mMainWidget->searchLine->text()))
|
|
|
|
matches[TQDate(curItem->date().year(),curItem->date().month(),rx.cap(1).toInt())].push_back(curItem->metaContact());
|
|
|
|
}
|
|
|
|
// this will happen when multiline messages are searched, properly
|
|
|
|
// parsing the files would fix this
|
|
|
|
else { }
|
|
|
|
}
|
|
|
|
tqApp->processEvents();
|
|
|
|
if (!mSearching) return;
|
|
|
|
}
|
|
|
|
file.close();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// relevant logfiles have been searched now, check if current date matches
|
|
|
|
if (matches[curItem->date()].contains(curItem->metaContact()))
|
|
|
|
curItem->setVisible(true);
|
|
|
|
|
|
|
|
// Next date item
|
|
|
|
mMainWidget->searchProgress->advance(1);
|
|
|
|
}
|
|
|
|
|
|
|
|
searchFinished:
|
|
|
|
mMainWidget->searchButton->setText(i18n("Se&arch"));
|
|
|
|
mSearching = false;
|
|
|
|
doneProgressBar();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// When a contact is selected in the combobox. Item 0 is All contacts.
|
|
|
|
void HistoryDialog::slotContactChanged(int index)
|
|
|
|
{
|
|
|
|
mMainWidget->dateListView->clear();
|
|
|
|
if (index == 0)
|
|
|
|
{
|
|
|
|
setCaption(i18n("History for All Contacts"));
|
|
|
|
mMetaContact = 0;
|
|
|
|
init();
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
mMetaContact = mMetaContactList.at(index-1);
|
|
|
|
setCaption(i18n("History for %1").arg(mMetaContact->displayName()));
|
|
|
|
init();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void HistoryDialog::initProgressBar(const TQString& text, int nbSteps)
|
|
|
|
{
|
|
|
|
mMainWidget->searchProgress->setTotalSteps(nbSteps);
|
|
|
|
mMainWidget->searchProgress->setProgress(0);
|
|
|
|
mMainWidget->searchProgress->show();
|
|
|
|
mMainWidget->statusLabel->setText(text);
|
|
|
|
}
|
|
|
|
|
|
|
|
void HistoryDialog::doneProgressBar()
|
|
|
|
{
|
|
|
|
mMainWidget->searchProgress->hide();
|
|
|
|
mMainWidget->statusLabel->setText(i18n("Ready"));
|
|
|
|
}
|
|
|
|
|
|
|
|
void HistoryDialog::slotRightClick(const TQString &url, const TQPoint &point)
|
|
|
|
{
|
|
|
|
KPopupMenu *chatWindowPopup = 0L;
|
|
|
|
chatWindowPopup = new KPopupMenu();
|
|
|
|
|
|
|
|
if ( !url.isEmpty() )
|
|
|
|
{
|
|
|
|
mURL = url;
|
|
|
|
mCopyURLAct->plug( chatWindowPopup );
|
|
|
|
chatWindowPopup->insertSeparator();
|
|
|
|
}
|
|
|
|
mCopyAct->setEnabled( mHtmlPart->hasSelection() );
|
|
|
|
mCopyAct->plug( chatWindowPopup );
|
|
|
|
|
|
|
|
connect( chatWindowPopup, TQT_SIGNAL( aboutToHide() ), chatWindowPopup, TQT_SLOT( deleteLater() ) );
|
|
|
|
chatWindowPopup->popup(point);
|
|
|
|
}
|
|
|
|
|
|
|
|
void HistoryDialog::slotCopy()
|
|
|
|
{
|
|
|
|
TQString qsSelection;
|
|
|
|
qsSelection = mHtmlPart->selectedText();
|
|
|
|
if ( qsSelection.isEmpty() ) return;
|
|
|
|
|
|
|
|
disconnect( kapp->clipboard(), TQT_SIGNAL( selectionChanged()), mHtmlPart, TQT_SLOT(slotClearSelection()));
|
|
|
|
TQApplication::tqclipboard()->setText(qsSelection, TQClipboard::Clipboard);
|
|
|
|
TQApplication::tqclipboard()->setText(qsSelection, TQClipboard::Selection);
|
|
|
|
connect( kapp->clipboard(), TQT_SIGNAL( selectionChanged()), mHtmlPart, TQT_SLOT(slotClearSelection()));
|
|
|
|
}
|
|
|
|
|
|
|
|
void HistoryDialog::slotCopyURL()
|
|
|
|
{
|
|
|
|
disconnect( kapp->clipboard(), TQT_SIGNAL( selectionChanged()), mHtmlPart, TQT_SLOT(slotClearSelection()));
|
|
|
|
TQApplication::tqclipboard()->setText( mURL, TQClipboard::Clipboard);
|
|
|
|
TQApplication::tqclipboard()->setText( mURL, TQClipboard::Selection);
|
|
|
|
connect( kapp->clipboard(), TQT_SIGNAL( selectionChanged()), mHtmlPart, TQT_SLOT(slotClearSelection()));
|
|
|
|
}
|
|
|
|
|
|
|
|
#include "historydialog.moc"
|