From a9c86fd580bc342bf08f55a8888457aecd84751d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20T=C5=AFma?= Date: Sun, 27 Sep 2020 00:34:38 +0200 Subject: [PATCH] Added PNG export --- gpxsee.pro | 10 +- src/GUI/fileselectwidget.cpp | 30 ++ src/GUI/fileselectwidget.h | 3 +- src/GUI/gui.cpp | 280 +++++++++++++----- src/GUI/gui.h | 19 +- src/GUI/mapview.cpp | 16 +- src/GUI/mapview.h | 11 +- src/GUI/margins.h | 28 ++ src/GUI/optionsdialog.cpp | 234 +++++++-------- src/GUI/optionsdialog.h | 7 +- .../{exportdialog.cpp => pdfexportdialog.cpp} | 87 ++---- src/GUI/{exportdialog.h => pdfexportdialog.h} | 20 +- src/GUI/pngexportdialog.cpp | 120 ++++++++ src/GUI/pngexportdialog.h | 43 +++ src/GUI/settings.h | 41 ++- 15 files changed, 651 insertions(+), 298 deletions(-) rename src/GUI/{exportdialog.cpp => pdfexportdialog.cpp} (69%) rename src/GUI/{exportdialog.h => pdfexportdialog.h} (71%) create mode 100644 src/GUI/pngexportdialog.cpp create mode 100644 src/GUI/pngexportdialog.h diff --git a/gpxsee.pro b/gpxsee.pro index 85ecc01c..ebed7457 100644 --- a/gpxsee.pro +++ b/gpxsee.pro @@ -53,7 +53,6 @@ HEADERS += src/common/config.h \ src/GUI/palette.h \ src/GUI/heartrategraph.h \ src/GUI/trackinfo.h \ - src/GUI/exportdialog.h \ src/GUI/fileselectwidget.h \ src/GUI/margins.h \ src/GUI/temperaturegraph.h \ @@ -198,7 +197,9 @@ HEADERS += src/common/config.h \ src/data/cupparser.h \ src/data/gpiparser.h \ src/data/address.h \ - src/data/smlparser.h + src/data/smlparser.h \ + src/GUI/pdfexportdialog.h \ + src/GUI/pngexportdialog.h SOURCES += src/main.cpp \ src/GUI/popup.cpp \ src/common/coordinates.cpp \ @@ -224,7 +225,6 @@ SOURCES += src/main.cpp \ src/GUI/palette.cpp \ src/GUI/heartrategraph.cpp \ src/GUI/trackinfo.cpp \ - src/GUI/exportdialog.cpp \ src/GUI/fileselectwidget.cpp \ src/GUI/temperaturegraph.cpp \ src/GUI/trackitem.cpp \ @@ -344,7 +344,9 @@ SOURCES += src/main.cpp \ src/data/cupparser.cpp \ src/GUI/graphicsscene.cpp \ src/data/gpiparser.cpp \ - src/data/smlparser.cpp + src/data/smlparser.cpp \ + src/GUI/pdfexportdialog.cpp \ + src/GUI/pngexportdialog.cpp greaterThan(QT_MAJOR_VERSION, 4) { HEADERS += src/data/geojsonparser.h diff --git a/src/GUI/fileselectwidget.cpp b/src/GUI/fileselectwidget.cpp index b9230f6b..3d6acd6f 100644 --- a/src/GUI/fileselectwidget.cpp +++ b/src/GUI/fileselectwidget.cpp @@ -41,3 +41,33 @@ void FileSelectWidget::browse() if (!fileName.isEmpty()) _edit->setText(fileName); } + +bool FileSelectWidget::checkFile(QString &error) const +{ + if (_edit->text().isEmpty()) { + error = tr("No output file selected."); + return false; + } + + QFile file(_edit->text()); + QFileInfo fi(file); + bool exists = fi.exists(); + bool opened = false; + + if (exists && fi.isDir()) { + error = tr("%1 is a directory.").arg(file.fileName()); + return false; + } else if ((exists && !fi.isWritable()) + || !(opened = file.open(QFile::Append))) { + error = tr("%1 is not writable.").arg(file.fileName()); + return false; + } + + if (opened) { + file.close(); + if (!exists) + file.remove(); + } + + return true; +} diff --git a/src/GUI/fileselectwidget.h b/src/GUI/fileselectwidget.h index ce68b0b2..619b9c2b 100644 --- a/src/GUI/fileselectwidget.h +++ b/src/GUI/fileselectwidget.h @@ -14,9 +14,10 @@ class FileSelectWidget : public QWidget public: FileSelectWidget(QWidget *parent = 0); - QString file() {return _edit->text();} + QString file() const {return _edit->text();} void setFile(const QString &file) {_edit->setText(file);} void setFilter(const QString &filter) {_filter = filter;} + bool checkFile(QString &error) const; private slots: void browse(); diff --git a/src/GUI/gui.cpp b/src/GUI/gui.cpp index 29b5e47e..8274c682 100644 --- a/src/GUI/gui.cpp +++ b/src/GUI/gui.cpp @@ -230,13 +230,20 @@ void GUI::createActions() _printFileAction->setActionGroup(_fileActionGroup); connect(_printFileAction, SIGNAL(triggered()), this, SLOT(printFile())); addAction(_printFileAction); - _exportFileAction = new QAction(QIcon(EXPORT_FILE_ICON), + _exportPDFFileAction = new QAction(QIcon(EXPORT_FILE_ICON), tr("Export to PDF..."), this); - _exportFileAction->setMenuRole(QAction::NoRole); - _exportFileAction->setShortcut(EXPORT_SHORTCUT); - _exportFileAction->setActionGroup(_fileActionGroup); - connect(_exportFileAction, SIGNAL(triggered()), this, SLOT(exportFile())); - addAction(_exportFileAction); + _exportPDFFileAction->setMenuRole(QAction::NoRole); + _exportPDFFileAction->setShortcut(EXPORT_SHORTCUT); + _exportPDFFileAction->setActionGroup(_fileActionGroup); + connect(_exportPDFFileAction, SIGNAL(triggered()), this, SLOT(exportPDFFile())); + addAction(_exportPDFFileAction); + _exportPNGFileAction = new QAction(QIcon(EXPORT_FILE_ICON), + tr("Export to PNG..."), this); + _exportPNGFileAction->setMenuRole(QAction::NoRole); + _exportPNGFileAction->setShortcut(EXPORT_SHORTCUT); + _exportPNGFileAction->setActionGroup(_fileActionGroup); + connect(_exportPNGFileAction, SIGNAL(triggered()), this, SLOT(exportPNGFile())); + addAction(_exportPNGFileAction); _closeFileAction = new QAction(QIcon(CLOSE_FILE_ICON), tr("Close"), this); _closeFileAction->setMenuRole(QAction::NoRole); _closeFileAction->setShortcut(CLOSE_SHORTCUT); @@ -497,7 +504,8 @@ void GUI::createMenus() fileMenu->addAction(_openFileAction); fileMenu->addSeparator(); fileMenu->addAction(_printFileAction); - fileMenu->addAction(_exportFileAction); + fileMenu->addAction(_exportPDFFileAction); + fileMenu->addAction(_exportPNGFileAction); fileMenu->addSeparator(); fileMenu->addAction(_statisticsAction); fileMenu->addSeparator(); @@ -928,7 +936,7 @@ void GUI::openOptions() Options options(_options); bool reload = false; - OptionsDialog dialog(&options, this); + OptionsDialog dialog(options, _units, this); if (dialog.exec() != QDialog::Accepted) return; @@ -1019,9 +1027,9 @@ void GUI::printFile() plot(&printer); } -void GUI::exportFile() +void GUI::exportPDFFile() { - ExportDialog dialog(&_export, this); + PDFExportDialog dialog(_pdfExport, _units, this); if (dialog.exec() != QDialog::Accepted) return; @@ -1029,16 +1037,53 @@ void GUI::exportFile() printer.setOutputFormat(QPrinter::PdfFormat); printer.setCreator(QString(APP_NAME) + QString(" ") + QString(APP_VERSION)); - printer.setResolution(_export.resolution); - printer.setOrientation(_export.orientation); - printer.setOutputFileName(_export.fileName); - printer.setPaperSize(_export.paperSize); - printer.setPageMargins(_export.margins.left(), _export.margins.top(), - _export.margins.right(), _export.margins.bottom(), QPrinter::Millimeter); + printer.setResolution(_pdfExport.resolution); + printer.setOrientation(_pdfExport.orientation); + printer.setOutputFileName(_pdfExport.fileName); + printer.setPaperSize(_pdfExport.paperSize); + printer.setPageMargins(_pdfExport.margins.left(), _pdfExport.margins.top(), + _pdfExport.margins.right(), _pdfExport.margins.bottom(), + QPrinter::Millimeter); plot(&printer); } +void GUI::exportPNGFile() +{ + PNGExportDialog dialog(_pngExport, this); + if (dialog.exec() != QDialog::Accepted) + return; + + QImage img(_pngExport.size, QImage::Format_ARGB32_Premultiplied); + QPainter p(&img); + QRectF rect(0, 0, img.width(), img.height()); + QRectF contentRect(rect.adjusted(_pngExport.margins.left(), + _pngExport.margins.top(), -_pngExport.margins.right(), + -_pngExport.margins.bottom())); + + if (_pngExport.antialiasing) + p.setRenderHint(QPainter::Antialiasing); + p.fillRect(rect, Qt::white); + plotMainPage(&p, contentRect, 1.0, true); + img.save(_pngExport.fileName); + + if (!_tabs.isEmpty() && _options.separateGraphPage) { + QImage img2(_pngExport.size.width(), (int)graphPlotHeight(rect, 1), + QImage::Format_ARGB32_Premultiplied); + QPainter p2(&img2); + QRectF rect2(0, 0, img2.width(), img2.height()); + + if (_pngExport.antialiasing) + p2.setRenderHint(QPainter::Antialiasing); + p2.fillRect(rect2, Qt::white); + plotGraphsPage(&p2, contentRect, 1); + + QFileInfo fi(_pngExport.fileName); + img2.save(fi.absolutePath() + "/" + fi.baseName() + "-graphs." + + fi.suffix()); + } +} + void GUI::statistics() { QLocale l(QLocale::system()); @@ -1110,12 +1155,12 @@ void GUI::statistics() msgBox.exec(); } -void GUI::plot(QPrinter *printer) +void GUI::plotMainPage(QPainter *painter, const QRectF &rect, qreal ratio, + bool expand) { QLocale l(QLocale::system()); - QPainter p(printer); TrackInfo info; - qreal ih, gh, mh, ratio; + qreal ih, gh, mh; if (!_pathName.isNull() && _options.printName) @@ -1151,53 +1196,87 @@ void GUI::plot(QPrinter *printer) if (movingTime() > 0 && _options.printMovingTime) info.insert(tr("Moving time"), Format::timeSpan(movingTime())); - qreal fsr = 1085.0 / (qMax(printer->width(), printer->height()) - / (qreal)printer->resolution()); - ratio = p.paintEngine()->paintDevice()->logicalDpiX() / fsr; if (info.isEmpty()) { ih = 0; mh = 0; } else { ih = info.contentSize().height() * ratio; mh = ih / 2; - info.plot(&p, QRectF(0, 0, printer->width(), ih), ratio); + info.plot(painter, QRectF(rect.x(), rect.y(), rect.width(), ih), ratio); } if (_graphTabWidget->isVisible() && !_options.separateGraphPage) { - qreal r = (((qreal)(printer)->width()) / (qreal)(printer->height())); - gh = (printer->width() > printer->height()) - ? 0.15 * r * (printer->height() - ih - 2*mh) - : 0.15 * (printer->height() - ih - 2*mh); + qreal r = rect.width() / rect.height(); + gh = (rect.width() > rect.height()) + ? 0.15 * r * (rect.height() - ih - 2*mh) + : 0.15 * (rect.height() - ih - 2*mh); GraphTab *gt = static_cast(_graphTabWidget->currentWidget()); - gt->plot(&p, QRectF(0, printer->height() - gh, printer->width(), gh), - ratio); - } else + gt->plot(painter, QRectF(rect.x(), rect.y() + rect.height() - gh, + rect.width(), gh), ratio); + } else { gh = 0; - _mapView->plot(&p, QRectF(0, ih + mh, printer->width(), printer->height() - - (ih + 2*mh + gh)), ratio, _options.hiresPrint); + } - if (_graphTabWidget->isVisible() && _options.separateGraphPage) { - printer->newPage(); + MapView::PlotFlags flags = MapView::NoFlags; + if (_options.hiresPrint) + flags |= MapView::HiRes; + if (expand) + flags |= MapView::Expand; - int cnt = 0; - for (int i = 0; i < _tabs.size(); i++) - if (!_tabs.at(i)->isEmpty()) - cnt++; + _mapView->plot(painter, QRectF(rect.x(), rect.y() + ih + mh, rect.width(), + rect.height() - (ih + 2*mh + gh)), ratio, flags); +} - qreal sp = ratio * 20; - gh = qMin((printer->height() - ((cnt - 1) * sp))/(qreal)cnt, - 0.20 * printer->height()); +void GUI::plotGraphsPage(QPainter *painter, const QRectF &rect, qreal ratio) +{ + int cnt = 0; + for (int i = 0; i < _tabs.size(); i++) + if (!_tabs.at(i)->isEmpty()) + cnt++; - qreal y = 0; - for (int i = 0; i < _tabs.size(); i++) { - if (!_tabs.at(i)->isEmpty()) { - _tabs.at(i)->plot(&p, QRectF(0, y, printer->width(), gh), - ratio); - y += gh + sp; - } + qreal sp = ratio * 20; + qreal gh = qMin((rect.height() - ((cnt - 1) * sp))/(qreal)cnt, + 0.20 * rect.height()); + + qreal y = 0; + for (int i = 0; i < _tabs.size(); i++) { + if (!_tabs.at(i)->isEmpty()) { + _tabs.at(i)->plot(painter, QRectF(rect.x(), rect.y() + y, + rect.width(), gh), ratio); + y += gh + sp; } } } +qreal GUI::graphPlotHeight(const QRectF &rect, qreal ratio) +{ + int cnt = 0; + for (int i = 0; i < _tabs.size(); i++) + if (!_tabs.at(i)->isEmpty()) + cnt++; + + qreal sp = ratio * 20; + qreal gh = qMin((rect.height() - ((cnt - 1) * sp))/(qreal)cnt, + 0.20 * rect.height()); + + return cnt * gh + (cnt - 1) * sp; +} + +void GUI::plot(QPrinter *printer) +{ + QPainter p(printer); + qreal fsr = 1085.0 / (qMax(printer->width(), printer->height()) + / (qreal)printer->resolution()); + qreal ratio = p.paintEngine()->paintDevice()->logicalDpiX() / fsr; + QRectF rect(0, 0, printer->width(), printer->height()); + + plotMainPage(&p, rect, ratio); + + if (!_tabs.isEmpty() && _options.separateGraphPage) { + printer->newPage(); + plotGraphsPage(&p, rect, ratio); + } +} + void GUI::reloadFiles() { _trackCount = 0; @@ -1552,8 +1631,7 @@ void GUI::setTimeType(TimeType type) void GUI::setUnits(Units units) { - _export.units = units; - _options.units = units; + _units = units; _mapView->setUnits(units); for (int i = 0; i <_tabs.count(); i++) @@ -1796,23 +1874,42 @@ void GUI::writeSettings() _showTicksAction->isChecked()); settings.endGroup(); - settings.beginGroup(EXPORT_SETTINGS_GROUP); - if (_export.orientation != PAPER_ORIENTATION_DEFAULT) - settings.setValue(PAPER_ORIENTATION_SETTING, _export.orientation); - if (_export.resolution != RESOLUTION_DEFAULT) - settings.setValue(RESOLUTION_SETTING, _export.resolution); - if (_export.paperSize != PAPER_SIZE_DEFAULT) - settings.setValue(PAPER_SIZE_SETTING, _export.paperSize); - if (_export.margins.left() != MARGIN_LEFT_DEFAULT) - settings.setValue(MARGIN_LEFT_SETTING, _export.margins.left()); - if (_export.margins.top() != MARGIN_TOP_DEFAULT) - settings.setValue(MARGIN_TOP_SETTING, _export.margins.top()); - if (_export.margins.right() != MARGIN_RIGHT_DEFAULT) - settings.setValue(MARGIN_RIGHT_SETTING, _export.margins.right()); - if (_export.margins.bottom() != MARGIN_BOTTOM_DEFAULT) - settings.setValue(MARGIN_BOTTOM_SETTING, _export.margins.bottom()); - if (_export.fileName != EXPORT_FILENAME_DEFAULT) - settings.setValue(EXPORT_FILENAME_SETTING, _export.fileName); + settings.beginGroup(PDF_EXPORT_SETTINGS_GROUP); + if (_pdfExport.orientation != PAPER_ORIENTATION_DEFAULT) + settings.setValue(PAPER_ORIENTATION_SETTING, _pdfExport.orientation); + if (_pdfExport.resolution != RESOLUTION_DEFAULT) + settings.setValue(RESOLUTION_SETTING, _pdfExport.resolution); + if (_pdfExport.paperSize != PAPER_SIZE_DEFAULT) + settings.setValue(PAPER_SIZE_SETTING, _pdfExport.paperSize); + if (_pdfExport.margins.left() != PDF_MARGIN_LEFT_DEFAULT) + settings.setValue(PDF_MARGIN_LEFT_SETTING, _pdfExport.margins.left()); + if (_pdfExport.margins.top() != PDF_MARGIN_TOP_DEFAULT) + settings.setValue(PDF_MARGIN_TOP_SETTING, _pdfExport.margins.top()); + if (_pdfExport.margins.right() != PDF_MARGIN_RIGHT_DEFAULT) + settings.setValue(PDF_MARGIN_RIGHT_SETTING, _pdfExport.margins.right()); + if (_pdfExport.margins.bottom() != PDF_MARGIN_BOTTOM_DEFAULT) + settings.setValue(PDF_MARGIN_BOTTOM_SETTING, _pdfExport.margins.bottom()); + if (_pdfExport.fileName != PDF_FILENAME_DEFAULT) + settings.setValue(PDF_FILENAME_SETTING, _pdfExport.fileName); + settings.endGroup(); + + settings.beginGroup(PNG_EXPORT_SETTINGS_GROUP); + if (_pngExport.size.width() != PNG_WIDTH_DEFAULT) + settings.setValue(PNG_WIDTH_SETTING, _pngExport.size.width()); + if (_pngExport.size.height() != PNG_HEIGHT_DEFAULT) + settings.setValue(PNG_HEIGHT_SETTING, _pngExport.size.height()); + if (_pngExport.margins.left() != PNG_MARGIN_LEFT_DEFAULT) + settings.setValue(PNG_MARGIN_LEFT_SETTING, _pngExport.margins.left()); + if (_pngExport.margins.top() != PNG_MARGIN_TOP_DEFAULT) + settings.setValue(PNG_MARGIN_TOP_SETTING, _pngExport.margins.top()); + if (_pngExport.margins.right() != PNG_MARGIN_RIGHT_DEFAULT) + settings.setValue(PNG_MARGIN_RIGHT_SETTING, _pngExport.margins.right()); + if (_pngExport.margins.bottom() != PNG_MARGIN_BOTTOM_DEFAULT) + settings.setValue(PNG_MARGIN_BOTTOM_SETTING, _pngExport.margins.bottom()); + if (_pngExport.antialiasing != PNG_ANTIALIASING_DEFAULT) + settings.setValue(PNG_ANTIALIASING_SETTING, _pngExport.antialiasing); + if (_pngExport.fileName != PNG_FILENAME_DEFAULT) + settings.setValue(PNG_FILENAME_SETTING, _pngExport.fileName); settings.endGroup(); settings.beginGroup(OPTIONS_SETTINGS_GROUP); @@ -2078,23 +2175,42 @@ void GUI::readSettings() } settings.endGroup(); - settings.beginGroup(EXPORT_SETTINGS_GROUP); - _export.orientation = (QPrinter::Orientation) settings.value( + settings.beginGroup(PDF_EXPORT_SETTINGS_GROUP); + _pdfExport.orientation = (QPrinter::Orientation) settings.value( PAPER_ORIENTATION_SETTING, PAPER_ORIENTATION_DEFAULT).toInt(); - _export.resolution = settings.value(RESOLUTION_SETTING, RESOLUTION_DEFAULT) + _pdfExport.resolution = settings.value(RESOLUTION_SETTING, + RESOLUTION_DEFAULT).toInt(); + _pdfExport.paperSize = (QPrinter::PaperSize) settings.value( + PAPER_SIZE_SETTING, PAPER_SIZE_DEFAULT).toInt(); + qreal ml = settings.value(PDF_MARGIN_LEFT_SETTING, PDF_MARGIN_LEFT_DEFAULT) + .toReal(); + qreal mt = settings.value(PDF_MARGIN_TOP_SETTING, PDF_MARGIN_TOP_DEFAULT) + .toReal(); + qreal mr = settings.value(PDF_MARGIN_RIGHT_SETTING, + PDF_MARGIN_RIGHT_DEFAULT).toReal(); + qreal mb = settings.value(PDF_MARGIN_BOTTOM_SETTING, + PDF_MARGIN_BOTTOM_DEFAULT).toReal(); + _pdfExport.margins = MarginsF(ml, mt, mr, mb); + _pdfExport.fileName = settings.value(PDF_FILENAME_SETTING, + PDF_FILENAME_DEFAULT).toString(); + settings.endGroup(); + + settings.beginGroup(PNG_EXPORT_SETTINGS_GROUP); + _pngExport.size = QSize(settings.value(PNG_WIDTH_SETTING, PNG_WIDTH_DEFAULT) + .toInt(), settings.value(PNG_HEIGHT_SETTING, PNG_HEIGHT_DEFAULT).toInt()); + int mli = settings.value(PNG_MARGIN_LEFT_SETTING, PNG_MARGIN_LEFT_DEFAULT) .toInt(); - _export.paperSize = (QPrinter::PaperSize) settings.value(PAPER_SIZE_SETTING, - PAPER_SIZE_DEFAULT).toInt(); - qreal ml = settings.value(MARGIN_LEFT_SETTING, MARGIN_LEFT_DEFAULT) - .toReal(); - qreal mt = settings.value(MARGIN_TOP_SETTING, MARGIN_TOP_DEFAULT).toReal(); - qreal mr = settings.value(MARGIN_RIGHT_SETTING, MARGIN_RIGHT_DEFAULT) - .toReal(); - qreal mb = settings.value(MARGIN_BOTTOM_SETTING, MARGIN_BOTTOM_DEFAULT) - .toReal(); - _export.margins = MarginsF(ml, mt, mr, mb); - _export.fileName = settings.value(EXPORT_FILENAME_SETTING, - EXPORT_FILENAME_DEFAULT).toString(); + int mti = settings.value(PNG_MARGIN_TOP_SETTING, PNG_MARGIN_TOP_DEFAULT) + .toInt(); + int mri = settings.value(PNG_MARGIN_RIGHT_SETTING, PNG_MARGIN_RIGHT_DEFAULT) + .toInt(); + int mbi = settings.value(PNG_MARGIN_BOTTOM_SETTING, PNG_MARGIN_BOTTOM_DEFAULT) + .toInt(); + _pngExport.margins = Margins(mli, mti, mri, mbi); + _pngExport.antialiasing = settings.value(PNG_ANTIALIASING_SETTING, + PNG_ANTIALIASING_DEFAULT).toBool(); + _pngExport.fileName = settings.value(PNG_FILENAME_SETTING, + PNG_FILENAME_DEFAULT).toString(); settings.endGroup(); settings.beginGroup(OPTIONS_SETTINGS_GROUP); diff --git a/src/GUI/gui.h b/src/GUI/gui.h index 5faa0834..18775d87 100644 --- a/src/GUI/gui.h +++ b/src/GUI/gui.h @@ -10,7 +10,8 @@ #include "units.h" #include "timetype.h" #include "format.h" -#include "exportdialog.h" +#include "pdfexportdialog.h" +#include "pngexportdialog.h" #include "optionsdialog.h" class QMenu; @@ -45,7 +46,8 @@ private slots: void keys(); void paths(); void printFile(); - void exportFile(); + void exportPDFFile(); + void exportPNGFile(); void openFile(); void closeAll(); void reloadFiles(); @@ -97,6 +99,10 @@ private: void loadPOIs(); void closeFiles(); void plot(QPrinter *printer); + void plotMainPage(QPainter *painter, const QRectF &rect, qreal ratio, + bool expand = false); + void plotGraphsPage(QPainter *painter, const QRectF &rect, qreal ratio); + qreal graphPlotHeight(const QRectF &rect, qreal ratio); QAction *createPOIFileAction(const QString &fileName); MapAction *createMapAction(Map *map); @@ -113,7 +119,6 @@ private: bool openPOIFile(const QString &fileName); bool loadFile(const QString &fileName); bool loadMap(const QString &fileName); - void exportFile(const QString &fileName); void updateStatusBarInfo(); void updateWindowTitle(); void updateNavigationActions(); @@ -153,7 +158,8 @@ private: QAction *_aboutAction; QAction *_aboutQtAction; QAction *_printFileAction; - QAction *_exportFileAction; + QAction *_exportPDFFileAction; + QAction *_exportPNGFileAction; QAction *_openFileAction; QAction *_closeFileAction; QAction *_reloadFileAction; @@ -228,10 +234,13 @@ private: QList _windowStates; int _frameStyle; - Export _export; + PDFExport _pdfExport; + PNGExport _pngExport; Options _options; QString _dataDir, _mapDir, _poiDir; + + Units _units; }; #endif // GUI_H diff --git a/src/GUI/mapview.cpp b/src/GUI/mapview.cpp index 46d308c3..444aef77 100644 --- a/src/GUI/mapview.cpp +++ b/src/GUI/mapview.cpp @@ -531,7 +531,7 @@ void MapView::keyPressEvent(QKeyEvent *event) } void MapView::plot(QPainter *painter, const QRectF &target, qreal scale, - bool hires) + PlotFlags flags) { QRect orig, adj; qreal ratio, diff, q; @@ -559,10 +559,18 @@ void MapView::plot(QPainter *painter, const QRectF &target, qreal scale, diff = (orig.height() * ratio) - orig.width(); adj = orig.adjusted(-diff/2, 0, diff/2, 0); } - q = (target.width() / scale) / adj.width(); + + // Expand the view if plotting into a bitmap + if (flags & Expand) { + qreal xdiff = (target.width() - adj.width()) / 2.0; + qreal ydiff = (target.height() - adj.height()) / 2.0; + adj.adjust(-xdiff, -ydiff, xdiff, ydiff); + q = 1.0; + } else + q = (target.width() / scale) / adj.width(); // Adjust the view for printing - if (hires) { + if (flags & HiRes) { zoom = _map->zoom(); QRectF vr(mapToScene(orig).boundingRect()); origScene = vr.center(); @@ -594,7 +602,7 @@ void MapView::plot(QPainter *painter, const QRectF &target, qreal scale, render(painter, target, adj); // Revert view changes to display mode - if (hires) { + if (flags) { _map->setZoom(zoom); rescale(); centerOn(origScene); diff --git a/src/GUI/mapview.h b/src/GUI/mapview.h index fb57e091..a75edf91 100644 --- a/src/GUI/mapview.h +++ b/src/GUI/mapview.h @@ -5,6 +5,7 @@ #include #include #include +#include #include "common/rectc.h" #include "common/config.h" #include "data/waypoint.h" @@ -38,6 +39,13 @@ class MapView : public QGraphicsView Q_OBJECT public: + enum Flag { + NoFlags = 0, + HiRes = 1, + Expand = 2 + }; + Q_DECLARE_FLAGS(PlotFlags, Flag) + MapView(Map *map, POI *poi, QWidget *parent = 0); QList loadData(const Data &data); @@ -46,7 +54,8 @@ public: void setPOI(POI *poi); void setMap(Map *map); - void plot(QPainter *painter, const QRectF &target, qreal scale, bool hires); + void plot(QPainter *painter, const QRectF &target, qreal scale, + PlotFlags flags); void clear(); diff --git a/src/GUI/margins.h b/src/GUI/margins.h index c8f54e59..c6caee92 100644 --- a/src/GUI/margins.h +++ b/src/GUI/margins.h @@ -4,6 +4,27 @@ #include #include +class Margins +{ +public: + Margins() {_left = 0; _top = 0; _right = 0; _bottom = 0;} + Margins(int left, int top, int right, int bottom) + {_left = left, _top = top; _right = right; _bottom = bottom;} + + int left() const {return _left;} + int top() const {return _top;} + int right() const {return _right;} + int bottom() const {return _bottom;} + + int &rleft() {return _left;} + int &rtop() {return _top;} + int &rright() {return _right;} + int &rbottom() {return _bottom;} + +private: + int _left, _top, _right, _bottom; +}; + class MarginsF { public: @@ -26,6 +47,13 @@ private: }; #ifndef QT_NO_DEBUG +inline QDebug operator<<(QDebug dbg, const Margins &margins) +{ + dbg.nospace() << "Margins(" << margins.left() << ", " << margins.top() + << ", " << margins.right() << margins.bottom() << ")"; + return dbg.space(); +} + inline QDebug operator<<(QDebug dbg, const MarginsF &margins) { dbg.nospace() << "MarginsF(" << margins.left() << ", " << margins.top() diff --git a/src/GUI/optionsdialog.cpp b/src/GUI/optionsdialog.cpp index 69ace537..fb1e0d74 100644 --- a/src/GUI/optionsdialog.cpp +++ b/src/GUI/optionsdialog.cpp @@ -56,12 +56,12 @@ QWidget *OptionsDialog::createMapPage() + projections.at(i).value(); _projection->addItem(text, QVariant(projections.at(i).key())); } - _projection->setCurrentIndex(_projection->findData(_options->projection)); + _projection->setCurrentIndex(_projection->findData(_options.projection)); #ifdef ENABLE_HIDPI _hidpi = new QRadioButton(tr("High-resolution")); _lodpi = new QRadioButton(tr("Standard")); - if (_options->hidpiMap) + if (_options.hidpiMap) _hidpi->setChecked(true); else _lodpi->setChecked(true); @@ -112,10 +112,10 @@ QWidget *OptionsDialog::createAppearancePage() { // Tracks _trackWidth = new QSpinBox(); - _trackWidth->setValue(_options->trackWidth); + _trackWidth->setValue(_options.trackWidth); _trackWidth->setMinimum(1); _trackStyle = new StyleComboBox(); - _trackStyle->setValue(_options->trackStyle); + _trackStyle->setValue(_options.trackStyle); QFormLayout *trackLayout = new QFormLayout(); #ifdef Q_OS_MAC trackLayout->addRow(tr("Track width:"), _trackWidth); @@ -129,10 +129,10 @@ QWidget *OptionsDialog::createAppearancePage() // Routes _routeWidth = new QSpinBox(); - _routeWidth->setValue(_options->routeWidth); + _routeWidth->setValue(_options.routeWidth); _routeWidth->setMinimum(1); _routeStyle = new StyleComboBox(); - _routeStyle->setValue(_options->routeStyle); + _routeStyle->setValue(_options.routeStyle); QFormLayout *routeLayout = new QFormLayout(); #ifdef Q_OS_MAC routeLayout->addRow(tr("Route width:"), _routeWidth); @@ -146,11 +146,11 @@ QWidget *OptionsDialog::createAppearancePage() // Areas _areaWidth = new QSpinBox(); - _areaWidth->setValue(_options->areaWidth); + _areaWidth->setValue(_options.areaWidth); _areaStyle = new StyleComboBox(); - _areaStyle->setValue(_options->areaStyle); + _areaStyle->setValue(_options.areaStyle); _areaOpacity = new PercentSlider(); - _areaOpacity->setValue(_options->areaOpacity); + _areaOpacity->setValue(_options.areaOpacity); QFormLayout *areaLayout = new QFormLayout(); #ifdef Q_OS_MAC areaLayout->addRow(tr("Area border width:"), _areaWidth); @@ -166,15 +166,15 @@ QWidget *OptionsDialog::createAppearancePage() // Palette & antialiasing _baseColor = new ColorBox(); - _baseColor->setColor(_options->palette.color()); + _baseColor->setColor(_options.palette.color()); _colorOffset = new PercentSlider(); - _colorOffset->setValue(_options->palette.shift() * 100); + _colorOffset->setValue(_options.palette.shift() * 100); QFormLayout *paletteLayout = new QFormLayout(); paletteLayout->addRow(tr("Base color:"), _baseColor); paletteLayout->addRow(tr("Palette shift:"), _colorOffset); _pathAA = new QCheckBox(tr("Use anti-aliasing")); - _pathAA->setChecked(_options->pathAntiAliasing); + _pathAA->setChecked(_options.pathAntiAliasing); QFormLayout *pathAALayout = new QFormLayout(); pathAALayout->addWidget(_pathAA); @@ -201,9 +201,9 @@ QWidget *OptionsDialog::createAppearancePage() // Waypoints _waypointSize = new QSpinBox(); _waypointSize->setMinimum(1); - _waypointSize->setValue(_options->waypointSize); + _waypointSize->setValue(_options.waypointSize); _waypointColor = new ColorBox(); - _waypointColor->setColor(_options->waypointColor); + _waypointColor->setColor(_options.waypointColor); QFormLayout *waypointLayout = new QFormLayout(); #ifdef Q_OS_MAC waypointLayout->addRow(tr("Waypoint color:"), _waypointColor); @@ -217,9 +217,9 @@ QWidget *OptionsDialog::createAppearancePage() _poiSize = new QSpinBox(); _poiSize->setMinimum(1); - _poiSize->setValue(_options->poiSize); + _poiSize->setValue(_options.poiSize); _poiColor = new ColorBox(); - _poiColor->setColor(_options->poiColor); + _poiColor->setColor(_options.poiColor); QFormLayout *poiLayout = new QFormLayout(); #ifdef Q_OS_MAC poiLayout->addRow(tr("POI color:"), _poiColor); @@ -247,9 +247,9 @@ QWidget *OptionsDialog::createAppearancePage() // Graphs _sliderColor = new ColorBox(); - _sliderColor->setColor(_options->sliderColor); + _sliderColor->setColor(_options.sliderColor); _graphWidth = new QSpinBox(); - _graphWidth->setValue(_options->graphWidth); + _graphWidth->setValue(_options.graphWidth); _graphWidth->setMinimum(1); QFormLayout *graphLayout = new QFormLayout(); @@ -257,7 +257,7 @@ QWidget *OptionsDialog::createAppearancePage() graphLayout->addRow(tr("Slider color:"), _sliderColor); _graphAA = new QCheckBox(tr("Use anti-aliasing")); - _graphAA->setChecked(_options->graphAntiAliasing); + _graphAA->setChecked(_options.graphAntiAliasing); QFormLayout *graphAALayout = new QFormLayout(); graphAALayout->addWidget(_graphAA); @@ -271,9 +271,9 @@ QWidget *OptionsDialog::createAppearancePage() // Map _mapOpacity = new PercentSlider(); - _mapOpacity->setValue(_options->mapOpacity); + _mapOpacity->setValue(_options.mapOpacity); _backgroundColor = new ColorBox(); - _backgroundColor->setColor(_options->backgroundColor); + _backgroundColor->setColor(_options.backgroundColor); _backgroundColor->enableAlphaChannel(false); QFormLayout *mapLayout = new QFormLayout(); @@ -301,19 +301,19 @@ QWidget *OptionsDialog::createDataPage() QString filterToolTip = tr("Moving average window size"); _elevationFilter = new OddSpinBox(); - _elevationFilter->setValue(_options->elevationFilter); + _elevationFilter->setValue(_options.elevationFilter); _elevationFilter->setToolTip(filterToolTip); _speedFilter = new OddSpinBox(); - _speedFilter->setValue(_options->speedFilter); + _speedFilter->setValue(_options.speedFilter); _speedFilter->setToolTip(filterToolTip); _heartRateFilter = new OddSpinBox(); - _heartRateFilter->setValue(_options->heartRateFilter); + _heartRateFilter->setValue(_options.heartRateFilter); _heartRateFilter->setToolTip(filterToolTip); _cadenceFilter = new OddSpinBox(); - _cadenceFilter->setValue(_options->cadenceFilter); + _cadenceFilter->setValue(_options.cadenceFilter); _cadenceFilter->setToolTip(filterToolTip); _powerFilter = new OddSpinBox(); - _powerFilter->setValue(_options->powerFilter); + _powerFilter->setValue(_options.powerFilter); _powerFilter->setToolTip(filterToolTip); QFormLayout *smoothLayout = new QFormLayout(); @@ -328,7 +328,7 @@ QWidget *OptionsDialog::createDataPage() #endif // Q_OS_MAC _outlierEliminate = new QCheckBox(tr("Eliminate GPS outliers")); - _outlierEliminate->setChecked(_options->outlierEliminate); + _outlierEliminate->setChecked(_options.outlierEliminate); QFormLayout *outlierLayout = new QFormLayout(); outlierLayout->addWidget(_outlierEliminate); @@ -349,7 +349,7 @@ QWidget *OptionsDialog::createDataPage() _automaticPause = new QRadioButton(tr("Automatic")); _manualPause = new QRadioButton(tr("Custom")); - if (_options->automaticPause) + if (_options.automaticPause) _automaticPause->setChecked(true); else _manualPause->setChecked(true); @@ -359,20 +359,20 @@ QWidget *OptionsDialog::createDataPage() _pauseSpeed->setSingleStep(0.1); _pauseSpeed->setMinimum(0.1); _pauseSpeed->setEnabled(_manualPause->isChecked()); - if (_options->units == Imperial) { - _pauseSpeed->setValue(_options->pauseSpeed * MS2MIH); + if (_units == Imperial) { + _pauseSpeed->setValue(_options.pauseSpeed * MS2MIH); _pauseSpeed->setSuffix(UNIT_SPACE + tr("mi/h")); - } else if (_options->units == Nautical) { - _pauseSpeed->setValue(_options->pauseSpeed * MS2KN); + } else if (_units == Nautical) { + _pauseSpeed->setValue(_options.pauseSpeed * MS2KN); _pauseSpeed->setSuffix(UNIT_SPACE + tr("kn")); } else { - _pauseSpeed->setValue(_options->pauseSpeed * MS2KMH); + _pauseSpeed->setValue(_options.pauseSpeed * MS2KMH); _pauseSpeed->setSuffix(UNIT_SPACE + tr("km/h")); } _pauseInterval = new QSpinBox(); _pauseInterval->setMinimum(1); _pauseInterval->setSuffix(UNIT_SPACE + tr("s")); - _pauseInterval->setValue(_options->pauseInterval); + _pauseInterval->setValue(_options.pauseInterval); _pauseInterval->setEnabled(_manualPause->isChecked()); connect(_automaticPause, SIGNAL(toggled(bool)), this, @@ -400,29 +400,29 @@ QWidget *OptionsDialog::createDataPage() _computedSpeed = new QRadioButton(tr("Computed from distance/time")); _reportedSpeed = new QRadioButton(tr("Recorded by device")); - if (_options->useReportedSpeed) + if (_options.useReportedSpeed) _reportedSpeed->setChecked(true); else _computedSpeed->setChecked(true); _showSecondarySpeed = new QCheckBox(tr("Show secondary speed")); - _showSecondarySpeed->setChecked(_options->showSecondarySpeed); + _showSecondarySpeed->setChecked(_options.showSecondarySpeed); _dataGPSElevation = new QRadioButton(tr("GPS data")); _dataDEMElevation = new QRadioButton(tr("DEM data")); - if (_options->dataUseDEM) + if (_options.dataUseDEM) _dataDEMElevation->setChecked(true); else _dataGPSElevation->setChecked(true); _showSecondaryElevation = new QCheckBox(tr("Show secondary elevation")); - _showSecondaryElevation->setChecked(_options->showSecondaryElevation); + _showSecondaryElevation->setChecked(_options.showSecondaryElevation); #ifdef ENABLE_TIMEZONES _utcZone = new QRadioButton(tr("UTC")); _systemZone = new QRadioButton(tr("System")); _customZone = new QRadioButton(tr("Custom")); - if (_options->timeZone.type() == TimeZoneInfo::UTC) + if (_options.timeZone.type() == TimeZoneInfo::UTC) _utcZone->setChecked(true); - else if (_options->timeZone.type() == TimeZoneInfo::System) + else if (_options.timeZone.type() == TimeZoneInfo::System) _systemZone->setChecked(true); else _customZone->setChecked(true); @@ -431,7 +431,7 @@ QWidget *OptionsDialog::createDataPage() QList zones = QTimeZone::availableTimeZoneIds(); for (int i = 0; i < zones.size(); i++) _timeZone->addItem(zones.at(i)); - _timeZone->setCurrentText(_options->timeZone.customZone().id()); + _timeZone->setCurrentText(_options.timeZone.customZone().id()); connect(_customZone, SIGNAL(toggled(bool)), _timeZone, SLOT(setEnabled(bool))); QHBoxLayout *customZoneLayout = new QHBoxLayout(); @@ -440,7 +440,7 @@ QWidget *OptionsDialog::createDataPage() #endif // ENABLE_TIMEZONES _useSegments = new QCheckBox(tr("Use segments")); - _useSegments->setChecked(_options->useSegments); + _useSegments->setChecked(_options.useSegments); QWidget *sourceTab = new QWidget(); QVBoxLayout *sourceTabLayout = new QVBoxLayout(); @@ -541,14 +541,14 @@ QWidget *OptionsDialog::createPOIPage() _poiRadius = new QDoubleSpinBox(); _poiRadius->setSingleStep(1); _poiRadius->setDecimals(1); - if (_options->units == Imperial) { - _poiRadius->setValue(_options->poiRadius / MIINM); + if (_units == Imperial) { + _poiRadius->setValue(_options.poiRadius / MIINM); _poiRadius->setSuffix(UNIT_SPACE + tr("mi")); - } else if (_options->units == Nautical) { - _poiRadius->setValue(_options->poiRadius / NMIINM); + } else if (_units == Nautical) { + _poiRadius->setValue(_options.poiRadius / NMIINM); _poiRadius->setSuffix(UNIT_SPACE + tr("nmi")); } else { - _poiRadius->setValue(_options->poiRadius / KMINM); + _poiRadius->setValue(_options.poiRadius / KMINM); _poiRadius->setSuffix(UNIT_SPACE + tr("km")); } @@ -568,7 +568,7 @@ QWidget *OptionsDialog::createExportPage() { _wysiwyg = new QRadioButton(tr("WYSIWYG")); _hires = new QRadioButton(tr("High-Resolution")); - if (_options->hiresPrint) + if (_options.hiresPrint) _hires->setChecked(true); else _wysiwyg->setChecked(true); @@ -597,17 +597,17 @@ QWidget *OptionsDialog::createExportPage() _name = new QCheckBox(tr("Name")); - _name->setChecked(_options->printName); + _name->setChecked(_options.printName); _date = new QCheckBox(tr("Date")); - _date->setChecked(_options->printDate); + _date->setChecked(_options.printDate); _distance = new QCheckBox(tr("Distance")); - _distance->setChecked(_options->printDistance); + _distance->setChecked(_options.printDistance); _time = new QCheckBox(tr("Time")); - _time->setChecked(_options->printTime); + _time->setChecked(_options.printTime); _movingTime = new QCheckBox(tr("Moving time")); - _movingTime->setChecked(_options->printMovingTime); + _movingTime->setChecked(_options.printMovingTime); _itemCount = new QCheckBox(tr("Item count (>1)")); - _itemCount->setChecked(_options->printItemCount); + _itemCount->setChecked(_options.printItemCount); QFormLayout *headerTabLayout = new QFormLayout(); headerTabLayout->addWidget(_name); @@ -622,7 +622,7 @@ QWidget *OptionsDialog::createExportPage() _separateGraphPage = new QCheckBox(tr("Separate graph page")); - _separateGraphPage->setChecked(_options->separateGraphPage); + _separateGraphPage->setChecked(_options.separateGraphPage); QFormLayout *graphTabLayout = new QFormLayout(); graphTabLayout->addWidget(_separateGraphPage); @@ -641,23 +641,23 @@ QWidget *OptionsDialog::createExportPage() QWidget *OptionsDialog::createSystemPage() { _useOpenGL = new QCheckBox(tr("Use OpenGL")); - _useOpenGL->setChecked(_options->useOpenGL); + _useOpenGL->setChecked(_options.useOpenGL); #ifdef ENABLE_HTTP2 _enableHTTP2 = new QCheckBox(tr("Enable HTTP/2")); - _enableHTTP2->setChecked(_options->enableHTTP2); + _enableHTTP2->setChecked(_options.enableHTTP2); #endif // ENABLE_HTTP2 _pixmapCache = new QSpinBox(); _pixmapCache->setMinimum(16); _pixmapCache->setMaximum(1024); _pixmapCache->setSuffix(UNIT_SPACE + tr("MB")); - _pixmapCache->setValue(_options->pixmapCache); + _pixmapCache->setValue(_options.pixmapCache); _connectionTimeout = new QSpinBox(); _connectionTimeout->setMinimum(30); _connectionTimeout->setMaximum(120); _connectionTimeout->setSuffix(UNIT_SPACE + tr("s")); - _connectionTimeout->setValue(_options->connectionTimeout); + _connectionTimeout->setValue(_options.connectionTimeout); QFormLayout *formLayout = new QFormLayout(); formLayout->addRow(tr("Image cache size:"), _pixmapCache); @@ -682,8 +682,8 @@ QWidget *OptionsDialog::createSystemPage() return systemPage; } -OptionsDialog::OptionsDialog(Options *options, QWidget *parent) - : QDialog(parent), _options(options) +OptionsDialog::OptionsDialog(Options &options, Units units, QWidget *parent) + : QDialog(parent), _options(options), _units(units) { QStackedWidget *pages = new QStackedWidget(); pages->addWidget(createAppearancePage()); @@ -735,82 +735,82 @@ OptionsDialog::OptionsDialog(Options *options, QWidget *parent) void OptionsDialog::accept() { - _options->palette.setColor(_baseColor->color()); - _options->palette.setShift(_colorOffset->value() / 100.0); - _options->mapOpacity = _mapOpacity->value(); - _options->backgroundColor = _backgroundColor->color(); - _options->trackWidth = _trackWidth->value(); - _options->trackStyle = (Qt::PenStyle) _trackStyle->itemData( + _options.palette.setColor(_baseColor->color()); + _options.palette.setShift(_colorOffset->value() / 100.0); + _options.mapOpacity = _mapOpacity->value(); + _options.backgroundColor = _backgroundColor->color(); + _options.trackWidth = _trackWidth->value(); + _options.trackStyle = (Qt::PenStyle) _trackStyle->itemData( _trackStyle->currentIndex()).toInt(); - _options->routeWidth = _routeWidth->value(); - _options->routeStyle = (Qt::PenStyle) _routeStyle->itemData( + _options.routeWidth = _routeWidth->value(); + _options.routeStyle = (Qt::PenStyle) _routeStyle->itemData( _routeStyle->currentIndex()).toInt(); - _options->pathAntiAliasing = _pathAA->isChecked(); - _options->areaWidth = _areaWidth->value(); - _options->areaStyle = (Qt::PenStyle) _areaStyle->itemData( + _options.pathAntiAliasing = _pathAA->isChecked(); + _options.areaWidth = _areaWidth->value(); + _options.areaStyle = (Qt::PenStyle) _areaStyle->itemData( _areaStyle->currentIndex()).toInt(); - _options->areaOpacity = _areaOpacity->value(); - _options->waypointSize = _waypointSize->value(); - _options->waypointColor = _waypointColor->color(); - _options->poiSize = _poiSize->value(); - _options->poiColor = _poiColor->color(); - _options->graphWidth = _graphWidth->value(); - _options->sliderColor = _sliderColor->color(); - _options->graphAntiAliasing = _graphAA->isChecked(); + _options.areaOpacity = _areaOpacity->value(); + _options.waypointSize = _waypointSize->value(); + _options.waypointColor = _waypointColor->color(); + _options.poiSize = _poiSize->value(); + _options.poiColor = _poiColor->color(); + _options.graphWidth = _graphWidth->value(); + _options.sliderColor = _sliderColor->color(); + _options.graphAntiAliasing = _graphAA->isChecked(); - _options->projection = _projection->itemData(_projection->currentIndex()) + _options.projection = _projection->itemData(_projection->currentIndex()) .toInt(); #ifdef ENABLE_HIDPI - _options->hidpiMap = _hidpi->isChecked(); + _options.hidpiMap = _hidpi->isChecked(); #endif // ENABLE_HIDPI - _options->elevationFilter = _elevationFilter->value(); - _options->speedFilter = _speedFilter->value(); - _options->heartRateFilter = _heartRateFilter->value(); - _options->cadenceFilter = _cadenceFilter->value(); - _options->powerFilter = _powerFilter->value(); - _options->outlierEliminate = _outlierEliminate->isChecked(); - _options->automaticPause = _automaticPause->isChecked(); - qreal pauseSpeed = (_options->units == Imperial) - ? _pauseSpeed->value() / MS2MIH : (_options->units == Nautical) + _options.elevationFilter = _elevationFilter->value(); + _options.speedFilter = _speedFilter->value(); + _options.heartRateFilter = _heartRateFilter->value(); + _options.cadenceFilter = _cadenceFilter->value(); + _options.powerFilter = _powerFilter->value(); + _options.outlierEliminate = _outlierEliminate->isChecked(); + _options.automaticPause = _automaticPause->isChecked(); + qreal pauseSpeed = (_units == Imperial) + ? _pauseSpeed->value() / MS2MIH : (_units == Nautical) ? _pauseSpeed->value() / MS2KN : _pauseSpeed->value() / MS2KMH; - if (qAbs(pauseSpeed - _options->pauseSpeed) > 0.01) - _options->pauseSpeed = pauseSpeed; - _options->pauseInterval = _pauseInterval->value(); - _options->useReportedSpeed = _reportedSpeed->isChecked(); - _options->dataUseDEM = _dataDEMElevation->isChecked(); - _options->showSecondaryElevation = _showSecondaryElevation->isChecked(); - _options->showSecondarySpeed = _showSecondarySpeed->isChecked(); + if (qAbs(pauseSpeed - _options.pauseSpeed) > 0.01) + _options.pauseSpeed = pauseSpeed; + _options.pauseInterval = _pauseInterval->value(); + _options.useReportedSpeed = _reportedSpeed->isChecked(); + _options.dataUseDEM = _dataDEMElevation->isChecked(); + _options.showSecondaryElevation = _showSecondaryElevation->isChecked(); + _options.showSecondarySpeed = _showSecondarySpeed->isChecked(); #ifdef ENABLE_TIMEZONES - _options->timeZone.setType(_utcZone->isChecked() + _options.timeZone.setType(_utcZone->isChecked() ? TimeZoneInfo::UTC : _systemZone->isChecked() ? TimeZoneInfo::System : TimeZoneInfo::Custom); - _options->timeZone.setCustomZone(QTimeZone(_timeZone->currentText() + _options.timeZone.setCustomZone(QTimeZone(_timeZone->currentText() .toLatin1())); #endif // ENABLE_TIMEZONES - _options->useSegments = _useSegments->isChecked(); + _options.useSegments = _useSegments->isChecked(); - qreal poiRadius = (_options->units == Imperial) - ? _poiRadius->value() * MIINM : (_options->units == Nautical) + qreal poiRadius = (_units == Imperial) + ? _poiRadius->value() * MIINM : (_units == Nautical) ? _poiRadius->value() * NMIINM : _poiRadius->value() * KMINM; - if (qAbs(poiRadius - _options->poiRadius) > 0.01) - _options->poiRadius = poiRadius; + if (qAbs(poiRadius - _options.poiRadius) > 0.01) + _options.poiRadius = poiRadius; - _options->useOpenGL = _useOpenGL->isChecked(); + _options.useOpenGL = _useOpenGL->isChecked(); #ifdef ENABLE_HTTP2 - _options->enableHTTP2 = _enableHTTP2->isChecked(); + _options.enableHTTP2 = _enableHTTP2->isChecked(); #endif // ENABLE_HTTP2 - _options->pixmapCache = _pixmapCache->value(); - _options->connectionTimeout = _connectionTimeout->value(); + _options.pixmapCache = _pixmapCache->value(); + _options.connectionTimeout = _connectionTimeout->value(); - _options->hiresPrint = _hires->isChecked(); - _options->printName = _name->isChecked(); - _options->printDate = _date->isChecked(); - _options->printDistance = _distance->isChecked(); - _options->printTime = _time->isChecked(); - _options->printMovingTime = _movingTime->isChecked(); - _options->printItemCount = _itemCount->isChecked(); - _options->separateGraphPage = _separateGraphPage->isChecked(); + _options.hiresPrint = _hires->isChecked(); + _options.printName = _name->isChecked(); + _options.printDate = _date->isChecked(); + _options.printDistance = _distance->isChecked(); + _options.printTime = _time->isChecked(); + _options.printMovingTime = _movingTime->isChecked(); + _options.printItemCount = _itemCount->isChecked(); + _options.separateGraphPage = _separateGraphPage->isChecked(); QDialog::accept(); } diff --git a/src/GUI/optionsdialog.h b/src/GUI/optionsdialog.h index a2284d31..d9c4b987 100644 --- a/src/GUI/optionsdialog.h +++ b/src/GUI/optionsdialog.h @@ -82,8 +82,6 @@ struct Options { bool printMovingTime; bool printItemCount; bool separateGraphPage; - - Units units; }; class OptionsDialog : public QDialog @@ -94,7 +92,7 @@ public slots: void accept(); public: - OptionsDialog(Options *options, QWidget *parent = 0); + OptionsDialog(Options &options, Units units, QWidget *parent = 0); private slots: void automaticPauseDetectionSet(bool set); @@ -107,8 +105,9 @@ private: QWidget *createSystemPage(); QWidget *createExportPage(); - Options *_options; + Options &_options; + Units _units; // Appearance ColorBox *_baseColor; PercentSlider *_colorOffset; diff --git a/src/GUI/exportdialog.cpp b/src/GUI/pdfexportdialog.cpp similarity index 69% rename from src/GUI/exportdialog.cpp rename to src/GUI/pdfexportdialog.cpp index 88194c21..b7cbf361 100644 --- a/src/GUI/exportdialog.cpp +++ b/src/GUI/pdfexportdialog.cpp @@ -6,25 +6,24 @@ #include #include #include -#include #include #include #include #include #include "fileselectwidget.h" #include "units.h" -#include "exportdialog.h" +#include "pdfexportdialog.h" -ExportDialog::ExportDialog(Export *exp, QWidget *parent) - : QDialog(parent), _export(exp) +PDFExportDialog::PDFExportDialog(PDFExport &exp, Units units, QWidget *parent) + : QDialog(parent), _export(exp), _units(units) { int index; _fileSelect = new FileSelectWidget(); _fileSelect->setFilter(tr("PDF files") + " (*.pdf);;" + tr("All files") + " (*)"); - _fileSelect->setFile(_export->fileName); + _fileSelect->setFile(_export.fileName); _paperSize = new QComboBox(); _paperSize->addItem("A2", QPrinter::A2); @@ -39,14 +38,14 @@ ExportDialog::ExportDialog(Export *exp, QWidget *parent) _paperSize->addItem("Tabloid", QPrinter::Tabloid); _paperSize->addItem("Legal", QPrinter::Legal); _paperSize->addItem("Letter", QPrinter::Letter); - if ((index = _paperSize->findData(_export->paperSize)) >= 0) + if ((index = _paperSize->findData(_export.paperSize)) >= 0) _paperSize->setCurrentIndex(index); _resolution = new QComboBox(); _resolution->addItem("150 DPI", 150); _resolution->addItem("300 DPI", 300); _resolution->addItem("600 DPI", 600); - if ((index = _resolution->findData(_export->resolution)) >= 0) + if ((index = _resolution->findData(_export.resolution)) >= 0) _resolution->setCurrentIndex(index); _portrait = new QRadioButton(tr("Portrait")); @@ -54,7 +53,7 @@ ExportDialog::ExportDialog(Export *exp, QWidget *parent) QHBoxLayout *orientationLayout = new QHBoxLayout(); orientationLayout->addWidget(_portrait); orientationLayout->addWidget(_landscape); - if (_export->orientation == QPrinter::Portrait) + if (_export.orientation == QPrinter::Portrait) _portrait->setChecked(true); else _landscape->setChecked(true); @@ -63,21 +62,21 @@ ExportDialog::ExportDialog(Export *exp, QWidget *parent) _bottomMargin = new QDoubleSpinBox(); _leftMargin = new QDoubleSpinBox(); _rightMargin = new QDoubleSpinBox(); - QString us = (_export->units == Metric) ? tr("mm") : tr("in"); + QString us = (units == Metric) ? tr("mm") : tr("in"); _topMargin->setSuffix(UNIT_SPACE + us); _bottomMargin->setSuffix(UNIT_SPACE + us); _leftMargin->setSuffix(UNIT_SPACE + us); _rightMargin->setSuffix(UNIT_SPACE + us); - if (_export->units == Metric) { - _topMargin->setValue(_export->margins.top()); - _bottomMargin->setValue(_export->margins.bottom()); - _leftMargin->setValue(_export->margins.left()); - _rightMargin->setValue(_export->margins.right()); + if (units == Metric) { + _topMargin->setValue(_export.margins.top()); + _bottomMargin->setValue(_export.margins.bottom()); + _leftMargin->setValue(_export.margins.left()); + _rightMargin->setValue(_export.margins.right()); } else { - _topMargin->setValue(_export->margins.top() * MM2IN); - _bottomMargin->setValue(_export->margins.bottom() * MM2IN); - _leftMargin->setValue(_export->margins.left() * MM2IN); - _rightMargin->setValue(_export->margins.right() * MM2IN); + _topMargin->setValue(_export.margins.top() * MM2IN); + _bottomMargin->setValue(_export.margins.bottom() * MM2IN); + _leftMargin->setValue(_export.margins.left() * MM2IN); + _rightMargin->setValue(_export.margins.right() * MM2IN); _topMargin->setSingleStep(0.1); _bottomMargin->setSingleStep(0.1); _leftMargin->setSingleStep(0.1); @@ -136,41 +135,13 @@ ExportDialog::ExportDialog(Export *exp, QWidget *parent) setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint); } -bool ExportDialog::checkFile() +void PDFExportDialog::accept() { - if (_fileSelect->file().isEmpty()) { - QMessageBox::warning(this, tr("Error"), tr("No output file selected.")); - return false; - } - - QFile file(_fileSelect->file()); - QFileInfo fi(file); - bool exists = fi.exists(); - bool opened = false; - - if (exists && fi.isDir()) { - QMessageBox::warning(this, tr("Error"), tr("%1 is a directory.") - .arg(file.fileName())); - return false; - } else if ((exists && !fi.isWritable()) - || !(opened = file.open(QFile::Append))) { - QMessageBox::warning(this, tr("Error"), tr("%1 is not writable.") - .arg(file.fileName())); - return false; - } - if (opened) { - file.close(); - if (!exists) - file.remove(); - } - - return true; -} - -void ExportDialog::accept() -{ - if (!checkFile()) + QString error; + if (!_fileSelect->checkFile(error)) { + QMessageBox::warning(this, tr("Error"), error); return; + } QPrinter::Orientation orientation = _portrait->isChecked() ? QPrinter::Portrait : QPrinter::Landscape; @@ -178,16 +149,16 @@ void ExportDialog::accept() (_paperSize->itemData(_paperSize->currentIndex()).toInt()); int resolution = _resolution->itemData(_resolution->currentIndex()).toInt(); - _export->fileName = _fileSelect->file(); - _export->paperSize = paperSize; - _export->resolution = resolution; - _export->orientation = orientation; - if (_export->units == Imperial) - _export->margins = MarginsF(_leftMargin->value() / MM2IN, + _export.fileName = _fileSelect->file(); + _export.paperSize = paperSize; + _export.resolution = resolution; + _export.orientation = orientation; + if (_units == Imperial) + _export.margins = MarginsF(_leftMargin->value() / MM2IN, _topMargin->value() / MM2IN, _rightMargin->value() / MM2IN, _bottomMargin->value() / MM2IN); else - _export->margins = MarginsF(_leftMargin->value(), _topMargin->value(), + _export.margins = MarginsF(_leftMargin->value(), _topMargin->value(), _rightMargin->value(), _bottomMargin->value()); QDialog::accept(); diff --git a/src/GUI/exportdialog.h b/src/GUI/pdfexportdialog.h similarity index 71% rename from src/GUI/exportdialog.h rename to src/GUI/pdfexportdialog.h index 71e811bf..54e04d8a 100644 --- a/src/GUI/exportdialog.h +++ b/src/GUI/pdfexportdialog.h @@ -1,5 +1,5 @@ -#ifndef EXPORTDIALOG_H -#define EXPORTDIALOG_H +#ifndef PDFEXPORTDIALOG_H +#define PDFEXPORTDIALOG_H #include #include @@ -11,31 +11,29 @@ class QRadioButton; class FileSelectWidget; class QDoubleSpinBox; -struct Export { +struct PDFExport +{ QString fileName; QPrinter::PaperSize paperSize; QPrinter::Orientation orientation; MarginsF margins; int resolution; - - Units units; }; -class ExportDialog : public QDialog +class PDFExportDialog : public QDialog { Q_OBJECT public: - ExportDialog(Export *exp, QWidget *parent = 0); + PDFExportDialog(PDFExport &exp, Units units, QWidget *parent = 0); public slots: void accept(); private: - bool checkFile(); - - Export *_export; + PDFExport &_export; + Units _units; FileSelectWidget *_fileSelect; QComboBox *_paperSize; QComboBox *_resolution; @@ -47,4 +45,4 @@ private: QDoubleSpinBox *_rightMargin; }; -#endif // EXPORTDIALOG_H +#endif // PDFEXPORTDIALOG_H diff --git a/src/GUI/pngexportdialog.cpp b/src/GUI/pngexportdialog.cpp new file mode 100644 index 00000000..44d60b42 --- /dev/null +++ b/src/GUI/pngexportdialog.cpp @@ -0,0 +1,120 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "units.h" +#include "fileselectwidget.h" +#include "pngexportdialog.h" + +PNGExportDialog::PNGExportDialog(PNGExport &exp, QWidget *parent) + : QDialog(parent), _export(exp) +{ + _fileSelect = new FileSelectWidget(); + _fileSelect->setFilter(tr("PNG files") + " (*.png);;" + tr("All files") + + " (*)"); + _fileSelect->setFile(_export.fileName); + + _width = new QSpinBox(); + _width->setMinimum(256); + _width->setMaximum(4096); + _width->setValue(_export.size.width()); + _width->setSuffix(UNIT_SPACE + tr("px")); + _height = new QSpinBox(); + _height->setMinimum(256); + _height->setMaximum(4096); + _height->setValue(_export.size.height()); + _height->setSuffix(UNIT_SPACE + tr("px")); + + _topMargin = new QDoubleSpinBox(); + _bottomMargin = new QDoubleSpinBox(); + _leftMargin = new QDoubleSpinBox(); + _rightMargin = new QDoubleSpinBox(); + _topMargin->setSuffix(UNIT_SPACE + tr("px")); + _bottomMargin->setSuffix(UNIT_SPACE + tr("px")); + _leftMargin->setSuffix(UNIT_SPACE + tr("px")); + _rightMargin->setSuffix(UNIT_SPACE + tr("px")); + _topMargin->setValue(_export.margins.top()); + _bottomMargin->setValue(_export.margins.bottom()); + _leftMargin->setValue(_export.margins.left()); + _rightMargin->setValue(_export.margins.right()); + + QGridLayout *marginsLayout = new QGridLayout(); + marginsLayout->addWidget(_topMargin, 0, 0, 1, 2, Qt::AlignCenter); + marginsLayout->addWidget(_leftMargin, 1, 0, 1, 1, Qt::AlignRight); + marginsLayout->addWidget(_rightMargin, 1, 1, 1, 1, Qt::AlignLeft); + marginsLayout->addWidget(_bottomMargin, 2, 0, 1, 2, Qt::AlignCenter); + + _antialiasing = new QCheckBox("Use antialiasing"); + _antialiasing->setChecked(_export.antialiasing); + +#ifndef Q_OS_MAC + QGroupBox *pageSetupBox = new QGroupBox(tr("Image Setup")); +#endif // Q_OS_MAC + QFormLayout *pageSetupLayout = new QFormLayout; + pageSetupLayout->addRow(tr("Image width:"), _width); + pageSetupLayout->addRow(tr("Image height:"), _height); + pageSetupLayout->addRow(tr("Margins:"), marginsLayout); + pageSetupLayout->addWidget(_antialiasing); +#ifdef Q_OS_MAC + QFrame *line = new QFrame(); + line->setFrameShape(QFrame::HLine); + line->setFrameShadow(QFrame::Sunken); + pageSetupLayout->addRow(line); + pageSetupLayout->addRow(tr("File:"), _fileSelect); + pageSetupLayout->setFieldGrowthPolicy(QFormLayout::ExpandingFieldsGrow); +#else // Q_OS_MAC + pageSetupBox->setLayout(pageSetupLayout); +#endif // Q_OS_MAC + +#ifndef Q_OS_MAC + QGroupBox *outputFileBox = new QGroupBox(tr("Output file")); + QHBoxLayout *outputFileLayout = new QHBoxLayout(); + outputFileLayout->addWidget(_fileSelect); + outputFileBox->setLayout(outputFileLayout); +#endif // Q_OS_MAC + + QDialogButtonBox *buttonBox = new QDialogButtonBox(); + buttonBox->addButton(tr("Export"), QDialogButtonBox::AcceptRole); + buttonBox->addButton(QDialogButtonBox::Cancel); + connect(buttonBox, SIGNAL(accepted()), this, SLOT(accept())); + connect(buttonBox, SIGNAL(rejected()), this, SLOT(reject())); + + QVBoxLayout *layout = new QVBoxLayout; +#ifdef Q_OS_MAC + layout->addLayout(pageSetupLayout); +#else // Q_OS_MAC + layout->addWidget(pageSetupBox); + layout->addWidget(outputFileBox); +#endif // Q_OS_MAC + layout->addWidget(buttonBox); + setLayout(layout); + + setWindowTitle(tr("Export to PNG")); + setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint); +} + +void PNGExportDialog::accept() +{ + QString error; + if (!_fileSelect->checkFile(error)) { + QMessageBox::warning(this, tr("Error"), error); + return; + } + + _export.fileName = _fileSelect->file(); + _export.size = QSize(_width->value(), _height->value()); + _export.margins = Margins(_leftMargin->value(), _topMargin->value(), + _rightMargin->value(), _bottomMargin->value()); + _export.antialiasing = _antialiasing->isChecked(); + + QDialog::accept(); +} diff --git a/src/GUI/pngexportdialog.h b/src/GUI/pngexportdialog.h new file mode 100644 index 00000000..81b2d903 --- /dev/null +++ b/src/GUI/pngexportdialog.h @@ -0,0 +1,43 @@ +#ifndef PNGEXPORTDIALOG_H +#define PNGEXPORTDIALOG_H + +#include +#include "margins.h" + +class FileSelectWidget; +class QSpinBox; +class QDoubleSpinBox; +class QCheckBox; + +struct PNGExport +{ + QString fileName; + QSize size; + Margins margins; + bool antialiasing; +}; + +class PNGExportDialog : public QDialog +{ + Q_OBJECT + +public: + PNGExportDialog(PNGExport &exp, QWidget *parent = 0); + +public slots: + void accept(); + +private: + PNGExport &_export; + + FileSelectWidget *_fileSelect; + QSpinBox *_width; + QSpinBox *_height; + QDoubleSpinBox *_topMargin; + QDoubleSpinBox *_bottomMargin; + QDoubleSpinBox *_leftMargin; + QDoubleSpinBox *_rightMargin; + QCheckBox *_antialiasing; +}; + +#endif // PNGEXPORTDIALOG_H diff --git a/src/GUI/settings.h b/src/GUI/settings.h index 9c38ac22..19869565 100644 --- a/src/GUI/settings.h +++ b/src/GUI/settings.h @@ -66,26 +66,45 @@ #define SHOW_WAYPOINT_LABELS_SETTING "waypointLabels" #define SHOW_WAYPOINT_LABELS_DEFAULT true -#define EXPORT_SETTINGS_GROUP "Export" +#define PDF_EXPORT_SETTINGS_GROUP "Export" #define PAPER_ORIENTATION_SETTING "orientation" #define PAPER_ORIENTATION_DEFAULT QPrinter::Portrait #define PAPER_SIZE_SETTING "size" #define PAPER_SIZE_DEFAULT (IMPERIAL_UNITS() ? QPrinter::Letter \ : QPrinter::A4) -#define MARGIN_LEFT_SETTING "marginLeft" -#define MARGIN_LEFT_DEFAULT 5 /* mm */ -#define MARGIN_TOP_SETTING "marginTop" -#define MARGIN_TOP_DEFAULT 5 /* mm */ -#define MARGIN_RIGHT_SETTING "marginRight" -#define MARGIN_RIGHT_DEFAULT 5 /* mm */ -#define MARGIN_BOTTOM_SETTING "marginBottom" -#define MARGIN_BOTTOM_DEFAULT 5 /* mm */ -#define EXPORT_FILENAME_SETTING "fileName" -#define EXPORT_FILENAME_DEFAULT QString("%1/export.pdf"). \ +#define PDF_MARGIN_LEFT_SETTING "marginLeft" +#define PDF_MARGIN_LEFT_DEFAULT 5 /* mm */ +#define PDF_MARGIN_TOP_SETTING "marginTop" +#define PDF_MARGIN_TOP_DEFAULT 5 /* mm */ +#define PDF_MARGIN_RIGHT_SETTING "marginRight" +#define PDF_MARGIN_RIGHT_DEFAULT 5 /* mm */ +#define PDF_MARGIN_BOTTOM_SETTING "marginBottom" +#define PDF_MARGIN_BOTTOM_DEFAULT 5 /* mm */ +#define PDF_FILENAME_SETTING "fileName" +#define PDF_FILENAME_DEFAULT QString("%1/export.pdf"). \ arg(QDir::currentPath()) #define RESOLUTION_SETTING "resolution" #define RESOLUTION_DEFAULT 600 +#define PNG_EXPORT_SETTINGS_GROUP "PNGExport" +#define PNG_WIDTH_SETTING "width" +#define PNG_WIDTH_DEFAULT 600 +#define PNG_HEIGHT_SETTING "height" +#define PNG_HEIGHT_DEFAULT 800 +#define PNG_MARGIN_LEFT_SETTING "marginLeft" +#define PNG_MARGIN_LEFT_DEFAULT 5 /* px */ +#define PNG_MARGIN_TOP_SETTING "marginTop" +#define PNG_MARGIN_TOP_DEFAULT 5 /* px */ +#define PNG_MARGIN_RIGHT_SETTING "marginRight" +#define PNG_MARGIN_RIGHT_DEFAULT 5 /* px */ +#define PNG_MARGIN_BOTTOM_SETTING "marginBottom" +#define PNG_MARGIN_BOTTOM_DEFAULT 5 /* px */ +#define PNG_ANTIALIASING_SETTING "antialiasing" +#define PNG_ANTIALIASING_DEFAULT true +#define PNG_FILENAME_SETTING "fileName" +#define PNG_FILENAME_DEFAULT QString("%1/export.png"). \ + arg(QDir::currentPath()) + #define OPTIONS_SETTINGS_GROUP "Options" #define PALETTE_COLOR_SETTING "paletteColor" #define PALETTE_COLOR_DEFAULT QColor(Qt::blue)