diff --git a/examples/xlsx/richtext/doc/images/richtext.png b/examples/xlsx/richtext/doc/images/richtext.png new file mode 100644 index 0000000..75afb38 Binary files /dev/null and b/examples/xlsx/richtext/doc/images/richtext.png differ diff --git a/examples/xlsx/richtext/doc/src/richtext.qdoc b/examples/xlsx/richtext/doc/src/richtext.qdoc new file mode 100644 index 0000000..4e57722 --- /dev/null +++ b/examples/xlsx/richtext/doc/src/richtext.qdoc @@ -0,0 +1,11 @@ +/*! + \example richtext + \title Rich Text Example + \brief This is a simplest Qt Xlsx example. + \ingroup qtxlsx-examples + + This example demonstrates how to create a new + .xlsx file containing some basic data and calculations + with Qt Xlsx Library. So lets see how this is achieved. + \image richtext.png +*/ diff --git a/examples/xlsx/richtext/main.cpp b/examples/xlsx/richtext/main.cpp new file mode 100644 index 0000000..1647e9b --- /dev/null +++ b/examples/xlsx/richtext/main.cpp @@ -0,0 +1,35 @@ +#include +#include "xlsxdocument.h" +#include "xlsxrichstring.h" +#include "xlsxformat.h" +int main() +{ + //![0] + QXlsx::Document xlsx; + //![0] + + //![1] + QXlsx::Format blue; + blue.setFontColor(Qt::blue); + QXlsx::Format red; + red.setFontColor(Qt::red); + red.setFontSize(15); + QXlsx::Format bold; + bold.setFontBold(true); + + QXlsx::RichString rich; + rich.addFragment("Hello ", blue); + rich.addFragment("Qt ", red); + rich.addFragment("Xlsx", bold); + xlsx.write("B2", rich); + //![1] + + //![2] + xlsx.saveAs("Test1.xlsx"); + //![2] + + QXlsx::Document("Test1.xlsx"); + xlsx.saveAs("Test2.xlsx"); + + return 0; +} diff --git a/examples/xlsx/richtext/richtext.pro b/examples/xlsx/richtext/richtext.pro new file mode 100644 index 0000000..10d2978 --- /dev/null +++ b/examples/xlsx/richtext/richtext.pro @@ -0,0 +1,9 @@ +TARGET = hello + +#include(../../../src/xlsx/qtxlsx.pri) +QT+=xlsx + +CONFIG += console +CONFIG -= app_bundle + +SOURCES += main.cpp diff --git a/examples/xlsx/xlsx.pro b/examples/xlsx/xlsx.pro index 302109c..36a30ec 100644 --- a/examples/xlsx/xlsx.pro +++ b/examples/xlsx/xlsx.pro @@ -10,5 +10,6 @@ SUBDIRS = hello \ datavalidation \ definename \ formulas \ + richtext \ demo diff --git a/src/xlsx/qtxlsx.pri b/src/xlsx/qtxlsx.pri index 53e0025..a0454b8 100755 --- a/src/xlsx/qtxlsx.pri +++ b/src/xlsx/qtxlsx.pri @@ -32,7 +32,8 @@ HEADERS += $$PWD/xlsxdocpropscore_p.h \ $$PWD/xlsxdatavalidation.h \ $$PWD/xlsxdatavalidation_p.h \ $$PWD/xlsxcellrange.h \ - $$PWD/xlsxrichstring_p.h + $$PWD/xlsxrichstring_p.h \ + $$PWD/xlsxrichstring.h SOURCES += $$PWD/xlsxdocpropscore.cpp \ $$PWD/xlsxdocpropsapp.cpp \ diff --git a/src/xlsx/xlsxcell_p.h b/src/xlsx/xlsxcell_p.h index ab122ec..84fa27a 100644 --- a/src/xlsx/xlsxcell_p.h +++ b/src/xlsx/xlsxcell_p.h @@ -28,7 +28,7 @@ #include "xlsxglobal.h" #include "xlsxcell.h" #include "xlsxcellrange.h" -#include "xlsxrichstring_p.h" +#include "xlsxrichstring.h" #include #include diff --git a/src/xlsx/xlsxformat.h b/src/xlsx/xlsxformat.h index 361d5fd..639176f 100755 --- a/src/xlsx/xlsxformat.h +++ b/src/xlsx/xlsxformat.h @@ -39,7 +39,7 @@ QT_BEGIN_NAMESPACE_XLSX class Styles; class Worksheet; class WorksheetPrivate; -class RichString; +class RichStringPrivate; class SharedStrings; class FormatPrivate; @@ -234,7 +234,7 @@ private: friend class Styles; friend class Worksheet; friend class WorksheetPrivate; - friend class RichString; + friend class RichStringPrivate; friend class SharedStrings; friend class ::FormatTest; diff --git a/src/xlsx/xlsxrichstring.cpp b/src/xlsx/xlsxrichstring.cpp index dfff582..2b9db35 100644 --- a/src/xlsx/xlsxrichstring.cpp +++ b/src/xlsx/xlsxrichstring.cpp @@ -22,22 +22,72 @@ ** WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ** ****************************************************************************/ +#include "xlsxrichstring.h" #include "xlsxrichstring_p.h" #include "xlsxformat_p.h" QT_BEGIN_NAMESPACE_XLSX +RichStringPrivate::RichStringPrivate() + :_dirty(true) +{ + +} + +RichStringPrivate::RichStringPrivate(const RichStringPrivate &other) + :QSharedData(other), fragmentTexts(other.fragmentTexts) + ,fragmentFormats(other.fragmentFormats) + , _idKey(other.idKey()), _dirty(other._dirty) +{ + +} + +RichStringPrivate::~RichStringPrivate() +{ + +} + +/*! + \class RichString + +*/ + RichString::RichString() - :m_dirty(true) + :d(new RichStringPrivate) { } RichString::RichString(const QString text) - :m_dirty(true) + :d(new RichStringPrivate) { addFragment(text, Format()); } +RichString::RichString(const RichString &other) + :d(other.d) +{ + +} + +RichString::~RichString() +{ + +} + +RichString &RichString::operator =(const RichString &other) +{ + this->d = other.d; + return *this; +} + +/*! + Returns the rich string as a QVariant +*/ +RichString::operator QVariant() const +{ + return QVariant(qMetaTypeId(), this); +} + bool RichString::isRichString() const { if (fragmentCount() > 1) //Is this enough?? @@ -47,29 +97,29 @@ bool RichString::isRichString() const bool RichString::isEmtpy() const { - return m_fragmentTexts.size() == 0; + return d->fragmentTexts.size() == 0; } QString RichString::toPlainString() const { if (isEmtpy()) return QString(); - if (m_fragmentTexts.size() == 1) - return m_fragmentTexts[0]; + if (d->fragmentTexts.size() == 1) + return d->fragmentTexts[0]; - return m_fragmentTexts.join(QString()); + return d->fragmentTexts.join(QString()); } int RichString::fragmentCount() const { - return m_fragmentTexts.size(); + return d->fragmentTexts.size(); } void RichString::addFragment(const QString &text, const Format &format) { - m_fragmentTexts.append(text); - m_fragmentFormats.append(format); - m_dirty = true; + d->fragmentTexts.append(text); + d->fragmentFormats.append(format); + d->_dirty = true; } QString RichString::fragmentText(int index) const @@ -77,7 +127,7 @@ QString RichString::fragmentText(int index) const if (index < 0 || index >= fragmentCount()) return QString(); - return m_fragmentTexts[index]; + return d->fragmentTexts[index]; } Format RichString::fragmentFormat(int index) const @@ -85,35 +135,35 @@ Format RichString::fragmentFormat(int index) const if (index < 0 || index >= fragmentCount()) return Format(); - return m_fragmentFormats[index]; + return d->fragmentFormats[index]; } /*! * \internal */ -QByteArray RichString::idKey() const +QByteArray RichStringPrivate::idKey() const { - if (m_dirty) { - RichString *rs = const_cast(this); + if (_dirty) { + RichStringPrivate *rs = const_cast(this); QByteArray bytes; - if (!isRichString()) { - bytes = toPlainString().toUtf8(); + if (fragmentTexts.size() == 1) { + bytes = fragmentTexts[0].toUtf8(); } else { //Generate a hash value base on QByteArray ? bytes.append("@@QtXlsxRichString="); - for (int i=0; im_idKey = bytes; - rs->m_dirty = false; + rs->_idKey = bytes; + rs->_dirty = false; } - return m_idKey; + return _idKey; } bool operator==(const RichString &rs1, const RichString &rs2) @@ -121,7 +171,7 @@ bool operator==(const RichString &rs1, const RichString &rs2) if (rs1.fragmentCount() != rs2.fragmentCount()) return false; - return rs1.idKey() == rs2.idKey(); + return rs1.d->idKey() == rs2.d->idKey(); } bool operator!=(const RichString &rs1, const RichString &rs2) @@ -129,7 +179,7 @@ bool operator!=(const RichString &rs1, const RichString &rs2) if (rs1.fragmentCount() != rs2.fragmentCount()) return true; - return rs1.idKey() != rs2.idKey(); + return rs1.d->idKey() != rs2.d->idKey(); } /*! @@ -137,7 +187,7 @@ bool operator!=(const RichString &rs1, const RichString &rs2) */ bool operator<(const RichString &rs1, const RichString &rs2) { - return rs1.idKey() < rs2.idKey(); + return rs1.d->idKey() < rs2.d->idKey(); } bool operator ==(const RichString &rs1, const QString &rs2) @@ -168,7 +218,7 @@ bool operator !=(const QString &rs1, const RichString &rs2) uint qHash(const RichString &rs, uint seed) Q_DECL_NOTHROW { - return qHash(rs.idKey(), seed); + return qHash(rs.d->idKey(), seed); } QT_END_NAMESPACE_XLSX diff --git a/src/xlsx/xlsxrichstring.h b/src/xlsx/xlsxrichstring.h new file mode 100644 index 0000000..3886982 --- /dev/null +++ b/src/xlsx/xlsxrichstring.h @@ -0,0 +1,81 @@ +/**************************************************************************** +** Copyright (c) 2013 Debao Zhang +** All right reserved. +** +** Permission is hereby granted, free of charge, to any person obtaining +** a copy of this software and associated documentation files (the +** "Software"), to deal in the Software without restriction, including +** without limitation the rights to use, copy, modify, merge, publish, +** distribute, sublicense, and/or sell copies of the Software, and to +** permit persons to whom the Software is furnished to do so, subject to +** the following conditions: +** +** The above copyright notice and this permission notice shall be +** included in all copies or substantial portions of the Software. +** +** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +** NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +** LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +** OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +** WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +** +****************************************************************************/ +#ifndef XLSXRICHSTRING_H +#define XLSXRICHSTRING_H + +#include "xlsxglobal.h" +#include "xlsxformat.h" +#include +#include +#include + +QT_BEGIN_NAMESPACE_XLSX +class RichStringPrivate; +class RichString; +// qHash is a friend, but we can't use default arguments for friends (§8.3.6.4) +Q_XLSX_EXPORT uint qHash(const RichString &rs, uint seed = 0) Q_DECL_NOTHROW; + +class Q_XLSX_EXPORT RichString +{ +public: + RichString(); + explicit RichString(const QString text); + RichString(const RichString &other); + ~RichString(); + + bool isRichString() const; + bool isEmtpy() const; + QString toPlainString() const; + + int fragmentCount() const; + void addFragment(const QString &text, const Format &format); + QString fragmentText(int index) const; + Format fragmentFormat(int index) const; + + operator QVariant() const; + + RichString &operator=(const RichString &other); +private: + friend Q_XLSX_EXPORT uint qHash(const RichString &rs, uint seed) Q_DECL_NOTHROW; + friend Q_XLSX_EXPORT bool operator==(const RichString &rs1, const RichString &rs2); + friend Q_XLSX_EXPORT bool operator!=(const RichString &rs1, const RichString &rs2); + friend Q_XLSX_EXPORT bool operator<(const RichString &rs1, const RichString &rs2); + + QSharedDataPointer d; +}; + +Q_XLSX_EXPORT bool operator==(const RichString &rs1, const RichString &rs2); +Q_XLSX_EXPORT bool operator!=(const RichString &rs1, const RichString &rs2); +Q_XLSX_EXPORT bool operator<(const RichString &rs1, const RichString &rs2); +Q_XLSX_EXPORT bool operator==(const RichString &rs1, const QString &rs2); +Q_XLSX_EXPORT bool operator==(const QString &rs1, const RichString &rs2); +Q_XLSX_EXPORT bool operator!=(const RichString &rs1, const QString &rs2); +Q_XLSX_EXPORT bool operator!=(const QString &rs1, const RichString &rs2); + +QT_END_NAMESPACE_XLSX + +Q_DECLARE_METATYPE(QXlsx::RichString) + +#endif // XLSXRICHSTRING_H diff --git a/src/xlsx/xlsxrichstring_p.h b/src/xlsx/xlsxrichstring_p.h index 1b3fa42..5fd87e1 100644 --- a/src/xlsx/xlsxrichstring_p.h +++ b/src/xlsx/xlsxrichstring_p.h @@ -25,56 +25,25 @@ #ifndef XLSXRICHSTRING_P_H #define XLSXRICHSTRING_P_H -#include "xlsxglobal.h" -#include "xlsxformat.h" -#include -#include +#include "xlsxrichstring.h" QT_BEGIN_NAMESPACE_XLSX -class RichString; -// qHash is a friend, but we can't use default arguments for friends (§8.3.6.4) -XLSX_AUTOTEST_EXPORT uint qHash(const RichString &rs, uint seed = 0) Q_DECL_NOTHROW; - -class XLSX_AUTOTEST_EXPORT RichString +class RichStringPrivate : public QSharedData { public: - RichString(); - explicit RichString(const QString text); - bool isRichString() const; - bool isEmtpy() const; - QString toPlainString() const; - - int fragmentCount() const; - void addFragment(const QString &text, const Format &format); - QString fragmentText(int index) const; - Format fragmentFormat(int index) const; - -private: - friend XLSX_AUTOTEST_EXPORT uint qHash(const RichString &rs, uint seed) Q_DECL_NOTHROW; - friend XLSX_AUTOTEST_EXPORT bool operator==(const RichString &rs1, const RichString &rs2); - friend XLSX_AUTOTEST_EXPORT bool operator!=(const RichString &rs1, const RichString &rs2); - friend XLSX_AUTOTEST_EXPORT bool operator<(const RichString &rs1, const RichString &rs2); + RichStringPrivate(); + RichStringPrivate(const RichStringPrivate &other); + ~RichStringPrivate(); QByteArray idKey() const; - QStringList m_fragmentTexts; - QList m_fragmentFormats; - QByteArray m_idKey; - bool m_dirty; + QStringList fragmentTexts; + QList fragmentFormats; + QByteArray _idKey; + bool _dirty; }; - -XLSX_AUTOTEST_EXPORT bool operator==(const RichString &rs1, const RichString &rs2); -XLSX_AUTOTEST_EXPORT bool operator!=(const RichString &rs1, const RichString &rs2); -XLSX_AUTOTEST_EXPORT bool operator<(const RichString &rs1, const RichString &rs2); -XLSX_AUTOTEST_EXPORT bool operator==(const RichString &rs1, const QString &rs2); -XLSX_AUTOTEST_EXPORT bool operator==(const QString &rs1, const RichString &rs2); -XLSX_AUTOTEST_EXPORT bool operator!=(const RichString &rs1, const QString &rs2); -XLSX_AUTOTEST_EXPORT bool operator!=(const QString &rs1, const RichString &rs2); - QT_END_NAMESPACE_XLSX -Q_DECLARE_METATYPE(QXlsx::RichString) - #endif // XLSXRICHSTRING_P_H diff --git a/src/xlsx/xlsxsharedstrings.cpp b/src/xlsx/xlsxsharedstrings.cpp index b96fa93..9b0fc0a 100755 --- a/src/xlsx/xlsxsharedstrings.cpp +++ b/src/xlsx/xlsxsharedstrings.cpp @@ -22,7 +22,7 @@ ** WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ** ****************************************************************************/ -#include "xlsxrichstring_p.h" +#include "xlsxrichstring.h" #include "xlsxsharedstrings_p.h" #include "xlsxxmlwriter_p.h" #include "xlsxxmlreader_p.h" diff --git a/src/xlsx/xlsxsharedstrings_p.h b/src/xlsx/xlsxsharedstrings_p.h index af45ea6..7fcf04c 100755 --- a/src/xlsx/xlsxsharedstrings_p.h +++ b/src/xlsx/xlsxsharedstrings_p.h @@ -26,7 +26,7 @@ #define XLSXSHAREDSTRINGS_H #include "xlsxglobal.h" -#include "xlsxrichstring_p.h" +#include "xlsxrichstring.h" #include #include #include diff --git a/src/xlsx/xlsxworksheet.cpp b/src/xlsx/xlsxworksheet.cpp index 7fcc214..f1a6ab1 100755 --- a/src/xlsx/xlsxworksheet.cpp +++ b/src/xlsx/xlsxworksheet.cpp @@ -22,7 +22,7 @@ ** WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ** ****************************************************************************/ -#include "xlsxrichstring_p.h" +#include "xlsxrichstring.h" #include "xlsxworksheet.h" #include "xlsxworksheet_p.h" #include "xlsxworkbook.h" @@ -441,6 +441,8 @@ int Worksheet::write(int row, int column, const QVariant &value, const Format &f if (value.isNull()) { //blank ret = writeBlank(row, column, format); + } else if (value.userType() == qMetaTypeId()) { + ret = writeString(row, column, value.value(), format); } else if (value.userType() == QMetaType::Bool) { //Bool ret = writeBool(row,column, value.toBool(), format); } else if (value.toDateTime().isValid()) { //DateTime @@ -542,6 +544,44 @@ Format WorksheetPrivate::cellFormat(int row, int col) const return cellTable[row][col]->format(); } +/*! + \overload + */ +int Worksheet::writeString(const QString &row_column, const RichString &value, const Format &format) +{ + //convert the "A1" notation to row/column notation + QPoint pos = xl_cell_to_rowcol(row_column); + if (pos == QPoint(-1, -1)) + return -1; + + return writeString(pos.x(), pos.y(), value, format); +} + +/*! + Write string \a value to the cell (\a row, \a column) with the \a format +*/ +int Worksheet::writeString(int row, int column, const RichString &value, const Format &format) +{ + Q_D(Worksheet); + int error = 0; +// QString content = value.toPlainString(); + if (d->checkDimensions(row, column)) + return -1; + +// if (content.size() > d->xls_strmax) { +// content = content.left(d->xls_strmax); +// error = -2; +// } + + d->sharedStrings()->addSharedString(value); + Format fmt = format.isValid() ? format : d->cellFormat(row, column); + d->workbook->styles()->addFormat(fmt); + QSharedPointer cell = QSharedPointer(new Cell(QString(), Cell::String, fmt, this)); + cell->d_ptr->richString = value; + d->cellTable[row][column] = cell; + return error; +} + /*! \overload */ diff --git a/src/xlsx/xlsxworksheet.h b/src/xlsx/xlsxworksheet.h index da8b0fa..b16d08e 100755 --- a/src/xlsx/xlsxworksheet.h +++ b/src/xlsx/xlsxworksheet.h @@ -47,6 +47,7 @@ class Drawing; class DataValidation; class CellRange; struct XlsxImageData; +class RichString; class WorksheetPrivate; class Q_XLSX_EXPORT Worksheet @@ -59,6 +60,8 @@ public: QVariant read(int row, int column) const; int writeString(const QString &row_column, const QString &value, const Format &format=Format()); int writeString(int row, int column, const QString &value, const Format &format=Format()); + int writeString(const QString &row_column, const RichString &value, const Format &format=Format()); + int writeString(int row, int column, const RichString &value, const Format &format=Format()); int writeInlineString(const QString &row_column, const QString &value, const Format &format=Format()); int writeInlineString(int row, int column, const QString &value, const Format &format=Format()); int writeNumeric(const QString &row_column, double value, const Format &format=Format()); diff --git a/tests/auto/richstring/tst_richstringtest.cpp b/tests/auto/richstring/tst_richstringtest.cpp index a7b912e..23ff39b 100644 --- a/tests/auto/richstring/tst_richstringtest.cpp +++ b/tests/auto/richstring/tst_richstringtest.cpp @@ -1,4 +1,4 @@ -#include "private/xlsxrichstring_p.h" +#include "xlsxrichstring.h" #include #include diff --git a/tests/auto/sharedstrings/tst_sharedstringstest.cpp b/tests/auto/sharedstrings/tst_sharedstringstest.cpp index 281e611..6a40fb9 100644 --- a/tests/auto/sharedstrings/tst_sharedstringstest.cpp +++ b/tests/auto/sharedstrings/tst_sharedstringstest.cpp @@ -1,5 +1,5 @@ #include "private/xlsxsharedstrings_p.h" -#include "private/xlsxrichstring_p.h" +#include "xlsxrichstring.h" #include "xlsxformat.h" #include #include diff --git a/tests/auto/worksheet/tst_worksheet.cpp b/tests/auto/worksheet/tst_worksheet.cpp index 03f536d..73f0b5a 100644 --- a/tests/auto/worksheet/tst_worksheet.cpp +++ b/tests/auto/worksheet/tst_worksheet.cpp @@ -8,7 +8,7 @@ #include "private/xlsxworksheet_p.h" #include "private/xlsxxmlreader_p.h" #include "private/xlsxsharedstrings_p.h" -#include "private/xlsxrichstring_p.h" +#include "xlsxrichstring.h" class WorksheetTest : public QObject {