package XbelTree; use strict; use warnings; use QtCore4; use QtGui4; use QtXml4; use QtCore4::isa qw( Qt::TreeWidget ); use QtCore4::slots updateDomElement => ['QTreeWidgetItem *', 'int']; sub domDocument() { return this->{domDocument}; } sub domElementForItem() { return this->{domElementForItem}; } sub folderIcon() { return this->{folderIcon}; } sub bookmarkIcon() { return this->{bookmarkIcon}; } sub NEW { my ( $class, $parent ) = @_; $class->SUPER::NEW($parent); my @labels = ( this->tr('Title'), this->tr('Location') ); header()->setResizeMode(Qt::HeaderView::Stretch()); setHeaderLabels(\@labels); this->{domDocument} = Qt::DomDocument(); this->{domElementForItem} = {}; this->{folderIcon} = Qt::Icon(); this->{bookmarkIcon} = Qt::Icon(); folderIcon->addPixmap(style()->standardPixmap(Qt::Style::SP_DirClosedIcon()), Qt::Icon::Normal(), Qt::Icon::Off()); folderIcon->addPixmap(style()->standardPixmap(Qt::Style::SP_DirOpenIcon()), Qt::Icon::Normal(), Qt::Icon::On()); bookmarkIcon->addPixmap(style()->standardPixmap(Qt::Style::SP_FileIcon())); } sub read { my ($device) = @_; my $errorStr; my $errorLine; my $errorColumn; if (!domDocument->setContent($device, 1, \$errorStr, \$errorLine, \$errorColumn)) { Qt::MessageBox::information(window(), this->tr('DOM Bookmarks'), sprintf this->tr('Parse error at line %s, column %s:\n%s'), $errorLine, $errorColumn, $errorStr); return 0; } my $root = domDocument->documentElement(); if ($root->tagName() ne 'xbel') { Qt::MessageBox::information(window(), this->tr('DOM Bookmarks'), this->tr('The file is not an XBEL file.')); return 0; } elsif ($root->hasAttribute('version') && $root->attribute('version') ne '1.0') { Qt::MessageBox::information(window(), this->tr('DOM Bookmarks'), this->tr('The file is not an XBEL version 1.0 '. 'file.')); return 0; } clear(); this->disconnect(this, SIGNAL 'itemChanged(QTreeWidgetItem*,int)', this, SLOT 'updateDomElement(QTreeWidgetItem*,int)'); my $child = $root->firstChildElement('folder'); while (!$child->isNull()) { parseFolderElement($child); $child = $child->nextSiblingElement('folder'); } this->connect(this, SIGNAL 'itemChanged(QTreeWidgetItem*,int)', this, SLOT 'updateDomElement(QTreeWidgetItem*,int)'); return 1; } sub write { my ($device) = @_; my $IndentSize = 4; my $out = Qt::TextStream($device); domDocument->save($out, $IndentSize); return 1; } sub updateDomElement { my ($item, $column) = @_; # We must use some unique identifier that is compatible with perl hashes. my $id = indexFromItem($item)->internalId(); my $element = domElementForItem->{$id}; if ($element && !$element->isNull()) { if ($column == 0) { my $oldTitleElement = $element->firstChildElement('title'); my $newTitleElement = domDocument->createElement('title'); my $newTitleText = domDocument->createTextNode($item->text(0)); $newTitleElement->appendChild($newTitleText); $element->replaceChild($newTitleElement, $oldTitleElement); } else { if ($element->tagName() eq 'bookmark') { $element->setAttribute('href', $item->text(1)); } } } } sub parseFolderElement { my ($element, $parentItem) = @_; my $item = createItem($element, $parentItem); my $title = $element->firstChildElement('title')->text(); if (!$title) { $title = Qt::Object::this->tr('Folder'); } $item->setFlags($item->flags() | Qt::ItemIsEditable()); $item->setIcon(0, folderIcon); $item->setText(0, $title); my $folded = $element->attribute('folded') ne 'no'; setItemExpanded($item, !$folded); my $child = $element->firstChildElement(); while (!$child->isNull()) { if ($child->tagName() eq 'folder') { parseFolderElement($child, $item); } elsif ($child->tagName() eq 'bookmark') { my $childItem = createItem($child, $item); my $title = $child->firstChildElement('title')->text(); if (!$title) { $title = Qt::Object::this->tr('Folder'); } $childItem->setFlags($item->flags() | Qt::ItemIsEditable()); $childItem->setIcon(0, bookmarkIcon); $childItem->setText(0, $title); $childItem->setText(1, $child->attribute('href')); } elsif ($child->tagName() eq 'separator') { my $childItem = createItem($child, $item); $childItem->setFlags($item->flags() & ~(Qt::ItemIsSelectable() | Qt::ItemIsEditable())); $childItem->setText(0, chr(0xB7) x 30); } $child = $child->nextSiblingElement(); } } sub createItem { my ($element, $parentItem) = @_; my $item; if ($parentItem) { $item = Qt::TreeWidgetItem($parentItem); } else { $item = Qt::TreeWidgetItem(this); } # We must use some unique identifier that is compatible with perl hashes. my $id = indexFromItem($item)->internalId(); domElementForItem->{$id} = $element; return $item; } 1;