Application de signets DOM
Fournit un lecteur pour les fichiers au format XML Bookmark Exchange Language.
L'application « Signets DOM » propose un lecteur de fichiers XML Bookmark Exchange Language (XBEL) qui utilise l'API XML basée sur le DOM de Qt pour lire et analyser ces fichiers. L'exemple « Signets » de QXmlStream propose une autre méthode pour lire ce type de fichier.

Définition de la classe XbelTree
La classe XbelTree dispose de fonctions permettant de lire et d'écrire sur le système de fichiers. Elle hérite de la classe « QTreeWidget », contient le modèle d'affichage des signets et permet de les modifier.
class XbelTree : public QTreeWidget
{
Q_OBJECT
public:
explicit XbelTree(QWidget *parent = nullptr);
bool read(QIODevice *device);
bool write(QIODevice *device) const;
protected:
#if QT_CONFIG(clipboard) && QT_CONFIG(contextmenu)
void contextMenuEvent(QContextMenuEvent *event) override;
#endif
private slots:
void updateDomElement(const QTreeWidgetItem *item, int column);
private:
void parseFolderElement(const QDomElement &element,
QTreeWidgetItem *parentItem = nullptr);
QTreeWidgetItem *createItem(const QDomElement &element,
QTreeWidgetItem *parentItem = nullptr);
QDomDocument domDocument;
QIcon folderIcon;
QIcon bookmarkIcon;
};Implémentation de la classe XbelTree
Le constructeur de XbelTree accepte un objet ` QWidget ` dans lequel il est placé. Le paramètre ` folderIcon ` est défini sur le mode `QIcon::Normal`, dans lequel la carte de pixels n’est affichée que lorsque l’utilisateur n’interagit pas avec l’icône. Les paramètres ` QStyle::SP_DirClosedIcon`, ` QStyle::SP_DirOpenIcon` et ` QStyle::SP_FileIcon ` correspondent à des cartes de pixels standard qui respectent le style de votre interface graphique.
XbelTree::XbelTree(QWidget *parent)
: QTreeWidget(parent)
{
header()->setSectionResizeMode(QHeaderView::Stretch);
setHeaderLabels({tr("Title"), tr("Location")});
folderIcon.addPixmap(style()->standardPixmap(QStyle::SP_DirClosedIcon),
QIcon::Normal, QIcon::Off);
folderIcon.addPixmap(style()->standardPixmap(QStyle::SP_DirOpenIcon),
QIcon::Normal, QIcon::On);
bookmarkIcon.addPixmap(style()->standardPixmap(QStyle::SP_FileIcon));
}La fonction read() ouvre l’ QIODevice on spécifiée à l’aide de QDomDocument::setContent. Si l’ouverture du fichier réussit et que les en-têtes de premier niveau sont validées, le contenu de la classe est effacé avant que le contenu du fichier ne soit analysé, en parcourant tous les nœuds XML de premier niveau et en appelant parseFolderElement() sur chacun d’entre eux.
bool XbelTree::read(QIODevice *device)
{
QDomDocument::ParseResult result =
domDocument.setContent(device, QDomDocument::ParseOption::UseNamespaceProcessing);
if (!result) {
QMessageBox::information(window(), tr("DOM Bookmarks"),
tr("Parse error at line %1, column %2:\n%3")
.arg(result.errorLine)
.arg(result.errorColumn)
.arg(result.errorMessage));
return false;
}
QDomElement root = domDocument.documentElement();
if (root.tagName() != "xbel") {
QMessageBox::information(window(), tr("DOM Bookmarks"),
tr("The file is not an XBEL file."));
return false;
} else if (root.hasAttribute(versionAttribute)
&& root.attribute(versionAttribute) != "1.0"_L1) {
QMessageBox::information(window(), tr("DOM Bookmarks"),
tr("The file is not an XBEL version 1.0 "
"file."));
return false;
}
clear();
disconnect(this, &QTreeWidget::itemChanged, this, &XbelTree::updateDomElement);
QDomElement child = root.firstChildElement(folderElement);
while (!child.isNull()) {
parseFolderElement(child);
child = child.nextSiblingElement(folderElement);
}
connect(this, &QTreeWidget::itemChanged, this, &XbelTree::updateDomElement);
return true;
}La fonction parseFolderElement() gère les différents types d’éléments et s’appelle elle-même de manière récursive si l’élément est un sous-dossier.
void XbelTree::parseFolderElement(const QDomElement &element,
QTreeWidgetItem *parentItem)
{
QTreeWidgetItem *item = createItem(element, parentItem);
QString title = element.firstChildElement(titleElement).text();
if (title.isEmpty())
title = tr("Folder");
item->setFlags(item->flags() | Qt::ItemIsEditable);
item->setIcon(0, folderIcon);
item->setText(0, title);
bool folded = (element.attribute(foldedAttribute) != "no"_L1);
item->setExpanded(!folded);
constexpr char16_t midDot = u'\xB7';
static const QString dots = QString(30, midDot);
QDomElement child = element.firstChildElement();
while (!child.isNull()) {
if (child.tagName() == folderElement) {
parseFolderElement(child, item);
} else if (child.tagName() == bookmarkElement) {
QTreeWidgetItem *childItem = createItem(child, item);
QString title = child.firstChildElement(titleElement).text();
if (title.isEmpty())
title = tr("Folder");
childItem->setFlags(item->flags() | Qt::ItemIsEditable);
childItem->setIcon(0, bookmarkIcon);
childItem->setText(0, title);
childItem->setText(1, child.attribute(hrefAttribute));
} else if (child.tagName() == "separator"_L1) {
QTreeWidgetItem *childItem = createItem(child, item);
childItem->setFlags(item->flags() & ~(Qt::ItemIsSelectable | Qt::ItemIsEditable));
childItem->setText(0, dots);
}
child = child.nextSiblingElement();
}
}La fonction ` write() ` enregistre le `domDocument` dans le fichier ` QIODevice ` spécifié à l’aide de `QDomDocument::save`.
bool XbelTree::write(QIODevice *device) const
{
const int IndentSize = 4;
QTextStream out(device);
domDocument.save(out, IndentSize);
return true;
}Définition de la classe MainWindow
La classe ` MainWindow ` est une sous-classe de ` QMainWindow`, dotée d'un menu ` File ` et d'un menu ` Help `.
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow();
public slots:
void open();
void saveAs();
void about();
private:
void createMenus();
XbelTree *xbelTree;
};Implémentation de la classe MainWindow
Le constructeur de MainWindow instancie l’objet membre XbelTree et définit son en-tête à l’aide d’un objet QStringList, labels. Le constructeur appelle également createMenus() pour configurer les menus. La fonction statusBar() est utilisée pour afficher le message « Ready ».
MainWindow::MainWindow()
{
xbelTree = new XbelTree;
setCentralWidget(xbelTree);
createMenus();
statusBar()->showMessage(tr("Ready"));
setWindowTitle(tr("DOM Bookmarks"));
const QSize availableSize = screen()->availableGeometry().size();
resize(availableSize.width() / 2, availableSize.height() / 3);
}La fonction createMenus() remplit les menus et définit les raccourcis clavier.
void MainWindow::createMenus()
{
QMenu *fileMenu = menuBar()->addMenu(tr("&File"));
QAction *openAct = fileMenu->addAction(tr("&Open..."), this, &MainWindow::open);
openAct->setShortcuts(QKeySequence::Open);
QAction *saveAsAct = fileMenu->addAction(tr("&Save As..."), this, &MainWindow::saveAs);
saveAsAct->setShortcuts(QKeySequence::SaveAs);
QAction *exitAct = fileMenu->addAction(tr("E&xit"), this, &QWidget::close);
exitAct->setShortcuts(QKeySequence::Quit);
menuBar()->addSeparator();
QMenu *helpMenu = menuBar()->addMenu(tr("&Help"));
helpMenu->addAction(tr("&About"), this, &MainWindow::about);
helpMenu->addAction(tr("About &Qt"), qApp, &QApplication::aboutQt);
}La fonction open() permet à l’utilisateur d’ouvrir un fichier XBEL à l’aide de QFileDialog. Un message d’avertissement s’affiche, ainsi que fileName et errorString si le fichier ne peut pas être lu ou s’il y a une erreur d’analyse. En cas de réussite, elle appelle XbelTree::read().
void MainWindow::open()
{
QFileDialog fileDialog(this, tr("Open Bookmark File"), QDir::currentPath());
fileDialog.setMimeTypeFilters({"application/x-xbel"_L1});
if (fileDialog.exec() != QDialog::Accepted)
return;
const QString fileName = fileDialog.selectedFiles().constFirst();
QFile file(fileName);
if (!file.open(QFile::ReadOnly | QFile::Text)) {
QMessageBox::warning(this, tr("DOM Bookmarks"),
tr("Cannot read file %1:\n%2.")
.arg(QDir::toNativeSeparators(fileName),
file.errorString()));
return;
}
if (xbelTree->read(&file))
statusBar()->showMessage(tr("File loaded"), 2000);
}La fonction saveAs() affiche une page QFileDialog et invite l'utilisateur à saisir une adresse fileName. À l'instar de la fonction open(), cette fonction affiche également un message d'avertissement si l'écriture dans le fichier échoue. En cas de réussite, elle appelle la fonction XbelTree::write().
void MainWindow::saveAs()
{
QFileDialog fileDialog(this, tr("Save Bookmark File"), QDir::currentPath());
fileDialog.setAcceptMode(QFileDialog::AcceptSave);
fileDialog.setDefaultSuffix("xbel"_L1);
fileDialog.setMimeTypeFilters({"application/x-xbel"_L1});
if (fileDialog.exec() != QDialog::Accepted)
return;
const QString fileName = fileDialog.selectedFiles().constFirst();
QFile file(fileName);
if (!file.open(QFile::WriteOnly | QFile::Text)) {
QMessageBox::warning(this, tr("DOM Bookmarks"),
tr("Cannot write file %1:\n%2.")
.arg(QDir::toNativeSeparators(fileName),
file.errorString()));
return;
}
if (xbelTree->write(&file))
statusBar()->showMessage(tr("File saved"), 2000);
}La fonction about() affiche une QMessageBox accompagnée d’une brève description de l’exemple.
void MainWindow::about()
{
QMessageBox::about(this, tr("About DOM Bookmarks"),
tr("The <b>DOM Bookmarks</b> example demonstrates how to "
"use Qt's DOM classes to read and write XML "
"documents."));
}Consultez la page de ressources consacrée au langage XML Bookmark Exchange (XBEL) pour plus d'informations sur les fichiers XBEL.
© 2026 The Qt Company Ltd. Documentation contributions included herein are the copyrights of their respective owners. The documentation provided herein is licensed under the terms of the GNU Free Documentation License version 1.3 as published by the Free Software Foundation. Qt and respective logos are trademarks of The Qt Company Ltd. in Finland and/or other countries worldwide. All other trademarks are property of their respective owners.