diff options
-rw-r--r-- | dive.h | 2 | ||||
-rw-r--r-- | parse-xml.c | 71 | ||||
-rw-r--r-- | qt-ui/mainwindow.cpp | 19 | ||||
-rw-r--r-- | qt-ui/mainwindow.h | 1 |
4 files changed, 68 insertions, 25 deletions
@@ -49,6 +49,8 @@ extern "C" { #endif extern int last_xml_version; +extern bool abort_read_of_old_file; +extern bool v2_question_shown; enum dive_comp_type {OC, CCR, PSCR, FREEDIVE, NUM_DC_TYPE}; // Flags (Open-circuit and Closed-circuit-rebreather) for setting dive computer type enum cylinderuse {OC_GAS, DILUENT, OXYGEN, NUM_GAS_USE}; // The different uses for cylinders diff --git a/parse-xml.c b/parse-xml.c index 2e7882ece..90559d6c4 100644 --- a/parse-xml.c +++ b/parse-xml.c @@ -22,6 +22,8 @@ int verbose, quit; int metric = 1; int last_xml_version = -1; +bool abort_read_of_old_file = false; +bool v2_question_shown = false; static xmlDoc *test_xslt_transforms(xmlDoc *doc, const char **params); @@ -1669,44 +1671,54 @@ static void userid_stop(void) in_userid = false; } -static void entry(const char *name, char *buf) +static bool entry(const char *name, char *buf) { if (!strncmp(name, "version.program", sizeof("version.program") - 1) || - !strncmp(name, "version.divelog", sizeof("version.divelog") - 1)) + !strncmp(name, "version.divelog", sizeof("version.divelog") - 1)) { last_xml_version = atoi(buf); + if (last_xml_version < 3 && !v2_question_shown) { + // let's ask the user what they want to do about reverse geo coding + // and warn them that opening older XML files can take a while + // since C code shouldn't call the UI we set a global flag and bail + // from reading the file for now + abort_read_of_old_file = true; + return false; + } + } if (in_userid) { try_to_fill_userid(name, buf); - return; + return true; } if (in_settings) { try_to_fill_dc_settings(name, buf); try_to_match_autogroup(name, buf); - return; + return true; } if (cur_dive_site) { try_to_fill_dive_site(&cur_dive_site, name, buf); - return; + return true; } if (!cur_event.deleted) { try_to_fill_event(name, buf); - return; + return true; } if (cur_sample) { try_to_fill_sample(cur_sample, name, buf); - return; + return true; } if (cur_dc) { try_to_fill_dc(cur_dc, name, buf); - return; + return true; } if (cur_dive) { try_to_fill_dive(cur_dive, name, buf); - return; + return true; } if (cur_trip) { try_to_fill_trip(&cur_trip, name, buf); - return; + return true; } + return true; } static const char *nodename(xmlNode *node, char *buf, int len) @@ -1748,7 +1760,7 @@ static const char *nodename(xmlNode *node, char *buf, int len) #define MAXNAME 32 -static void visit_one_node(xmlNode *node) +static bool visit_one_node(xmlNode *node) { char *content; static char buffer[MAXNAME]; @@ -1756,28 +1768,29 @@ static void visit_one_node(xmlNode *node) content = node->content; if (!content || xmlIsBlankNode(node)) - return; + return true; name = nodename(node, buffer, sizeof(buffer)); - entry(name, content); + return entry(name, content); } -static void traverse(xmlNode *root); +static bool traverse(xmlNode *root); -static void traverse_properties(xmlNode *node) +static bool traverse_properties(xmlNode *node) { xmlAttr *p; + bool ret = true; for (p = node->properties; p; p = p->next) - traverse(p->children); + if ((ret = traverse(p->children)) == false) + break; + return ret; } -static void visit(xmlNode *n) +static bool visit(xmlNode *n) { - visit_one_node(n); - traverse_properties(n); - traverse(n->children); + return visit_one_node(n) && traverse_properties(n) && traverse(n->children); } static void DivingLog_importer(void) @@ -1840,15 +1853,17 @@ static struct nesting { { NULL, } }; -static void traverse(xmlNode *root) +static bool traverse(xmlNode *root) { xmlNode *n; + bool ret = true; for (n = root; n; n = n->next) { struct nesting *rule = nesting; if (!n->name) { - visit(n); + if ((ret = visit(n)) == false) + break; continue; } @@ -1860,10 +1875,12 @@ static void traverse(xmlNode *root) if (rule->start) rule->start(); - visit(n); + if ((ret = visit(n)) == false) + break; if (rule->end) rule->end(); } + return ret; } /* Per-file reset */ @@ -1910,6 +1927,7 @@ int parse_xml_buffer(const char *url, const char *buffer, int size, { xmlDoc *doc; const char *res = preprocess_divelog_de(buffer); + int ret = 0; target_table = table; doc = xmlReadMemory(res, strlen(res), url, NULL, 0); @@ -1924,11 +1942,14 @@ int parse_xml_buffer(const char *url, const char *buffer, int size, reset_all(); dive_start(); doc = test_xslt_transforms(doc, params); - traverse(xmlDocGetRootElement(doc)); + if (!traverse(xmlDocGetRootElement(doc))) { + // we decided to give up on parsing... why? + ret = -1; + } dive_end(); xmlFreeDoc(doc); - return 0; + return ret; } void parse_mkvi_buffer(struct membuffer *txt, struct membuffer *csv, const char *starttime) diff --git a/qt-ui/mainwindow.cpp b/qt-ui/mainwindow.cpp index 648ead174..7b204626c 100644 --- a/qt-ui/mainwindow.cpp +++ b/qt-ui/mainwindow.cpp @@ -1345,6 +1345,18 @@ void MainWindow::importTxtFiles(const QStringList fileNames) refreshDisplay(); } +void MainWindow::showV2Dialog() +{ + // here we need to ask the user if / how they want to do the reverse geo coding + // for now this is just a warning that things could take a long time + QMessageBox d(QMessageBox::Information, + tr("Welcom to Subsurface %1").arg(subsurface_version()), + tr("Importing data files from earlier versions of Subsurface can take a significant amount of time"), + QMessageBox::Ok, + this); + d.exec(); +} + void MainWindow::loadFiles(const QStringList fileNames) { if (fileNames.isEmpty()) @@ -1362,6 +1374,13 @@ void MainWindow::loadFiles(const QStringList fileNames) set_filename(fileNamePtr.data(), true); setTitle(MWTF_FILENAME); } else { + if (!v2_question_shown && abort_read_of_old_file) { + v2_question_shown = true; + abort_read_of_old_file = false; + showV2Dialog(); + i--; // so we re-try this file + continue; + } failedParses.append(fileNames.at(i)); } } diff --git a/qt-ui/mainwindow.h b/qt-ui/mainwindow.h index 85a63123b..5f4567f76 100644 --- a/qt-ui/mainwindow.h +++ b/qt-ui/mainwindow.h @@ -90,6 +90,7 @@ public: void printPlan(); void checkSurvey(QSettings *s); void setApplicationState(const QByteArray& state); + void showV2Dialog(); QUndoStack *undoStack; private slots: |