mirror of
https://github.com/crystalidea/qt6windows7.git
synced 2025-07-08 02:17:43 +08:00
6.5.3 clean
This commit is contained in:
Binary file not shown.
After Width: | Height: | Size: 3.6 KiB |
Binary file not shown.
After Width: | Height: | Size: 2.0 KiB |
Binary file not shown.
After Width: | Height: | Size: 65 KiB |
Binary file not shown.
Before Width: | Height: | Size: 9.2 KiB |
Binary file not shown.
Before Width: | Height: | Size: 11 KiB |
Binary file not shown.
Before Width: | Height: | Size: 22 KiB |
@ -3,169 +3,221 @@
|
||||
|
||||
/*!
|
||||
\example serialization/streambookmarks
|
||||
\examplecategory {Data Processing & I/O}
|
||||
\meta tag {network}
|
||||
\title QXmlStream Bookmarks Example
|
||||
\examplecategory {Input/Output}
|
||||
\brief Demonstrates how to read and write to XBEL files.
|
||||
\brief Demonstrates how to read and write XBEL files.
|
||||
\ingroup xml-examples
|
||||
|
||||
The QXmlStream Bookmarks example provides a reader for XML Bookmark
|
||||
Exchange Language (XBEL) files using Qt's QXmlStreamReader class
|
||||
for reading, and QXmlStreamWriter class for writing the files.
|
||||
The QXmlStream Bookmarks example provides a viewer for XML Bookmark Exchange
|
||||
Language (XBEL) files. It can read bookmarks using Qt's QXmlStreamReader and
|
||||
write them back out again using QXmlStreamWriter. As this example aims to
|
||||
show how to use these reader and writer types, it provides no means to open
|
||||
a bookmark, add a new one, or merge two bookmark files, and only minimal
|
||||
scope for editing bookmarks. None the less, it could surely be extended with
|
||||
such features, if desired.
|
||||
|
||||
\image xmlstreamexample-screenshot.png
|
||||
\image screenshot.png
|
||||
|
||||
\section1 XbelWriter Class Definition
|
||||
|
||||
The \c XbelWriter class contains a private instance of QXmlStreamWriter,
|
||||
which provides an XML writer with a streaming API. \c XbelWriter also
|
||||
has a reference to the QTreeWidget instance where the bookmark hierarchy
|
||||
is stored.
|
||||
The \c XbelWriter class takes a \l{QTreeWidget}{tree widget} describing a
|
||||
hierarchy of folders containing bookmarks. Its \c writeFile() provides the
|
||||
means to write out this hierarchy, in XBEL format, to a given output device.
|
||||
|
||||
Internally, it records the tree widget it was given and packages a private
|
||||
instance of QXmlStreamWriter, which provides it with the means to stream
|
||||
XML. It has an internal \c writeItem() to write each item in its tree.
|
||||
|
||||
\snippet serialization/streambookmarks/xbelwriter.h 0
|
||||
|
||||
\section1 XbelWriter Class Implementation
|
||||
|
||||
The \c XbelWriter constructor accepts a \a treeWidget to initialize within
|
||||
its definition. We enable \l{QXmlStreamWriter}'s auto-formatting property
|
||||
to ensure line-breaks and indentations are added automatically to empty
|
||||
sections between elements, increasing readability as the data is split into
|
||||
several lines.
|
||||
The \c XbelWriter constructor accepts the \a treeWidget it will describe. It
|
||||
stores that and enables \l{QXmlStreamWriter}'s auto-formatting property.
|
||||
This last splits the data into several lines, with indentation to indicate
|
||||
the structure of the tree, which makes the XML output easier to read.
|
||||
|
||||
\snippet serialization/streambookmarks/xbelwriter.cpp 0
|
||||
|
||||
The \c writeFile() function accepts a QIODevice object and sets it using
|
||||
\c setDevice(). This function then writes the document type
|
||||
definition(DTD), the start element, the version, and \c{treeWidget}'s
|
||||
top-level items.
|
||||
The \c writeFile() function accepts a QIODevice object and directs its
|
||||
QXmlStreamWriter member to write to this device, using \c setDevice(). This
|
||||
function then writes the document type definition(DTD), the start element,
|
||||
the version, and delegates writing of each of the \c{treeWidget}'s top-level
|
||||
items to \c writeItem(). Finally, it closes the document and returns.
|
||||
|
||||
\snippet serialization/streambookmarks/xbelwriter.cpp 1
|
||||
|
||||
The \c writeItem() function accepts a QTreeWidgetItem object and writes it
|
||||
to the stream, depending on its \c tagName, which can either be a "folder",
|
||||
"bookmark", or "separator".
|
||||
The \c writeItem() function accepts a QTreeWidgetItem object and writes to
|
||||
its XML stream a representation of the object, which depends on its \c
|
||||
UserRole, which can be one of a \c{"folder"}, \c{"bookmark"},
|
||||
or \c{"separator"}. Within each folder, it calls itself recursively on each
|
||||
child item, to recursively include a representation of each child within the
|
||||
folder's XML element.
|
||||
|
||||
\snippet serialization/streambookmarks/xbelwriter.cpp 2
|
||||
|
||||
\section1 XbelReader Class Definition
|
||||
|
||||
The \c XbelReader contains a private instance of QXmlStreamReader, the
|
||||
companion class to QXmlStreamWriter. \c XbelReader also contains a
|
||||
reference to the QTreeWidget that is used to group the bookmarks according
|
||||
to their hierarchy.
|
||||
The \c XbelReader takes a \l{QTreeWidget}{tree widget} to populate with
|
||||
items describing a bookmark hierarchy. It supports reading XBEL data from a
|
||||
QIODevice as a source of these items. If parsing of the XBEL data fails, it
|
||||
can report what went wrong.
|
||||
|
||||
Internally, it records the QTreeWidget that it will populate and packages an
|
||||
instance of QXmlStreamReader, the companion class to QXmlStreamWriter, which
|
||||
it will use to read XBEL data.
|
||||
|
||||
\snippet serialization/streambookmarks/xbelreader.h 0
|
||||
|
||||
\section1 XbelReader Class Implementation
|
||||
|
||||
The \c XbelReader constructor accepts a QTreeWidget to initialize the
|
||||
\c treeWidget within its definition. A QStyle object is used to set
|
||||
\c{treeWidget}'s style property. The \c folderIcon is set to QIcon::Normal
|
||||
mode where the pixmap is only displayed when the user is not interacting
|
||||
with the icon. The QStyle::SP_DirClosedIcon, QStyle::SP_DirOpenIcon, and
|
||||
QStyle::SP_FileIcon correspond to standard pixmaps that follow the style
|
||||
of your GUI.
|
||||
Since the XBEL reader is only concerned with reading XML elements, it makes
|
||||
extensive use of the \l{QXmlStreamReader::}{readNextStartElement()}
|
||||
convenience function.
|
||||
|
||||
The \c XbelReader constructor requires a QTreeWidget that it will populate.
|
||||
It populates the tree widget's style with suitable icons: a folder icon that
|
||||
changes form to indicate whether each folder as open or closed; and a
|
||||
standard file icon for the individual bookmarks within those folders.
|
||||
|
||||
\snippet serialization/streambookmarks/xbelreader.cpp 0
|
||||
|
||||
The \c read() function accepts a QIODevice and sets it using
|
||||
\l{QXmlStreamReader::}{setDevice()}. The actual process of reading only
|
||||
takes place if the file is a valid XBEL 1.0 file. Note that the XML input
|
||||
needs to be well-formed to be accepted by QXmlStreamReader. Otherwise, the
|
||||
\l{QXmlStreamReader::}{raiseError()} function is used to display an error
|
||||
message. Since the XBEL reader is only concerned with reading XML elements,
|
||||
it makes extensive use of the \l{QXmlStreamReader::}{readNextStartElement()}
|
||||
convenience function.
|
||||
The \c read() function accepts a QIODevice. It directs its QXmlStreamReader
|
||||
member to read content from that device. Note that the XML input must be
|
||||
well-formed to be accepted by QXmlStreamReader. First it reads the outer
|
||||
structure and verifies the content is an XBEL 1.0 file; if it is, \c read()
|
||||
delegates the actual reading of content to the internal \c readXBEL().
|
||||
|
||||
Otherwise, the \l{QXmlStreamReader::}{raiseError()} function is used to
|
||||
record an error message. The reader itself may also do the same if it
|
||||
encounters errors in the input. When \c read() has finished, it returns
|
||||
true if there were no errors.
|
||||
|
||||
\snippet serialization/streambookmarks/xbelreader.cpp 1
|
||||
|
||||
The \c errorString() function is used if an error occurred, in order to
|
||||
obtain a description of the error complete with line and column number
|
||||
information.
|
||||
If \c read() returns false, its caller can obtain a description of the
|
||||
error, complete with line and column number within the stream, by calling
|
||||
the \c errorString() function.
|
||||
|
||||
\snippet serialization/streambookmarks/xbelreader.cpp 2
|
||||
|
||||
The \c readXBEL() function reads the name of a startElement and calls
|
||||
the appropriate function to read it, depending on whether if its a
|
||||
"folder", "bookmark" or "separator". Otherwise, it calls
|
||||
\l{QXmlStreamReader::}{skipCurrentElement()}. The Q_ASSERT() macro is used
|
||||
to provide a pre-condition for the function.
|
||||
The \c readXBEL() function reads the name of a startElement and calls the
|
||||
appropriate function to read it, depending on whether if its tag name
|
||||
is \c{"folder"}, \c{"bookmark"} or \c{"separator"}. Any other elements
|
||||
encountered are skipped. The function starts with a precondition, verifying
|
||||
that the XML reader has just opened an \c{"xbel"} element.
|
||||
|
||||
\snippet serialization/streambookmarks/xbelreader.cpp 3
|
||||
|
||||
The \c readTitle() function reads the bookmark's title.
|
||||
|
||||
\snippet serialization/streambookmarks/xbelreader.cpp 4
|
||||
|
||||
The \c readSeparator() function creates a separator and sets its flags.
|
||||
The text is set to 30 "0xB7", the HEX equivalent for period. The element
|
||||
is then skipped using \l{QXmlStreamReader::}{skipCurrentElement()}.
|
||||
The \c readBookmark() function creates a new editable item representing a
|
||||
single bookmark. It records the XML \c{"href"} attribute of the current
|
||||
element as second column text of the item and provisionally sets its first
|
||||
column text to \c{"Unknown title"} before scanning the rest of the element
|
||||
for a title element to over-ride that, skipping any unrecognized child
|
||||
elements.
|
||||
|
||||
\snippet serialization/streambookmarks/xbelreader.cpp 5
|
||||
|
||||
The \c readTitle() function reads a bookmark's title and records it as the
|
||||
title (first column text) of the item for which it was called.
|
||||
|
||||
\snippet serialization/streambookmarks/xbelreader.cpp 6
|
||||
|
||||
The \c readSeparator() function creates a separator and sets its flags. The
|
||||
separator item's text is set to 30 centered dots. The rest of the element is
|
||||
then skipped using \l{QXmlStreamReader::}{skipCurrentElement()}.
|
||||
|
||||
\snippet serialization/streambookmarks/xbelreader.cpp 6
|
||||
|
||||
The \c readFolder() function creates an item and iterates the content of the
|
||||
folder element, adding children to this item to represent the contents of
|
||||
the folder element. The loop over folder content is similar in form to the
|
||||
one in \c readXBEL(), save that it now accepts a title element to set the
|
||||
title of the folder.
|
||||
|
||||
\snippet serialization/streambookmarks/xbelreader.cpp 7
|
||||
|
||||
The \c createChildItem() helper function creates a new tree widget item
|
||||
that's either a child of the given item or, if no parent item is given, a
|
||||
direct child of the tree widget. It sets the new item's \c UserRole to the
|
||||
tag name of the current XML element, matching how XbelWriter::writeFile()
|
||||
uses that \c UserRole.
|
||||
|
||||
\snippet serialization/streambookmarks/xbelreader.cpp 8
|
||||
|
||||
\section1 MainWindow Class Definition
|
||||
|
||||
The \c MainWindow class is a subclass of QMainWindow, with a
|
||||
\c File menu and a \c Help menu.
|
||||
The \c MainWindow class is a subclass of QMainWindow, with a \c File menu
|
||||
and a \c Help menu.
|
||||
|
||||
\snippet serialization/streambookmarks/mainwindow.h 0
|
||||
|
||||
\section1 MainWindow Class Implementation
|
||||
|
||||
The \c MainWindow constructor instantiates the QTreeWidget object, \c
|
||||
treeWidget and sets its header with a QStringList object, \c labels.
|
||||
The constructor also invokes \c createActions() and \c createMenus()
|
||||
to set up the menus and their corresponding actions. The \c statusBar()
|
||||
is used to display the message "Ready" and the window's size is fixed
|
||||
to 480x320 pixels.
|
||||
The \c MainWindow constructor sets up its QTreeWidget object, \c treeWidget,
|
||||
as its own central widget, with column headings for the title and location
|
||||
of each book-mark. It configures a custom menu that enables the user to
|
||||
perform actions on individual bookmarks within the tree widget.
|
||||
|
||||
It invokes \c createMenus() to set up its own menus and their corresponding
|
||||
actions. It sets its title, announces itself as ready and sets its size to a
|
||||
reasonable proportion of the available screen space.
|
||||
|
||||
\snippet serialization/streambookmarks/mainwindow.cpp 0
|
||||
|
||||
The \c open() function enables the user to open an XBEL file using
|
||||
QFileDialog::getOpenFileName(). A warning message is displayed along
|
||||
with the \c fileName and \c errorString if the file cannot be read or
|
||||
if there is a parse error.
|
||||
A custom menu, triggered when the user right-clicks on a bookmark, provides
|
||||
for copying the bookmark as a link or directing a desktop browser to open
|
||||
the URL it references. This menu is implemented (when relevant features are
|
||||
enabled) by \c onCustomContextMenuRequested().
|
||||
|
||||
\snippet serialization/streambookmarks/mainwindow.cpp 1
|
||||
|
||||
The \c saveAs() function displays a QFileDialog, prompting the user for
|
||||
a \c fileName using QFileDialog::getSaveFileName(). Similar to the
|
||||
\c open() function, this function also displays a warning message if
|
||||
the file cannot be written to.
|
||||
The \c createMenus() function creates the \c fileMenu and \c helpMenu and
|
||||
adds QAction objects to them, bound variously to the \c open(), \c saveAs()
|
||||
and \c about() functions, along with QWidget::close() and
|
||||
QApplication::aboutQt(). The connections are as shown below:
|
||||
|
||||
\snippet serialization/streambookmarks/mainwindow.cpp 2
|
||||
|
||||
The \c about() function displays a QMessageBox with a brief description
|
||||
of the example.
|
||||
|
||||
\snippet serialization/streambookmarks/mainwindow.cpp 3
|
||||
|
||||
In order to implement the \c open(), \c saveAs(), \c exit(), \c about()
|
||||
and \c aboutQt() functions, we connect them to QAction objects and
|
||||
add them to the \c fileMenu and \c helpMenu. The connections are as shown
|
||||
below:
|
||||
|
||||
\snippet serialization/streambookmarks/mainwindow.cpp 5
|
||||
|
||||
The \c createMenus() function creates the \c fileMenu and \c helpMenu
|
||||
and adds the QAction objects to them in order to create the menu shown
|
||||
in the screenshot below:
|
||||
This creates the menu shown in the screenshots below:
|
||||
|
||||
\table
|
||||
\row
|
||||
\li \inlineimage xmlstreamexample-filemenu.png
|
||||
\li \inlineimage xmlstreamexample-helpmenu.png
|
||||
\li \inlineimage filemenu.png
|
||||
\li \inlineimage helpmenu.png
|
||||
\endtable
|
||||
|
||||
The \c open() function, when triggered, offers the user a file dialog to use
|
||||
to select a bookmarks file. If a file is selected, it is parsed using an \c
|
||||
XBelReader to populate the \c treeWidget with bookmarks. If problems arise
|
||||
with opening or parsing the file, a suitable warning message is displayed to
|
||||
the user, including file name and error message. Otherwise, the bookmarks
|
||||
read from the file are displayed and the window's status bar briefly reports
|
||||
that the file has been loaded.
|
||||
|
||||
\snippet serialization/streambookmarks/mainwindow.cpp 3
|
||||
|
||||
The \c saveAs() function displays a QFileDialog, prompting the user for a \c
|
||||
fileName, to which to save a copy of the bookmarks data. Similar to the \c
|
||||
open() function, this function also displays a warning message if the file
|
||||
cannot be written to.
|
||||
|
||||
\snippet serialization/streambookmarks/mainwindow.cpp 4
|
||||
|
||||
The \c about() function displays a QMessageBox with a brief description of
|
||||
the example, or general information about Qt and the version of it in use.
|
||||
|
||||
\snippet serialization/streambookmarks/mainwindow.cpp 5
|
||||
|
||||
\section1 \c{main()} Function
|
||||
|
||||
The \c main() function instantiates \c MainWindow and invokes the \c show()
|
||||
function.
|
||||
function to display it, then its \c open(), as this is most likely what the
|
||||
user shall want to do first.
|
||||
|
||||
\snippet serialization/streambookmarks/main.cpp 0
|
||||
|
||||
See the \l{http://pyxml.sourceforge.net/topics/xbel/}
|
||||
{XML Bookmark Exchange Language Resource Page} for more information
|
||||
about XBEL files.
|
||||
See the \l{https://pyxml.sourceforge.net/topics/xbel/} {XML Bookmark
|
||||
Exchange Language Resource Page} for more information about XBEL files.
|
||||
*/
|
||||
|
@ -3,66 +3,66 @@
|
||||
<xbel version="1.0">
|
||||
<folder folded="no">
|
||||
<title>Qt Resources</title>
|
||||
<bookmark href="http://qt.io/">
|
||||
<bookmark href="https://www.qt.io/">
|
||||
<title>Qt home page</title>
|
||||
</bookmark>
|
||||
<bookmark href="https://www.qt.io/partners/">
|
||||
<bookmark href="https://www.qt.io/contact-us/partners">
|
||||
<title>Qt Partners</title>
|
||||
</bookmark>
|
||||
<bookmark href="https://www.qt.io/qt-training/">
|
||||
<title>Training</title>
|
||||
<bookmark href="https://www.qt.io/qt-professional-services">
|
||||
<title>Professional Services</title>
|
||||
</bookmark>
|
||||
<bookmark href="http://doc.qt.io/">
|
||||
<title>Qt 5 documentation</title>
|
||||
</bookmark>
|
||||
<bookmark href="http://qt-project.org/faq/">
|
||||
<title>Frequently Asked Questions</title>
|
||||
<bookmark href="https://doc.qt.io/">
|
||||
<title>Qt Documentation</title>
|
||||
</bookmark>
|
||||
<folder folded="yes">
|
||||
<title>Community Resources</title>
|
||||
<bookmark href="http://www.qtcentre.org/content/">
|
||||
<bookmark href="https://contribute.qt-project.org">
|
||||
<title>The Qt Project</title>
|
||||
</bookmark>
|
||||
<bookmark href="https://www.qtcentre.org/content/">
|
||||
<title>Qt Centre</title>
|
||||
</bookmark>
|
||||
<bookmark href="http://www.qtforum.org/">
|
||||
<title>QtForum.org</title>
|
||||
<bookmark href="https://forum.qt.io/">
|
||||
<title>Forum.Qt.org</title>
|
||||
</bookmark>
|
||||
<bookmark href="http://digitalfanatics.org/projects/qt_tutorial/">
|
||||
<bookmark href="https://digitalfanatics.org/projects/qt_tutorial/">
|
||||
<title>The Independent Qt Tutorial</title>
|
||||
</bookmark>
|
||||
<bookmark href="http://www.qtforum.de/">
|
||||
<bookmark href="https://www.qtforum.de/">
|
||||
<title>German Qt Forum</title>
|
||||
</bookmark>
|
||||
<bookmark href="http://www.korone.net/">
|
||||
<bookmark href="https://www.qt-dev.com/">
|
||||
<title>Korean Qt Community Site</title>
|
||||
</bookmark>
|
||||
<bookmark href="http://prog.org.ru/">
|
||||
<bookmark href="http://www.prog.org.ru/">
|
||||
<title>Russian Qt Forum</title>
|
||||
</bookmark>
|
||||
</folder>
|
||||
</folder>
|
||||
<folder folded="no">
|
||||
<title>Online Dictionaries</title>
|
||||
<bookmark href="http://www.dictionary.com/">
|
||||
<bookmark href="https://www.dictionary.com/">
|
||||
<title>Dictionary.com</title>
|
||||
</bookmark>
|
||||
<bookmark href="http://www.m-w.com/">
|
||||
<bookmark href="https://www.merriam-webster.com/">
|
||||
<title>Merriam-Webster Online</title>
|
||||
</bookmark>
|
||||
<bookmark href="http://dictionary.cambridge.org/">
|
||||
<bookmark href="https://dictionary.cambridge.org/">
|
||||
<title>Cambridge Dictionaries Online</title>
|
||||
</bookmark>
|
||||
<bookmark href="http://www.onelook.com/">
|
||||
<bookmark href="https://www.onelook.com/">
|
||||
<title>OneLook Dictionary Search</title>
|
||||
</bookmark>
|
||||
<separator/>
|
||||
<bookmark href="http://dict.tu-chemnitz.de/">
|
||||
<title>TU Chemnitz German-English Dictionary</title>
|
||||
<bookmark href="https://dict.tu-chemnitz.de/">
|
||||
<title>BEOLINGUS, a service of TU Chemnitz</title>
|
||||
</bookmark>
|
||||
<separator/>
|
||||
<bookmark href="http://atilf.atilf.fr/tlf.htm">
|
||||
<title>Trésor de la Langue Française informatisé</title>
|
||||
</bookmark>
|
||||
<bookmark href="http://dictionnaires.atilf.fr/dictionnaires/ACADEMIE/">
|
||||
<bookmark href="https://www.dictionnaire-academie.fr/">
|
||||
<title>Dictionnaire de l'Académie Française</title>
|
||||
</bookmark>
|
||||
</folder>
|
||||
|
@ -1,10 +1,10 @@
|
||||
// Copyright (C) 2016 The Qt Company Ltd.
|
||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
|
||||
|
||||
#include <QApplication>
|
||||
|
||||
#include "mainwindow.h"
|
||||
|
||||
#include <QApplication>
|
||||
|
||||
//! [0]
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
|
@ -1,22 +1,33 @@
|
||||
// Copyright (C) 2016 The Qt Company Ltd.
|
||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
|
||||
|
||||
#include <QtWidgets>
|
||||
|
||||
#include "mainwindow.h"
|
||||
#include "xbelreader.h"
|
||||
#include "xbelwriter.h"
|
||||
|
||||
//! [0]
|
||||
MainWindow::MainWindow()
|
||||
{
|
||||
QStringList labels;
|
||||
labels << tr("Title") << tr("Location");
|
||||
#include <QFileDialog>
|
||||
#include <QHeaderView>
|
||||
#include <QMenuBar>
|
||||
#include <QMessageBox>
|
||||
#include <QStatusBar>
|
||||
#include <QTreeWidget>
|
||||
|
||||
treeWidget = new QTreeWidget;
|
||||
#include <QAction>
|
||||
#if QT_CONFIG(clipboard)
|
||||
# include <QClipboard>
|
||||
#endif
|
||||
#include <QDesktopServices>
|
||||
#include <QApplication>
|
||||
#include <QScreen>
|
||||
|
||||
using namespace Qt::StringLiterals;
|
||||
|
||||
//! [0]
|
||||
MainWindow::MainWindow() : treeWidget(new QTreeWidget)
|
||||
{
|
||||
treeWidget->header()->setSectionResizeMode(QHeaderView::Stretch);
|
||||
treeWidget->setHeaderLabels(labels);
|
||||
#if !defined(QT_NO_CONTEXTMENU) && !defined(QT_NO_CLIPBOARD)
|
||||
treeWidget->setHeaderLabels(QStringList{tr("Title"), tr("Location")});
|
||||
#if QT_CONFIG(clipboard) && QT_CONFIG(contextmenu)
|
||||
treeWidget->setContextMenuPolicy(Qt::CustomContextMenu);
|
||||
connect(treeWidget, &QWidget::customContextMenuRequested,
|
||||
this, &MainWindow::onCustomContextMenuRequested);
|
||||
@ -33,7 +44,8 @@ MainWindow::MainWindow()
|
||||
}
|
||||
//! [0]
|
||||
|
||||
#if !defined(QT_NO_CONTEXTMENU) && !defined(QT_NO_CLIPBOARD)
|
||||
//! [1]
|
||||
#if QT_CONFIG(clipboard) && QT_CONFIG(contextmenu)
|
||||
void MainWindow::onCustomContextMenuRequested(const QPoint &pos)
|
||||
{
|
||||
const QTreeWidgetItem *item = treeWidget->itemAt(pos);
|
||||
@ -49,78 +61,10 @@ void MainWindow::onCustomContextMenuRequested(const QPoint &pos)
|
||||
else if (action == openAction)
|
||||
QDesktopServices::openUrl(QUrl(url));
|
||||
}
|
||||
#endif // !QT_NO_CONTEXTMENU && !QT_NO_CLIPBOARD
|
||||
|
||||
//! [1]
|
||||
void MainWindow::open()
|
||||
{
|
||||
QString fileName =
|
||||
QFileDialog::getOpenFileName(this, tr("Open Bookmark File"),
|
||||
QDir::currentPath(),
|
||||
tr("XBEL Files (*.xbel *.xml)"));
|
||||
if (fileName.isEmpty())
|
||||
return;
|
||||
|
||||
treeWidget->clear();
|
||||
|
||||
|
||||
QFile file(fileName);
|
||||
if (!file.open(QFile::ReadOnly | QFile::Text)) {
|
||||
QMessageBox::warning(this, tr("QXmlStream Bookmarks"),
|
||||
tr("Cannot read file %1:\n%2.")
|
||||
.arg(QDir::toNativeSeparators(fileName),
|
||||
file.errorString()));
|
||||
return;
|
||||
}
|
||||
|
||||
XbelReader reader(treeWidget);
|
||||
if (!reader.read(&file)) {
|
||||
QMessageBox::warning(this, tr("QXmlStream Bookmarks"),
|
||||
tr("Parse error in file %1:\n\n%2")
|
||||
.arg(QDir::toNativeSeparators(fileName),
|
||||
reader.errorString()));
|
||||
} else {
|
||||
statusBar()->showMessage(tr("File loaded"), 2000);
|
||||
}
|
||||
|
||||
}
|
||||
#endif // QT_CONFIG(clipboard) && QT_CONFIG(contextmenu)
|
||||
//! [1]
|
||||
|
||||
//! [2]
|
||||
void MainWindow::saveAs()
|
||||
{
|
||||
QString fileName =
|
||||
QFileDialog::getSaveFileName(this, tr("Save Bookmark File"),
|
||||
QDir::currentPath(),
|
||||
tr("XBEL Files (*.xbel *.xml)"));
|
||||
if (fileName.isEmpty())
|
||||
return;
|
||||
|
||||
QFile file(fileName);
|
||||
if (!file.open(QFile::WriteOnly | QFile::Text)) {
|
||||
QMessageBox::warning(this, tr("QXmlStream Bookmarks"),
|
||||
tr("Cannot write file %1:\n%2.")
|
||||
.arg(QDir::toNativeSeparators(fileName),
|
||||
file.errorString()));
|
||||
return;
|
||||
}
|
||||
|
||||
XbelWriter writer(treeWidget);
|
||||
if (writer.writeFile(&file))
|
||||
statusBar()->showMessage(tr("File saved"), 2000);
|
||||
}
|
||||
//! [2]
|
||||
|
||||
//! [3]
|
||||
void MainWindow::about()
|
||||
{
|
||||
QMessageBox::about(this, tr("About QXmlStream Bookmarks"),
|
||||
tr("The <b>QXmlStream Bookmarks</b> example demonstrates how to use Qt's "
|
||||
"QXmlStream classes to read and write XML documents."));
|
||||
}
|
||||
//! [3]
|
||||
|
||||
//! [5]
|
||||
void MainWindow::createMenus()
|
||||
{
|
||||
QMenu *fileMenu = menuBar()->addMenu(tr("&File"));
|
||||
@ -137,6 +81,71 @@ void MainWindow::createMenus()
|
||||
|
||||
QMenu *helpMenu = menuBar()->addMenu(tr("&Help"));
|
||||
helpMenu->addAction(tr("&About"), this, &MainWindow::about);
|
||||
helpMenu->addAction(tr("About &Qt"), qApp, &QCoreApplication::quit);
|
||||
helpMenu->addAction(tr("About &Qt"), qApp, &QApplication::aboutQt);
|
||||
}
|
||||
//! [2]
|
||||
|
||||
//! [3]
|
||||
void MainWindow::open()
|
||||
{
|
||||
QFileDialog fileDialog(this, tr("Open Bookmark File"), QDir::currentPath());
|
||||
fileDialog.setMimeTypeFilters({"application/x-xbel"_L1});
|
||||
if (fileDialog.exec() != QDialog::Accepted)
|
||||
return;
|
||||
|
||||
treeWidget->clear();
|
||||
|
||||
const QString fileName = fileDialog.selectedFiles().constFirst();
|
||||
QFile file(fileName);
|
||||
if (!file.open(QFile::ReadOnly | QFile::Text)) {
|
||||
QMessageBox::warning(this, tr("QXmlStream Bookmarks"),
|
||||
tr("Cannot read file %1:\n%2.")
|
||||
.arg(QDir::toNativeSeparators(fileName), file.errorString()));
|
||||
return;
|
||||
}
|
||||
|
||||
XbelReader reader(treeWidget);
|
||||
if (!reader.read(&file)) {
|
||||
QMessageBox::warning(
|
||||
this, tr("QXmlStream Bookmarks"),
|
||||
tr("Parse error in file %1:\n\n%2")
|
||||
.arg(QDir::toNativeSeparators(fileName), reader.errorString()));
|
||||
} else {
|
||||
statusBar()->showMessage(tr("File loaded"), 2000);
|
||||
}
|
||||
}
|
||||
//! [3]
|
||||
|
||||
//! [4]
|
||||
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("QXmlStream Bookmarks"),
|
||||
tr("Cannot write file %1:\n%2.")
|
||||
.arg(QDir::toNativeSeparators(fileName), file.errorString()));
|
||||
return;
|
||||
}
|
||||
|
||||
XbelWriter writer(treeWidget);
|
||||
if (writer.writeFile(&file))
|
||||
statusBar()->showMessage(tr("File saved"), 2000);
|
||||
}
|
||||
//! [4]
|
||||
|
||||
//! [5]
|
||||
void MainWindow::about()
|
||||
{
|
||||
QMessageBox::about(this, tr("About QXmlStream Bookmarks"),
|
||||
tr("The <b>QXmlStream Bookmarks</b> example demonstrates how to use Qt's "
|
||||
"QXmlStream classes to read and write XML documents."));
|
||||
}
|
||||
//! [5]
|
||||
|
@ -22,13 +22,13 @@ public slots:
|
||||
void open();
|
||||
void saveAs();
|
||||
void about();
|
||||
#if !defined(QT_NO_CONTEXTMENU) && !defined(QT_NO_CLIPBOARD)
|
||||
#if QT_CONFIG(clipboard) && QT_CONFIG(contextmenu)
|
||||
void onCustomContextMenuRequested(const QPoint &pos);
|
||||
#endif
|
||||
private:
|
||||
void createMenus();
|
||||
|
||||
QTreeWidget *treeWidget;
|
||||
QTreeWidget *const treeWidget;
|
||||
};
|
||||
//! [0]
|
||||
|
||||
|
@ -8,7 +8,7 @@ SOURCES = main.cpp \
|
||||
QT += widgets
|
||||
requires(qtConfig(filedialog))
|
||||
|
||||
EXAMPLE_FILES = frank.xbel jennifer.xbel
|
||||
EXAMPLE_FILES = jennifer.xbel
|
||||
|
||||
# install
|
||||
target.path = $$[QT_INSTALL_EXAMPLES]/corelib/serialization/streambookmarks
|
||||
|
@ -1,20 +1,21 @@
|
||||
// Copyright (C) 2016 The Qt Company Ltd.
|
||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
|
||||
|
||||
#include <QtWidgets>
|
||||
|
||||
#include "xbelreader.h"
|
||||
|
||||
#include <QStyle>
|
||||
#include <QTreeWidget>
|
||||
|
||||
using namespace Qt::StringLiterals;
|
||||
|
||||
//! [0]
|
||||
XbelReader::XbelReader(QTreeWidget *treeWidget)
|
||||
: treeWidget(treeWidget)
|
||||
XbelReader::XbelReader(QTreeWidget *treeWidget) : treeWidget(treeWidget)
|
||||
{
|
||||
QStyle *style = treeWidget->style();
|
||||
|
||||
folderIcon.addPixmap(style->standardPixmap(QStyle::SP_DirClosedIcon),
|
||||
QIcon::Normal, QIcon::Off);
|
||||
folderIcon.addPixmap(style->standardPixmap(QStyle::SP_DirOpenIcon),
|
||||
QIcon::Normal, QIcon::On);
|
||||
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));
|
||||
}
|
||||
//! [0]
|
||||
@ -25,12 +26,10 @@ bool XbelReader::read(QIODevice *device)
|
||||
xml.setDevice(device);
|
||||
|
||||
if (xml.readNextStartElement()) {
|
||||
if (xml.name() == QLatin1String("xbel")
|
||||
&& xml.attributes().value(versionAttribute()) == QLatin1String("1.0")) {
|
||||
if (xml.name() == "xbel"_L1 && xml.attributes().value("version"_L1) == "1.0"_L1)
|
||||
readXBEL();
|
||||
} else {
|
||||
else
|
||||
xml.raiseError(QObject::tr("The file is not an XBEL version 1.0 file."));
|
||||
}
|
||||
}
|
||||
|
||||
return !xml.error();
|
||||
@ -50,15 +49,15 @@ QString XbelReader::errorString() const
|
||||
//! [3]
|
||||
void XbelReader::readXBEL()
|
||||
{
|
||||
Q_ASSERT(xml.isStartElement() && xml.name() == QLatin1String("xbel"));
|
||||
Q_ASSERT(xml.isStartElement() && xml.name() == "xbel"_L1);
|
||||
|
||||
while (xml.readNextStartElement()) {
|
||||
if (xml.name() == QLatin1String("folder"))
|
||||
readFolder(0);
|
||||
else if (xml.name() == QLatin1String("bookmark"))
|
||||
readBookmark(0);
|
||||
else if (xml.name() == QLatin1String("separator"))
|
||||
readSeparator(0);
|
||||
if (xml.name() == "folder"_L1)
|
||||
readFolder(nullptr);
|
||||
else if (xml.name() == "bookmark"_L1)
|
||||
readBookmark(nullptr);
|
||||
else if (xml.name() == "separator"_L1)
|
||||
readSeparator(nullptr);
|
||||
else
|
||||
xml.skipCurrentElement();
|
||||
}
|
||||
@ -66,75 +65,76 @@ void XbelReader::readXBEL()
|
||||
//! [3]
|
||||
|
||||
//! [4]
|
||||
void XbelReader::readTitle(QTreeWidgetItem *item)
|
||||
{
|
||||
Q_ASSERT(xml.isStartElement() && xml.name() == QLatin1String("title"));
|
||||
|
||||
QString title = xml.readElementText();
|
||||
item->setText(0, title);
|
||||
}
|
||||
//! [4]
|
||||
|
||||
//! [5]
|
||||
void XbelReader::readSeparator(QTreeWidgetItem *item)
|
||||
{
|
||||
Q_ASSERT(xml.isStartElement() && xml.name() == QLatin1String("separator"));
|
||||
|
||||
QTreeWidgetItem *separator = createChildItem(item);
|
||||
separator->setFlags(item->flags() & ~Qt::ItemIsSelectable);
|
||||
separator->setText(0, QString(30, u'\xB7'));
|
||||
xml.skipCurrentElement();
|
||||
}
|
||||
//! [5]
|
||||
|
||||
void XbelReader::readFolder(QTreeWidgetItem *item)
|
||||
{
|
||||
Q_ASSERT(xml.isStartElement() && xml.name() == QLatin1String("folder"));
|
||||
|
||||
QTreeWidgetItem *folder = createChildItem(item);
|
||||
bool folded = (xml.attributes().value(foldedAttribute()) != QLatin1String("no"));
|
||||
folder->setExpanded(!folded);
|
||||
|
||||
while (xml.readNextStartElement()) {
|
||||
if (xml.name() == QLatin1String("title"))
|
||||
readTitle(folder);
|
||||
else if (xml.name() == QLatin1String("folder"))
|
||||
readFolder(folder);
|
||||
else if (xml.name() == QLatin1String("bookmark"))
|
||||
readBookmark(folder);
|
||||
else if (xml.name() == QLatin1String("separator"))
|
||||
readSeparator(folder);
|
||||
else
|
||||
xml.skipCurrentElement();
|
||||
}
|
||||
}
|
||||
|
||||
void XbelReader::readBookmark(QTreeWidgetItem *item)
|
||||
{
|
||||
Q_ASSERT(xml.isStartElement() && xml.name() == QLatin1String("bookmark"));
|
||||
Q_ASSERT(xml.isStartElement() && xml.name() == "bookmark"_L1);
|
||||
|
||||
QTreeWidgetItem *bookmark = createChildItem(item);
|
||||
bookmark->setFlags(bookmark->flags() | Qt::ItemIsEditable);
|
||||
bookmark->setIcon(0, bookmarkIcon);
|
||||
bookmark->setText(0, QObject::tr("Unknown title"));
|
||||
bookmark->setText(1, xml.attributes().value(hrefAttribute()).toString());
|
||||
bookmark->setText(1, xml.attributes().value("href"_L1).toString());
|
||||
|
||||
while (xml.readNextStartElement()) {
|
||||
if (xml.name() == QLatin1String("title"))
|
||||
if (xml.name() == "title"_L1)
|
||||
readTitle(bookmark);
|
||||
else
|
||||
xml.skipCurrentElement();
|
||||
}
|
||||
}
|
||||
//! [4]
|
||||
|
||||
//! [5]
|
||||
void XbelReader::readTitle(QTreeWidgetItem *item)
|
||||
{
|
||||
Q_ASSERT(xml.isStartElement() && xml.name() == "title"_L1);
|
||||
item->setText(0, xml.readElementText());
|
||||
}
|
||||
//! [5]
|
||||
|
||||
//! [6]
|
||||
void XbelReader::readSeparator(QTreeWidgetItem *item)
|
||||
{
|
||||
Q_ASSERT(xml.isStartElement() && xml.name() == "separator"_L1);
|
||||
constexpr char16_t midDot = u'\xB7';
|
||||
static const QString dots(30, midDot);
|
||||
|
||||
QTreeWidgetItem *separator = createChildItem(item);
|
||||
separator->setFlags(item ? item->flags() & ~Qt::ItemIsSelectable : Qt::ItemFlags{});
|
||||
separator->setText(0, dots);
|
||||
xml.skipCurrentElement();
|
||||
}
|
||||
//! [6]
|
||||
|
||||
//! [7]
|
||||
void XbelReader::readFolder(QTreeWidgetItem *item)
|
||||
{
|
||||
Q_ASSERT(xml.isStartElement() && xml.name() == "folder"_L1);
|
||||
|
||||
QTreeWidgetItem *folder = createChildItem(item);
|
||||
bool folded = xml.attributes().value("folded"_L1) != "no"_L1;
|
||||
folder->setExpanded(!folded);
|
||||
|
||||
while (xml.readNextStartElement()) {
|
||||
if (xml.name() == "title"_L1)
|
||||
readTitle(folder);
|
||||
else if (xml.name() == "folder"_L1)
|
||||
readFolder(folder);
|
||||
else if (xml.name() == "bookmark"_L1)
|
||||
readBookmark(folder);
|
||||
else if (xml.name() == "separator"_L1)
|
||||
readSeparator(folder);
|
||||
else
|
||||
xml.skipCurrentElement();
|
||||
}
|
||||
}
|
||||
//! [7]
|
||||
|
||||
//! [8]
|
||||
QTreeWidgetItem *XbelReader::createChildItem(QTreeWidgetItem *item)
|
||||
{
|
||||
QTreeWidgetItem *childItem;
|
||||
if (item) {
|
||||
childItem = new QTreeWidgetItem(item);
|
||||
} else {
|
||||
childItem = new QTreeWidgetItem(treeWidget);
|
||||
}
|
||||
QTreeWidgetItem *childItem = item ? new QTreeWidgetItem(item) : new QTreeWidgetItem(treeWidget);
|
||||
childItem->setData(0, Qt::UserRole, xml.name().toString());
|
||||
return childItem;
|
||||
}
|
||||
//! [8]
|
||||
|
@ -21,13 +21,8 @@ public:
|
||||
//! [1]
|
||||
|
||||
bool read(QIODevice *device);
|
||||
|
||||
QString errorString() const;
|
||||
|
||||
static inline QString versionAttribute() { return QStringLiteral("version"); }
|
||||
static inline QString hrefAttribute() { return QStringLiteral("href"); }
|
||||
static inline QString foldedAttribute() { return QStringLiteral("folded"); }
|
||||
|
||||
private:
|
||||
//! [2]
|
||||
void readXBEL();
|
||||
|
@ -1,18 +1,15 @@
|
||||
// Copyright (C) 2016 The Qt Company Ltd.
|
||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
|
||||
|
||||
#include <QtWidgets>
|
||||
|
||||
#include "xbelwriter.h"
|
||||
#include "xbelreader.h"
|
||||
|
||||
static inline QString yesValue() { return QStringLiteral("yes"); }
|
||||
static inline QString noValue() { return QStringLiteral("no"); }
|
||||
static inline QString titleElement() { return QStringLiteral("title"); }
|
||||
#include <QTreeWidget>
|
||||
|
||||
using namespace Qt::StringLiterals;
|
||||
|
||||
//! [0]
|
||||
XbelWriter::XbelWriter(const QTreeWidget *treeWidget)
|
||||
: treeWidget(treeWidget)
|
||||
XbelWriter::XbelWriter(const QTreeWidget *treeWidget) : treeWidget(treeWidget)
|
||||
{
|
||||
xml.setAutoFormatting(true);
|
||||
}
|
||||
@ -24,9 +21,9 @@ bool XbelWriter::writeFile(QIODevice *device)
|
||||
xml.setDevice(device);
|
||||
|
||||
xml.writeStartDocument();
|
||||
xml.writeDTD(QStringLiteral("<!DOCTYPE xbel>"));
|
||||
xml.writeStartElement(QStringLiteral("xbel"));
|
||||
xml.writeAttribute(XbelReader::versionAttribute(), QStringLiteral("1.0"));
|
||||
xml.writeDTD("<!DOCTYPE xbel>"_L1);
|
||||
xml.writeStartElement("xbel"_L1);
|
||||
xml.writeAttribute("version"_L1, "1.0"_L1);
|
||||
for (int i = 0; i < treeWidget->topLevelItemCount(); ++i)
|
||||
writeItem(treeWidget->topLevelItem(i));
|
||||
|
||||
@ -39,21 +36,21 @@ bool XbelWriter::writeFile(QIODevice *device)
|
||||
void XbelWriter::writeItem(const QTreeWidgetItem *item)
|
||||
{
|
||||
QString tagName = item->data(0, Qt::UserRole).toString();
|
||||
if (tagName == QLatin1String("folder")) {
|
||||
if (tagName == "folder"_L1) {
|
||||
bool folded = !item->isExpanded();
|
||||
xml.writeStartElement(tagName);
|
||||
xml.writeAttribute(XbelReader::foldedAttribute(), folded ? yesValue() : noValue());
|
||||
xml.writeTextElement(titleElement(), item->text(0));
|
||||
xml.writeAttribute("folded"_L1, folded ? "yes"_L1 : "no"_L1);
|
||||
xml.writeTextElement("title"_L1, item->text(0));
|
||||
for (int i = 0; i < item->childCount(); ++i)
|
||||
writeItem(item->child(i));
|
||||
xml.writeEndElement();
|
||||
} else if (tagName == QLatin1String("bookmark")) {
|
||||
} else if (tagName == "bookmark"_L1) {
|
||||
xml.writeStartElement(tagName);
|
||||
if (!item->text(1).isEmpty())
|
||||
xml.writeAttribute(XbelReader::hrefAttribute(), item->text(1));
|
||||
xml.writeTextElement(titleElement(), item->text(0));
|
||||
xml.writeAttribute("href"_L1, item->text(1));
|
||||
xml.writeTextElement("title"_L1, item->text(0));
|
||||
xml.writeEndElement();
|
||||
} else if (tagName == QLatin1String("separator")) {
|
||||
} else if (tagName == "separator"_L1) {
|
||||
xml.writeEmptyElement(tagName);
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user