You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
krusader/krusader/Dialogs/popularurls.cpp

308 lines
7.9 KiB

#include <tdemessagebox.h>
#include <tdelocale.h>
#include <tqpushbutton.h>
#include <tdelistview.h>
#include <kiconloader.h>
#include <tdelistviewsearchline.h>
#include <tqheader.h>
#include <tqlayout.h>
#include <tqlabel.h>
#include <tdetoolbarbutton.h>
#include "../krusader.h"
#include "../krslots.h"
#include "popularurls.h"
#define STARTING_RANK 20
#define INCREASE 2
#define DECREASE 1
PopularUrls::PopularUrls(TQObject *parent, const char *name) : TQObject(parent, name),
head(0), tail(0), count(0) {
dlg = new PopularUrlsDlg();
}
PopularUrls::~PopularUrls() {
clearList();
delete dlg;
}
void PopularUrls::clearList() {
if (head) {
UrlNodeP p=head, tmp;
while (p) {
tmp = p;
p=p->next;
delete tmp;
}
}
ranks.clear();
head = tail = 0;
}
void PopularUrls::save() {
TDEConfigGroupSaver svr(krConfig, "Private");
// prepare the string list containing urls and int list with ranks
TQStringList urlList;
TQValueList<int> rankList;
UrlNodeP p = head;
while (p) {
urlList << p->url.prettyURL();
rankList << p->rank;
p = p->next;
}
krConfig->writeEntry("PopularUrls", urlList);
krConfig->writeEntry("PopularUrlsRank", rankList);
}
void PopularUrls::load() {
TDEConfigGroupSaver svr(krConfig, "Private");
TQStringList urlList = krConfig->readListEntry("PopularUrls");
TQValueList<int> rankList = krConfig->readIntListEntry("PopularUrlsRank");
if (urlList.count() != rankList.count()) {
KMessageBox::error(krApp, i18n("Saved 'Popular Urls' are invalid. List will be cleared"));
return;
}
clearList();
count = 0;
// iterate through both lists and
TQStringList::Iterator uit;
TQValueList<int>::Iterator rit;
for (uit=urlList.begin(), rit=rankList.begin(); uit!=urlList.end() && rit!=rankList.end(); ++uit, ++rit) {
UrlNodeP node = new UrlNode;
node->url = KURL::fromPathOrURL( *uit );
node->rank = *rit;
appendNode(node);
ranks.insert(*uit, node);
}
}
// returns a url list with the 'max' top popular urls
KURL::List PopularUrls::getMostPopularUrls(int max) {
// get at most 'max' urls
KURL::List list;
UrlNodeP p = head;
int tmp = 0;
if (maxUrls < max) max = maxUrls; // don't give more than maxUrls
while (p && tmp < max) {
list << p->url;
p = p->next;
++tmp;
}
return list;
}
// adds a url to the list, or increase rank of an existing url, making
// sure to bump it up the list if needed
void PopularUrls::addUrl(const KURL& url) {
KURL tmpurl = url;
tmpurl.adjustPath(1); // make a uniform trailing slash policy
UrlNodeP pnode;
decreaseRanks();
if (!head) { // if the list is empty ... (assumes dict to be empty as well)
pnode = new UrlNode;
pnode->rank = STARTING_RANK;
pnode->url = tmpurl;
appendNode(pnode);
ranks.insert(tmpurl.url(), head);
} else {
pnode = ranks.find(tmpurl.url());
if (!pnode) { // is the added url new? if so, append it
pnode = new UrlNode;
pnode->rank = STARTING_RANK;
pnode->url = tmpurl;
appendNode(pnode);
ranks.insert(tmpurl.url(), pnode);
} else {
pnode->rank += INCREASE;
}
}
// do we need to change location for this one?
relocateIfNeeded(pnode);
// too many urls?
if (count > maxUrls) removeNode(tail);
//dumpList();
}
// checks if 'node' needs to be bumped-up the ranking list and does it if needed
void PopularUrls::relocateIfNeeded(UrlNodeP node) {
if (node->prev && (node->prev->rank < node->rank)) {
// iterate until we find the correct place to put it
UrlNodeP tmp = node->prev->prev;
while (tmp) {
if (tmp->rank >= node->rank)
break; // found it!
else tmp = tmp->prev;
}
// now, if tmp isn't null, we need to move node to tmp->next
// else move it to become head
removeNode(node);
insertNode(node, tmp);
}
}
// iterate over the list, decreasing each url's rank
// this is very naive, but a 1..30 for loop is acceptable (i hope)
void PopularUrls::decreaseRanks() {
if (head) {
UrlNodeP p=head;
while (p) {
if (p->rank-DECREASE>=0)
p->rank -= DECREASE;
else p->rank = 0;
p=p->next;
}
}
}
// removes a node from the list, but doesn't free memory!
// note: this will be buggy in case the list becomes empty (which should never happen)
void PopularUrls::removeNode(UrlNodeP node) {
if (node->prev) {
if (tail == node) tail = node->prev;
node->prev->next = node->next;
}
if (node->next) {
if (head == node) head = node->next;
node->next->prev = node->prev;
}
--count;
}
void PopularUrls::insertNode(UrlNodeP node, UrlNodeP after) {
if (!after) { // make node head
node->next = head;
node->prev = 0;
head->prev = node;
head = node;
} else {
if (tail == after) tail = node;
node->prev = after;
node->next = after->next;
if( node->next ) {
after->next->prev = node;
after->next = node;
}
}
++count;
}
// appends 'node' to the end of the list, collecting garbage if needed
void PopularUrls::appendNode(UrlNodeP node) {
if (!tail) { // creating the first element
head = tail = node;
node->prev = node->next = 0;
} else {
node->next = 0;
node->prev = tail;
tail->next = node;
tail = node;
}
++count;
}
void PopularUrls::dumpList() {
UrlNodeP p = head;
printf("====start %d====\n",count);
while (p) {
printf("%d : %s\n", p->rank, p->url.url().latin1());
p = p->next;
}
fflush(stdout);
}
void PopularUrls::showDialog() {
KURL::List list = getMostPopularUrls(maxUrls);
dlg->run(list);
if (dlg->result() == -1) return;
SLOTS->refresh(list[dlg->result()]);
//printf("running %s\n", list[dlg->result()].url().latin1());fflush(stdout);
}
// ===================================== PopularUrlsDlg ======================================
PopularUrlsDlg::PopularUrlsDlg():
KDialogBase(Plain, i18n("Popular Urls"), Close, KDialogBase::NoDefault, krApp) {
TQGridLayout *layout = new TQGridLayout( plainPage(), 0, KDialog::spacingHint() );
// listview to contain the urls
urls = new TDEListView(plainPage());
urls->header()->hide();
urls->addColumn("");
urls->setSorting(-1);
urls->setVScrollBarMode(TQScrollView::AlwaysOn);
// quick search
TQToolButton *btn = new TQToolButton(plainPage());
btn->setIconSet(SmallIcon("locationbar_erase"));
search = new TDEListViewSearchLine(plainPage(), urls);
search->setTrapReturnKey(true);
TQLabel *lbl = new TQLabel(search, i18n(" &Search: "), plainPage());
layout->addWidget(btn,0,0);
layout->addWidget(lbl,0,1);
layout->addWidget(search,0,2);
layout->addMultiCellWidget(urls,1,1,0,2);
setMaximumSize(600, 500);
setTabOrder(search, urls);
setTabOrder(urls, actionButton(Close));
connect(urls, TQ_SIGNAL(executed(TQListViewItem*)),
this, TQ_SLOT(slotItemSelected(TQListViewItem*)));
connect(urls, TQ_SIGNAL(returnPressed(TQListViewItem*)),
this, TQ_SLOT(slotItemSelected(TQListViewItem*)));
connect(btn, TQ_SIGNAL(clicked()), search, TQ_SLOT(clear()));
connect(search, TQ_SIGNAL(returnPressed(const TQString&)),
this, TQ_SLOT(slotSearchReturnPressed(const TQString&)));
}
void PopularUrlsDlg::slotItemSelected(TQListViewItem *it) {
selection = urls->itemIndex(it);
accept();
}
void PopularUrlsDlg::slotSearchReturnPressed(const TQString&) {
urls->setFocus();
// select the first visible item
TQListViewItemIterator it( urls );
while ( it.current() ) {
if ( it.current()->isVisible() ) {
urls->setSelected(it.current(), true);
urls->setCurrentItem(it.current());
break;
} else ++it;
}
}
PopularUrlsDlg::~PopularUrlsDlg() {
delete search;
delete urls;
}
void PopularUrlsDlg::run(KURL::List list) {
// populate the listview
urls->clear();
KURL::List::Iterator it;
for (it = list.begin(); it!=list.end(); ++it) {
TDEListViewItem *item = new TDEListViewItem(urls, urls->lastItem());
item->setText(0, (*it).isLocalFile() ? (*it).path() : (*it).prettyURL());
item->setPixmap(0, (*it).isLocalFile() ? SmallIcon("folder") : SmallIcon("folder_html"));
}
//urls->setCurrentItem(urls->firstChild());
//urls->setSelected(urls->firstChild(), true);
setMinimumSize(urls->sizeHint().width()+45, 400);
search->clear();
search->setFocus();
selection = -1;
exec();
}
#include "popularurls.moc"