/usr/local/CPAN/Qt/XbelTree.pm
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;