From 99303e92ae9cf461f99b8eff8b37b42f758118b6 Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Fri, 11 Mar 2016 10:00:33 +0100 Subject: Polish the SVG viewer example. - Use Qt 5 connection syntax, demonstrating lambdas. - Use QCommandLineParser. - Improve error handling. - Use Mime API of QFileDialog, point to pictures location initially. - Prevent the application from shrinking when loading small images. - Minor polishing, status messages on loading, About Qt dialog. Change-Id: I76f14001c9ab12cbfaaacc2ca4828b404e4b13b2 Reviewed-by: aavit --- examples/svg/svgviewer/main.cpp | 21 ++++-- examples/svg/svgviewer/mainwindow.cpp | 121 ++++++++++++++++------------------ examples/svg/svgviewer/mainwindow.h | 6 +- examples/svg/svgviewer/svgview.cpp | 28 +++++--- examples/svg/svgviewer/svgview.h | 13 ++-- 5 files changed, 102 insertions(+), 87 deletions(-) diff --git a/examples/svg/svgviewer/main.cpp b/examples/svg/svgviewer/main.cpp index 671262c..9155c87 100644 --- a/examples/svg/svgviewer/main.cpp +++ b/examples/svg/svgviewer/main.cpp @@ -39,7 +39,9 @@ ****************************************************************************/ #include -#include +#include +#include +#include #ifndef QT_NO_OPENGL #include #endif @@ -51,12 +53,21 @@ int main(int argc, char **argv) Q_INIT_RESOURCE(svgviewer); QApplication app(argc, argv); + QCoreApplication::setApplicationName("SVG Viewer"); + QGuiApplication::setApplicationDisplayName(QCoreApplication::applicationName()); + QCoreApplication::setOrganizationName("QtProject"); + QCoreApplication::setApplicationVersion(QT_VERSION_STR); + + QCommandLineParser parser; + parser.setApplicationDescription("Qt SVG Viewer"); + parser.addHelpOption(); + parser.addVersionOption(); + parser.addPositionalArgument("file", "The file to open."); + parser.process(app); MainWindow window; - if (argc == 2) - window.openFile(argv[1]); - else - window.openFile(":/files/bubbles.svg"); + if (!window.loadFile(parser.positionalArguments().value(0, QLatin1String(":/files/bubbles.svg")))) + return -1; window.show(); return app.exec(); } diff --git a/examples/svg/svgviewer/mainwindow.cpp b/examples/svg/svgviewer/mainwindow.cpp index d78c5fb..4e94642 100644 --- a/examples/svg/svgviewer/mainwindow.cpp +++ b/examples/svg/svgviewer/mainwindow.cpp @@ -48,47 +48,47 @@ MainWindow::MainWindow() : QMainWindow() , m_view(new SvgView) { - QMenu *fileMenu = new QMenu(tr("&File"), this); - QAction *openAction = fileMenu->addAction(tr("&Open...")); - openAction->setShortcut(QKeySequence(tr("Ctrl+O"))); - QAction *quitAction = fileMenu->addAction(tr("E&xit")); + QMenu *fileMenu = menuBar()->addMenu(tr("&File")); + QAction *openAction = fileMenu->addAction(tr("&Open..."), this, &MainWindow::openFile); + openAction->setShortcut(QKeySequence::Open); + QAction *quitAction = fileMenu->addAction(tr("E&xit"), qApp, QCoreApplication::quit); quitAction->setShortcuts(QKeySequence::Quit); - menuBar()->addMenu(fileMenu); - - QMenu *viewMenu = new QMenu(tr("&View"), this); + QMenu *viewMenu = menuBar()->addMenu(tr("&View")); m_backgroundAction = viewMenu->addAction(tr("&Background")); m_backgroundAction->setEnabled(false); m_backgroundAction->setCheckable(true); m_backgroundAction->setChecked(false); - connect(m_backgroundAction, SIGNAL(toggled(bool)), m_view, SLOT(setViewBackground(bool))); + connect(m_backgroundAction, &QAction::toggled, m_view, &SvgView::setViewBackground); m_outlineAction = viewMenu->addAction(tr("&Outline")); m_outlineAction->setEnabled(false); m_outlineAction->setCheckable(true); m_outlineAction->setChecked(true); - connect(m_outlineAction, SIGNAL(toggled(bool)), m_view, SLOT(setViewOutline(bool))); - - menuBar()->addMenu(viewMenu); + connect(m_outlineAction, &QAction::toggled, m_view, &SvgView::setViewOutline); - QMenu *rendererMenu = new QMenu(tr("&Renderer"), this); + QMenu *rendererMenu = menuBar()->addMenu(tr("&Renderer")); m_nativeAction = rendererMenu->addAction(tr("&Native")); m_nativeAction->setCheckable(true); m_nativeAction->setChecked(true); + m_nativeAction->setData(int(SvgView::Native)); #ifndef QT_NO_OPENGL m_glAction = rendererMenu->addAction(tr("&OpenGL")); m_glAction->setCheckable(true); + m_glAction->setData(int(SvgView::OpenGL)); #endif m_imageAction = rendererMenu->addAction(tr("&Image")); m_imageAction->setCheckable(true); + m_imageAction->setData(int(SvgView::Image)); -#ifndef QT_NO_OPENGL rendererMenu->addSeparator(); m_highQualityAntialiasingAction = rendererMenu->addAction(tr("&High Quality Antialiasing")); m_highQualityAntialiasingAction->setEnabled(false); m_highQualityAntialiasingAction->setCheckable(true); m_highQualityAntialiasingAction->setChecked(false); - connect(m_highQualityAntialiasingAction, SIGNAL(toggled(bool)), m_view, SLOT(setHighQualityAntialiasing(bool))); + connect(m_highQualityAntialiasingAction, &QAction::toggled, m_view, &SvgView::setHighQualityAntialiasing); +#ifdef QT_NO_OPENGL + m_highQualityAntialiasingAction->setVisible(false); #endif QActionGroup *rendererGroup = new QActionGroup(this); @@ -100,64 +100,57 @@ MainWindow::MainWindow() menuBar()->addMenu(rendererMenu); - connect(openAction, SIGNAL(triggered()), this, SLOT(openFile())); - connect(quitAction, SIGNAL(triggered()), qApp, SLOT(quit())); - connect(rendererGroup, SIGNAL(triggered(QAction*)), - this, SLOT(setRenderer(QAction*))); + connect(rendererGroup, &QActionGroup::triggered, + [this] (QAction *a) { setRenderer(a->data().toInt()); }); + + QMenu *help = menuBar()->addMenu(tr("&Help")); + help->addAction(tr("About Qt"), qApp, &QApplication::aboutQt); setCentralWidget(m_view); - setWindowTitle(tr("SVG Viewer")); } -void MainWindow::openFile(const QString &path) +void MainWindow::openFile() { - QString fileName; - if (path.isNull()) - fileName = QFileDialog::getOpenFileName(this, tr("Open SVG File"), - m_currentPath, "SVG files (*.svg *.svgz *.svg.gz)"); - else - fileName = path; - - if (!fileName.isEmpty()) { - QFile file(fileName); - if (!file.exists()) { - QMessageBox::critical(this, tr("Open SVG File"), - QString("Could not open file '%1'.").arg(fileName)); - - m_outlineAction->setEnabled(false); - m_backgroundAction->setEnabled(false); - return; - } - - m_view->openFile(file); - - if (!fileName.startsWith(":/")) { - m_currentPath = fileName; - setWindowTitle(tr("%1 - SVGViewer").arg(m_currentPath)); - } - - m_outlineAction->setEnabled(true); - m_backgroundAction->setEnabled(true); - - resize(m_view->sizeHint() + QSize(80, 80 + menuBar()->height())); - } + QFileDialog fileDialog(this); + fileDialog.setAcceptMode(QFileDialog::AcceptOpen); + fileDialog.setMimeTypeFilters(QStringList() << "image/svg+xml" << "image/svg+xml-compressed"); + fileDialog.setWindowTitle(tr("Open SVG File")); + if (m_currentPath.isEmpty()) + fileDialog.setDirectory(QStandardPaths::standardLocations(QStandardPaths::PicturesLocation).value(0, QDir::currentPath())); + + while (fileDialog.exec() == QDialog::Accepted && !loadFile(fileDialog.selectedFiles().constFirst())) + ; } -void MainWindow::setRenderer(QAction *action) +bool MainWindow::loadFile(const QString &fileName) { -#ifndef QT_NO_OPENGL - m_highQualityAntialiasingAction->setEnabled(false); -#endif - - if (action == m_nativeAction) - m_view->setRenderer(SvgView::Native); -#ifndef QT_NO_OPENGL - else if (action == m_glAction) { - m_highQualityAntialiasingAction->setEnabled(true); - m_view->setRenderer(SvgView::OpenGL); + if (!QFileInfo::exists(fileName) || !m_view->openFile(fileName)) { + QMessageBox::critical(this, tr("Open SVG File"), + QString("Could not open file '%1'.").arg(QDir::toNativeSeparators(fileName))); + return false; } -#endif - else if (action == m_imageAction) { - m_view->setRenderer(SvgView::Image); + + if (!fileName.startsWith(":/")) { + m_currentPath = fileName; + setWindowFilePath(fileName); + const QSize size = m_view->svgSize(); + const QString message = + tr("Opened %1, %2x%3").arg(QFileInfo(fileName).fileName()).arg(size.width()).arg(size.width()); + statusBar()->showMessage(message); } + + m_outlineAction->setEnabled(true); + m_backgroundAction->setEnabled(true); + + const QSize availableSize = QApplication::desktop()->availableGeometry(this).size(); + resize(m_view->sizeHint().expandedTo(availableSize / 4) + QSize(80, 80 + menuBar()->height())); + + return true; +} + +void MainWindow::setRenderer(int renderMode) +{ + + m_highQualityAntialiasingAction->setEnabled(renderMode == SvgView::OpenGL); + m_view->setRenderer(static_cast(renderMode)); } diff --git a/examples/svg/svgviewer/mainwindow.h b/examples/svg/svgviewer/mainwindow.h index 1c43da6..215f4a6 100644 --- a/examples/svg/svgviewer/mainwindow.h +++ b/examples/svg/svgviewer/mainwindow.h @@ -60,9 +60,11 @@ class MainWindow : public QMainWindow public: MainWindow(); + bool loadFile(const QString &path); + public slots: - void openFile(const QString &path = QString()); - void setRenderer(QAction *action); + void openFile(); + void setRenderer(int renderMode); private: QAction *m_nativeAction; diff --git a/examples/svg/svgviewer/svgview.cpp b/examples/svg/svgviewer/svgview.cpp index 5283bf1..dd9de1a 100644 --- a/examples/svg/svgviewer/svgview.cpp +++ b/examples/svg/svgviewer/svgview.cpp @@ -39,7 +39,8 @@ ****************************************************************************/ #include "svgview.h" -#include +#include + #include #include #include @@ -54,9 +55,9 @@ SvgView::SvgView(QWidget *parent) : QGraphicsView(parent) , m_renderer(Native) - , m_svgItem(0) - , m_backgroundItem(0) - , m_outlineItem(0) + , m_svgItem(nullptr) + , m_backgroundItem(nullptr) + , m_outlineItem(nullptr) { setScene(new QGraphicsScene(this)); setTransformationAnchor(AnchorUnderMouse); @@ -83,20 +84,26 @@ void SvgView::drawBackground(QPainter *p, const QRectF &) p->restore(); } -void SvgView::openFile(const QFile &file) +QSize SvgView::svgSize() const { - if (!file.exists()) - return; + return m_svgItem ? m_svgItem->boundingRect().size().toSize() : QSize(); +} +bool SvgView::openFile(const QString &fileName) +{ QGraphicsScene *s = scene(); - bool drawBackground = (m_backgroundItem ? m_backgroundItem->isVisible() : false); - bool drawOutline = (m_outlineItem ? m_outlineItem->isVisible() : true); + const bool drawBackground = (m_backgroundItem ? m_backgroundItem->isVisible() : false); + const bool drawOutline = (m_outlineItem ? m_outlineItem->isVisible() : true); + + QScopedPointer svgItem(new QGraphicsSvgItem(fileName)); + if (!svgItem->renderer()->isValid()) + return false; s->clear(); resetTransform(); - m_svgItem = new QGraphicsSvgItem(file.fileName()); + m_svgItem = svgItem.take(); m_svgItem->setFlags(QGraphicsItem::ItemClipsToShape); m_svgItem->setCacheMode(QGraphicsItem::NoCache); m_svgItem->setZValue(0); @@ -120,6 +127,7 @@ void SvgView::openFile(const QFile &file) s->addItem(m_outlineItem); s->setSceneRect(m_outlineItem->boundingRect().adjusted(-10, -10, 10, 10)); + return true; } void SvgView::setRenderer(RendererType type) diff --git a/examples/svg/svgviewer/svgview.h b/examples/svg/svgviewer/svgview.h index b6d1b01..41c0ca5 100644 --- a/examples/svg/svgviewer/svgview.h +++ b/examples/svg/svgviewer/svgview.h @@ -46,7 +46,6 @@ QT_BEGIN_NAMESPACE class QWheelEvent; class QPaintEvent; -class QFile; QT_END_NAMESPACE class SvgView : public QGraphicsView @@ -56,11 +55,13 @@ class SvgView : public QGraphicsView public: enum RendererType { Native, OpenGL, Image }; - SvgView(QWidget *parent = 0); + explicit SvgView(QWidget *parent = nullptr); - void openFile(const QFile &file); + bool openFile(const QString &fileName); void setRenderer(RendererType type = Native); - void drawBackground(QPainter *p, const QRectF &rect); + void drawBackground(QPainter *p, const QRectF &rect) override; + + QSize svgSize() const; public slots: void setHighQualityAntialiasing(bool highQualityAntialiasing); @@ -68,8 +69,8 @@ public slots: void setViewOutline(bool enable); protected: - void wheelEvent(QWheelEvent *event); - void paintEvent(QPaintEvent *event); + void wheelEvent(QWheelEvent *event) override; + void paintEvent(QPaintEvent *event) override; private: RendererType m_renderer; -- cgit v1.2.1