Set application metadata
[Skavegra.git] / svgviewer.cpp
blob1766ea0ab02d718825863fa90f67611d2f7d4a14
1 #include "svgviewer.h"
3 SVGViewer::SVGViewer(QWidget *parent) : QGraphicsView(parent) {
4 /* Init scene */
5 setScene(new QGraphicsScene(this));
6 setTransformationAnchor(QGraphicsView::AnchorUnderMouse);
7 setViewportUpdateMode(QGraphicsView::BoundingRectViewportUpdate);
8 setOptimizationFlag(QGraphicsView::DontSavePainterState, true);
11 void SVGViewer::paintEvent(QPaintEvent *event) {
12 QGraphicsView::paintEvent(event);
15 QString SVGViewer::SVGRemoveWhitespace(QString text) {
16 /* Remove whitespace according to SVG spec.
17 (xml:space="default")
20 /* Remove newlines */
21 text = text.remove('\n');
22 /* Replace tabs by spaces */
23 text.replace("\t", " ");
24 text.replace("\v", " ");
25 /* Remove leading and traling spaces */
26 int i;
27 for(i=0; i<text.length(); i++) {
28 if(!(text[i] == ' ')) {
29 break;
32 text.remove(0, i);
33 for(i=text.length()-1; i>=0; i--) {
34 if(!(text[i] == ' ')) {
35 break;
38 text.truncate(i+1);
39 /* Squash consecutive spaces into a single space */
40 int len = text.length();
41 int newlen;
42 while(len!=newlen) {
43 len = text.length();
44 text.replace(" ", " ");
45 newlen = text.length();
48 return text;
50 QString SVGViewer::SVGPreserveWhitespace(QString text) {
51 /* Preserve whitespace according to SVG spec.
52 (xml:space="preserve") */
54 /* Replace newlines and tabs by spaces */
55 text.replace("\n", " ");
56 text.replace("\t", " ");
57 text.replace("\v", " ");
59 return text;
62 QString SVGViewer::SVGReadText(QXmlStreamReader* reader, bool keepWhitespace) {
63 if(keepWhitespace) {
64 return SVGPreserveWhitespace(reader->text().toString());
65 } else {
66 return SVGRemoveWhitespace(reader->text().toString());
70 bool SVGViewer::openFile(QString fileName) {
71 /* Read SVG's XML to gather some metadata and settings. */
72 /* FIXME: Only works for non-compressed SVGs */
73 QFile xmlFile(fileName);
74 if (!xmlFile.open(QFile::ReadOnly)) {
75 QMessageBox::critical(this, tr("Error"), tr("The file could not be opened."));
76 return false;
78 QByteArray bytes = xmlFile.readAll();
79 xmlFile.close();
80 QXmlStreamReader* xmlReader = new QXmlStreamReader();
81 xmlReader->addData(bytes);
83 /* Default values for various settings according to SVG spec. */
84 zoomAndPan = true;
85 title = QString();
86 desc = QString();
88 /* Waiter variables remember element names */
89 bool waiterTitle = false;
90 bool waiterDesc = false;
91 bool keepWhitespace = false;
93 while(!xmlReader->atEnd()) {
94 if(xmlReader->readNext()) {
95 if(xmlReader->tokenType() == QXmlStreamReader::StartElement) {
96 if(xmlReader->namespaceUri() == "http://www.w3.org/2000/svg") {
97 if(xmlReader->name() == "svg") {
98 QString s(xmlReader->attributes().value("zoomAndPan").toString());
99 /* Check if zooming and pan in XML is disabled */
100 if(s == "disable") {
101 zoomAndPan = false;
103 } else if(xmlReader->name() == "title") {
104 waiterTitle = true;
105 } else if(xmlReader->name() == "desc") {
106 waiterDesc = true;
108 if(xmlReader->attributes().value("xml:space").toString() == "preserve") {
109 keepWhitespace = true;
110 } else {
111 keepWhitespace = false;
114 } else if(xmlReader->tokenType() == QXmlStreamReader::Characters) {
115 if(waiterTitle && title.isNull()) {
116 title = SVGReadText(xmlReader, keepWhitespace);
117 waiterTitle = false;
118 } else if(waiterDesc && desc.isNull()) {
119 desc = SVGReadText(xmlReader, keepWhitespace);
120 waiterDesc = false;
126 /* Create SVG item and load the file */
127 svgItem = new QGraphicsSvgItem(fileName);
128 svgRenderer = svgItem->renderer();
130 /* Reject invalid SVG documents */
131 if (!svgRenderer->isValid()) {
132 /* TODO: Also show details in error message */
133 QMessageBox::critical(this, tr("Invalid SVG document"),
134 tr("The selected file is not a valid SVG document and could not be opened."));
135 return false;
138 /* Set up scene */
139 if(zoomAndPan) {
140 setDragMode(ScrollHandDrag);
141 } else {
142 setDragMode(NoDrag);
145 scene()->clear();
146 resetTransform();
148 svgItem->setFlags(QGraphicsItem::ItemClipsToShape);
149 svgItem->setCacheMode(QGraphicsItem::NoCache);
151 /* Show image */
152 scene()->addItem(svgItem);
153 return true;
156 void SVGViewer::closeFile() {
157 delete svgItem;
158 svgItem = NULL;
159 /* Reset view parameters */
160 scene()->clear();
161 resetTransform();
162 setDragMode(NoDrag);
165 void SVGViewer::zoomIn() {
166 if(zoomAndPan && svgItem != NULL) {
167 zoomChange(1.25);
170 void SVGViewer::zoomOut() {
171 if(zoomAndPan && svgItem != NULL) {
172 zoomChange(0.8);
175 void SVGViewer::zoomReset() {
176 if(zoomAndPan && svgItem != NULL) {
177 resetTransform();
181 void SVGViewer::zoomSet(qreal factor) {
182 if(zoomAndPan && svgItem != NULL) {
183 zoomReset();
184 zoomChange(factor);
188 void SVGViewer::zoomChange(qreal factor) {
189 if(zoomAndPan && svgItem != NULL) {
190 scale(factor, factor);
194 #ifndef QT_NO_WHEELEVENT
195 void SVGViewer::wheelEvent(QWheelEvent *event) {
196 /* Change zoom on using the mouse wheel */
197 qreal factor = qPow(1.2, event->delta() / 240.0);
198 zoomChange(factor);
199 event->accept();
201 #endif
203 bool SVGViewer::getZoomAndPan() {
204 return zoomAndPan;
207 bool SVGViewer::getAnim() {
208 if(svgItem != NULL) {
209 return svgRenderer->animated();
210 } else {
211 return false;
215 QString SVGViewer::getTitle() {
216 return title;
219 QString SVGViewer::getDesc() {
220 return desc;
223 QSize SVGViewer::getImageSize() {
224 if(svgItem != NULL) {
225 return svgRenderer->defaultSize();
226 } else {
227 return QSize();