From 987ca2dcdc08cd394af6449a76d92ac46181a01a Mon Sep 17 00:00:00 2001 From: Debao Zhang Date: Thu, 24 Oct 2013 14:56:38 +0800 Subject: [PATCH] Code refactor for Worksheet::writeHyperlink() --- src/xlsx/xlsxworksheet.cpp | 87 +++++++++++--------------- src/xlsx/xlsxworksheet.h | 2 +- src/xlsx/xlsxworksheet_p.h | 11 +++- tests/auto/worksheet/tst_worksheet.cpp | 25 ++++++++ 4 files changed, 71 insertions(+), 54 deletions(-) diff --git a/src/xlsx/xlsxworksheet.cpp b/src/xlsx/xlsxworksheet.cpp index 43d3472..fd3f6c4 100755 --- a/src/xlsx/xlsxworksheet.cpp +++ b/src/xlsx/xlsxworksheet.cpp @@ -306,16 +306,14 @@ int Worksheet::write(int row, int column, const QVariant &value, Format *format) ret = writeNumeric(row, column, value.toDouble(), format); } } else if (value.type() == QMetaType::QUrl) { //url - ret = writeUrl(row, column, value.toUrl(), format); + ret = writeHyperlink(row, column, value.toUrl(), format); } else if (value.type() == QMetaType::QString) { //string QString token = value.toString(); - QRegularExpression urlPattern(QStringLiteral("^([fh]tt?ps?://)|(mailto:)|((in|ex)ternal:)")); + QRegularExpression urlPattern(QStringLiteral("^([fh]tt?ps?://)|(mailto:)|(file://)")); if (token.startsWith(QLatin1String("="))) { ret = writeFormula(row, column, token, format); - } else if (token.startsWith(QLatin1String("{")) && token.endsWith(QLatin1String("}"))) { - } else if (token.contains(urlPattern)) { - ret = writeUrl(row, column, QUrl(token)); + ret = writeHyperlink(row, column, QUrl(token)); } else { ret = writeString(row, column, token, format); } @@ -469,67 +467,54 @@ int Worksheet::writeDateTime(int row, int column, const QDateTime &dt, Format *f return 0; } -int Worksheet::writeUrl(int row, int column, const QUrl &url, Format *format, const QString &display, const QString &tip) +int Worksheet::writeHyperlink(int row, int column, const QUrl &url, Format *format, const QString &display, const QString &tip) { Q_D(Worksheet); if (d->checkDimensions(row, column)) return -1; - int link_type = 1; - QString urlString = url.toString(); - QString displayString = display; - if (urlString.startsWith(QLatin1String("internal:"))) { - urlString.replace(QLatin1String("internal:"), QString()); - link_type = 2; - } else if (urlString.startsWith(QLatin1String("external:"))) { - urlString.replace(QLatin1String("external:"), QString()); - link_type = 3; - } - - if (display.isEmpty()) - displayString = urlString; - - //For external links, chagne the directory separator from Unix to Dos - if (link_type == 3) { - urlString.replace(QLatin1Char('/'), QLatin1String("\\")); - displayString.replace(QLatin1Char('/'), QLatin1String("\\")); - } + int error = 0; - displayString.replace(QLatin1String("mailto:"), QString()); + QString urlString = url.toString(); - int error = 0; + //Generate proper display string + QString displayString = display.isEmpty() ? urlString : display; + if (displayString.startsWith(QLatin1String("mailto:"))) + displayString.replace(QLatin1String("mailto:"), QString()); if (displayString.size() > d->xls_strmax) { displayString = displayString.left(d->xls_strmax); error = -2; } - QString locationString = displayString; - if (link_type == 1) { - locationString = QString(); - } else if (link_type == 3) { - // External Workbook links need to be modified into correct format. - // The URL will look something like 'c:\temp\file.xlsx#Sheet!A1'. - // We need the part to the left of the # as the URL and the part to - //the right as the "location" string (if it exists). - if (urlString.contains(QLatin1Char('#'))) { - QStringList list = urlString.split(QLatin1Char('#')); - urlString = list[0]; - locationString = list[1]; - } else { - locationString = QString(); - } - link_type = 1; + /* + Location within target. If target is a workbook (or this workbook) + this shall refer to a sheet and cell or a defined name. Can also + be an HTML anchor if target is HTML file. + + c:\temp\file.xlsx#Sheet!A1 + http://a.com/aaa.html#aaaaa + */ + QString locationString; + if (url.hasFragment()) { + locationString = url.fragment(); + urlString = url.toString(QUrl::RemoveFragment); } + //Given a default style for hyperlink + if (!format) { + format = d->workbook->createFormat(); + format->setFontColor(Qt::blue); + format->setFontUnderline(Format::FontUnderlineSingle); + } //Write the hyperlink string as normal string. - d->sharedStrings()->addSharedString(urlString); - d->cellTable[row][column] = QSharedPointer(new Cell(urlString, Cell::String, format)); - - //Store the hyperlink data in sa separate table - d->urlTable[row][column] = new XlsxUrlData(link_type, urlString, locationString, tip); + d->sharedStrings()->addSharedString(displayString); + d->cellTable[row][column] = QSharedPointer(new Cell(displayString, Cell::String, format)); d->workbook->styles()->addFormat(format); + //Store the hyperlink data in a separate table + d->urlTable[row][column] = new XlsxUrlData(XlsxUrlData::External, urlString, locationString, tip); + return error; } @@ -821,14 +806,14 @@ void WorksheetPrivate::writeHyperlinks(XmlStreamWriter &writer) QString ref = xl_rowcol_to_cell(row, col); writer.writeEmptyElement(QStringLiteral("hyperlink")); writer.writeAttribute(QStringLiteral("ref"), ref); - if (data->linkType == 1) { + if (data->linkType == XlsxUrlData::External) { rel_count += 1; externUrlList.append(data->url); writer.writeAttribute(QStringLiteral("r:id"), QStringLiteral("rId%1").arg(rel_count)); if (!data->location.isEmpty()) writer.writeAttribute(QStringLiteral("location"), data->location); -// if (!data->url.isEmpty()) -// writer.writeAttribute(QStringLiteral("display"), data->url); + if (!data->display.isEmpty()) + writer.writeAttribute(QStringLiteral("display"), data->url); if (!data->tip.isEmpty()) writer.writeAttribute(QStringLiteral("tooltip"), data->tip); } else { diff --git a/src/xlsx/xlsxworksheet.h b/src/xlsx/xlsxworksheet.h index e1ccd15..dea9d17 100755 --- a/src/xlsx/xlsxworksheet.h +++ b/src/xlsx/xlsxworksheet.h @@ -59,7 +59,7 @@ public: int writeBlank(int row, int column, Format *format=0); int writeBool(int row, int column, bool value, Format *format=0); int writeDateTime(int row, int column, const QDateTime& dt, Format *format=0); - int writeUrl(int row, int column, const QUrl &url, Format *format=0, const QString &display=QString(), const QString &tip=QString()); + int writeHyperlink(int row, int column, const QUrl &url, Format *format=0, const QString &display=QString(), const QString &tip=QString()); Cell *cellAt(const QString &row_column) const; Cell *cellAt(int row, int column) const; diff --git a/src/xlsx/xlsxworksheet_p.h b/src/xlsx/xlsxworksheet_p.h index c81aa3b..1c0163e 100644 --- a/src/xlsx/xlsxworksheet_p.h +++ b/src/xlsx/xlsxworksheet_p.h @@ -39,15 +39,22 @@ class SharedStrings; struct XlsxUrlData { - XlsxUrlData(int linkType=1, const QString &url=QString(), const QString &location=QString(), const QString &tip=QString()) : + enum LinkType + { + External, + Internal + }; + + XlsxUrlData(LinkType linkType=External, const QString &url=QString(), const QString &location=QString(), const QString &tip=QString()) : linkType(linkType), url(url), location(location), tip(tip) { } - int linkType; + LinkType linkType; QString url; QString location; //location string + QString display; QString tip; }; diff --git a/tests/auto/worksheet/tst_worksheet.cpp b/tests/auto/worksheet/tst_worksheet.cpp index 34bf6bb..f70da1f 100644 --- a/tests/auto/worksheet/tst_worksheet.cpp +++ b/tests/auto/worksheet/tst_worksheet.cpp @@ -18,6 +18,7 @@ private Q_SLOTS: void testEmptySheet(); void testWriteCells(); + void testWriteHyperlinks(); void testMerge(); void testUnMerge(); @@ -62,6 +63,30 @@ void WorksheetTest::testWriteCells() QCOMPARE(sheet.d_ptr->sharedStrings()->getSharedString(0), QStringLiteral("Hello")); } +void WorksheetTest::testWriteHyperlinks() +{ + QXlsx::Worksheet sheet("", 0); + sheet.write("A1", QUrl::fromUserInput("http://qt-project.org")); + sheet.write("B1", QUrl::fromUserInput("http://qt-project.org/abc")); + sheet.write("C1", QUrl::fromUserInput("http://qt-project.org/abc.html#test")); + sheet.write("D1", QUrl::fromUserInput("mailto:xyz@debao.me")); + sheet.write("E1", QUrl::fromUserInput("mailto:xyz@debao.me?subject=Test")); + + QByteArray xmldata = sheet.saveToXmlData(); + + QVERIFY2(xmldata.contains(""), "simple"); + QVERIFY2(xmldata.contains(""), "url with path"); + QVERIFY2(xmldata.contains(""), "url with location"); + QVERIFY2(xmldata.contains(""), "mail"); + QVERIFY2(xmldata.contains(""), "mail with subject"); + + QCOMPARE(sheet.d_ptr->sharedStrings()->getSharedString(0), QStringLiteral("http://qt-project.org")); + QCOMPARE(sheet.d_ptr->sharedStrings()->getSharedString(1), QStringLiteral("http://qt-project.org/abc")); + QCOMPARE(sheet.d_ptr->sharedStrings()->getSharedString(2), QStringLiteral("http://qt-project.org/abc.html#test")); + QCOMPARE(sheet.d_ptr->sharedStrings()->getSharedString(3), QStringLiteral("xyz@debao.me")); + QCOMPARE(sheet.d_ptr->sharedStrings()->getSharedString(4), QStringLiteral("xyz@debao.me?subject=Test")); +} + void WorksheetTest::testMerge() { QXlsx::Worksheet sheet("", 0);