diff options
author | Dirk Hohndel <dirk@hohndel.org> | 2013-12-09 17:22:33 +0100 |
---|---|---|
committer | Dirk Hohndel <dirk@hohndel.org> | 2013-12-09 17:22:33 +0100 |
commit | 8ac58181f75e494a242126751646285d4db672bc (patch) | |
tree | 10ec814fc20f3ce53a46b1df767eff56422e64b7 /qt-ui | |
parent | 4675ab0617ed4536ad0196c7a09035b9c586dff7 (diff) | |
parent | 04b62a46e9f28f0e3b4a4f2e3c3aa9c18445df2f (diff) | |
download | subsurface-8ac58181f75e494a242126751646285d4db672bc.tar.gz |
Merge branch 'web' of github.com:neolit123/subsurface
Diffstat (limited to 'qt-ui')
-rw-r--r-- | qt-ui/divelistview.cpp | 8 | ||||
-rw-r--r-- | qt-ui/divelistview.h | 1 | ||||
-rw-r--r-- | qt-ui/subsurfacewebservices.cpp | 194 | ||||
-rw-r--r-- | qt-ui/subsurfacewebservices.h | 3 |
4 files changed, 186 insertions, 20 deletions
diff --git a/qt-ui/divelistview.cpp b/qt-ui/divelistview.cpp index a1c4cf7fc..06b691c17 100644 --- a/qt-ui/divelistview.cpp +++ b/qt-ui/divelistview.cpp @@ -8,6 +8,7 @@ #include "models.h" #include "modeldelegates.h" #include "mainwindow.h" +#include "subsurfacewebservices.h" #include "../display.h" #include <QApplication> #include <QHeaderView> @@ -726,6 +727,8 @@ void DiveListView::contextMenuEvent(QContextMenuEvent *event) popup.addAction(tr("export As UDDF"), this, SLOT(exportSelectedDivesAsUDDF())); popup.addAction(tr("shift times"), this, SLOT(shiftTimes())); } + if (d) + popup.addAction(tr("upload dive(s) to divelogs.de"), this, SLOT(uploadToDivelogsDE())); // "collapse all" really closes all trips, // "collapse" keeps the trip with the selected dive open QAction * actionTaken = popup.exec(event->globalPos()); @@ -781,3 +784,8 @@ void DiveListView::shiftTimes() { ShiftTimesDialog::instance()->show(); } + +void DiveListView::uploadToDivelogsDE() +{ + DivelogsDeWebServices::instance()->prepareDivesForUpload(); +} diff --git a/qt-ui/divelistview.h b/qt-ui/divelistview.h index c20b6e822..f65a6780b 100644 --- a/qt-ui/divelistview.h +++ b/qt-ui/divelistview.h @@ -49,6 +49,7 @@ public slots: void saveSelectedDivesAs(); void exportSelectedDivesAsUDDF(); void shiftTimes(); + void uploadToDivelogsDE(); signals: void currentDiveChanged(int divenr); diff --git a/qt-ui/subsurfacewebservices.cpp b/qt-ui/subsurfacewebservices.cpp index 193f7c41b..a336a4864 100644 --- a/qt-ui/subsurfacewebservices.cpp +++ b/qt-ui/subsurfacewebservices.cpp @@ -1,7 +1,6 @@ #include "subsurfacewebservices.h" #include "../webservice.h" #include "mainwindow.h" - #include <libxml/parser.h> #include <zip.h> #include <errno.h> @@ -99,6 +98,97 @@ static void clear_table(struct dive_table *table) table->nr = 0; } +static char *prepare_dives_for_divelogs(const bool selected) +{ + int i; + struct dive *dive; + FILE *f; + char filename[PATH_MAX], *tempfile; + size_t streamsize; + char *membuf; + xmlDoc *doc; + xsltStylesheetPtr xslt = NULL; + xmlDoc *transformed; + struct zip_source *s[dive_table.nr]; + struct zip *zip; + char *error = NULL; + + /* generate a random filename and create/open that file with zip_open */ + QString tempfileQ = QDir::tempPath() + "/import-" + QString::number(qrand() % 99999999) + ".dld"; + tempfile = tempfileQ.toLocal8Bit().data(); + zip = zip_open(tempfile, ZIP_CREATE, NULL); + + if (!zip) { + fprintf(stderr, "divelog.de-upload: cannot open file as zip\n"); + return NULL; + } + if (!amount_selected) { + fprintf(stderr, "divelog.de-upload: no dives selected\n"); + return NULL; + } + + /* walk the dive list in chronological order */ + for (i = 0; i < dive_table.nr; i++) { + dive = get_dive(i); + if (!dive) + continue; + if (selected && !dive->selected) + continue; + f = tmpfile(); + if (!f) { + fprintf(stderr, "divelog.de-upload: cannot create temp file\n"); + return NULL; + } + save_dive(f, dive); + fseek(f, 0, SEEK_END); + streamsize = ftell(f); + rewind(f); + membuf = (char *)malloc(streamsize + 1); + if (!membuf || !fread(membuf, streamsize, 1, f)) { + fprintf(stderr, "divelog.de-upload: memory error\n"); + return NULL; + } + membuf[streamsize] = 0; + fclose(f); + /* + * Parse the memory buffer into XML document and + * transform it to divelogs.de format, finally dumping + * the XML into a character buffer. + */ + doc = xmlReadMemory(membuf, strlen(membuf), "divelog", NULL, 0); + if (!doc) { + fprintf(stderr, "divelog.de-upload: xml error\n"); + continue; + } + free((void *)membuf); + // this call is overriding our local variable tempfile! not a good sign! + xslt = get_stylesheet("divelogs-export.xslt"); + if (!xslt) { + fprintf(stderr, "divelog.de-upload: missing stylesheet\n"); + return NULL; + } + transformed = xsltApplyStylesheet(xslt, doc, NULL); + xsltFreeStylesheet(xslt); + xmlDocDumpMemory(transformed, (xmlChar **) &membuf, (int *)&streamsize); + xmlFreeDoc(doc); + xmlFreeDoc(transformed); + /* + * Save the XML document into a zip file. + */ + snprintf(filename, PATH_MAX, "%d.xml", i + 1); + s[i] = zip_source_buffer(zip, membuf, streamsize, 1); + if (s[i]) { + int64_t ret = zip_add(zip, filename, s[i]); + if (ret == -1) + fprintf(stderr, "divelog.de-upload: failed to include dive %d\n", i); + } + } + zip_close(zip); + /* let's call this again */ + tempfile = tempfileQ.toLocal8Bit().data(); + return tempfile; +} + WebServices::WebServices(QWidget* parent, Qt::WindowFlags f): QDialog(parent, f) , reply(0) { @@ -237,9 +327,11 @@ void SubsurfaceWebServices::buttonClicked(QAbstractButton* button) } break; case QDialogButtonBox::RejectRole: - // we may want to clean up after ourselves - // reply->deleteLater(); - reply = NULL; + if (reply != NULL && reply->isOpen()) { + reply->abort(); + delete reply; + reply = NULL; + } resetState(); break; case QDialogButtonBox::HelpRole: @@ -447,20 +539,47 @@ void DivelogsDeWebServices::downloadDives() exec(); } +void DivelogsDeWebServices::prepareDivesForUpload() +{ + QString errorText(tr("Cannot create DLD file")); + char *filename = prepare_dives_for_divelogs(true); + if (filename) { + QFile f(filename); + if (f.exists()) { + f.open(QIODevice::ReadOnly); + uploadDives((QIODevice *)&f); + f.close(); + f.remove(); + return; + } + mainWindow()->showError(errorText.append(": ").append(filename)); + return; + } + mainWindow()->showError(errorText.append("!")); +} + void DivelogsDeWebServices::uploadDives(QIODevice *dldContent) { QHttpMultiPart mp(QHttpMultiPart::FormDataType); QHttpPart part; - part.setRawHeader("Content-Disposition", "form-data; name=\"userfile\""); + QFile *f = (QFile *)dldContent; + QFileInfo fi(*f); + QString args("form-data; name=\"userfile\"; filename=\"" + fi.absoluteFilePath() + "\""); + part.setRawHeader("Content-Disposition", args.toLatin1()); part.setBodyDevice(dldContent); mp.append(part); multipart = ∓ hideDownload(); + resetState(); exec(); - multipart = NULL; - delete reply; // we need to ensure it has stopped using our QHttpMultiPart + multipart = NULL; + if (reply != NULL && reply->isOpen()) { + reply->abort(); + delete reply; + reply = NULL; + } } DivelogsDeWebServices::DivelogsDeWebServices(QWidget* parent, Qt::WindowFlags f): WebServices(parent, f) @@ -473,6 +592,11 @@ DivelogsDeWebServices::DivelogsDeWebServices(QWidget* parent, Qt::WindowFlags f) void DivelogsDeWebServices::startUpload() { + QSettings s; + s.setValue("divelogde_user", ui.userID->text()); + s.setValue("divelogde_pass", ui.password->text()); + s.sync(); + ui.status->setText(tr("Uploading dive list...")); ui.progressBar->setRange(0,0); // this makes the progressbar do an 'infinite spin' ui.upload->setEnabled(false); @@ -638,8 +762,25 @@ void DivelogsDeWebServices::uploadFinished() // check what the server sent us: it might contain // an error condition, such as a failed login QByteArray xmlData = reply->readAll(); - - // ### FIXME: what's the format? + reply->deleteLater(); + reply = NULL; + char *resp = xmlData.data(); + if (resp) { + char *parsed = strstr(resp, "<Login>"); + if (parsed) { + if (strstr(resp, "<Login>succeeded</Login>")) { + if (strstr(resp, "<FileCopy>failed</FileCopy>")) { + ui.status->setText(tr("Upload failed")); + return; + } + ui.status->setText(tr("Upload successful")); + return; + } + ui.status->setText(tr("Login failed")); + return; + } + ui.status->setText(tr("Cannot parse response")); + } } void DivelogsDeWebServices::setStatusText(int status) @@ -650,7 +791,7 @@ void DivelogsDeWebServices::setStatusText(int status) void DivelogsDeWebServices::downloadError(QNetworkReply::NetworkError) { resetState(); - ui.status->setText(tr("Download error: %1").arg(reply->errorString())); + ui.status->setText(tr("Error: %1").arg(reply->errorString())); reply->deleteLater(); reply = NULL; } @@ -663,22 +804,37 @@ void DivelogsDeWebServices::uploadError(QNetworkReply::NetworkError error) void DivelogsDeWebServices::buttonClicked(QAbstractButton* button) { ui.buttonBox->button(QDialogButtonBox::Apply)->setEnabled(false); - switch(ui.buttonBox->buttonRole(button)){ case QDialogButtonBox::ApplyRole:{ - char *errorptr = NULL; - parse_file(zipFile.fileName().toUtf8().constData(), &errorptr); + /* parse file and import dives */ + char *error = NULL; + parse_file(zipFile.fileName().toLocal8Bit().data(), &error); + if (error != NULL) { + mainWindow()->showError(error); + free(error); + } process_dives(TRUE, FALSE); - // ### FIXME: do something useful with the error - but there shouldn't be one, right? - if (errorptr) - qDebug() << errorptr; + mainWindow()->refreshDisplay(); + /* store last entered user/pass in config */ + QSettings s; + s.setValue("divelogde_user", ui.userID->text()); + s.setValue("divelogde_pass", ui.password->text()); + s.sync(); hide(); close(); resetState(); - mark_divelist_changed(TRUE); - mainWindow()->refreshDisplay(); } + break; + case QDialogButtonBox::RejectRole: + // these two seem to be causing a crash: + // reply->deleteLater(); + resetState(); + break; + case QDialogButtonBox::HelpRole: + QDesktopServices::openUrl(QUrl("http://divelogs.de")); + break; + default: + break; } } - diff --git a/qt-ui/subsurfacewebservices.h b/qt-ui/subsurfacewebservices.h index 3c41b08d1..07f902b8f 100644 --- a/qt-ui/subsurfacewebservices.h +++ b/qt-ui/subsurfacewebservices.h @@ -66,7 +66,7 @@ class DivelogsDeWebServices : public WebServices { public: static DivelogsDeWebServices * instance(); void downloadDives(); - void uploadDives(QIODevice *dldContent); + void prepareDivesForUpload(); private slots: void startDownload(); @@ -79,6 +79,7 @@ private slots: void uploadError(QNetworkReply::NetworkError error); void startUpload(); private: + void uploadDives(QIODevice *dldContent); explicit DivelogsDeWebServices (QWidget* parent = 0, Qt::WindowFlags f = 0); void setStatusText(int status); void download_dialog_traverse_xml(xmlNodePtr node, unsigned int *download_status); |