source: subsurface/desktop-widgets/divelogexportdialog.cpp @ 9b8a040

Last change on this file since 9b8a040 was 9b8a040, checked in by Dirk Hohndel <dirk@…>, 14 months ago

Export to TeX file initialized

This does the basic export as a TeX file including a template.

It still lacks proper location parsing.

Signed-off-by: Robert C. Helling <helling@…>
Signed-off-by: Dirk Hohndel <dirk@…>

  • Property mode set to 100644
File size: 11.8 KB
Line 
1#include <QFileDialog>
2#include <QShortcut>
3#include <QSettings>
4#include <QtConcurrent>
5
6#include "desktop-widgets/divelogexportdialog.h"
7#include "core/divelogexportlogic.h"
8#include "desktop-widgets/diveshareexportdialog.h"
9#include "ui_divelogexportdialog.h"
10#include "desktop-widgets/subsurfacewebservices.h"
11#include "core/worldmap-save.h"
12#include "core/save-html.h"
13#include "desktop-widgets/mainwindow.h"
14#include "profile-widget/profilewidget2.h"
15
16
17#define GET_UNIT(name, field, f, t)                   \
18        v = settings.value(QString(name));            \
19        if (v.isValid())                              \
20                field = (v.toInt() == 0) ? (t) : (f); \
21        else                                          \
22                field = default_prefs.units.field
23
24DiveLogExportDialog::DiveLogExportDialog(QWidget *parent) : QDialog(parent),
25        ui(new Ui::DiveLogExportDialog)
26{
27        ui->setupUi(this);
28        showExplanation();
29        QShortcut *quit = new QShortcut(QKeySequence(Qt::CTRL + Qt::Key_Q), this);
30        connect(quit, SIGNAL(activated()), MainWindow::instance(), SLOT(close()));
31        QShortcut *close = new QShortcut(QKeySequence(Qt::CTRL + Qt::Key_W), this);
32        connect(close, SIGNAL(activated()), this, SLOT(close()));
33
34        /* the names are not the actual values exported to the json files,The font-family property should hold several
35        font names as a "fallback" system, to ensure maximum compatibility between browsers/operating systems */
36        ui->fontSelection->addItem("Arial", "Arial, Helvetica, sans-serif");
37        ui->fontSelection->addItem("Impact", "Impact, Charcoal, sans-serif");
38        ui->fontSelection->addItem("Georgia", "Georgia, serif");
39        ui->fontSelection->addItem("Courier", "Courier, monospace");
40        ui->fontSelection->addItem("Verdana", "Verdana, Geneva, sans-serif");
41
42        QSettings settings;
43        settings.beginGroup("HTML");
44        if (settings.contains("fontSelection")) {
45                ui->fontSelection->setCurrentIndex(settings.value("fontSelection").toInt());
46        }
47        if (settings.contains("fontSizeSelection")) {
48                ui->fontSizeSelection->setCurrentIndex(settings.value("fontSizeSelection").toInt());
49        }
50        if (settings.contains("themeSelection")) {
51                ui->themeSelection->setCurrentIndex(settings.value("themeSelection").toInt());
52        }
53        if (settings.contains("subsurfaceNumbers")) {
54                ui->exportSubsurfaceNumber->setChecked(settings.value("subsurfaceNumbers").toBool());
55        }
56        if (settings.contains("yearlyStatistics")) {
57                ui->exportStatistics->setChecked(settings.value("yearlyStatistics").toBool());
58        }
59        if (settings.contains("listOnly")) {
60                ui->exportListOnly->setChecked(settings.value("listOnly").toBool());
61        }
62        if (settings.contains("exportPhotos")) {
63                ui->exportPhotos->setChecked(settings.value("exportPhotos").toBool());
64        }
65        settings.endGroup();
66}
67
68DiveLogExportDialog::~DiveLogExportDialog()
69{
70        delete ui;
71}
72
73void DiveLogExportDialog::showExplanation()
74{
75        if (ui->exportUDDF->isChecked()) {
76                ui->description->setText(tr("Generic format that is used for data exchange between a variety of diving related programs."));
77        } else if (ui->exportCSV->isChecked()) {
78                ui->description->setText(tr("Comma separated values describing the dive profile."));
79        } else if (ui->exportCSVDetails->isChecked()) {
80                ui->description->setText(tr("Comma separated values of the dive information. This includes most of the dive details but no profile information."));
81        } else if (ui->exportDivelogs->isChecked()) {
82                ui->description->setText(tr("Send the dive data to divelogs.de website."));
83        } else if (ui->exportDiveshare->isChecked()) {
84                ui->description->setText(tr("Send the dive data to dive-share.appspot.com website"));
85        } else if (ui->exportWorldMap->isChecked()) {
86                ui->description->setText(tr("HTML export of the dive locations, visualized on a world map."));
87        } else if (ui->exportSubsurfaceXML->isChecked()) {
88                ui->description->setText(tr("Subsurface native XML format."));
89        } else if (ui->exportImageDepths->isChecked()) {
90                ui->description->setText(tr("Write depths of images to file."));
91        } else if (ui->exportTeX->isChecked()) {
92                ui->description->setText(tr("Write dive as TeX macros to file."));
93        }
94}
95
96void DiveLogExportDialog::exportHtmlInit(const QString &filename)
97{
98        struct htmlExportSetting hes;
99        hes.themeFile = (ui->themeSelection->currentText() == tr("Light")) ? "light.css" : "sand.css";
100        hes.exportPhotos = ui->exportPhotos->isChecked();
101        hes.selectedOnly = ui->exportSelectedDives->isChecked();
102        hes.listOnly = ui->exportListOnly->isChecked();
103        hes.fontFamily = ui->fontSelection->itemData(ui->fontSelection->currentIndex()).toString();
104        hes.fontSize = ui->fontSizeSelection->currentText();
105        hes.themeSelection = ui->themeSelection->currentIndex();
106        hes.subsurfaceNumbers = ui->exportSubsurfaceNumber->isChecked();
107        hes.yearlyStatistics = ui->exportStatistics->isChecked();
108
109        exportHtmlInitLogic(filename, hes);
110}
111
112void DiveLogExportDialog::on_exportGroup_buttonClicked(QAbstractButton *button)
113{
114        Q_UNUSED(button)
115        showExplanation();
116}
117
118void DiveLogExportDialog::on_buttonBox_accepted()
119{
120        QString filename;
121        QString stylesheet;
122        QSettings settings;
123        QString lastDir = QDir::homePath();
124
125        settings.beginGroup("FileDialog");
126        if (settings.contains("LastDir")) {
127                if (QDir::setCurrent(settings.value("LastDir").toString())) {
128                        lastDir = settings.value("LastDir").toString();
129                }
130        }
131        settings.endGroup();
132
133        switch (ui->tabWidget->currentIndex()) {
134        case 0:
135                if (ui->exportUDDF->isChecked()) {
136                        stylesheet = "uddf-export.xslt";
137                        filename = QFileDialog::getSaveFileName(this, tr("Export UDDF file as"), lastDir,
138                                                                tr("UDDF files (*.uddf *.UDDF)"));
139                } else if (ui->exportCSV->isChecked()) {
140                        stylesheet = "xml2csv.xslt";
141                        filename = QFileDialog::getSaveFileName(this, tr("Export CSV file as"), lastDir,
142                                                                tr("CSV files (*.csv *.CSV)"));
143                } else if (ui->exportCSVDetails->isChecked()) {
144                        stylesheet = "xml2manualcsv.xslt";
145                        filename = QFileDialog::getSaveFileName(this, tr("Export CSV file as"), lastDir,
146                                                                tr("CSV files (*.csv *.CSV)"));
147                } else if (ui->exportDivelogs->isChecked()) {
148                        DivelogsDeWebServices::instance()->prepareDivesForUpload(ui->exportSelected->isChecked());
149                } else if (ui->exportDiveshare->isChecked()) {
150                        DiveShareExportDialog::instance()->prepareDivesForUpload(ui->exportSelected->isChecked());
151                } else if (ui->exportWorldMap->isChecked()) {
152                        filename = QFileDialog::getSaveFileName(this, tr("Export world map"), lastDir,
153                                                                tr("HTML files (*.html)"));
154                        if (!filename.isNull() && !filename.isEmpty())
155                                export_worldmap_HTML(filename.toUtf8().data(), ui->exportSelected->isChecked());
156                } else if (ui->exportSubsurfaceXML->isChecked()) {
157                        filename = QFileDialog::getSaveFileName(this, tr("Export Subsurface XML"), lastDir,
158                                                                tr("XML files (*.xml *.ssrf)"));
159                        if (!filename.isNull() && !filename.isEmpty()) {
160                                if (!filename.contains('.'))
161                                        filename.append(".ssrf");
162                                QByteArray bt = QFile::encodeName(filename);
163                                save_dives_logic(bt.data(), ui->exportSelected->isChecked());
164                        }
165                } else if (ui->exportImageDepths->isChecked()) {
166                        filename = QFileDialog::getSaveFileName(this, tr("Save image depths"), lastDir);
167                        if (!filename.isNull() && !filename.isEmpty())
168                                export_depths(filename.toUtf8().data(), ui->exportSelected->isChecked());
169                } else if (ui->exportTeX->isChecked()) {
170                        filename = QFileDialog::getSaveFileName(this, tr("Export to TeX file"), lastDir, tr("TeX files (*.tex)"));
171                        if (!filename.isNull() && !filename.isEmpty())
172                                export_TeX(filename.toUtf8().data(), ui->exportSelected->isChecked());
173                }
174                break;
175        case 1:
176                filename = QFileDialog::getSaveFileName(this, tr("Export HTML files as"), lastDir,
177                                                        tr("HTML files (*.html)"));
178                if (!filename.isNull() && !filename.isEmpty())
179                        exportHtmlInit(filename);
180                break;
181        }
182
183        if (!filename.isNull() && !filename.isEmpty()) {
184                // remember the last export path
185                QFileInfo fileInfo(filename);
186                settings.beginGroup("FileDialog");
187                settings.setValue("LastDir", fileInfo.dir().path());
188                settings.endGroup();
189                // the non XSLT exports are called directly above, the XSLT based ons are called here
190                if (!stylesheet.isEmpty()) {
191                        future = QtConcurrent::run(export_dives_xslt, filename.toUtf8(), ui->exportSelected->isChecked(), ui->CSVUnits_2->currentIndex(), stylesheet.toUtf8());
192                        MainWindow::instance()->getNotificationWidget()->showNotification(tr("Please wait, exporting..."), KMessageWidget::Information);
193                        MainWindow::instance()->getNotificationWidget()->setFuture(future);
194                }
195        }
196}
197
198void DiveLogExportDialog::export_depths(const char *filename, const bool selected_only)
199{
200        FILE *f;
201        struct dive *dive;
202        depth_t depth;
203        int i;
204        const char *unit = NULL;
205
206        struct membuffer buf = {};
207
208        for_each_dive (i, dive) {
209                if (selected_only && !dive->selected)
210                        continue;
211
212                FOR_EACH_PICTURE (dive) {
213                        int n = dive->dc.samples;
214                        struct sample *s = dive->dc.sample;
215                        depth.mm = 0;
216                        while (--n >= 0 && (int32_t)s->time.seconds <= picture->offset.seconds) {
217                                depth.mm = s->depth.mm;
218                                s++;
219                        }
220                        put_format(&buf, "%s\t%.1f", picture->filename, get_depth_units(depth.mm, NULL, &unit));
221                        put_format(&buf, "%s\n", unit);
222                }
223        }
224
225        f = subsurface_fopen(filename, "w+");
226        if (!f) {
227                report_error(tr("Can't open file %s").toUtf8().data(), filename);
228        } else {
229                flush_buffer(&buf, f); /*check for writing errors? */
230                fclose(f);
231        }
232        free_buffer(&buf);
233}
234
235void DiveLogExportDialog::export_TeX(const char *filename, const bool selected_only)
236{
237        FILE *f;
238        struct dive *dive;
239        depth_t depth;
240        int i;
241        const char *unit = NULL;
242        bool need_pagebreak = false;
243
244        struct membuffer buf = {};
245
246        put_format(&buf, "\\input subsurfacetemplate\n");
247        put_format(&buf, "%% This is a plain TeX file. Compile with pdftex, not pdflatex!\n");
248        put_format(&buf, "%% You will also need a subsurfacetemplate.tex in the current directory.\n");
249        put_format(&buf, "%% You can downlaod an example from http://www.atdotde.de/~robert/subsurfacetemplate\n%%\n");
250        for_each_dive (i, dive) {
251                if (selected_only && !dive->selected)
252                        continue;
253
254                QString filename = "profile%1.png";
255                ProfileWidget2 *profile = MainWindow::instance()->graphics();
256                profile->plotDive(dive, true);
257                profile->setToolTipVisibile(false);
258                QPixmap pix = QPixmap::grabWidget(profile);
259                profile->setToolTipVisibile(true);
260                pix.save(filename.arg(dive->number));
261
262
263
264                struct tm tm;
265                utc_mkdate(dive->when, &tm);
266
267                dive_site *site = get_dive_site_by_uuid(dive->dive_site_uuid);;
268
269                pressure_t delta_p = {.mbar = 0};
270
271                QString star = "*";
272                QString viz = star.repeated(dive->visibility);
273                int i;
274
275                for (i = 0; i < MAX_CYLINDERS; i++)
276                        if (is_cylinder_used(dive, i))
277                                delta_p.mbar += dive->cylinder[i].start.mbar - dive->cylinder[i].end.mbar;
278
279                if (need_pagebreak)
280                        put_format(&buf, "\\vfill\\eject\n");
281                need_pagebreak = true;
282                put_format(&buf, "\\def\\date{%04u-%02u-%02u}\n",
283                      tm.tm_year, tm.tm_mon+1, tm.tm_mday);
284                put_format(&buf, "\\def\\number{%d}\n", dive->number);
285                put_format(&buf, "\\def\\place{%s}\n", site->name);
286                put_format(&buf, "\\def\\spot{}\n");
287                put_format(&buf, "\\def\\country{}\n");
288                put_format(&buf, "\\def\\entrance{}\n");
289                put_format(&buf, "\\def\\time{%u:%02u}\n", FRACTION(dive->duration.seconds, 60));
290                put_format(&buf, "\\def\\depth{%u.%01um}\n", FRACTION(dive->maxdepth.mm / 100, 10));
291                put_format(&buf, "\\def\\gasuse{%u.%01ubar}\n", FRACTION(delta_p.mbar / 100, 10));
292                put_format(&buf, "\\def\\sac{%u.%01u l/min}\n", FRACTION(dive->sac/100,10));
293                put_format(&buf, "\\def\\type{%s}\n", dive->tag_list ? dive->tag_list->tag->name : "");
294                put_format(&buf, "\\def\\viz{%s}\n", viz.toUtf8().data());
295                put_format(&buf, "\\def\\plot{\\includegraphics[width=9cm,height=4cm]{profile%d}}\n", dive->number);
296                put_format(&buf, "\\def\\comment{%s}\n", dive->notes);
297                put_format(&buf, "\\def\\buddy{%s}\n", dive->buddy);
298                put_format(&buf, "\\page\n");
299        }
300
301        put_format(&buf, "\\bye\n");
302
303        f = subsurface_fopen(filename, "w+");
304        if (!f) {
305                report_error(tr("Can't open file %s").toUtf8().data(), filename);
306        } else {
307                flush_buffer(&buf, f); /*check for writing errors? */
308                fclose(f);
309        }
310        free_buffer(&buf);
311}
Note: See TracBrowser for help on using the repository browser.