Don't lost rich text information
This commit is contained in:
@@ -39,6 +39,7 @@ class Styles;
|
|||||||
class Worksheet;
|
class Worksheet;
|
||||||
class WorksheetPrivate;
|
class WorksheetPrivate;
|
||||||
class RichString;
|
class RichString;
|
||||||
|
class SharedStrings;
|
||||||
|
|
||||||
class FormatPrivate;
|
class FormatPrivate;
|
||||||
class Q_XLSX_EXPORT Format
|
class Q_XLSX_EXPORT Format
|
||||||
@@ -216,6 +217,7 @@ private:
|
|||||||
friend class Worksheet;
|
friend class Worksheet;
|
||||||
friend class WorksheetPrivate;
|
friend class WorksheetPrivate;
|
||||||
friend class RichString;
|
friend class RichString;
|
||||||
|
friend class SharedStrings;
|
||||||
friend class ::FormatTest;
|
friend class ::FormatTest;
|
||||||
|
|
||||||
Format();
|
Format();
|
||||||
|
|||||||
@@ -87,6 +87,17 @@ Format *RichString::fragmentFormat(int index) const
|
|||||||
return m_fragmentFormats[index];
|
return m_fragmentFormats[index];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \internal
|
||||||
|
*/
|
||||||
|
Format *RichString::createFormat()
|
||||||
|
{
|
||||||
|
Format *format = new Format();
|
||||||
|
m_createdFormats.append(QSharedPointer<Format>(format));
|
||||||
|
|
||||||
|
return format;
|
||||||
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* \internal
|
* \internal
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -28,6 +28,7 @@
|
|||||||
#include "xlsxglobal.h"
|
#include "xlsxglobal.h"
|
||||||
#include "xlsxformat.h"
|
#include "xlsxformat.h"
|
||||||
#include <QStringList>
|
#include <QStringList>
|
||||||
|
#include <QSharedPointer>
|
||||||
|
|
||||||
QT_BEGIN_NAMESPACE_XLSX
|
QT_BEGIN_NAMESPACE_XLSX
|
||||||
|
|
||||||
@@ -49,6 +50,7 @@ public:
|
|||||||
QString fragmentText(int index) const;
|
QString fragmentText(int index) const;
|
||||||
Format *fragmentFormat(int index) const;
|
Format *fragmentFormat(int index) const;
|
||||||
|
|
||||||
|
Format *createFormat();
|
||||||
private:
|
private:
|
||||||
friend XLSX_AUTOTEST_EXPORT uint qHash(const RichString &rs, uint seed) Q_DECL_NOTHROW;
|
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);
|
||||||
@@ -61,6 +63,7 @@ private:
|
|||||||
QList<Format *> m_fragmentFormats;
|
QList<Format *> m_fragmentFormats;
|
||||||
QByteArray m_idKey;
|
QByteArray m_idKey;
|
||||||
bool m_dirty;
|
bool m_dirty;
|
||||||
|
QList<QSharedPointer<Format> > m_createdFormats;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -26,6 +26,8 @@
|
|||||||
#include "xlsxsharedstrings_p.h"
|
#include "xlsxsharedstrings_p.h"
|
||||||
#include "xlsxxmlwriter_p.h"
|
#include "xlsxxmlwriter_p.h"
|
||||||
#include "xlsxxmlreader_p.h"
|
#include "xlsxxmlreader_p.h"
|
||||||
|
#include "xlsxutility_p.h"
|
||||||
|
#include "xlsxformat_p.h"
|
||||||
#include <QDir>
|
#include <QDir>
|
||||||
#include <QFile>
|
#include <QFile>
|
||||||
#include <QRegularExpression>
|
#include <QRegularExpression>
|
||||||
@@ -123,6 +125,65 @@ QList<RichString> SharedStrings::getSharedStrings() const
|
|||||||
return m_stringList;
|
return m_stringList;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SharedStrings::writeRichStringPart_rPr(XmlStreamWriter &writer, Format *format) const
|
||||||
|
{
|
||||||
|
if (!format)
|
||||||
|
return;
|
||||||
|
|
||||||
|
FontData *font = &format->d_ptr->fontData;
|
||||||
|
|
||||||
|
if (font->bold)
|
||||||
|
writer.writeEmptyElement(QStringLiteral("b"));
|
||||||
|
if (font->italic)
|
||||||
|
writer.writeEmptyElement(QStringLiteral("i"));
|
||||||
|
if (font->strikeOut)
|
||||||
|
writer.writeEmptyElement(QStringLiteral("strike"));
|
||||||
|
if (font->outline)
|
||||||
|
writer.writeEmptyElement(QStringLiteral("outline"));
|
||||||
|
if (font->shadow)
|
||||||
|
writer.writeEmptyElement(QStringLiteral("shadow"));
|
||||||
|
if (font->underline != Format::FontUnderlineNone) {
|
||||||
|
writer.writeEmptyElement(QStringLiteral("u"));
|
||||||
|
if (font->underline == Format::FontUnderlineDouble)
|
||||||
|
writer.writeAttribute(QStringLiteral("val"), QStringLiteral("double"));
|
||||||
|
else if (font->underline == Format::FontUnderlineSingleAccounting)
|
||||||
|
writer.writeAttribute(QStringLiteral("val"), QStringLiteral("singleAccounting"));
|
||||||
|
else if (font->underline == Format::FontUnderlineDoubleAccounting)
|
||||||
|
writer.writeAttribute(QStringLiteral("val"), QStringLiteral("doubleAccounting"));
|
||||||
|
}
|
||||||
|
if (font->scirpt != Format::FontScriptNormal) {
|
||||||
|
writer.writeEmptyElement(QStringLiteral("vertAlign"));
|
||||||
|
if (font->scirpt == Format::FontScriptSuper)
|
||||||
|
writer.writeAttribute(QStringLiteral("val"), QStringLiteral("superscript"));
|
||||||
|
else
|
||||||
|
writer.writeAttribute(QStringLiteral("val"), QStringLiteral("subscript"));
|
||||||
|
}
|
||||||
|
|
||||||
|
writer.writeEmptyElement(QStringLiteral("sz"));
|
||||||
|
writer.writeAttribute(QStringLiteral("val"), QString::number(font->size));
|
||||||
|
|
||||||
|
if (font->color.isValid()) {
|
||||||
|
writer.writeEmptyElement(QStringLiteral("color"));
|
||||||
|
QString color = font->color.name();
|
||||||
|
writer.writeAttribute(QStringLiteral("rgb"), QStringLiteral("FF")+color.mid(1));//remove #
|
||||||
|
} else if (!font->themeColor.isEmpty()) {
|
||||||
|
writer.writeEmptyElement(QStringLiteral("color"));
|
||||||
|
QStringList themes = font->themeColor.split(QLatin1Char(':'));
|
||||||
|
writer.writeAttribute(QStringLiteral("theme"), themes[0]);
|
||||||
|
if (!themes[1].isEmpty())
|
||||||
|
writer.writeAttribute(QStringLiteral("tint"), themes[1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
writer.writeEmptyElement(QStringLiteral("rFont"));
|
||||||
|
writer.writeAttribute(QStringLiteral("val"), font->name);
|
||||||
|
writer.writeEmptyElement(QStringLiteral("family"));
|
||||||
|
writer.writeAttribute(QStringLiteral("val"), QString::number(font->family));
|
||||||
|
if (font->name == QLatin1String("Calibri")) {
|
||||||
|
writer.writeEmptyElement(QStringLiteral("scheme"));
|
||||||
|
writer.writeAttribute(QStringLiteral("val"), font->scheme);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void SharedStrings::saveToXmlFile(QIODevice *device) const
|
void SharedStrings::saveToXmlFile(QIODevice *device) const
|
||||||
{
|
{
|
||||||
XmlStreamWriter writer(device);
|
XmlStreamWriter writer(device);
|
||||||
@@ -138,15 +199,21 @@ void SharedStrings::saveToXmlFile(QIODevice *device) const
|
|||||||
if (string.isRichString()) {
|
if (string.isRichString()) {
|
||||||
//Rich text string
|
//Rich text string
|
||||||
for (int i=0; i<string.fragmentCount(); ++i) {
|
for (int i=0; i<string.fragmentCount(); ++i) {
|
||||||
|
writer.writeStartElement(QStringLiteral("r"));
|
||||||
if (string.fragmentFormat(i)) {
|
if (string.fragmentFormat(i)) {
|
||||||
writer.writeStartElement(QStringLiteral("rPr"));
|
writer.writeStartElement(QStringLiteral("rPr"));
|
||||||
//:Todo
|
writeRichStringPart_rPr(writer, string.fragmentFormat(i));
|
||||||
writer.writeEndElement();// rPr
|
writer.writeEndElement();// rPr
|
||||||
}
|
}
|
||||||
writer.writeStartElement(QStringLiteral("t"));
|
writer.writeStartElement(QStringLiteral("t"));
|
||||||
|
if (string.fragmentText(i).contains(QRegularExpression(QStringLiteral("^\\s")))
|
||||||
|
|| string.fragmentText(i).contains(QRegularExpression(QStringLiteral("\\s$")))) {
|
||||||
writer.writeAttribute(QStringLiteral("xml:space"), QStringLiteral("preserve"));
|
writer.writeAttribute(QStringLiteral("xml:space"), QStringLiteral("preserve"));
|
||||||
|
}
|
||||||
writer.writeCharacters(string.fragmentText(i));
|
writer.writeCharacters(string.fragmentText(i));
|
||||||
writer.writeEndElement();// t
|
writer.writeEndElement();// t
|
||||||
|
|
||||||
|
writer.writeEndElement(); //r
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
writer.writeStartElement(QStringLiteral("t"));
|
writer.writeStartElement(QStringLiteral("t"));
|
||||||
@@ -206,7 +273,7 @@ void SharedStrings::readRichStringPart(XmlStreamReader &reader, RichString &rich
|
|||||||
reader.readNextStartElement();
|
reader.readNextStartElement();
|
||||||
if (reader.tokenType() == QXmlStreamReader::StartElement) {
|
if (reader.tokenType() == QXmlStreamReader::StartElement) {
|
||||||
if (reader.name() == QLatin1String("rPr")) {
|
if (reader.name() == QLatin1String("rPr")) {
|
||||||
//:Todo
|
format = readRichStringPart_rPr(reader, richString);
|
||||||
} else if (reader.name() == QLatin1String("t")) {
|
} else if (reader.name() == QLatin1String("t")) {
|
||||||
text = reader.readElementText();
|
text = reader.readElementText();
|
||||||
}
|
}
|
||||||
@@ -225,6 +292,71 @@ void SharedStrings::readPlainStringPart(XmlStreamReader &reader, RichString &ric
|
|||||||
richString.addFragment(text, 0);
|
richString.addFragment(text, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Format *SharedStrings::readRichStringPart_rPr(XmlStreamReader &reader, RichString &richString)
|
||||||
|
{
|
||||||
|
Q_ASSERT(reader.name() == QLatin1String("rPr"));
|
||||||
|
Format *format = richString.createFormat();
|
||||||
|
while (!(reader.name() == QLatin1String("rPr") && reader.tokenType() == QXmlStreamReader::EndElement)) {
|
||||||
|
reader.readNextStartElement();
|
||||||
|
if (reader.tokenType() == QXmlStreamReader::StartElement) {
|
||||||
|
QXmlStreamAttributes attributes = reader.attributes();
|
||||||
|
if (reader.name() == QLatin1String("rFont")) {
|
||||||
|
format->setFontName(attributes.value(QLatin1String("val")).toString());
|
||||||
|
} else if (reader.name() == QLatin1String("charset")) {
|
||||||
|
format->d_ptr->fontData.charset = attributes.value(QLatin1String("val")).toString().toInt();
|
||||||
|
} else if (reader.name() == QLatin1String("family")) {
|
||||||
|
format->d_ptr->fontData.family = attributes.value(QLatin1String("val")).toString().toInt();
|
||||||
|
} else if (reader.name() == QLatin1String("b")) {
|
||||||
|
format->setFontBold(true);
|
||||||
|
} else if (reader.name() == QLatin1String("i")) {
|
||||||
|
format->setFontItalic(true);
|
||||||
|
} else if (reader.name() == QLatin1String("strike")) {
|
||||||
|
format->setFontStrikeOut(true);
|
||||||
|
} else if (reader.name() == QLatin1String("outline")) {
|
||||||
|
format->setFontOutline(true);
|
||||||
|
} else if (reader.name() == QLatin1String("shadow")) {
|
||||||
|
format->d_ptr->fontData.shadow = true;
|
||||||
|
} else if (reader.name() == QLatin1String("condense")) {
|
||||||
|
format->d_ptr->fontData.condense = attributes.value(QLatin1String("val")).toString().toInt();
|
||||||
|
} else if (reader.name() == QLatin1String("extend")) {
|
||||||
|
format->d_ptr->fontData.extend = attributes.value(QLatin1String("val")).toString().toInt();
|
||||||
|
} else if (reader.name() == QLatin1String("color")) {
|
||||||
|
if (attributes.hasAttribute(QLatin1String("rgb"))) {
|
||||||
|
QString colorString = attributes.value(QLatin1String("rgb")).toString();
|
||||||
|
format->setFontColor(fromARGBString(colorString));
|
||||||
|
} else if (attributes.hasAttribute(QLatin1String("indexed"))) {
|
||||||
|
// color = getColorByIndex(attributes.value(QLatin1String("indexed")).toString().toInt());
|
||||||
|
} else if (attributes.hasAttribute(QLatin1String("theme"))) {
|
||||||
|
QString theme = attributes.value(QLatin1String("theme")).toString();
|
||||||
|
QString tint = attributes.value(QLatin1String("tint")).toString();
|
||||||
|
format->d_ptr->fontData.themeColor = theme + QLatin1Char(':') + tint;
|
||||||
|
}
|
||||||
|
} else if (reader.name() == QLatin1String("sz")) {
|
||||||
|
format->setFontSize(attributes.value(QLatin1String("val")).toString().toInt());
|
||||||
|
} else if (reader.name() == QLatin1String("u")) {
|
||||||
|
QString value = attributes.value(QLatin1String("val")).toString();
|
||||||
|
if (value == QLatin1String("double"))
|
||||||
|
format->setFontUnderline(Format::FontUnderlineDouble);
|
||||||
|
else if (value == QLatin1String("doubleAccounting"))
|
||||||
|
format->setFontUnderline(Format::FontUnderlineDoubleAccounting);
|
||||||
|
else if (value == QLatin1String("singleAccounting"))
|
||||||
|
format->setFontUnderline(Format::FontUnderlineSingleAccounting);
|
||||||
|
else
|
||||||
|
format->setFontUnderline(Format::FontUnderlineSingle);
|
||||||
|
} else if (reader.name() == QLatin1String("vertAlign")) {
|
||||||
|
QString value = attributes.value(QLatin1String("val")).toString();
|
||||||
|
if (value == QLatin1String("superscript"))
|
||||||
|
format->setFontScript(Format::FontScriptSuper);
|
||||||
|
else if (value == QLatin1String("subscript"))
|
||||||
|
format->setFontScript(Format::FontScriptSub);
|
||||||
|
} else if (reader.name() == QLatin1String("scheme")) {
|
||||||
|
format->d_ptr->fontData.scheme = attributes.value(QLatin1String("val")).toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return format;
|
||||||
|
}
|
||||||
|
|
||||||
bool SharedStrings::loadFromXmlFile(QIODevice *device)
|
bool SharedStrings::loadFromXmlFile(QIODevice *device)
|
||||||
{
|
{
|
||||||
XmlStreamReader reader(device);
|
XmlStreamReader reader(device);
|
||||||
|
|||||||
@@ -36,6 +36,7 @@ class QIODevice;
|
|||||||
namespace QXlsx {
|
namespace QXlsx {
|
||||||
|
|
||||||
class XmlStreamReader;
|
class XmlStreamReader;
|
||||||
|
class XmlStreamWriter;
|
||||||
class RichString;
|
class RichString;
|
||||||
|
|
||||||
class XlsxSharedStringInfo
|
class XlsxSharedStringInfo
|
||||||
@@ -76,6 +77,8 @@ private:
|
|||||||
void readString(XmlStreamReader &reader); // <si>
|
void readString(XmlStreamReader &reader); // <si>
|
||||||
void readRichStringPart(XmlStreamReader &reader, RichString &rich); // <r>
|
void readRichStringPart(XmlStreamReader &reader, RichString &rich); // <r>
|
||||||
void readPlainStringPart(XmlStreamReader &reader, RichString &rich); // <v>
|
void readPlainStringPart(XmlStreamReader &reader, RichString &rich); // <v>
|
||||||
|
Format *readRichStringPart_rPr(XmlStreamReader &reader, RichString &richString);
|
||||||
|
void writeRichStringPart_rPr(XmlStreamWriter &writer, Format *format) const;
|
||||||
|
|
||||||
QHash<RichString, XlsxSharedStringInfo> m_stringTable; //for fast lookup
|
QHash<RichString, XlsxSharedStringInfo> m_stringTable; //for fast lookup
|
||||||
QList<RichString> m_stringList;
|
QList<RichString> m_stringList;
|
||||||
|
|||||||
@@ -1158,7 +1158,12 @@ void WorksheetPrivate::writeCellData(XmlStreamWriter &writer, int row, int col,
|
|||||||
writer.writeAttribute(QStringLiteral("s"), QString::number(colsInfoHelper[col]->format->xfIndex()));
|
writer.writeAttribute(QStringLiteral("s"), QString::number(colsInfoHelper[col]->format->xfIndex()));
|
||||||
|
|
||||||
if (cell->dataType() == Cell::String) {
|
if (cell->dataType() == Cell::String) {
|
||||||
int sst_idx = sharedStrings()->getSharedStringIndex(cell->value().toString());
|
int sst_idx;
|
||||||
|
if (cell->isRichString())
|
||||||
|
sst_idx = sharedStrings()->getSharedStringIndex(cell->d_ptr->richString);
|
||||||
|
else
|
||||||
|
sst_idx = sharedStrings()->getSharedStringIndex(cell->value().toString());
|
||||||
|
|
||||||
writer.writeAttribute(QStringLiteral("t"), QStringLiteral("s"));
|
writer.writeAttribute(QStringLiteral("t"), QStringLiteral("s"));
|
||||||
writer.writeTextElement(QStringLiteral("v"), QString::number(sst_idx));
|
writer.writeTextElement(QStringLiteral("v"), QString::number(sst_idx));
|
||||||
} else if (cell->dataType() == Cell::InlineString) {
|
} else if (cell->dataType() == Cell::InlineString) {
|
||||||
@@ -1168,13 +1173,17 @@ void WorksheetPrivate::writeCellData(XmlStreamWriter &writer, int row, int col,
|
|||||||
//Rich text string
|
//Rich text string
|
||||||
RichString string = cell->d_ptr->richString;
|
RichString string = cell->d_ptr->richString;
|
||||||
for (int i=0; i<string.fragmentCount(); ++i) {
|
for (int i=0; i<string.fragmentCount(); ++i) {
|
||||||
|
writer.writeStartElement(QStringLiteral("r"));
|
||||||
|
if (string.fragmentFormat(i)) {
|
||||||
writer.writeStartElement(QStringLiteral("rPr"));
|
writer.writeStartElement(QStringLiteral("rPr"));
|
||||||
//:Todo
|
//:Todo
|
||||||
writer.writeEndElement();// rPr
|
writer.writeEndElement();// rPr
|
||||||
|
}
|
||||||
writer.writeStartElement(QStringLiteral("t"));
|
writer.writeStartElement(QStringLiteral("t"));
|
||||||
writer.writeAttribute(QStringLiteral("xml:space"), QStringLiteral("preserve"));
|
writer.writeAttribute(QStringLiteral("xml:space"), QStringLiteral("preserve"));
|
||||||
writer.writeCharacters(string.fragmentText(i));
|
writer.writeCharacters(string.fragmentText(i));
|
||||||
writer.writeEndElement();// t
|
writer.writeEndElement();// t
|
||||||
|
writer.writeEndElement(); // r
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
writer.writeTextElement(QStringLiteral("t"), cell->value().toString());
|
writer.writeTextElement(QStringLiteral("t"), cell->value().toString());
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
#include "private/xlsxsharedstrings_p.h"
|
#include "private/xlsxsharedstrings_p.h"
|
||||||
#include "private/xlsxrichstring_p.h"
|
#include "private/xlsxrichstring_p.h"
|
||||||
|
#include "xlsxformat.h"
|
||||||
#include <QString>
|
#include <QString>
|
||||||
#include <QtTest>
|
#include <QtTest>
|
||||||
#include <QXmlStreamReader>
|
#include <QXmlStreamReader>
|
||||||
@@ -16,6 +17,7 @@ private Q_SLOTS:
|
|||||||
void testRemoveSharedString();
|
void testRemoveSharedString();
|
||||||
|
|
||||||
void testLoadXmlData();
|
void testLoadXmlData();
|
||||||
|
void testLoadRichStringXmlData();
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -127,6 +129,37 @@ void SharedStringsTest::testLoadXmlData()
|
|||||||
QCOMPARE(sst2->getSharedStringIndex("Hello World"), 4);
|
QCOMPARE(sst2->getSharedStringIndex("Hello World"), 4);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SharedStringsTest::testLoadRichStringXmlData()
|
||||||
|
{
|
||||||
|
QByteArray xmlData = "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>"
|
||||||
|
"<sst xmlns=\"http://schemas.openxmlformats.org/spreadsheetml/2006/main\" count=\"1\" uniqueCount=\"1\">"
|
||||||
|
"<si>"
|
||||||
|
"<r><t>e=mc</t></r>"
|
||||||
|
"<r>"
|
||||||
|
"<rPr><vertAlign val=\"superscript\"/>"
|
||||||
|
"<sz val=\"11\"/>"
|
||||||
|
"<rFont val=\"MyFontName\"/>"
|
||||||
|
"<family val=\"3\"/>"
|
||||||
|
"<charset val=\"134\"/>"
|
||||||
|
"<scheme val=\"minor\"/>"
|
||||||
|
"</rPr>"
|
||||||
|
"<t>2</t></r>"
|
||||||
|
"</si>"
|
||||||
|
"</sst>";
|
||||||
|
|
||||||
|
QSharedPointer<QXlsx::SharedStrings> sst(new QXlsx::SharedStrings);
|
||||||
|
sst->loadFromXmlData(xmlData);
|
||||||
|
QXlsx::RichString rs = sst->getSharedString(0);
|
||||||
|
QVERIFY(rs.fragmentText(0) == "e=mc");
|
||||||
|
QVERIFY(rs.fragmentText(1) == "2");
|
||||||
|
QVERIFY(rs.fragmentFormat(0) == 0);
|
||||||
|
QXlsx::Format *format = rs.fragmentFormat(1);
|
||||||
|
QCOMPARE(format->fontName(), QString("MyFontName"));
|
||||||
|
// QCOMPARE(format->fontFamily(), 3);
|
||||||
|
QCOMPARE(format->fontScript(), QXlsx::Format::FontScriptSuper);
|
||||||
|
QCOMPARE(format->fontSize(), 11);
|
||||||
|
}
|
||||||
|
|
||||||
QTEST_APPLESS_MAIN(SharedStringsTest)
|
QTEST_APPLESS_MAIN(SharedStringsTest)
|
||||||
|
|
||||||
#include "tst_sharedstringstest.moc"
|
#include "tst_sharedstringstest.moc"
|
||||||
|
|||||||
Reference in New Issue
Block a user