svg viewer
/**************************************************************************** ** ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). ** All rights reserved. ** Contact: Nokia Corporation (qt-info@nokia.com) ** ** This file is part of the examples of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial Usage ** Licensees holding valid Qt Commercial licenses may use this file in ** accordance with the Qt Commercial License Agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and Nokia. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 2.1 requirements ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, Nokia gives you certain additional ** rights. These rights are described in the Nokia Qt LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3.0 as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL included in the ** packaging of this file. Please review the following information to ** ensure the GNU General Public License version 3.0 requirements will be ** met: http://www.gnu.org/copyleft/gpl.html. ** ** If you have questions regarding the use of this file, please contact ** Nokia at qt-info@nokia.com. ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef SVGVIEW_H #define SVGVIEW_H #include <QGraphicsView> QT_BEGIN_NAMESPACE class QWheelEvent; class QPaintEvent; class QFile; QT_END_NAMESPACE class SvgView : public QGraphicsView { Q_OBJECT public: enum RendererType { Native, OpenGL, Image }; SvgView(QWidget *parent = 0); void openFile(const QFile &file); void setRenderer(RendererType type = Native); void drawBackground(QPainter *p, const QRectF &rect); public slots: void setHighQualityAntialiasing(bool highQualityAntialiasing); void setViewBackground(bool enable); void setViewOutline(bool enable); protected: void wheelEvent(QWheelEvent *event); void paintEvent(QPaintEvent *event); private: RendererType m_renderer; QGraphicsItem *m_svgItem; QGraphicsRectItem *m_backgroundItem; QGraphicsRectItem *m_outlineItem; QImage m_image; }; #end #include "svgview.h" #include <QFile> #include <QWheelEvent> #include <QMouseEvent> #include <QGraphicsRectItem> #include <QGraphicsSvgItem> #include <QPaintEvent> #include <qmath.h> #ifndef QT_NO_OPENGL #include <QGLWidget> #endif SvgView::SvgView(QWidget *parent) : QGraphicsView(parent) , m_renderer(Native) , m_svgItem(0) , m_backgroundItem(0) , m_outlineItem(0) { setScene(new QGraphicsScene(this)); setTransformationAnchor(AnchorUnderMouse); setDragMode(ScrollHandDrag); // Prepare background check-board pattern QPixmap tilePixmap(64, 64); tilePixmap.fill(Qt::white); QPainter tilePainter(&tilePixmap); QColor color(220, 220, 220); tilePainter.fillRect(0, 0, 32, 32, color); tilePainter.fillRect(32, 32, 32, 32, color); tilePainter.end(); setBackgroundBrush(tilePixmap); } void SvgView::drawBackground(QPainter *p, const QRectF &) { p->save(); p->resetTransform(); p->drawTiledPixmap(viewport()->rect(), backgroundBrush().texture()); p->restore(); } void SvgView::openFile(const QFile &file) { if (!file.exists()) return; QGraphicsScene *s = scene(); bool drawBackground = (m_backgroundItem ? m_backgroundItem->isVisible() : false); bool drawOutline = (m_outlineItem ? m_outlineItem->isVisible() : true); s->clear(); resetTransform(); m_svgItem = new QGraphicsSvgItem(file.fileName()); m_svgItem->setFlags(QGraphicsItem::ItemClipsToShape); m_svgItem->setCacheMode(QGraphicsItem::NoCache); m_svgItem->setZValue(0); m_backgroundItem = new QGraphicsRectItem(m_svgItem->boundingRect()); m_backgroundItem->setBrush(Qt::white); m_backgroundItem->setPen(Qt::NoPen); m_backgroundItem->setVisible(drawBackground); m_backgroundItem->setZValue(-1); m_outlineItem = new QGraphicsRectItem(m_svgItem->boundingRect()); QPen outline(Qt::black, 2, Qt::DashLine); outline.setCosmetic(true); m_outlineItem->setPen(outline); m_outlineItem->setBrush(Qt::NoBrush); m_outlineItem->setVisible(drawOutline); m_outlineItem->setZValue(1); s->addItem(m_backgroundItem); s->addItem(m_svgItem); s->addItem(m_outlineItem); s->setSceneRect(m_outlineItem->boundingRect().adjusted(-10, -10, 10, 10)); } void SvgView::setRenderer(RendererType type) { m_renderer = type; if (m_renderer == OpenGL) { #ifndef QT_NO_OPENGL setViewport(new QGLWidget(QGLFormat(QGL::SampleBuffers))); #endif } else { setViewport(new QWidget); } } void SvgView::setHighQualityAntialiasing(bool highQualityAntialiasing) { #ifndef QT_NO_OPENGL setRenderHint(QPainter::HighQualityAntialiasing, highQualityAntialiasing); #else Q_UNUSED(highQualityAntialiasing); #endif } void SvgView::setViewBackground(bool enable) { if (!m_backgroundItem) return; m_backgroundItem->setVisible(enable); } void SvgView::setViewOutline(bool enable) { if (!m_outlineItem) return; m_outlineItem->setVisible(enable); } void SvgView::paintEvent(QPaintEvent *event) { if (m_renderer == Image) { if (m_image.size() != viewport()->size()) { m_image = QImage(viewport()->size(), QImage::Format_ARGB32_Premultiplied); } QPainter imagePainter(&m_image); QGraphicsView::render(&imagePainter); imagePainter.end(); QPainter p(viewport()); p.drawImage(0, 0, m_image); } else { QGraphicsView::paintEvent(event); } } void SvgView::wheelEvent(QWheelEvent *event) { qreal factor = qPow(1.2, event->delta() / 240.0); scale(factor, factor); event->accept(); } #ifndef MAINWINDOW_H #define MAINWINDOW_H #include <QMainWindow> #include <QString> class SvgView; QT_BEGIN_NAMESPACE class QAction; class QGraphicsView; class QGraphicsScene; class QGraphicsRectItem; QT_END_NAMESPACE class MainWindow : public QMainWindow { Q_OBJECT public: MainWindow(); public slots: void openFile(const QString &path = QString()); void setRenderer(QAction *action); private: QAction *m_nativeAction; QAction *m_glAction; QAction *m_imageAction; QAction *m_highQualityAntialiasingAction; QAction *m_backgroundAction; QAction *m_outlineAction; SvgView *m_view; QString m_currentPath; }; #endif #include "mainwindow.h" #include <QtGui> #include "svgview.h" 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")); quitAction->setShortcut(QKeySequence(tr("Ctrl+Q"))); menuBar()->addMenu(fileMenu); QMenu *viewMenu = new QMenu(tr("&View"), this); 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))); 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); QMenu *rendererMenu = new QMenu(tr("&Renderer"), this); m_nativeAction = rendererMenu->addAction(tr("&Native")); m_nativeAction->setCheckable(true); m_nativeAction->setChecked(true); #ifndef QT_NO_OPENGL m_glAction = rendererMenu->addAction(tr("&OpenGL")); m_glAction->setCheckable(true); #endif m_imageAction = rendererMenu->addAction(tr("&Image")); m_imageAction->setCheckable(true); #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))); #endif QActionGroup *rendererGroup = new QActionGroup(this); rendererGroup->addAction(m_nativeAction); #ifndef QT_NO_OPENGL rendererGroup->addAction(m_glAction); #endif rendererGroup->addAction(m_imageAction); 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 *))); setCentralWidget(m_view); setWindowTitle(tr("SVG Viewer")); } void MainWindow::openFile(const QString &path) { 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())); } } void MainWindow::setRenderer(QAction *action) { #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); } #endif else if (action == m_imageAction) { m_view->setRenderer(SvgView::Image); } } #include <QApplication> #include <QString> #ifndef QT_NO_OPENGL #include <QGLFormat> #endif #include "mainwindow.h" int main(int argc, char **argv) { Q_INIT_RESOURCE(svgviewer); QApplication app(argc, argv); MainWindow window; if (argc == 2) window.openFile(argv[1]); else window.openFile(":/files/bubbles.svg"); window.show(); return app.exec(); }