From 8d71fae08078afbf4aa2de7429302f46d46fb43f Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Mon, 31 Oct 2016 11:09:00 +0100 Subject: Polish the XML bookmarks examples MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Use Qt 5 connect syntax. - Streamline code, remove unused members. - Add a context menu for copying and opening the URLs. - Add const to XML code. - In the XML code, show the use of QStringLiteral in static inline functions to create strings versus QLatin1String in comparison overloads to avoid allocating strings from const char * literals. Change-Id: Ib5e62ca188e271ffe01996dff3c9ea8e0b60739a Reviewed-by: Topi Reiniƶ --- examples/xml/dombookmarks/mainwindow.cpp | 44 ++++--------- examples/xml/dombookmarks/mainwindow.h | 9 --- examples/xml/dombookmarks/xbeltree.cpp | 74 ++++++++++++++------- examples/xml/dombookmarks/xbeltree.h | 11 ++-- examples/xml/saxbookmarks/mainwindow.cpp | 67 ++++++++++--------- examples/xml/saxbookmarks/mainwindow.h | 13 +--- examples/xml/saxbookmarks/xbelgenerator.cpp | 18 +++--- examples/xml/saxbookmarks/xbelgenerator.h | 6 +- examples/xml/saxbookmarks/xbelhandler.cpp | 28 ++++---- .../doc/src/qxmlstreambookmarks.qdoc | 2 +- examples/xml/streambookmarks/mainwindow.cpp | 75 ++++++++++++---------- examples/xml/streambookmarks/mainwindow.h | 13 +--- examples/xml/streambookmarks/xbelreader.cpp | 36 ++++++----- examples/xml/streambookmarks/xbelreader.h | 4 ++ examples/xml/streambookmarks/xbelwriter.cpp | 29 +++++---- examples/xml/streambookmarks/xbelwriter.h | 6 +- 16 files changed, 227 insertions(+), 208 deletions(-) diff --git a/examples/xml/dombookmarks/mainwindow.cpp b/examples/xml/dombookmarks/mainwindow.cpp index e0f208d336..fade2dfc96 100644 --- a/examples/xml/dombookmarks/mainwindow.cpp +++ b/examples/xml/dombookmarks/mainwindow.cpp @@ -58,13 +58,13 @@ MainWindow::MainWindow() xbelTree = new XbelTree; setCentralWidget(xbelTree); - createActions(); createMenus(); statusBar()->showMessage(tr("Ready")); setWindowTitle(tr("DOM Bookmarks")); - resize(480, 320); + const QSize availableSize = QApplication::desktop()->availableGeometry(this).size(); + resize(availableSize.width() / 2, availableSize.height() / 3); } void MainWindow::open() @@ -80,8 +80,8 @@ void MainWindow::open() if (!file.open(QFile::ReadOnly | QFile::Text)) { QMessageBox::warning(this, tr("SAX Bookmarks"), tr("Cannot read file %1:\n%2.") - .arg(fileName) - .arg(file.errorString())); + .arg(QDir::toNativeSeparators(fileName), + file.errorString())); return; } @@ -102,8 +102,8 @@ void MainWindow::saveAs() if (!file.open(QFile::WriteOnly | QFile::Text)) { QMessageBox::warning(this, tr("SAX Bookmarks"), tr("Cannot write file %1:\n%2.") - .arg(fileName) - .arg(file.errorString())); + .arg(QDir::toNativeSeparators(fileName), + file.errorString())); return; } @@ -119,37 +119,21 @@ void MainWindow::about() "documents.")); } -void MainWindow::createActions() +void MainWindow::createMenus() { - openAct = new QAction(tr("&Open..."), this); + QMenu *fileMenu = menuBar()->addMenu(tr("&File")); + QAction *openAct = fileMenu->addAction(tr("&Open..."), this, &MainWindow::open); openAct->setShortcuts(QKeySequence::Open); - connect(openAct, SIGNAL(triggered()), this, SLOT(open())); - saveAsAct = new QAction(tr("&Save As..."), this); + QAction *saveAsAct = fileMenu->addAction(tr("&Save As..."), this, &MainWindow::saveAs); saveAsAct->setShortcuts(QKeySequence::SaveAs); - connect(saveAsAct, SIGNAL(triggered()), this, SLOT(saveAs())); - exitAct = new QAction(tr("E&xit"), this); + QAction *exitAct = fileMenu->addAction(tr("E&xit"), this, &QWidget::close); exitAct->setShortcuts(QKeySequence::Quit); - connect(exitAct, SIGNAL(triggered()), this, SLOT(close())); - - aboutAct = new QAction(tr("&About"), this); - connect(aboutAct, SIGNAL(triggered()), this, SLOT(about())); - - aboutQtAct = new QAction(tr("About &Qt"), this); - connect(aboutQtAct, SIGNAL(triggered()), qApp, SLOT(aboutQt())); -} - -void MainWindow::createMenus() -{ - fileMenu = menuBar()->addMenu(tr("&File")); - fileMenu->addAction(openAct); - fileMenu->addAction(saveAsAct); - fileMenu->addAction(exitAct); menuBar()->addSeparator(); - helpMenu = menuBar()->addMenu(tr("&Help")); - helpMenu->addAction(aboutAct); - helpMenu->addAction(aboutQtAct); + QMenu *helpMenu = menuBar()->addMenu(tr("&Help")); + helpMenu->addAction(tr("&About"), this, &MainWindow::about); + helpMenu->addAction(tr("About &Qt"), qApp, &QCoreApplication::quit); } diff --git a/examples/xml/dombookmarks/mainwindow.h b/examples/xml/dombookmarks/mainwindow.h index 6d490caf64..0a8c7bdd82 100644 --- a/examples/xml/dombookmarks/mainwindow.h +++ b/examples/xml/dombookmarks/mainwindow.h @@ -68,18 +68,9 @@ public slots: void about(); private: - void createActions(); void createMenus(); XbelTree *xbelTree; - - QMenu *fileMenu; - QMenu *helpMenu; - QAction *openAct; - QAction *saveAsAct; - QAction *exitAct; - QAction *aboutAct; - QAction *aboutQtAct; }; #endif diff --git a/examples/xml/dombookmarks/xbeltree.cpp b/examples/xml/dombookmarks/xbeltree.cpp index 82afc48bd9..f7ff1de638 100644 --- a/examples/xml/dombookmarks/xbeltree.cpp +++ b/examples/xml/dombookmarks/xbeltree.cpp @@ -52,6 +52,18 @@ #include "xbeltree.h" +enum { DomElementRole = Qt::UserRole + 1 }; + +Q_DECLARE_METATYPE(QDomElement) + +static inline QString titleElement() { return QStringLiteral("title"); } +static inline QString folderElement() { return QStringLiteral("folder"); } +static inline QString bookmarkElement() { return QStringLiteral("bookmark"); } + +static inline QString versionAttribute() { return QStringLiteral("version"); } +static inline QString hrefAttribute() { return QStringLiteral("href"); } +static inline QString foldedAttribute() { return QStringLiteral("folded"); } + XbelTree::XbelTree(QWidget *parent) : QTreeWidget(parent) { @@ -68,6 +80,24 @@ XbelTree::XbelTree(QWidget *parent) bookmarkIcon.addPixmap(style()->standardPixmap(QStyle::SP_FileIcon)); } +#if !defined(QT_NO_CONTEXTMENU) && !defined(QT_NO_CLIPBOARD) +void XbelTree::contextMenuEvent(QContextMenuEvent *event) +{ + const QTreeWidgetItem *item = itemAt(event->pos()); + if (!item) + return; + const QString url = item->text(1); + QMenu contextMenu; + QAction *copyAction = contextMenu.addAction(tr("Copy Link to Clipboard")); + QAction *openAction = contextMenu.addAction(tr("Open")); + QAction *action = contextMenu.exec(event->globalPos()); + if (action == copyAction) + QGuiApplication::clipboard()->setText(url); + else if (action == openAction) + QDesktopServices::openUrl(QUrl(url)); +} +#endif // !QT_NO_CONTEXTMENU && !QT_NO_CLIPBOARD + bool XbelTree::read(QIODevice *device) { QString errorStr; @@ -89,8 +119,8 @@ bool XbelTree::read(QIODevice *device) QMessageBox::information(window(), tr("DOM Bookmarks"), tr("The file is not an XBEL file.")); return false; - } else if (root.hasAttribute("version") - && root.attribute("version") != "1.0") { + } else if (root.hasAttribute(versionAttribute()) + && root.attribute(versionAttribute()) != QLatin1String("1.0")) { QMessageBox::information(window(), tr("DOM Bookmarks"), tr("The file is not an XBEL version 1.0 " "file.")); @@ -99,22 +129,20 @@ bool XbelTree::read(QIODevice *device) clear(); - disconnect(this, SIGNAL(itemChanged(QTreeWidgetItem*,int)), - this, SLOT(updateDomElement(QTreeWidgetItem*,int))); + disconnect(this, &QTreeWidget::itemChanged, this, &XbelTree::updateDomElement); - QDomElement child = root.firstChildElement("folder"); + QDomElement child = root.firstChildElement(folderElement()); while (!child.isNull()) { parseFolderElement(child); - child = child.nextSiblingElement("folder"); + child = child.nextSiblingElement(folderElement()); } - connect(this, SIGNAL(itemChanged(QTreeWidgetItem*,int)), - this, SLOT(updateDomElement(QTreeWidgetItem*,int))); + connect(this, &QTreeWidget::itemChanged, this, &XbelTree::updateDomElement); return true; } -bool XbelTree::write(QIODevice *device) +bool XbelTree::write(QIODevice *device) const { const int IndentSize = 4; @@ -123,21 +151,21 @@ bool XbelTree::write(QIODevice *device) return true; } -void XbelTree::updateDomElement(QTreeWidgetItem *item, int column) +void XbelTree::updateDomElement(const QTreeWidgetItem *item, int column) { - QDomElement element = domElementForItem.value(item); + QDomElement element = item->data(0, DomElementRole).value(); if (!element.isNull()) { if (column == 0) { - QDomElement oldTitleElement = element.firstChildElement("title"); - QDomElement newTitleElement = domDocument.createElement("title"); + QDomElement oldTitleElement = element.firstChildElement(titleElement()); + QDomElement newTitleElement = domDocument.createElement(titleElement()); QDomText newTitleText = domDocument.createTextNode(item->text(0)); newTitleElement.appendChild(newTitleText); element.replaceChild(newTitleElement, oldTitleElement); } else { - if (element.tagName() == "bookmark") - element.setAttribute("href", item->text(1)); + if (element.tagName() == bookmarkElement()) + element.setAttribute(hrefAttribute(), item->text(1)); } } } @@ -147,7 +175,7 @@ void XbelTree::parseFolderElement(const QDomElement &element, { QTreeWidgetItem *item = createItem(element, parentItem); - QString title = element.firstChildElement("title").text(); + QString title = element.firstChildElement(titleElement()).text(); if (title.isEmpty()) title = QObject::tr("Folder"); @@ -155,25 +183,25 @@ void XbelTree::parseFolderElement(const QDomElement &element, item->setIcon(0, folderIcon); item->setText(0, title); - bool folded = (element.attribute("folded") != "no"); + bool folded = (element.attribute(foldedAttribute()) != QLatin1String("no")); setItemExpanded(item, !folded); QDomElement child = element.firstChildElement(); while (!child.isNull()) { - if (child.tagName() == "folder") { + if (child.tagName() == folderElement()) { parseFolderElement(child, item); - } else if (child.tagName() == "bookmark") { + } else if (child.tagName() == bookmarkElement()) { QTreeWidgetItem *childItem = createItem(child, item); - QString title = child.firstChildElement("title").text(); + QString title = child.firstChildElement(titleElement()).text(); if (title.isEmpty()) title = QObject::tr("Folder"); childItem->setFlags(item->flags() | Qt::ItemIsEditable); childItem->setIcon(0, bookmarkIcon); childItem->setText(0, title); - childItem->setText(1, child.attribute("href")); - } else if (child.tagName() == "separator") { + childItem->setText(1, child.attribute(hrefAttribute())); + } else if (child.tagName() == QLatin1String("separator")) { QTreeWidgetItem *childItem = createItem(child, item); childItem->setFlags(item->flags() & ~(Qt::ItemIsSelectable | Qt::ItemIsEditable)); childItem->setText(0, QString(30, 0xB7)); @@ -191,6 +219,6 @@ QTreeWidgetItem *XbelTree::createItem(const QDomElement &element, } else { item = new QTreeWidgetItem(this); } - domElementForItem.insert(item, element); + item->setData(0, DomElementRole, QVariant::fromValue(element)); return item; } diff --git a/examples/xml/dombookmarks/xbeltree.h b/examples/xml/dombookmarks/xbeltree.h index bf4b55ea74..f6c7ef8bfe 100644 --- a/examples/xml/dombookmarks/xbeltree.h +++ b/examples/xml/dombookmarks/xbeltree.h @@ -52,7 +52,6 @@ #define XBELTREE_H #include -#include #include #include @@ -64,10 +63,15 @@ public: XbelTree(QWidget *parent = 0); bool read(QIODevice *device); - bool write(QIODevice *device); + bool write(QIODevice *device) const; + +protected: +#if !defined(QT_NO_CONTEXTMENU) && !defined(QT_NO_CLIPBOARD) + void contextMenuEvent(QContextMenuEvent *event) Q_DECL_OVERRIDE; +#endif private slots: - void updateDomElement(QTreeWidgetItem *item, int column); + void updateDomElement(const QTreeWidgetItem *item, int column); private: void parseFolderElement(const QDomElement &element, @@ -76,7 +80,6 @@ private: QTreeWidgetItem *parentItem = 0); QDomDocument domDocument; - QHash domElementForItem; QIcon folderIcon; QIcon bookmarkIcon; }; diff --git a/examples/xml/saxbookmarks/mainwindow.cpp b/examples/xml/saxbookmarks/mainwindow.cpp index 2ce2b9a508..0583cd82cf 100644 --- a/examples/xml/saxbookmarks/mainwindow.cpp +++ b/examples/xml/saxbookmarks/mainwindow.cpp @@ -62,17 +62,40 @@ MainWindow::MainWindow() treeWidget = new QTreeWidget; treeWidget->header()->setSectionResizeMode(QHeaderView::Stretch); treeWidget->setHeaderLabels(labels); +#if !defined(QT_NO_CONTEXTMENU) && !defined(QT_NO_CLIPBOARD) + treeWidget->setContextMenuPolicy(Qt::CustomContextMenu); + connect(treeWidget, &QWidget::customContextMenuRequested, + this, &MainWindow::onCustomContextMenuRequested); +#endif setCentralWidget(treeWidget); - createActions(); createMenus(); statusBar()->showMessage(tr("Ready")); setWindowTitle(tr("SAX Bookmarks")); - resize(480, 320); + const QSize availableSize = QApplication::desktop()->availableGeometry(this).size(); + resize(availableSize.width() / 2, availableSize.height() / 3); } +#if !defined(QT_NO_CONTEXTMENU) && !defined(QT_NO_CLIPBOARD) +void MainWindow::onCustomContextMenuRequested(const QPoint &pos) +{ + const QTreeWidgetItem *item = treeWidget->itemAt(pos); + if (!item) + return; + const QString url = item->text(1); + QMenu contextMenu; + QAction *copyAction = contextMenu.addAction(tr("Copy Link to Clipboard")); + QAction *openAction = contextMenu.addAction(tr("Open")); + QAction *action = contextMenu.exec(treeWidget->viewport()->mapToGlobal(pos)); + if (action == copyAction) + QGuiApplication::clipboard()->setText(url); + else if (action == openAction) + QDesktopServices::openUrl(QUrl(url)); +} +#endif // !QT_NO_CONTEXTMENU && !QT_NO_CLIPBOARD + void MainWindow::open() { QString fileName = @@ -93,8 +116,8 @@ void MainWindow::open() if (!file.open(QFile::ReadOnly | QFile::Text)) { QMessageBox::warning(this, tr("SAX Bookmarks"), tr("Cannot read file %1:\n%2.") - .arg(fileName) - .arg(file.errorString())); + .arg(QDir::toNativeSeparators(fileName), + file.errorString())); return; } @@ -116,8 +139,8 @@ void MainWindow::saveAs() if (!file.open(QFile::WriteOnly | QFile::Text)) { QMessageBox::warning(this, tr("SAX Bookmarks"), tr("Cannot write file %1:\n%2.") - .arg(fileName) - .arg(file.errorString())); + .arg(QDir::toNativeSeparators(fileName), + file.errorString())); return; } @@ -134,37 +157,21 @@ void MainWindow::about() "hand.")); } -void MainWindow::createActions() +void MainWindow::createMenus() { - openAct = new QAction(tr("&Open..."), this); + QMenu *fileMenu = menuBar()->addMenu(tr("&File")); + QAction *openAct = fileMenu->addAction(tr("&Open..."), this, &MainWindow::open); openAct->setShortcuts(QKeySequence::Open); - connect(openAct, SIGNAL(triggered()), this, SLOT(open())); - saveAsAct = new QAction(tr("&Save As..."), this); + QAction *saveAsAct = fileMenu->addAction(tr("&Save As..."), this, &MainWindow::saveAs); saveAsAct->setShortcuts(QKeySequence::SaveAs); - connect(saveAsAct, SIGNAL(triggered()), this, SLOT(saveAs())); - exitAct = new QAction(tr("E&xit"), this); + QAction *exitAct = fileMenu->addAction(tr("E&xit"), this, &QWidget::close); exitAct->setShortcuts(QKeySequence::Quit); - connect(exitAct, SIGNAL(triggered()), this, SLOT(close())); - - aboutAct = new QAction(tr("&About"), this); - connect(aboutAct, SIGNAL(triggered()), this, SLOT(about())); - - aboutQtAct = new QAction(tr("About &Qt"), this); - connect(aboutQtAct, SIGNAL(triggered()), qApp, SLOT(aboutQt())); -} - -void MainWindow::createMenus() -{ - fileMenu = menuBar()->addMenu(tr("&File")); - fileMenu->addAction(openAct); - fileMenu->addAction(saveAsAct); - fileMenu->addAction(exitAct); menuBar()->addSeparator(); - helpMenu = menuBar()->addMenu(tr("&Help")); - helpMenu->addAction(aboutAct); - helpMenu->addAction(aboutQtAct); + QMenu *helpMenu = menuBar()->addMenu(tr("&Help")); + helpMenu->addAction(tr("&About"), this, &MainWindow::about); + helpMenu->addAction(tr("About &Qt"), qApp, &QCoreApplication::quit); } diff --git a/examples/xml/saxbookmarks/mainwindow.h b/examples/xml/saxbookmarks/mainwindow.h index 828a0ed14e..20a11bb202 100644 --- a/examples/xml/saxbookmarks/mainwindow.h +++ b/examples/xml/saxbookmarks/mainwindow.h @@ -68,20 +68,13 @@ public slots: void open(); void saveAs(); void about(); - +#if !defined(QT_NO_CONTEXTMENU) && !defined(QT_NO_CLIPBOARD) + void onCustomContextMenuRequested(const QPoint &pos); +#endif private: - void createActions(); void createMenus(); QTreeWidget *treeWidget; - - QMenu *fileMenu; - QMenu *helpMenu; - QAction *openAct; - QAction *saveAsAct; - QAction *exitAct; - QAction *aboutAct; - QAction *aboutQtAct; }; #endif diff --git a/examples/xml/saxbookmarks/xbelgenerator.cpp b/examples/xml/saxbookmarks/xbelgenerator.cpp index 30ce1428e6..ee6f113f9c 100644 --- a/examples/xml/saxbookmarks/xbelgenerator.cpp +++ b/examples/xml/saxbookmarks/xbelgenerator.cpp @@ -52,7 +52,7 @@ #include "xbelgenerator.h" -XbelGenerator::XbelGenerator(QTreeWidget *treeWidget) +XbelGenerator::XbelGenerator(const QTreeWidget *treeWidget) : treeWidget(treeWidget) { } @@ -81,25 +81,25 @@ QString XbelGenerator::indent(int depth) QString XbelGenerator::escapedText(const QString &str) { QString result = str; - result.replace("&", "&"); - result.replace("<", "<"); - result.replace(">", ">"); + result.replace('&', "&"); + result.replace('<', "<"); + result.replace('>', ">"); return result; } QString XbelGenerator::escapedAttribute(const QString &str) { QString result = escapedText(str); - result.replace("\"", """); + result.replace(QLatin1Char('"'), """); result.prepend(QLatin1Char('"')); result.append(QLatin1Char('"')); return result; } -void XbelGenerator::generateItem(QTreeWidgetItem *item, int depth) +void XbelGenerator::generateItem(const QTreeWidgetItem *item, int depth) { QString tagName = item->data(0, Qt::UserRole).toString(); - if (tagName == "folder") { + if (tagName == QLatin1String("folder")) { bool folded = !treeWidget->isItemExpanded(item); out << indent(depth) << "\n" @@ -110,7 +110,7 @@ void XbelGenerator::generateItem(QTreeWidgetItem *item, int depth) generateItem(item->child(i), depth + 1); out << indent(depth) << "\n"; - } else if (tagName == "bookmark") { + } else if (tagName == QLatin1String("bookmark")) { out << indent(depth) << "text(1).isEmpty()) out << " href=" << escapedAttribute(item->text(1)); @@ -118,7 +118,7 @@ void XbelGenerator::generateItem(QTreeWidgetItem *item, int depth) << indent(depth + 1) << "" << escapedText(item->text(0)) << "\n" << indent(depth) << "\n"; - } else if (tagName == "separator") { + } else if (tagName == QLatin1String("separator")) { out << indent(depth) << "\n"; } } diff --git a/examples/xml/saxbookmarks/xbelgenerator.h b/examples/xml/saxbookmarks/xbelgenerator.h index 44069599e2..abfabfd75c 100644 --- a/examples/xml/saxbookmarks/xbelgenerator.h +++ b/examples/xml/saxbookmarks/xbelgenerator.h @@ -61,7 +61,7 @@ QT_END_NAMESPACE class XbelGenerator { public: - XbelGenerator(QTreeWidget *treeWidget); + explicit XbelGenerator(const QTreeWidget *treeWidget); bool write(QIODevice *device); @@ -69,9 +69,9 @@ private: static QString indent(int indentLevel); static QString escapedText(const QString &str); static QString escapedAttribute(const QString &str); - void generateItem(QTreeWidgetItem *item, int depth); + void generateItem(const QTreeWidgetItem *item, int depth); - QTreeWidget *treeWidget; + const QTreeWidget *treeWidget; QTextStream out; }; diff --git a/examples/xml/saxbookmarks/xbelhandler.cpp b/examples/xml/saxbookmarks/xbelhandler.cpp index 03b16c81f1..7e2a9db3c2 100644 --- a/examples/xml/saxbookmarks/xbelhandler.cpp +++ b/examples/xml/saxbookmarks/xbelhandler.cpp @@ -52,6 +52,10 @@ #include "xbelhandler.h" +static inline QString versionAttribute() { return QStringLiteral("version"); } +static inline QString hrefAttribute() { return QStringLiteral("href"); } +static inline QString foldedAttribute() { return QStringLiteral("folded"); } + XbelHandler::XbelHandler(QTreeWidget *treeWidget) : treeWidget(treeWidget) { @@ -72,32 +76,32 @@ bool XbelHandler::startElement(const QString & /* namespaceURI */, const QString &qName, const QXmlAttributes &attributes) { - if (!metXbelTag && qName != "xbel") { + if (!metXbelTag && qName != QLatin1String("xbel")) { errorStr = QObject::tr("The file is not an XBEL file."); return false; } - if (qName == "xbel") { - QString version = attributes.value("version"); - if (!version.isEmpty() && version != "1.0") { + if (qName == QLatin1String("xbel")) { + QString version = attributes.value(versionAttribute()); + if (!version.isEmpty() && version != QLatin1String("1.0")) { errorStr = QObject::tr("The file is not an XBEL version 1.0 file."); return false; } metXbelTag = true; - } else if (qName == "folder") { + } else if (qName == QLatin1String("folder")) { item = createChildItem(qName); item->setFlags(item->flags() | Qt::ItemIsEditable); item->setIcon(0, folderIcon); item->setText(0, QObject::tr("Folder")); - bool folded = (attributes.value("folded") != "no"); + bool folded = (attributes.value(foldedAttribute()) != QLatin1String("no")); treeWidget->setItemExpanded(item, !folded); - } else if (qName == "bookmark") { + } else if (qName == QLatin1String("bookmark")) { item = createChildItem(qName); item->setFlags(item->flags() | Qt::ItemIsEditable); item->setIcon(0, bookmarkIcon); item->setText(0, QObject::tr("Unknown title")); - item->setText(1, attributes.value("href")); - } else if (qName == "separator") { + item->setText(1, attributes.value(hrefAttribute())); + } else if (qName == QLatin1String("separator")) { item = createChildItem(qName); item->setFlags(item->flags() & ~Qt::ItemIsSelectable); item->setText(0, QString(30, 0xB7)); @@ -111,11 +115,11 @@ bool XbelHandler::endElement(const QString & /* namespaceURI */, const QString & /* localName */, const QString &qName) { - if (qName == "title") { + if (qName == QLatin1String("title")) { if (item) item->setText(0, currentText); - } else if (qName == "folder" || qName == "bookmark" - || qName == "separator") { + } else if (qName == QLatin1String("folder") || qName == QLatin1String("bookmark") + || qName == QLatin1String("separator")) { item = item->parent(); } return true; diff --git a/examples/xml/streambookmarks/doc/src/qxmlstreambookmarks.qdoc b/examples/xml/streambookmarks/doc/src/qxmlstreambookmarks.qdoc index 0720e3eadd..ad093c2098 100644 --- a/examples/xml/streambookmarks/doc/src/qxmlstreambookmarks.qdoc +++ b/examples/xml/streambookmarks/doc/src/qxmlstreambookmarks.qdoc @@ -167,7 +167,7 @@ add them to the \c fileMenu and \c helpMenu. The connections are as shown below: - \snippet streambookmarks/mainwindow.cpp 4 + \snippet 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 diff --git a/examples/xml/streambookmarks/mainwindow.cpp b/examples/xml/streambookmarks/mainwindow.cpp index 7c0fd8720d..c9a18fa3c4 100644 --- a/examples/xml/streambookmarks/mainwindow.cpp +++ b/examples/xml/streambookmarks/mainwindow.cpp @@ -63,18 +63,41 @@ MainWindow::MainWindow() treeWidget = new QTreeWidget; treeWidget->header()->setSectionResizeMode(QHeaderView::Stretch); treeWidget->setHeaderLabels(labels); +#if !defined(QT_NO_CONTEXTMENU) && !defined(QT_NO_CLIPBOARD) + treeWidget->setContextMenuPolicy(Qt::CustomContextMenu); + connect(treeWidget, &QWidget::customContextMenuRequested, + this, &MainWindow::onCustomContextMenuRequested); +#endif setCentralWidget(treeWidget); - createActions(); createMenus(); statusBar()->showMessage(tr("Ready")); setWindowTitle(tr("QXmlStream Bookmarks")); - resize(480, 320); + const QSize availableSize = QApplication::desktop()->availableGeometry(this).size(); + resize(availableSize.width() / 2, availableSize.height() / 3); } //! [0] +#if !defined(QT_NO_CONTEXTMENU) && !defined(QT_NO_CLIPBOARD) +void MainWindow::onCustomContextMenuRequested(const QPoint &pos) +{ + const QTreeWidgetItem *item = treeWidget->itemAt(pos); + if (!item) + return; + const QString url = item->text(1); + QMenu contextMenu; + QAction *copyAction = contextMenu.addAction(tr("Copy Link to Clipboard")); + QAction *openAction = contextMenu.addAction(tr("Open")); + QAction *action = contextMenu.exec(treeWidget->viewport()->mapToGlobal(pos)); + if (action == copyAction) + QGuiApplication::clipboard()->setText(url); + else if (action == openAction) + QDesktopServices::openUrl(QUrl(url)); +} +#endif // !QT_NO_CONTEXTMENU && !QT_NO_CLIPBOARD + //! [1] void MainWindow::open() { @@ -92,8 +115,8 @@ void MainWindow::open() if (!file.open(QFile::ReadOnly | QFile::Text)) { QMessageBox::warning(this, tr("QXmlStream Bookmarks"), tr("Cannot read file %1:\n%2.") - .arg(fileName) - .arg(file.errorString())); + .arg(QDir::toNativeSeparators(fileName), + file.errorString())); return; } @@ -101,8 +124,8 @@ void MainWindow::open() if (!reader.read(&file)) { QMessageBox::warning(this, tr("QXmlStream Bookmarks"), tr("Parse error in file %1:\n\n%2") - .arg(fileName) - .arg(reader.errorString())); + .arg(QDir::toNativeSeparators(fileName), + reader.errorString())); } else { statusBar()->showMessage(tr("File loaded"), 2000); } @@ -124,8 +147,8 @@ void MainWindow::saveAs() if (!file.open(QFile::WriteOnly | QFile::Text)) { QMessageBox::warning(this, tr("QXmlStream Bookmarks"), tr("Cannot write file %1:\n%2.") - .arg(fileName) - .arg(file.errorString())); + .arg(QDir::toNativeSeparators(fileName), + file.errorString())); return; } @@ -144,41 +167,23 @@ void MainWindow::about() } //! [3] -//! [4] -void MainWindow::createActions() +//! [5] +void MainWindow::createMenus() { - openAct = new QAction(tr("&Open..."), this); + QMenu *fileMenu = menuBar()->addMenu(tr("&File")); + QAction *openAct = fileMenu->addAction(tr("&Open..."), this, &MainWindow::open); openAct->setShortcuts(QKeySequence::Open); - connect(openAct, SIGNAL(triggered()), this, SLOT(open())); - saveAsAct = new QAction(tr("&Save As..."), this); + QAction *saveAsAct = fileMenu->addAction(tr("&Save As..."), this, &MainWindow::saveAs); saveAsAct->setShortcuts(QKeySequence::SaveAs); - connect(saveAsAct, SIGNAL(triggered()), this, SLOT(saveAs())); - exitAct = new QAction(tr("E&xit"), this); + QAction *exitAct = fileMenu->addAction(tr("E&xit"), this, &QWidget::close); exitAct->setShortcuts(QKeySequence::Quit); - connect(exitAct, SIGNAL(triggered()), this, SLOT(close())); - - aboutAct = new QAction(tr("&About"), this); - connect(aboutAct, SIGNAL(triggered()), this, SLOT(about())); - - aboutQtAct = new QAction(tr("About &Qt"), this); - connect(aboutQtAct, SIGNAL(triggered()), qApp, SLOT(aboutQt())); -} -//! [4] - -//! [5] -void MainWindow::createMenus() -{ - fileMenu = menuBar()->addMenu(tr("&File")); - fileMenu->addAction(openAct); - fileMenu->addAction(saveAsAct); - fileMenu->addAction(exitAct); menuBar()->addSeparator(); - helpMenu = menuBar()->addMenu(tr("&Help")); - helpMenu->addAction(aboutAct); - helpMenu->addAction(aboutQtAct); + QMenu *helpMenu = menuBar()->addMenu(tr("&Help")); + helpMenu->addAction(tr("&About"), this, &MainWindow::about); + helpMenu->addAction(tr("About &Qt"), qApp, &QCoreApplication::quit); } //! [5] diff --git a/examples/xml/streambookmarks/mainwindow.h b/examples/xml/streambookmarks/mainwindow.h index 2b6feeb26f..fbdc1e0c62 100644 --- a/examples/xml/streambookmarks/mainwindow.h +++ b/examples/xml/streambookmarks/mainwindow.h @@ -69,20 +69,13 @@ public slots: void open(); void saveAs(); void about(); - +#if !defined(QT_NO_CONTEXTMENU) && !defined(QT_NO_CLIPBOARD) + void onCustomContextMenuRequested(const QPoint &pos); +#endif private: - void createActions(); void createMenus(); QTreeWidget *treeWidget; - - QMenu *fileMenu; - QMenu *helpMenu; - QAction *openAct; - QAction *saveAsAct; - QAction *exitAct; - QAction *aboutAct; - QAction *aboutQtAct; }; //! [0] diff --git a/examples/xml/streambookmarks/xbelreader.cpp b/examples/xml/streambookmarks/xbelreader.cpp index 53d6b94ba0..099985d91e 100644 --- a/examples/xml/streambookmarks/xbelreader.cpp +++ b/examples/xml/streambookmarks/xbelreader.cpp @@ -72,10 +72,12 @@ bool XbelReader::read(QIODevice *device) xml.setDevice(device); if (xml.readNextStartElement()) { - if (xml.name() == "xbel" && xml.attributes().value("version") == "1.0") + if (xml.name() == QLatin1String("xbel") + && xml.attributes().value(versionAttribute()) == QLatin1String("1.0")) { readXBEL(); - else + } else { xml.raiseError(QObject::tr("The file is not an XBEL version 1.0 file.")); + } } return !xml.error(); @@ -95,14 +97,14 @@ QString XbelReader::errorString() const //! [3] void XbelReader::readXBEL() { - Q_ASSERT(xml.isStartElement() && xml.name() == "xbel"); + Q_ASSERT(xml.isStartElement() && xml.name() == QLatin1String("xbel")); while (xml.readNextStartElement()) { - if (xml.name() == "folder") + if (xml.name() == QLatin1String("folder")) readFolder(0); - else if (xml.name() == "bookmark") + else if (xml.name() == QLatin1String("bookmark")) readBookmark(0); - else if (xml.name() == "separator") + else if (xml.name() == QLatin1String("separator")) readSeparator(0); else xml.skipCurrentElement(); @@ -113,7 +115,7 @@ void XbelReader::readXBEL() //! [4] void XbelReader::readTitle(QTreeWidgetItem *item) { - Q_ASSERT(xml.isStartElement() && xml.name() == "title"); + Q_ASSERT(xml.isStartElement() && xml.name() == QLatin1String("title")); QString title = xml.readElementText(); item->setText(0, title); @@ -123,7 +125,7 @@ void XbelReader::readTitle(QTreeWidgetItem *item) //! [5] void XbelReader::readSeparator(QTreeWidgetItem *item) { - Q_ASSERT(xml.isStartElement() && xml.name() == "separator"); + Q_ASSERT(xml.isStartElement() && xml.name() == QLatin1String("separator")); QTreeWidgetItem *separator = createChildItem(item); separator->setFlags(item->flags() & ~Qt::ItemIsSelectable); @@ -134,20 +136,20 @@ void XbelReader::readSeparator(QTreeWidgetItem *item) void XbelReader::readFolder(QTreeWidgetItem *item) { - Q_ASSERT(xml.isStartElement() && xml.name() == "folder"); + Q_ASSERT(xml.isStartElement() && xml.name() == QLatin1String("folder")); QTreeWidgetItem *folder = createChildItem(item); - bool folded = (xml.attributes().value("folded") != "no"); + bool folded = (xml.attributes().value(foldedAttribute()) != QLatin1String("no")); treeWidget->setItemExpanded(folder, !folded); while (xml.readNextStartElement()) { - if (xml.name() == "title") + if (xml.name() == QLatin1String("title")) readTitle(folder); - else if (xml.name() == "folder") + else if (xml.name() == QLatin1String("folder")) readFolder(folder); - else if (xml.name() == "bookmark") + else if (xml.name() == QLatin1String("bookmark")) readBookmark(folder); - else if (xml.name() == "separator") + else if (xml.name() == QLatin1String("separator")) readSeparator(folder); else xml.skipCurrentElement(); @@ -156,16 +158,16 @@ void XbelReader::readFolder(QTreeWidgetItem *item) void XbelReader::readBookmark(QTreeWidgetItem *item) { - Q_ASSERT(xml.isStartElement() && xml.name() == "bookmark"); + Q_ASSERT(xml.isStartElement() && xml.name() == QLatin1String("bookmark")); 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("href").toString()); + bookmark->setText(1, xml.attributes().value(hrefAttribute()).toString()); while (xml.readNextStartElement()) { - if (xml.name() == "title") + if (xml.name() == QLatin1String("title")) readTitle(bookmark); else xml.skipCurrentElement(); diff --git a/examples/xml/streambookmarks/xbelreader.h b/examples/xml/streambookmarks/xbelreader.h index 3175441ddd..fd486a430f 100644 --- a/examples/xml/streambookmarks/xbelreader.h +++ b/examples/xml/streambookmarks/xbelreader.h @@ -71,6 +71,10 @@ public: 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(); diff --git a/examples/xml/streambookmarks/xbelwriter.cpp b/examples/xml/streambookmarks/xbelwriter.cpp index fdf2e1095e..2959680678 100644 --- a/examples/xml/streambookmarks/xbelwriter.cpp +++ b/examples/xml/streambookmarks/xbelwriter.cpp @@ -51,9 +51,14 @@ #include #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"); } //! [0] -XbelWriter::XbelWriter(QTreeWidget *treeWidget) +XbelWriter::XbelWriter(const QTreeWidget *treeWidget) : treeWidget(treeWidget) { xml.setAutoFormatting(true); @@ -66,9 +71,9 @@ bool XbelWriter::writeFile(QIODevice *device) xml.setDevice(device); xml.writeStartDocument(); - xml.writeDTD(""); - xml.writeStartElement("xbel"); - xml.writeAttribute("version", "1.0"); + xml.writeDTD(QStringLiteral("")); + xml.writeStartElement(QStringLiteral("xbel")); + xml.writeAttribute(XbelReader::versionAttribute(), QStringLiteral("1.0")); for (int i = 0; i < treeWidget->topLevelItemCount(); ++i) writeItem(treeWidget->topLevelItem(i)); @@ -78,24 +83,24 @@ bool XbelWriter::writeFile(QIODevice *device) //! [1] //! [2] -void XbelWriter::writeItem(QTreeWidgetItem *item) +void XbelWriter::writeItem(const QTreeWidgetItem *item) { QString tagName = item->data(0, Qt::UserRole).toString(); - if (tagName == "folder") { + if (tagName == QLatin1String("folder")) { bool folded = !treeWidget->isItemExpanded(item); xml.writeStartElement(tagName); - xml.writeAttribute("folded", folded ? "yes" : "no"); - xml.writeTextElement("title", item->text(0)); + xml.writeAttribute(XbelReader::foldedAttribute(), folded ? yesValue() : noValue()); + xml.writeTextElement(titleElement(), item->text(0)); for (int i = 0; i < item->childCount(); ++i) writeItem(item->child(i)); xml.writeEndElement(); - } else if (tagName == "bookmark") { + } else if (tagName == QLatin1String("bookmark")) { xml.writeStartElement(tagName); if (!item->text(1).isEmpty()) - xml.writeAttribute("href", item->text(1)); - xml.writeTextElement("title", item->text(0)); + xml.writeAttribute(XbelReader::hrefAttribute(), item->text(1)); + xml.writeTextElement(titleElement(), item->text(0)); xml.writeEndElement(); - } else if (tagName == "separator") { + } else if (tagName == QLatin1String("separator")) { xml.writeEmptyElement(tagName); } } diff --git a/examples/xml/streambookmarks/xbelwriter.h b/examples/xml/streambookmarks/xbelwriter.h index b15bf60e31..465d8f0dc4 100644 --- a/examples/xml/streambookmarks/xbelwriter.h +++ b/examples/xml/streambookmarks/xbelwriter.h @@ -62,13 +62,13 @@ QT_END_NAMESPACE class XbelWriter { public: - XbelWriter(QTreeWidget *treeWidget); + explicit XbelWriter(const QTreeWidget *treeWidget); bool writeFile(QIODevice *device); private: - void writeItem(QTreeWidgetItem *item); + void writeItem(const QTreeWidgetItem *item); QXmlStreamWriter xml; - QTreeWidget *treeWidget; + const QTreeWidget *treeWidget; }; //! [0] -- cgit v1.2.3