00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
#include "kbookmark.h"
00023
#include <qvaluestack.h>
00024
#include <kdebug.h>
00025
#include <kmimetype.h>
00026
#include <kstringhandler.h>
00027
#include <kinputdialog.h>
00028
#include <kglobal.h>
00029
#include <klocale.h>
00030
#include <assert.h>
00031
#include <kapplication.h>
00032
#include <dcopclient.h>
00033
#include <kbookmarkmanager.h>
00034
00035 KBookmarkGroup::KBookmarkGroup()
00036 : KBookmark(
QDomElement() )
00037 {
00038 }
00039
00040 KBookmarkGroup::KBookmarkGroup(
QDomElement elem )
00041 : KBookmark(elem)
00042 {
00043 }
00044
00045 QString KBookmarkGroup::groupAddress()
const
00046
{
00047
if (m_address.isEmpty())
00048 m_address = address();
00049
return m_address;
00050 }
00051
00052 bool KBookmarkGroup::isOpen()
const
00053
{
00054
return element.attribute(
"folded") ==
"no";
00055 }
00056
00057
00058
static QDomElement firstElement(
QDomNode n)
00059 {
00060
while(!n.isNull() && !n.isElement())
00061 n = n.nextSibling();
00062
return n.toElement();
00063 }
00064
00065
00066
static QDomElement lastElement(
QDomNode n)
00067 {
00068
while(!n.isNull() && !n.isElement())
00069 n = n.previousSibling();
00070
return n.toElement();
00071 }
00072
00073 KBookmark
KBookmarkGroup::first()
const
00074
{
00075
return KBookmark( nextKnownTag( firstElement(element.firstChild()),
true ) );
00076 }
00077
00078 KBookmark
KBookmarkGroup::previous(
const KBookmark & current )
const
00079
{
00080
return KBookmark( nextKnownTag( lastElement(current.element.previousSibling()),
false ) );
00081 }
00082
00083 KBookmark
KBookmarkGroup::next(
const KBookmark & current )
const
00084
{
00085
return KBookmark( nextKnownTag( firstElement(current.element.nextSibling()),
true ) );
00086 }
00087
00088
00089
00090
QDomElement KBookmarkGroup::nextKnownTag(
QDomElement start,
bool goNext )
const
00091
{
00092
static const QString & bookmark = KGlobal::staticQString(
"bookmark");
00093
static const QString & folder = KGlobal::staticQString(
"folder");
00094
static const QString & separator = KGlobal::staticQString(
"separator");
00095
00096
for(
QDomNode n = start; !n.isNull(); )
00097 {
00098
QDomElement elem = n.toElement();
00099
QString tag = elem.tagName();
00100
if (tag == folder || tag == bookmark || tag == separator)
00101
return elem;
00102
if (goNext)
00103 n = n.nextSibling();
00104
else
00105 n = n.previousSibling();
00106 }
00107
return QDomElement();
00108 }
00109
00110 KBookmarkGroup KBookmarkGroup::createNewFolder(
KBookmarkManager* mgr,
const QString & text,
bool emitSignal )
00111 {
00112
QString txt( text );
00113
if ( text.isEmpty() )
00114 {
00115
bool ok;
00116
QString caption = parentGroup().fullText().isEmpty() ?
00117 i18n(
"Create New Bookmark Folder" ) :
00118 i18n(
"Create New Bookmark Folder in %1" )
00119 .arg( parentGroup().text() );
00120 txt = KInputDialog::getText( caption, i18n(
"New folder:" ),
00121 QString::null, &ok );
00122
if ( !ok )
00123
return KBookmarkGroup();
00124 }
00125
00126 Q_ASSERT(!element.isNull());
00127
QDomDocument doc = element.ownerDocument();
00128
QDomElement groupElem = doc.createElement(
"folder" );
00129 element.appendChild( groupElem );
00130
QDomElement textElem = doc.createElement(
"title" );
00131 groupElem.appendChild( textElem );
00132 textElem.appendChild( doc.createTextNode( txt ) );
00133
00134
KBookmarkGroup grp(groupElem);
00135
00136
if (emitSignal)
00137 emit mgr->
notifier().
createdNewFolder(
00138 mgr->
path(), grp.fullText(),
00139 grp.address() );
00140
00141
return grp;
00142
00143 }
00144
00145 KBookmark
KBookmarkGroup::createNewSeparator()
00146 {
00147 Q_ASSERT(!element.isNull());
00148
QDomDocument doc = element.ownerDocument();
00149 Q_ASSERT(!doc.isNull());
00150
QDomElement sepElem = doc.createElement(
"separator" );
00151 element.appendChild( sepElem );
00152
return KBookmark(sepElem);
00153 }
00154
00155 bool KBookmarkGroup::moveItem(
const KBookmark & item,
const KBookmark & after )
00156 {
00157
QDomNode n;
00158
if ( !after.isNull() )
00159 n = element.insertAfter( item.element, after.element );
00160
else
00161 {
00162
if ( element.firstChild().isNull() )
00163 n = element.insertBefore( item.element,
QDomElement() );
00164
00165
00166
QDomElement firstChild = nextKnownTag(element.firstChild().toElement(),
true);
00167
if ( !firstChild.isNull() )
00168 n = element.insertBefore( item.element, firstChild );
00169
else
00170 {
00171
00172 n = element.appendChild( item.element );
00173 }
00174 }
00175
return (!n.isNull());
00176 }
00177
00178 KBookmark
KBookmarkGroup::addBookmark(
KBookmarkManager* mgr,
const KBookmark &bm,
bool emitSignal )
00179 {
00180 element.appendChild( bm.internalElement() );
00181
00182
if (emitSignal) {
00183
if ( bm.hasMetaData() ) {
00184 mgr->
notifyCompleteChange(
"" );
00185 }
else {
00186 emit mgr->
notifier().addedBookmark(
00187 mgr->
path(), bm.url().url(),
00188 bm.fullText(), bm.address(), bm.icon() );
00189 }
00190 }
00191
00192
return bm;
00193 }
00194
00195 KBookmark
KBookmarkGroup::addBookmark(
KBookmarkManager* mgr,
const QString & text,
const KURL & url,
const QString & icon,
bool emitSignal )
00196 {
00197
00198
QDomDocument doc = element.ownerDocument();
00199
QDomElement elem = doc.createElement(
"bookmark" );
00200 elem.setAttribute(
"href", url.
url( 0, 106 ) );
00201
QString _icon = icon;
00202
if ( _icon.isEmpty() )
00203 _icon = KMimeType::iconForURL( url );
00204 elem.setAttribute(
"icon", _icon );
00205
00206
QDomElement textElem = doc.createElement(
"title" );
00207 elem.appendChild( textElem );
00208 textElem.appendChild( doc.createTextNode( text ) );
00209
00210
return addBookmark( mgr, KBookmark( elem ), emitSignal );
00211 }
00212
00213 void KBookmarkGroup::deleteBookmark( KBookmark bk )
00214 {
00215 element.removeChild( bk.element );
00216 }
00217
00218 bool KBookmarkGroup::isToolbarGroup()
const
00219
{
00220
return ( element.attribute(
"toolbar") ==
"yes" );
00221 }
00222
00223
QDomElement KBookmarkGroup::findToolbar()
const
00224
{
00225
if ( element.attribute(
"toolbar") ==
"yes" )
00226
return element;
00227
for (
QDomNode n = element.firstChild(); !n.isNull() ; n = n.nextSibling() )
00228 {
00229
QDomElement e = n.toElement();
00230
00231
if ( e.tagName() ==
"folder" )
00232 {
00233
if ( e.attribute(
"toolbar") ==
"yes" )
00234
return e;
00235
else
00236 {
00237
QDomElement result =
KBookmarkGroup(e).findToolbar();
00238
if (!result.isNull())
00239
return result;
00240 }
00241 }
00242 }
00243
return QDomElement();
00244 }
00245
00246 QValueList<KURL> KBookmarkGroup::groupUrlList()
const
00247
{
00248
QValueList<KURL> urlList;
00249
for ( KBookmark bm =
first(); !bm.isNull(); bm =
next(bm) )
00250 {
00251
if ( bm.isSeparator() || bm.isGroup() )
00252
continue;
00253 urlList << bm.url();
00254 }
00255
return urlList;
00256 }
00257
00259
00260
bool KBookmark::isGroup()
const
00261
{
00262
QString tag = element.tagName();
00263
return ( tag ==
"folder"
00264 || tag ==
"xbel" );
00265 }
00266
00267
bool KBookmark::isSeparator()
const
00268
{
00269
return (element.tagName() ==
"separator");
00270 }
00271
00272
bool KBookmark::hasParent()
const
00273
{
00274
QDomElement parent = element.parentNode().toElement();
00275
return !parent.isNull();
00276 }
00277
00278
QString KBookmark::text()
const
00279
{
00280
return KStringHandler::csqueeze( fullText() );
00281 }
00282
00283
QString KBookmark::fullText()
const
00284
{
00285
if (isSeparator())
00286
return i18n(
"--- separator ---");
00287
00288
return element.namedItem(
"title").toElement().text();
00289 }
00290
00291
KURL KBookmark::url()
const
00292
{
00293
return KURL(element.attribute(
"href"), 106);
00294 }
00295
00296
QString KBookmark::icon()
const
00297
{
00298
QString icon = element.attribute(
"icon");
00299
if ( icon.isEmpty() )
00300
00301
00302
if ( isGroup() )
00303 icon =
"bookmark_folder";
00304
else
00305
if ( isSeparator() )
00306 icon =
"eraser";
00307
else
00308 icon =
KMimeType::iconForURL( url() );
00309
return icon;
00310 }
00311
00312
KBookmarkGroup KBookmark::parentGroup()
const
00313
{
00314
return KBookmarkGroup( element.parentNode().toElement() );
00315 }
00316
00317
KBookmarkGroup KBookmark::toGroup()
const
00318
{
00319 Q_ASSERT( isGroup() );
00320
return KBookmarkGroup(element);
00321 }
00322
00323
QString KBookmark::address()
const
00324
{
00325
if ( element.tagName() ==
"xbel" )
00326
return "";
00327
else
00328 {
00329
00330
if (!hasParent())
00331 {
00332 Q_ASSERT(hasParent());
00333
return "ERROR";
00334 }
00335
KBookmarkGroup group = parentGroup();
00336
QString parentAddress = group.address();
00337 uint counter = 0;
00338
00339
00340
for ( KBookmark bk = group.
first() ; !bk.isNull() ; bk = group.
next(bk), ++counter )
00341 {
00342
if ( bk.element == element )
00343
return parentAddress +
"/" + QString::number(counter);
00344 }
00345
kdWarning() <<
"KBookmark::address : this can't happen! " << parentAddress <<
endl;
00346
return "ERROR";
00347 }
00348 }
00349
00350 KBookmark KBookmark::standaloneBookmark(
const QString & text,
const KURL & url,
const QString & icon )
00351 {
00352
QDomDocument doc(
"xbel");
00353
QDomElement elem = doc.createElement(
"xbel");
00354 doc.appendChild( elem );
00355
KBookmarkGroup grp( elem );
00356 grp.
addBookmark( 0L, text, url, icon,
false );
00357
return grp.
first();
00358 }
00359
00360
static QDomNode cd_or_create(
QDomNode node,
QString name)
00361 {
00362
QDomNode subnode = node.namedItem(name);
00363
if (subnode.isNull())
00364 {
00365 subnode = node.ownerDocument().createElement(name);
00366 node.appendChild(subnode);
00367 }
00368
return subnode;
00369 }
00370
00371
static QDomText get_or_create_text(
QDomNode node)
00372 {
00373
QDomNode subnode = node.firstChild();
00374
if (subnode.isNull())
00375 {
00376 subnode = node.ownerDocument().createTextNode(
"");
00377 node.appendChild(subnode);
00378 }
00379
return subnode.toText();
00380 }
00381
00382
00383
static QDomNode findOrCreateMetadata(
QDomNode& parent )
00384 {
00385
static const char kdeOwner[] =
"http://www.kde.org";
00386
QDomElement metadataElement;
00387
for (
QDomNode _node = parent.firstChild(); !_node.isNull(); _node = _node.nextSibling() ) {
00388
QDomElement elem = _node.toElement();
00389
if ( !elem.isNull() && elem.tagName() ==
"metadata" ) {
00390
const QString owner = elem.attribute(
"owner" );
00391
if ( owner == kdeOwner )
00392
return elem;
00393
if ( owner.isEmpty() )
00394 metadataElement = elem;
00395 }
00396 }
00397
if ( metadataElement.isNull() ) {
00398 metadataElement = parent.ownerDocument().createElement(
"metadata" );
00399 parent.appendChild(metadataElement);
00400 }
00401 metadataElement.setAttribute(
"owner", kdeOwner );
00402
return metadataElement;
00403 }
00404
00405
bool KBookmark::hasMetaData()
const
00406
{
00407
00408
00409
00410
QDomNode n = cd_or_create( internalElement(),
"info" );
00411
return findOrCreateMetadata( n ).hasChildNodes();
00412 }
00413
00414
void KBookmark::updateAccessMetadata()
00415 {
00416
kdDebug(7043) <<
"KBookmark::updateAccessMetadata " << address() <<
" " << url().prettyURL() <<
endl;
00417
00418
const uint timet = QDateTime::currentDateTime().toTime_t();
00419 setMetaDataItem(
"time_added", QString::number( timet ), DontOverwriteMetaData );
00420 setMetaDataItem(
"time_visited", QString::number( timet ) );
00421
00422
QString countStr = metaDataItem(
"visit_count" );
00423
bool ok;
00424
int currentCount = countStr.toInt(&ok);
00425
if (!ok)
00426 currentCount = 0;
00427 currentCount++;
00428 setMetaDataItem(
"visit_count", QString::number( currentCount ) );
00429
00430
00431 }
00432
00433
QString KBookmark::metaDataItem(
const QString &key )
const
00434
{
00435
QDomNode infoNode = cd_or_create( internalElement(),
"info" );
00436 infoNode = findOrCreateMetadata( infoNode );
00437
for (
QDomNode n = infoNode.firstChild(); !n.isNull(); n = n.nextSibling() ) {
00438
if ( !n.isElement() ) {
00439
continue;
00440 }
00441
const QDomElement e = n.toElement();
00442
if ( e.tagName() ==
key ) {
00443
return e.text();
00444 }
00445 }
00446
return QString::null;
00447 }
00448
00449
void KBookmark::setMetaDataItem(
const QString &key,
const QString &value, MetaDataOverwriteMode mode )
00450 {
00451
QDomNode infoNode = cd_or_create( internalElement(),
"info" );
00452 infoNode = findOrCreateMetadata( infoNode );
00453
00454
QDomNode item = cd_or_create( infoNode, key );
00455
QDomText text = get_or_create_text( item );
00456
if ( mode == DontOverwriteMetaData && !text.data().isEmpty() ) {
00457
return;
00458 }
00459
00460 text.setData( value );
00461 }
00462
00463
void KBookmarkGroupTraverser::traverse(
const KBookmarkGroup &root)
00464 {
00465
00466
QValueStack<KBookmarkGroup> stack;
00467 stack.push(root);
00468 KBookmark bk = stack.top().first();
00469
for (;;) {
00470
if (bk.isNull())
00471 {
00472
if (stack.isEmpty())
00473
return;
00474
if (stack.count() > 1)
00475 visitLeave(stack.top());
00476 bk = stack.pop();
00477 bk = stack.top().next(bk);
00478
if (bk.isNull())
00479
continue;
00480 }
00481
00482
if (bk.isGroup())
00483 {
00484
KBookmarkGroup gp = bk.toGroup();
00485 visitEnter(gp);
00486
if (!gp.
first().isNull())
00487 {
00488 stack.push(gp);
00489 bk = gp.
first();
00490
continue;
00491 }
00492
00493 visitLeave(gp);
00494 }
00495
else
00496 visit(bk);
00497
00498 bk = stack.top().next(bk);
00499 }
00500
00501
00502 }
00503