File indexing completed on 2024-04-21 14:49:24

0001 /***************************************************************************
0002     File                 : ProjectImportTest.cpp
0003     Project              : LabPlot
0004     Description          : Tests for project imports
0005     --------------------------------------------------------------------
0006     Copyright            : (C) 2018 Alexander Semke (alexander.semke@web.de)
0007  ***************************************************************************/
0008 
0009 /***************************************************************************
0010  *                                                                         *
0011  *  This program is free software; you can redistribute it and/or modify   *
0012  *  it under the terms of the GNU General Public License as published by   *
0013  *  the Free Software Foundation; either version 2 of the License, or      *
0014  *  (at your option) any later version.                                    *
0015  *                                                                         *
0016  *  This program is distributed in the hope that it will be useful,        *
0017  *  but WITHOUT ANY WARRANTY; without even the implied warranty of         *
0018  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the          *
0019  *  GNU General Public License for more details.                           *
0020  *                                                                         *
0021  *   You should have received a copy of the GNU General Public License     *
0022  *   along with this program; if not, write to the Free Software           *
0023  *   Foundation, Inc., 51 Franklin Street, Fifth Floor,                    *
0024  *   Boston, MA  02110-1301  USA                                           *
0025  *                                                                         *
0026  ***************************************************************************/
0027 
0028 #include "ProjectImportTest.h"
0029 #ifdef HAVE_LIBORIGIN
0030 #include "backend/datasources/projects/OriginProjectParser.h"
0031 #endif
0032 #include "backend/core/Project.h"
0033 #include "backend/core/Workbook.h"
0034 #include "backend/matrix/Matrix.h"
0035 #include "backend/worksheet/Worksheet.h"
0036 #include "backend/worksheet/plots/cartesian/CartesianPlot.h"
0037 #include "backend/spreadsheet/Spreadsheet.h"
0038 
0039 void ProjectImportTest::initTestCase() {
0040     // needed in order to have the signals triggered by SignallingUndoCommand, see LabPlot.cpp
0041     //TODO: redesign/remove this
0042     qRegisterMetaType<const AbstractAspect*>("const AbstractAspect*");
0043     qRegisterMetaType<const AbstractColumn*>("const AbstractColumn*");
0044 }
0045 
0046 //##############################################################################
0047 //#####################  import of LabPlot projects ############################
0048 //##############################################################################
0049 
0050 
0051 #ifdef HAVE_LIBORIGIN
0052 //##############################################################################
0053 //######################  import of Origin projects ############################
0054 //##############################################################################
0055 //project tree of the file "origin8_test_tree_import.opj"
0056 /*
0057 test_tree_import\
0058                     \Book3
0059                     \Folder
0060                         \Book2
0061                             \Sheet1
0062                             \Sheet2
0063                         \MBook2
0064                             \MSheet1
0065                             \MSheet2
0066                     \Folder1
0067                         \MBook1
0068                             \Sheet1
0069                         \Book1
0070                             \Sheet1
0071                         \Book4
0072                             \MSheet1
0073                         \Graph2
0074                     \Excel1
0075 */
0076 
0077 void ProjectImportTest::testOrigin01() {
0078 
0079     //import the opj file into LabPlot's project object
0080     OriginProjectParser parser;
0081     parser.setProjectFileName(QFINDTESTDATA(QLatin1String("data/origin8_test_tree_import.opj")));
0082     Project project;
0083     parser.importTo(&project, QStringList());
0084 
0085     //check the project tree for the imported project
0086 
0087     //first child of the root folder, spreadsheet "Book3"
0088     auto* aspect = project.child<AbstractAspect>(0);
0089     QCOMPARE(aspect != nullptr, true);
0090     if (aspect != nullptr)
0091         QCOMPARE(aspect->name(), QLatin1String("Book3"));
0092     QCOMPARE(dynamic_cast<Spreadsheet*>(aspect) != nullptr, true);
0093 
0094 
0095     //first child of the root folder, folder "Folder" -> import into a Folder
0096     aspect = project.child<AbstractAspect>(1);
0097     QCOMPARE(aspect != nullptr, true);
0098     if (aspect != nullptr)
0099         QCOMPARE(aspect->name(), QLatin1String("Folder"));
0100     QCOMPARE(dynamic_cast<Folder*>(aspect) != nullptr, true);
0101 
0102     //first child of "Folder", workbook "Book2" with two sheets -> import into a Workbook with two Spreadsheets
0103     aspect = project.child<AbstractAspect>(1)->child<AbstractAspect>(0);
0104     QCOMPARE(aspect != nullptr, true);
0105     if (aspect != nullptr)
0106         QCOMPARE(aspect->name(), QLatin1String("Book2"));
0107     QCOMPARE(dynamic_cast<Workbook*>(aspect) != nullptr, true);
0108 
0109     aspect = project.child<AbstractAspect>(1)->child<AbstractAspect>(0)->child<AbstractAspect>(0);
0110     QCOMPARE(aspect != nullptr, true);
0111     if (aspect != nullptr)
0112         QCOMPARE(aspect->name(), QLatin1String("Sheet1"));
0113     QCOMPARE(dynamic_cast<Spreadsheet*>(aspect) != nullptr, true);
0114 
0115     aspect = project.child<AbstractAspect>(1)->child<AbstractAspect>(0)->child<AbstractAspect>(1);
0116     QCOMPARE(aspect != nullptr, true);
0117     if (aspect != nullptr)
0118         QCOMPARE(aspect->name(), QLatin1String("Sheet2"));
0119     QCOMPARE(dynamic_cast<Spreadsheet*>(aspect) != nullptr, true);
0120 
0121     //second child of "Folder", matrixbook "MBook" with two matrix sheets -> import into a Workbook with two Matrices
0122     aspect = project.child<AbstractAspect>(1)->child<AbstractAspect>(1);
0123     QCOMPARE(aspect != nullptr, true);
0124     if (aspect != nullptr)
0125         QCOMPARE(aspect->name(), QLatin1String("MBook2"));
0126     QCOMPARE(dynamic_cast<Workbook*>(aspect) != nullptr, true);
0127 
0128     aspect = project.child<AbstractAspect>(1)->child<AbstractAspect>(1)->child<AbstractAspect>(0);
0129     QCOMPARE(aspect != nullptr, true);
0130     if (aspect != nullptr)
0131         QCOMPARE(aspect->name(), QLatin1String("MSheet1"));
0132     QCOMPARE(dynamic_cast<Matrix*>(aspect) != nullptr, true);
0133 
0134     aspect = project.child<AbstractAspect>(1)->child<AbstractAspect>(1)->child<AbstractAspect>(1);
0135     QCOMPARE(aspect != nullptr, true);
0136     if (aspect != nullptr)
0137         QCOMPARE(aspect->name(), QLatin1String("MSheet2"));
0138     QCOMPARE(dynamic_cast<Matrix*>(aspect) != nullptr, true);
0139 
0140 
0141     //second child of the root folder, folder "Folder1" -> import into a Folder
0142     aspect = project.child<AbstractAspect>(2);
0143     QCOMPARE(aspect != nullptr, true);
0144     if (aspect != nullptr)
0145         QCOMPARE(aspect->name(), QLatin1String("Folder1"));
0146     QCOMPARE(dynamic_cast<Folder*>(aspect) != nullptr, true);
0147 
0148     //first child of "Folder1", matrix "MBook1"
0149     aspect = project.child<AbstractAspect>(2)->child<AbstractAspect>(0);
0150     QCOMPARE(aspect != nullptr, true);
0151     if (aspect != nullptr)
0152         QCOMPARE(aspect->name(), QLatin1String("MBook1"));
0153     QCOMPARE(dynamic_cast<Matrix*>(aspect) != nullptr, true);
0154 
0155     //second child of "Folder1", workbook "Book1" with on sheet -> import into a Spreadsheet
0156     aspect = project.child<AbstractAspect>(2)->child<AbstractAspect>(1);
0157     QCOMPARE(aspect != nullptr, true);
0158     if (aspect != nullptr)
0159         QCOMPARE(aspect->name(), QLatin1String("Book1"));
0160     QCOMPARE(dynamic_cast<Spreadsheet*>(aspect) != nullptr, true);
0161 
0162     //second child of "Folder1", workbook "Book4" with on sheet -> import into a Spreadsheet
0163     aspect = project.child<AbstractAspect>(2)->child<AbstractAspect>(2);
0164     QCOMPARE(aspect != nullptr, true);
0165     if (aspect != nullptr)
0166         QCOMPARE(aspect->name(), QLatin1String("Book4"));
0167     QCOMPARE(dynamic_cast<Spreadsheet*>(aspect) != nullptr, true);
0168 
0169     //third child of "Folder1", graph "Graph"-> import into a Worksheet
0170     aspect = project.child<AbstractAspect>(2)->child<AbstractAspect>(3);
0171     QCOMPARE(aspect != nullptr, true);
0172     if (aspect != nullptr)
0173         QCOMPARE(aspect->name(), QLatin1String("Graph2"));
0174     QCOMPARE(dynamic_cast<Worksheet*>(aspect) != nullptr, true);
0175     //TODO: check the created plot in the worksheet
0176 
0177     // TODO: loose window: spreadsheet "Excel1"
0178     //aspect = project.child<AbstractAspect>(3);
0179     //QCOMPARE(aspect != nullptr, true);
0180     //QCOMPARE(aspect->name(), QLatin1String("Excel1"));
0181     //QCOMPARE(dynamic_cast<Spreadsheet*>(aspect) != nullptr, true);
0182 }
0183 
0184 /*
0185  * import one single folder child
0186  */
0187 void ProjectImportTest::testOrigin02() {
0188     //import one single object
0189     OriginProjectParser parser;
0190     parser.setProjectFileName(QFINDTESTDATA(QLatin1String("data/origin8_test_tree_import.opj")));
0191     Project project;
0192     QStringList selectedPathes = {QLatin1String("test_tree_import/Folder1/Book1"), QLatin1String("test_tree_import/Folder1"), QLatin1String("test_tree_import")};
0193     parser.importTo(&project, selectedPathes);
0194 
0195     //check the project tree for the imported project
0196 
0197     //first child of the root folder, folder "Folder1" -> import into a Folder
0198     auto* aspect = project.child<AbstractAspect>(0);
0199     QCOMPARE(aspect != nullptr, true);
0200     if (aspect != nullptr)
0201         QCOMPARE(aspect->name(), QLatin1String("Folder1"));
0202     QCOMPARE(dynamic_cast<Folder*>(aspect) != nullptr, true);
0203     if (aspect != nullptr)
0204         QCOMPARE(aspect->childCount<AbstractAspect>(), 1);
0205 
0206     //first child of "Folder", workbook "Book" with one sheet -> import into a Spreadsheet
0207     aspect = project.child<AbstractAspect>(0)->child<AbstractAspect>(0);
0208     QCOMPARE(aspect != nullptr, true);
0209     if (aspect != nullptr)
0210         QCOMPARE(aspect->name(), QLatin1String("Book1"));
0211     QCOMPARE(dynamic_cast<Spreadsheet*>(aspect) != nullptr, true);
0212 }
0213 
0214 /*
0215  * 1. import one single folder child
0216  * 2. import another folder child
0217  * 3. check that both children are available after the second import
0218  */
0219 void ProjectImportTest::testOrigin03() {
0220     //import one single object
0221     OriginProjectParser parser;
0222     parser.setProjectFileName(QFINDTESTDATA(QLatin1String("data/origin8_test_tree_import.opj")));
0223     Project project;
0224 
0225     //import one single child in "Folder1"
0226     QStringList selectedPathes = {QLatin1String("test_tree_import/Folder1/Book1"), QLatin1String("test_tree_import/Folder1"), QLatin1String("test_tree_import")};
0227     parser.importTo(&project, selectedPathes);
0228 
0229     //first child of the root folder, folder "Folder1" -> import into a Folder
0230     auto* aspect = project.child<AbstractAspect>(0);
0231     QCOMPARE(aspect != nullptr, true);
0232     if (aspect != nullptr)
0233         QCOMPARE(aspect->name(), QLatin1String("Folder1"));
0234     QCOMPARE(dynamic_cast<Folder*>(aspect) != nullptr, true);
0235     if (aspect != nullptr)
0236         QCOMPARE(aspect->childCount<AbstractAspect>(), 1);
0237 
0238     //first child of "Folder", workbook "Book1" with one sheet -> import into a Spreadsheet
0239     aspect = project.child<AbstractAspect>(0)->child<AbstractAspect>(0);
0240     QCOMPARE(aspect != nullptr, true);
0241     if (aspect != nullptr)
0242         QCOMPARE(aspect->name(), QLatin1String("Book1"));
0243     QCOMPARE(dynamic_cast<Spreadsheet*>(aspect) != nullptr, true);
0244 
0245 
0246     //import another child in "Folder1"
0247     selectedPathes.clear();
0248     selectedPathes << QLatin1String("test_tree_import/Folder1/Book4") << QLatin1String("test_tree_import/Folder1") << QLatin1String("test_tree_import");
0249     parser.importTo(&project, selectedPathes);
0250 
0251     //the first child should still be available in the project -> check it
0252     aspect = project.child<AbstractAspect>(0);
0253     QCOMPARE(aspect != nullptr, true);
0254     if (aspect != nullptr)
0255         QCOMPARE(aspect->name(), QLatin1String("Folder1"));
0256     QCOMPARE(dynamic_cast<Folder*>(aspect) != nullptr, true);
0257 
0258     aspect = project.child<AbstractAspect>(0)->child<AbstractAspect>(0);
0259     QCOMPARE(aspect != nullptr, true);
0260     if (aspect != nullptr)
0261         QCOMPARE(aspect->name(), QLatin1String("Book1"));
0262     QCOMPARE(dynamic_cast<Spreadsheet*>(aspect) != nullptr, true);
0263 
0264     //check the second child, workbook "Book4" with one sheet -> import into a Spreadsheet
0265     aspect = project.child<AbstractAspect>(0)->child<AbstractAspect>(1);
0266     QCOMPARE(aspect != nullptr, true);
0267     if (aspect != nullptr)
0268         QCOMPARE(aspect->name(), QLatin1String("Book4"));
0269     QCOMPARE(dynamic_cast<Spreadsheet*>(aspect) != nullptr, true);
0270 
0271     if (aspect != nullptr)
0272         QCOMPARE(aspect->childCount<AbstractAspect>(), 2);
0273 }
0274 
0275 /*
0276  * 1. import a spreadsheet
0277  * 2. modify a cell in it
0278  * 3. import the same spreadsheet once more
0279  * 4. check that the changes were really over-written
0280  */
0281 void ProjectImportTest::testOrigin04() {
0282     OriginProjectParser parser;
0283     parser.setProjectFileName(QFINDTESTDATA(QLatin1String("data/origin8_test_tree_import.opj")));
0284     Project project;
0285 
0286     //import "Book1"
0287     QStringList selectedPathes = {QLatin1String("test_tree_import/Folder1/Book1"), QLatin1String("test_tree_import/Folder1"), QLatin1String("test_tree_import")};
0288     parser.importTo(&project, selectedPathes);
0289 
0290     //first child of folder "Folder1", workbook "Book1" with one sheet -> import into a spreadsheet
0291     auto* aspect = project.child<AbstractAspect>(0);
0292     QCOMPARE(aspect != nullptr, true);
0293     if (aspect != nullptr)
0294         QCOMPARE(aspect->name(), QLatin1String("Folder1"));
0295     aspect = project.child<AbstractAspect>(0)->child<AbstractAspect>(0);
0296     QCOMPARE(aspect != nullptr, true);
0297     if (aspect != nullptr)
0298         QCOMPARE(aspect->name(), QLatin1String("Book1"));
0299     auto* spreadsheet = dynamic_cast<Spreadsheet*>(aspect);
0300     QCOMPARE(spreadsheet != nullptr, true);
0301 
0302     //the (0,0)-cell has the value 1.0
0303     if (spreadsheet != nullptr) {
0304         QCOMPARE(spreadsheet->column(0)->valueAt(0), 1.0);
0305 
0306         //set the value to 5.0
0307         spreadsheet->column(0)->setValueAt(0, 5.0);
0308         QCOMPARE(spreadsheet->column(0)->valueAt(0), 5.0);
0309     }
0310 
0311     //re-import
0312     parser.importTo(&project, selectedPathes);
0313 
0314     //check the folder structure and the value of the (0,0)-cell again
0315     aspect = project.child<AbstractAspect>(0)->child<AbstractAspect>(0);
0316     QCOMPARE(aspect != nullptr, true);
0317     if (aspect != nullptr)
0318         QCOMPARE(aspect->name(), QLatin1String("Book1"));
0319     spreadsheet = dynamic_cast<Spreadsheet*>(aspect);
0320     QCOMPARE(spreadsheet != nullptr, true);
0321     if (spreadsheet != nullptr)
0322         QCOMPARE(spreadsheet->column(0)->valueAt(0), 1.0);
0323 }
0324 
0325 void ProjectImportTest::testOriginTextNumericColumns() {
0326     OriginProjectParser parser;
0327     parser.setProjectFileName(QFINDTESTDATA(QLatin1String("data/origin8_test_workbook.opj")));
0328     Project project;
0329 
0330     //import "Book1"
0331     QStringList selectedPathes = {QLatin1String("origin8_test_workbook/Folder1/Book1"), QLatin1String("origin8_test_workbook/Folder1"), QLatin1String("origin8_test_workbook")};
0332     parser.importTo(&project, selectedPathes);
0333 
0334     //first child of folder "Folder1", workbook "Book1" with one sheet -> import into a spreadsheet
0335     auto* aspect = project.child<AbstractAspect>(0);
0336     QCOMPARE(aspect != nullptr, true);
0337     if (aspect != nullptr)
0338         QCOMPARE(aspect->name(), QLatin1String("Folder1"));
0339     aspect = project.child<AbstractAspect>(0)->child<AbstractAspect>(0);
0340     QCOMPARE(aspect != nullptr, true);
0341     if (aspect != nullptr)
0342         QCOMPARE(aspect->name(), QLatin1String("Book1"));
0343     auto* spreadsheet = dynamic_cast<Spreadsheet*>(aspect);
0344     QCOMPARE(spreadsheet != nullptr, true);
0345 
0346     //additional pointer check for static code analysis tools like Coverity that are not aware of QCOMPARE above
0347     if (!spreadsheet)
0348         return;
0349 
0350     //check the values in the imported columns
0351     QCOMPARE(spreadsheet->columnCount(), 6);
0352 
0353     //1st column, Origin::TextNumeric:
0354     //first non-empty value is numerical, column is set to Numeric, empty or text values in the column a set to NAN
0355     Column* column = spreadsheet->column(0);
0356     QCOMPARE(column->columnMode(), AbstractColumn::ColumnMode::Numeric);
0357     QCOMPARE(!std::isnan(column->valueAt(0)), false);
0358     QCOMPARE(column->valueAt(1), 1.1);
0359     QCOMPARE(column->valueAt(2), 2.2);
0360     QCOMPARE(!std::isnan(column->valueAt(3)), false);
0361     QCOMPARE(!std::isnan(column->valueAt(4)), false);
0362 
0363     //2nd column, Origin::TextNumeric:
0364     //first non-empty value is string, the column is set to Text, numerical values are converted to strings
0365     column = spreadsheet->column(1);
0366     QCOMPARE(column->columnMode(), AbstractColumn::ColumnMode::Text);
0367     QCOMPARE(column->textAt(0).isEmpty(), true);
0368     QCOMPARE(column->textAt(1), QLatin1String("a"));
0369     QCOMPARE(column->textAt(2), QLatin1String("b"));
0370     QCOMPARE(column->textAt(3), QLatin1String("1.1"));
0371     QCOMPARE(column->textAt(4), QLatin1String("2.2"));
0372 
0373     //3rd column, Origin::TextNumeric:
0374     //first is numerical, column is set to Numeric, empty or text values in the column a set to NAN
0375     column = spreadsheet->column(2);
0376     QCOMPARE(column->columnMode(), AbstractColumn::ColumnMode::Numeric);
0377     QCOMPARE(column->valueAt(0), 1.1);
0378     QCOMPARE(column->valueAt(1), 2.2);
0379     QCOMPARE(!std::isnan(column->valueAt(2)), false);
0380     QCOMPARE(!std::isnan(column->valueAt(3)), false);
0381     QCOMPARE(column->valueAt(4), 3.3);
0382 
0383     //4th column, Origin::TextNumeric:
0384     //first value is string, the column is set to Text, numerical values are converted to strings
0385     column = spreadsheet->column(3);
0386     QCOMPARE(column->columnMode(), AbstractColumn::ColumnMode::Text);
0387     QCOMPARE(column->textAt(0), QLatin1String("a"));
0388     QCOMPARE(column->textAt(1), QLatin1String("b"));
0389     QCOMPARE(column->textAt(2), QLatin1String("1.1"));
0390     QCOMPARE(column->textAt(3), QLatin1String("2.2"));
0391     QCOMPARE(column->textAt(4), QLatin1String("c"));
0392 
0393     //5th column, Origin::Numeric
0394     //column is set to Numeric, empty values in the column a set to NAN
0395     column = spreadsheet->column(4);
0396     QCOMPARE(column->columnMode(), AbstractColumn::ColumnMode::Numeric);
0397     QCOMPARE(!std::isnan(column->valueAt(0)), false);
0398     QCOMPARE(column->valueAt(1), 1.1);
0399     QCOMPARE(column->valueAt(2), 2.2);
0400     QCOMPARE(column->valueAt(3), 3.3);
0401     QCOMPARE(!std::isnan(column->valueAt(4)), false);
0402 
0403     //6th column, Origin::Numeric
0404     //column is set to Numeric, empty values in the column a set to NAN
0405     column = spreadsheet->column(5);
0406     QCOMPARE(column->columnMode(), AbstractColumn::ColumnMode::Numeric);
0407     QCOMPARE(column->valueAt(0), 1.1);
0408     QCOMPARE(column->valueAt(1), 2.2);
0409     QCOMPARE(column->valueAt(2), 3.3);
0410     QCOMPARE(!std::isnan(column->valueAt(3)), false);
0411     QCOMPARE(!std::isnan(column->valueAt(4)), false);
0412 }
0413 
0414 void ProjectImportTest::testParseOriginTags_data() {
0415     QTest::addColumn<QString>("originTag");
0416     QTest::addColumn<QString>("labPlotHTML");
0417 
0418     QTest::newRow("bold") << "\\b(bold)" << "<b>bold</b>";
0419 
0420     QTest::newRow("italic") << "\\i(italic)" << "<i>italic</i>";
0421 
0422     QTest::newRow("strike through") << "\\s(strike through)" << "<s>strike through</s>";
0423 
0424     QTest::newRow("underlined") << "\\u(underlined)" << "<u>underlined</u>";
0425 
0426     QTest::newRow("greek char") << "\\g(a)" << "<font face=Symbol>a</font>";
0427 
0428     QTest::newRow("sub-script") << "a\\-(b)" << "a<sub>b</sub>";
0429 
0430     QTest::newRow("super-script") << "a\\+(b)" << "a<sup>b</sup>";
0431 
0432     QTest::newRow("set-font") << "\\f:dejavu sans(text)" << "<font face=\"dejavu sans\">text</font>";
0433 
0434     QTest::newRow("font-size")  << "some \\p200(big) text"
0435                                 << "some <span style=\"font-size: 200%\">big</span> text";
0436 
0437     QTest::newRow("color")  << "some \\c15(colored) text"
0438                             << "some <span style=\"color: #8000ff\">colored</span> text";
0439 
0440     QTest::newRow("nested-non-tag-parenthesis")
0441             << "\\b(text (c) and (fh) and a(t) and empty ())"
0442             << "<b>text (c) and (fh) and a(t) and empty ()</b>";
0443 
0444     QTest::newRow("nested-tags")
0445             << "\\b(bold text with some \\i(italic) bits and some \\c15(color)) "
0446                "then a change of \\f:dejavu sans(font)"
0447             << "<b>bold text with some <i>italic</i> bits and some "
0448                "<span style=\"color: #8000ff\">color</span></b> "
0449                "then a change of <font face=\"dejavu sans\">font</font>";
0450 
0451     QTest::newRow("nested-tags-with-extra-spaces")
0452             << "\\ b (bold text with some \\ i(italic) bits and some \\c 15 (color)) "
0453                "then a change of \\ f:dejavu sans( font)"
0454             << "<b>bold text with some <i>italic</i> bits and some "
0455                "<span style=\"color: #8000ff\">color</span></b> "
0456                "then a change of <font face=\"dejavu sans\"> font</font>";
0457 }
0458 
0459 void ProjectImportTest::testParseOriginTags() {
0460     QFETCH(QString, originTag);
0461     QFETCH(QString, labPlotHTML);
0462 
0463     OriginProjectParser parser;
0464     QCOMPARE(parser.parseOriginTags(originTag), labPlotHTML);
0465 }
0466 
0467 #endif
0468 
0469 QTEST_MAIN(ProjectImportTest)