File indexing completed on 2024-05-05 12:57:19
0001 /* 0002 * Copyright (C) 2010-2015 by Stephen Allewell 0003 * steve.allewell@gmail.com 0004 * 0005 * This program is free software; you can redistribute it and/or modify 0006 * it under the terms of the GNU General Public License as published by 0007 * the Free Software Foundation; either version 2 of the License, or 0008 * (at your option) any later version. 0009 */ 0010 0011 #include "Document.h" 0012 0013 #include <QDataStream> 0014 #include <QFile> 0015 #include <QVariant> 0016 0017 #include <KLocalizedString> 0018 #include <KMessageBox> 0019 0020 #include "Editor.h" 0021 #include "Exceptions.h" 0022 #include "Floss.h" 0023 #include "FlossScheme.h" 0024 #include "Layers.h" 0025 #include "Palette.h" 0026 #include "Preview.h" 0027 #include "SchemeManager.h" 0028 0029 Document::Document() 0030 : m_editor(nullptr) 0031 , m_palette(nullptr) 0032 , m_preview(nullptr) 0033 , m_pattern(nullptr) 0034 { 0035 initialiseNew(); 0036 } 0037 0038 Document::~Document() 0039 { 0040 delete m_pattern; 0041 } 0042 0043 void Document::initialiseNew() 0044 { 0045 m_undoStack.clear(); 0046 0047 m_backgroundImages.clear(); 0048 m_printerConfiguration = PrinterConfiguration(); 0049 0050 delete m_pattern; 0051 m_pattern = new Pattern(this); 0052 0053 QString scheme = Configuration::palette_DefaultScheme(); 0054 0055 if (SchemeManager::scheme(scheme) == nullptr) { 0056 scheme = SchemeManager::schemes().at(scheme.toInt()); 0057 } 0058 0059 m_pattern->palette().setSchemeName(scheme); 0060 0061 double documentWidth = Configuration::document_Width(); 0062 double documentHeight = Configuration::document_Height(); 0063 0064 double horizontalClothCount = Configuration::editor_HorizontalClothCount(); 0065 double verticalClothCount = Configuration::editor_VerticalClothCount(); 0066 Configuration::EnumEditor_ClothCountUnits::type clothCountUnits = Configuration::editor_ClothCountUnits(); 0067 0068 if (clothCountUnits == Configuration::EnumEditor_ClothCountUnits::Default) { 0069 clothCountUnits = (QLocale::system().measurementSystem() == QLocale::MetricSystem) ? Configuration::EnumEditor_ClothCountUnits::Centimeters 0070 : Configuration::EnumEditor_ClothCountUnits::Inches; 0071 } 0072 0073 switch (Configuration::document_UnitsFormat()) { 0074 case Configuration::EnumDocument_UnitsFormat::Stitches: 0075 // nothing needs to be done to convert these values 0076 break; 0077 0078 case Configuration::EnumDocument_UnitsFormat::Inches: 0079 documentWidth *= horizontalClothCount; 0080 documentHeight *= verticalClothCount; 0081 0082 if (clothCountUnits == Configuration::EnumEditor_ClothCountUnits::Centimeters) { 0083 documentWidth *= 2.54; 0084 documentHeight *= 2.54; 0085 } 0086 0087 break; 0088 0089 case Configuration::EnumDocument_UnitsFormat::Centimeters: 0090 documentWidth *= horizontalClothCount; 0091 documentHeight *= verticalClothCount; 0092 0093 if (clothCountUnits == Configuration::EnumEditor_ClothCountUnits::Inches) { 0094 documentWidth /= 2.54; 0095 documentHeight /= 2.54; 0096 } 0097 0098 break; 0099 0100 default: // Avoid compiler warning about unhandled value 0101 break; 0102 } 0103 0104 m_pattern->stitches().resize(static_cast<int>(documentWidth), static_cast<int>(documentHeight)); 0105 0106 setProperty(QStringLiteral("unitsFormat"), Configuration::document_UnitsFormat()); 0107 setProperty(QStringLiteral("title"), QString()); 0108 setProperty(QStringLiteral("author"), QString()); 0109 setProperty(QStringLiteral("copyright"), QString()); 0110 setProperty(QStringLiteral("fabric"), QString()); 0111 setProperty(QStringLiteral("fabricColor"), Configuration::editor_BackgroundColor()); 0112 setProperty(QStringLiteral("instructions"), QString()); 0113 setProperty(QStringLiteral("cellHorizontalGrouping"), Configuration::editor_CellHorizontalGrouping()); 0114 setProperty(QStringLiteral("cellVerticalGrouping"), Configuration::editor_CellVerticalGrouping()); 0115 setProperty(QStringLiteral("horizontalClothCount"), Configuration::editor_HorizontalClothCount()); 0116 setProperty(QStringLiteral("verticalClothCount"), Configuration::editor_VerticalClothCount()); 0117 setProperty(QStringLiteral("clothCountUnits"), clothCountUnits); 0118 setProperty(QStringLiteral("clothCountLink"), Configuration::editor_ClothCountLink()); 0119 setProperty(QStringLiteral("thickLineColor"), Configuration::editor_ThickLineColor()); 0120 setProperty(QStringLiteral("thinLineColor"), Configuration::editor_ThinLineColor()); 0121 0122 setUrl(QUrl(i18n("Untitled"))); 0123 } 0124 0125 QUndoStack &Document::undoStack() 0126 { 0127 return m_undoStack; 0128 } 0129 0130 void Document::setUrl(const QUrl &url) 0131 { 0132 m_url = url; 0133 } 0134 0135 QUrl Document::url() const 0136 { 0137 return m_url; 0138 } 0139 0140 void Document::addView(Editor *editor) 0141 { 0142 m_editor = editor; 0143 } 0144 0145 void Document::addView(Palette *palette) 0146 { 0147 m_palette = palette; 0148 } 0149 0150 void Document::addView(Preview *preview) 0151 { 0152 m_preview = preview; 0153 } 0154 0155 Editor *Document::editor() const 0156 { 0157 return m_editor; 0158 } 0159 0160 Palette *Document::palette() const 0161 { 0162 return m_palette; 0163 } 0164 0165 Preview *Document::preview() const 0166 { 0167 return m_preview; 0168 } 0169 0170 BackgroundImages &Document::backgroundImages() 0171 { 0172 return m_backgroundImages; 0173 } 0174 0175 Pattern *Document::pattern() 0176 { 0177 return m_pattern; 0178 } 0179 0180 const PrinterConfiguration &Document::printerConfiguration() const 0181 { 0182 return m_printerConfiguration; 0183 } 0184 0185 void Document::setPrinterConfiguration(const PrinterConfiguration &printerConfiguration) 0186 { 0187 m_printerConfiguration = printerConfiguration; 0188 } 0189 0190 void Document::readKXStitch(QDataStream &stream) 0191 { 0192 initialiseNew(); 0193 0194 char header[30]; 0195 stream.readRawData(header, 30); 0196 0197 if (strncmp(header, "KXStitchDoc", 11) == 0) { 0198 // a current KXStitchDoc format file 0199 stream.device()->seek(11); 0200 Layers layers; 0201 qint32 version; 0202 stream >> version; 0203 0204 switch (version) { 0205 case 104: 0206 stream.setVersion(QDataStream::Qt_4_0); // maintain consistancy in the qt types 0207 stream >> m_properties; 0208 stream >> m_backgroundImages; 0209 stream >> *m_pattern; 0210 stream >> m_printerConfiguration; 0211 break; 0212 0213 case 103: 0214 stream.setVersion(QDataStream::Qt_4_0); // maintain consistancy in the qt types 0215 stream >> m_properties; 0216 stream >> m_backgroundImages; 0217 stream >> m_pattern->palette(); 0218 stream >> m_pattern->stitches(); 0219 stream >> m_printerConfiguration; 0220 break; 0221 0222 case 102: 0223 stream.setVersion(QDataStream::Qt_4_0); // maintain consistancy in the qt types 0224 stream >> m_properties; 0225 stream >> layers; 0226 stream >> m_backgroundImages; 0227 stream >> m_pattern->palette(); 0228 stream >> m_pattern->stitches(); 0229 stream >> m_printerConfiguration; 0230 break; 0231 0232 case 101: 0233 stream.setVersion(QDataStream::Qt_4_0); // maintain consistancy in the qt types 0234 [[gnu::fallthrough]]; // flow through to version 100 0235 0236 case 100: 0237 stream >> m_properties; 0238 stream >> layers; 0239 stream >> m_backgroundImages; 0240 stream >> m_pattern->palette(); 0241 stream >> m_pattern->stitches(); 0242 break; 0243 0244 default: 0245 throw InvalidFileVersion(QString(i18n("KXStitch version %1", version))); 0246 break; 0247 } 0248 } else if (strncmp(header, "\x00\x00\x00\x10\x00\x4B\x00\x58\x00\x53\x00\x74\x00\x69\x00\x74\x00\x63\x00\x68", 20) == 0) { // QString("KXStitch") 0249 stream.device()->seek(20); 0250 qint16 version; 0251 stream >> version; 0252 0253 switch (version) { 0254 case 2: 0255 readKXStitchV2File(stream); 0256 break; 0257 0258 case 3: 0259 readKXStitchV3File(stream); 0260 break; 0261 0262 case 4: 0263 readKXStitchV4File(stream); 0264 break; 0265 0266 case 5: 0267 readKXStitchV5File(stream); 0268 break; 0269 0270 case 6: 0271 readKXStitchV6File(stream); 0272 break; 0273 0274 case 7: 0275 readKXStitchV7File(stream); 0276 break; 0277 0278 default: 0279 throw InvalidFileVersion(QString(i18n("KXStitch version %1", version))); 0280 break; 0281 } 0282 } else { 0283 throw InvalidFile(); 0284 } 0285 } 0286 0287 void Document::readPCStitch(QDataStream &stream) 0288 { 0289 initialiseNew(); 0290 0291 char header[23]; 0292 stream.readRawData(header, 23); 0293 0294 if (strncmp(header, "PCStitch 5 Pattern File", 23) == 0) { 0295 readPCStitch5File(stream); 0296 } else if (strncmp(header, "PCStitch 6 Pattern File", 23) == 0) { 0297 readPCStitch6File(stream); 0298 } else if (strncmp(header, "PCStitch 7 Pattern File", 23) == 0) { 0299 readPCStitch7File(stream); 0300 } else { 0301 throw InvalidFile(); 0302 } 0303 } 0304 0305 void Document::write(QDataStream &stream) 0306 { 0307 stream.setVersion(QDataStream::Qt_4_0); // maintain consistancy in the qt types 0308 stream.writeRawData("KXStitchDoc", 11); 0309 stream << version; 0310 stream << m_properties; 0311 stream << m_backgroundImages; 0312 stream << *m_pattern; 0313 stream << m_printerConfiguration; 0314 0315 if (stream.status() != QDataStream::Ok) { 0316 throw FailedWriteFile(stream.status()); 0317 } 0318 } 0319 0320 QVariant Document::property(const QString &name) const 0321 { 0322 QVariant p; 0323 0324 if (m_properties.contains(name)) { 0325 p = m_properties[name]; 0326 } else { 0327 qDebug() << "Asked for non existing property" << name; 0328 } 0329 0330 return p; 0331 } 0332 0333 void Document::setProperty(const QString &name, const QVariant &value) 0334 { 0335 m_properties[name] = value; 0336 } 0337 0338 void Document::readPCStitch5File(QDataStream &stream) 0339 { 0340 /* File Format 0341 uchar[256] // header 'PCStitch 5 Pattern File' 0342 // other information is contained here 0343 uchar[4] // unknown 0344 uchar[4] // unknown, there is something unique to each file here 0345 quint16 // pattern width; 0346 quint16 // pattern height; 0347 quint16 // cloth count width; 0348 quint16 // cloth count height; 0349 quint16 // string length 0350 char[] // author 0351 quint16 // string length 0352 char[] // copyright 0353 quint16 // string length 0354 char[] // title 0355 quint16 // string length 0356 char[] // fabric 0357 quint16 // string length 0358 char[] // instructions 0359 char[25] // 'PCStitch 5 Floss Palette!' 0360 quint16 // palette entries 0361 char[10] // 'DMC ' 0362 char[10] // 'Anchor ' 0363 char[10] // 'Coates ' 0364 quint16 // string length 0365 char[] // symbol font 0366 uchar[4] // unknown 0367 0368 struct paletteEntry { 0369 uchar[4] // RGBA 0370 char[10]; // dmc color name 0371 char[10]; // anchor color name 0372 char[10]; // coates color name 0373 char[50]; // color description 0374 char // symbol 0375 quint16 // number of strands for stitches 0376 quint16 // number of strands for backstitches 0377 } repeated for the number of palette entries 0378 0379 struct stitches { 0380 quint16 // stitch count in columns from top left downward 0381 quint8 // color, 1 based index of color list, 0xFF for none 0382 quint8 // stitch type, 0xFF for none 0383 } repeat until sum of stitchCount == width * height; 0384 0385 quint32 extras 0386 struct extra { 0387 quint16 // x coordinate, 1 based index of cell 0388 quint16 // y coordinate, 1 based index of cell 0389 struct quadrant { 0390 quint8 // color, 1 based index of color list, 0xFF for none 0391 quint8 // stitch type, 0xFF for none 0392 } repeated 4 times 0393 } repeated for extras 0394 0395 quint32 knots 0396 struct knot { 0397 quint16 // x coordinate, 1 based index of snap points 0398 quint16 // y coordinate, 1 based index of snap points 0399 quint8 // color, 1 based index of color list 0400 } repeated for knots 0401 0402 quint32 backstitches 0403 struct backstitch { 0404 quint16 // start x, 1 based index of cell 0405 quint16 // start y, 1 based index of cell 0406 quint16 // start position, (1-9) based on snap points 0407 quint16 // end x, 1 based index of cell 0408 quint16 // end y, 1 based index of cell 0409 quint16 // end position, (1-9) based on snap points 0410 quint8 // color, 1 based index of color list 0411 } repeat for backstitches 0412 0413 uchar[4] // unknown; 0414 uchar[4] // unknown; 0415 */ 0416 stream.setByteOrder(QDataStream::LittleEndian); 0417 stream.device()->seek(256); 0418 0419 quint32 unknown32; 0420 stream >> unknown32; 0421 stream >> unknown32; 0422 0423 quint16 width; 0424 quint16 height; 0425 stream >> width; 0426 stream >> height; 0427 0428 m_pattern->stitches().resize(width, height); 0429 setProperty(QStringLiteral("unitsFormat"), Configuration::EnumDocument_UnitsFormat::Stitches); 0430 0431 quint16 clothCount; 0432 stream >> clothCount; 0433 setProperty(QStringLiteral("horizontalClothCount"), double(clothCount)); 0434 stream >> clothCount; 0435 setProperty(QStringLiteral("verticalClothCount"), double(clothCount)); 0436 setProperty(QStringLiteral("clothCountUnits"), Configuration::EnumEditor_ClothCountUnits::Inches); 0437 0438 setProperty(QStringLiteral("author"), readPCStitchString(stream)); 0439 setProperty(QStringLiteral("copyright"), readPCStitchString(stream)); 0440 setProperty(QStringLiteral("title"), readPCStitchString(stream)); 0441 setProperty(QStringLiteral("fabric"), readPCStitchString(stream)); 0442 setProperty(QStringLiteral("fabricColor"), QColor(Qt::white)); 0443 0444 QString instructions = readPCStitchString(stream); 0445 0446 if (!instructions.isEmpty()) { 0447 int index = instructions.indexOf(QLatin1String("}}")); // end of font defs 0448 index += 4; // skip paste }} and CR LF 0449 index = instructions.indexOf(QLatin1Char('}'), index); // end of color table defs 0450 index += 3; // skip paste } and CR LF 0451 index = instructions.indexOf(QLatin1Char(' '), index); // find first space - end of text def 0452 index++; // and skip past it 0453 // index should now point to the first character of the instructions 0454 instructions = instructions.remove(0, index); 0455 instructions.truncate(instructions.length() - 10); 0456 } 0457 0458 setProperty(QStringLiteral("instructions"), instructions); 0459 0460 char buffer[51]; 0461 stream.readRawData(buffer, 25); 0462 0463 if (strncmp(buffer, "PCStitch 5 Floss Palette!", 25) == 0) { 0464 quint16 colors; 0465 stream >> colors; 0466 0467 stream.readRawData(buffer, 30); // this should be 'DMC Anchor Coates ' 0468 0469 QString fontName = readPCStitchString(stream); // the font name, usually 'PCStitch Symbols' 0470 0471 m_pattern->palette().setSchemeName(QStringLiteral("DMC")); // assume this palette will be DMC 0472 FlossScheme *scheme = SchemeManager::scheme(QStringLiteral("DMC")); 0473 0474 if (scheme == nullptr) { 0475 throw FailedReadFile(QString(i18n("The floss scheme DMC was not found"))); // this shouldn't happen because DMC should always be available 0476 } 0477 0478 stream >> unknown32; 0479 0480 for (int i = 0; i < colors; i++) { 0481 #pragma pack(push) 0482 #pragma pack(1) 0483 struct PALETTE_ENTRY { 0484 unsigned char RGBA[4]; 0485 char colorName[30]; 0486 char colorDescription[50]; 0487 unsigned char symbol; 0488 unsigned short stitchStrands; 0489 unsigned short backstitchStrands; 0490 } paletteEntry; 0491 #pragma pack(pop) 0492 0493 stream.readRawData(reinterpret_cast<char *>(&paletteEntry), sizeof(struct PALETTE_ENTRY)); 0494 0495 QColor color(int(paletteEntry.RGBA[0]), int(paletteEntry.RGBA[1]), int(paletteEntry.RGBA[2])); 0496 QString colorName = QString::fromLatin1(paletteEntry.colorName, 10).trimmed(); 0497 0498 if (colorName == QLatin1String("White")) { 0499 colorName = QLatin1String("Blanc"); // fix colorName 0500 } 0501 0502 if (colorName == QLatin1String("5200")) { 0503 colorName = QLatin1String("B5200"); // fix colorName 0504 } 0505 0506 Floss *floss = scheme->find(colorName); 0507 0508 if (floss == nullptr) { 0509 floss = scheme->convert(color); 0510 } 0511 0512 colorName = floss->name(); 0513 DocumentFloss *documentFloss = 0514 new DocumentFloss(colorName, 0515 m_pattern->palette().freeSymbol(), 0516 Qt::SolidLine, 0517 (paletteEntry.stitchStrands) ? paletteEntry.stitchStrands : Configuration::palette_StitchStrands(), 0518 (paletteEntry.backstitchStrands) ? paletteEntry.backstitchStrands : Configuration::palette_BackstitchStrands()); 0519 documentFloss->setFlossColor(floss->color()); 0520 m_pattern->palette().add(i, documentFloss); 0521 } 0522 } else { 0523 throw FailedReadFile(QString(i18n("Invalid data read."))); 0524 } 0525 0526 m_pattern->palette().setCurrentIndex(-1); 0527 0528 Stitch::Type stitchType[] = {Stitch::Delete, 0529 Stitch::Full, 0530 Stitch::TL3Qtr, 0531 Stitch::TR3Qtr, 0532 Stitch::BL3Qtr, 0533 Stitch::BR3Qtr, 0534 Stitch::TBHalf, 0535 Stitch::BTHalf, 0536 Stitch::Delete, 0537 Stitch::TLQtr, 0538 Stitch::TRQtr, 0539 Stitch::BLQtr, 0540 Stitch::BRQtr}; // conversion of PCStitch to KXStitch 0541 0542 int documentWidth = m_pattern->stitches().width(); 0543 int documentHeight = m_pattern->stitches().height(); 0544 int cells = documentWidth * documentHeight; 0545 0546 quint16 cellCount; 0547 0548 for (int i = 0; i < cells; i += cellCount) { 0549 quint8 color; 0550 quint8 type; 0551 0552 stream >> cellCount; 0553 stream >> color; 0554 stream >> type; 0555 0556 if (type != 0xff) { 0557 for (int c = 0; c < cellCount; c++) { 0558 int xc = (i + c) / documentHeight; 0559 int yc = (i + c) % documentHeight; 0560 m_pattern->stitches().addStitch(QPoint(xc, yc), stitchType[type], color - 1); // color-1 because PCStitch uses 1 based array 0561 } 0562 } 0563 } 0564 0565 quint32 extras; 0566 stream >> extras; 0567 0568 while (extras--) { 0569 quint16 x; 0570 quint16 y; 0571 quint8 color; 0572 quint8 type; 0573 0574 stream >> x; 0575 stream >> y; 0576 0577 for (int dx = 0; dx < 4; dx++) { 0578 stream >> color; 0579 stream >> type; 0580 0581 if (type != 0xff) { 0582 m_pattern->stitches().addStitch(QPoint(x - 1, y - 1), stitchType[type], color - 1); 0583 } 0584 } 0585 } 0586 0587 // read french knots 0588 0589 quint32 knots; 0590 stream >> knots; 0591 0592 while (knots--) { 0593 quint16 x; 0594 quint16 y; 0595 quint8 color; 0596 0597 stream >> x; 0598 stream >> y; 0599 stream >> color; 0600 m_pattern->stitches().addFrenchKnot(QPoint(x - 1, y - 1), color - 1); 0601 } 0602 0603 // read backstitches 0604 0605 quint32 backstitches; 0606 stream >> backstitches; 0607 0608 while (backstitches--) { 0609 quint16 sx; 0610 quint16 sy; 0611 quint16 sp; 0612 quint16 ex; 0613 quint16 ey; 0614 quint16 ep; 0615 quint8 color; 0616 stream >> sx >> sy >> sp >> ex >> ey >> ep >> color; 0617 m_pattern->stitches().addBackstitch(QPoint(--sx * 2 + ((sp - 1) % 3), --sy * 2 + ((sp - 1) / 3)), 0618 QPoint(--ex * 2 + ((ep - 1) % 3), --ey * 2 + ((ep - 1) / 3)), 0619 color - 1); 0620 } 0621 0622 if (stream.status() != QDataStream::Ok) { 0623 throw FailedReadFile(QString(i18n("Stream error"))); 0624 } 0625 } 0626 0627 void Document::readPCStitch6File(QDataStream &stream) 0628 { 0629 /* File Format 0630 uchar[256] // header 'PCStitch 6 Pattern File' 0631 // other information is contained here 0632 uchar[4] // unknown 0633 uchar[4] // unknown, there is something unique to each file here 0634 quint16 // pattern width 0635 quint16 // pattern height 0636 quint16 // cloth count width 0637 quint16 // cloth count height 0638 quint16 // string length 0639 char[] // author 0640 quint16 // string length 0641 char[] // copyright 0642 quint16 // string length 0643 char[] // title 0644 quint16 // string length 0645 char[] // fabric 0646 quint16 // string length 0647 char[] // instructions 0648 char[25] // 'PCStitch 6 Floss Palette!' 0649 quint16 // unknown 0650 char[30] // 'DMC' padded with spaces 0651 char[10] // scheme 0652 quint16 // palette entries 0653 quint16 // string length 0654 char[] // symbol font 0655 uchar[4] // unknown 0656 0657 struct paletteEntry { 0658 char[30] // color description 0659 uchar[4] // RGBA 0660 char[10] // color name 0661 uchar[65] // unknown 0662 // 59 unknown 0663 // quint16 stitchStrands 0664 // quint16 backstitchStrands 0665 // quint16 possibly palette index (seems to increment from 1 to the number of palette entries, but odd files don't) 0666 char[30] // color description 0667 uchar[5] // unknown 0668 uchar[25] // some color // Black <padded with spaces> (possibly symbol color) 0669 } repeated for the number of palette entries 0670 0671 struct stitches { 0672 quint16 // stitch count in columns from top left downward 0673 quint8 // color, 1 based index of color list, 0xFF for none 0674 quint8 // stitch type, 0xFF for none 0675 } repeated until sum of stitchCount == width * height 0676 0677 quint32 extras 0678 struct extra { 0679 quint16 // x coordinate, 1 based index of cell 0680 quint16 // y coordinate, 1 based index of cell 0681 struct quadrant { 0682 quint8 // color, 1 based index of color list, 0xFF for none 0683 quint8 // stitch type, 0xFF for none 0684 } repeated 4 times 0685 } repeated for extras 0686 0687 quint32 // unknown 0688 0689 quint32 knots 0690 struct knot { 0691 quint16 // x coordinate, 1 based index of snap points 0692 quint16 // y coordinate, 1 based index of snap points 0693 quint8 // color, 1 based index of color list 0694 } repeated for knots 0695 0696 uint32 backstitches 0697 struct backstitch { 0698 quint16 // start x, 1 based index of cell 0699 quint16 // start y, 1 based index of cell 0700 quint16 // start position, (1..9) based on snap points 0701 quint16 // end x, 1 based index of cell 0702 quint16 // end y, 1 based index of cell 0703 quint16 // end position, (1..9) based on snap points 0704 quint16 // color, 1 based index of color list 0705 } repeat for backstitches 0706 0707 uchar[4] // unknown 0708 uchar[4] // unknown 0709 */ 0710 stream.setByteOrder(QDataStream::LittleEndian); 0711 stream.device()->seek(256); 0712 0713 quint16 unknown16; 0714 quint32 unknown32; 0715 0716 stream >> unknown32; 0717 stream >> unknown32; 0718 0719 quint16 width; 0720 quint16 height; 0721 stream >> width; 0722 stream >> height; 0723 0724 m_pattern->stitches().resize(width, height); 0725 setProperty(QStringLiteral("unitsFormat"), Configuration::EnumDocument_UnitsFormat::Stitches); 0726 0727 quint16 clothCount; 0728 stream >> clothCount; 0729 setProperty(QStringLiteral("horizontalClothCount"), double(clothCount)); 0730 stream >> clothCount; 0731 setProperty(QStringLiteral("verticalClothCount"), double(clothCount)); 0732 setProperty(QStringLiteral("clothCountUnits"), Configuration::EnumEditor_ClothCountUnits::Inches); 0733 0734 setProperty(QStringLiteral("author"), readPCStitchString(stream)); 0735 setProperty(QStringLiteral("copyright"), readPCStitchString(stream)); 0736 setProperty(QStringLiteral("title"), readPCStitchString(stream)); 0737 setProperty(QStringLiteral("fabric"), readPCStitchString(stream)); 0738 setProperty(QStringLiteral("fabricColor"), QColor(Qt::white)); 0739 0740 QString instructions = readPCStitchString(stream); 0741 0742 if (!instructions.isEmpty()) { 0743 int index = instructions.indexOf(QLatin1String("}}")); // end of font defs 0744 index += 4; // skip paste }} and CR LF 0745 index = instructions.indexOf(QLatin1Char(' '), index); // find first space - end of text def 0746 index++; // and skip past it 0747 // index should now point to the first character of the instructions 0748 instructions = instructions.remove(0, index); 0749 instructions.truncate(instructions.length() - 10); 0750 } 0751 0752 setProperty(QStringLiteral("instructions"), instructions); 0753 0754 char buffer[125]; 0755 stream.readRawData(buffer, 25); 0756 0757 if (strncmp(buffer, "PCStitch 6 Floss Palette!", 25) == 0) { 0758 stream >> unknown16; 0759 stream.readRawData(buffer, 40); 0760 0761 quint16 colors; 0762 stream >> colors; 0763 0764 readPCStitchString(stream); // symbols font 0765 0766 stream >> unknown32; 0767 0768 m_pattern->palette().setSchemeName(QStringLiteral("DMC")); 0769 FlossScheme *scheme = SchemeManager::scheme(QStringLiteral("DMC")); 0770 0771 if (scheme == nullptr) { 0772 throw FailedReadFile(QString(i18n("The floss scheme DMC was not found"))); // this shouldn't happen because DMC should always be available 0773 } 0774 0775 for (int i = 0; i < colors; i++) { 0776 #pragma pack(push) 0777 #pragma pack(1) // pack the structure 0778 struct PALETTE_ENTRY { 0779 char colorDescription_1[30]; 0780 unsigned char RGBA[4]; 0781 char colorName_1[10]; 0782 unsigned char unknown_1[59]; 0783 unsigned short stitchStrands; 0784 unsigned short backstitchStrands; 0785 unsigned short unknown_2; 0786 char colorDescription_2[30]; 0787 unsigned char unknown_3[5]; 0788 char colorName_2[25]; // seems to be Black all the time 0789 } paletteEntry; 0790 #pragma pack(pop) 0791 0792 stream.readRawData(reinterpret_cast<char *>(&paletteEntry), sizeof(struct PALETTE_ENTRY)); 0793 0794 QColor color = QColor(paletteEntry.RGBA[0], paletteEntry.RGBA[1], paletteEntry.RGBA[2]); 0795 QString colorName = QString::fromLatin1(paletteEntry.colorName_1, 10).trimmed(); // minus the white space 0796 0797 if (colorName == QLatin1String("White")) { 0798 colorName = QLatin1String("Blanc"); // fix colorName 0799 } 0800 0801 if (colorName == QLatin1String("5200")) { 0802 colorName = QLatin1String("B5200"); // fix colorName 0803 } 0804 0805 Floss *floss = scheme->find(colorName); 0806 0807 if (floss == nullptr) { 0808 floss = scheme->convert(color); // the name wasn't found so look for a similar color in DMC 0809 } 0810 0811 colorName = floss->name(); 0812 DocumentFloss *documentFloss = 0813 new DocumentFloss(colorName, m_pattern->palette().freeSymbol(), Qt::SolidLine, paletteEntry.stitchStrands, paletteEntry.backstitchStrands); 0814 documentFloss->setFlossColor(floss->color()); 0815 m_pattern->palette().add(i, documentFloss); 0816 } 0817 } else { 0818 throw FailedReadFile(QString(i18n("Invalid data read."))); 0819 } 0820 0821 m_pattern->palette().setCurrentIndex(-1); 0822 0823 Stitch::Type stitchType[] = {Stitch::Delete, 0824 Stitch::Full, 0825 Stitch::TL3Qtr, 0826 Stitch::TR3Qtr, 0827 Stitch::BL3Qtr, 0828 Stitch::BR3Qtr, 0829 Stitch::TBHalf, 0830 Stitch::BTHalf, 0831 Stitch::Delete, 0832 Stitch::TLQtr, 0833 Stitch::TRQtr, 0834 Stitch::BLQtr, 0835 Stitch::BRQtr}; // conversion of PCStitch to KXStitch 0836 0837 int documentWidth = m_pattern->stitches().width(); 0838 int documentHeight = m_pattern->stitches().height(); 0839 int cells = documentWidth * documentHeight; 0840 0841 quint16 cellCount; 0842 0843 for (int i = 0; i < cells; i += cellCount) { 0844 quint8 color; 0845 quint8 type; 0846 0847 stream >> cellCount; 0848 stream >> color; 0849 stream >> type; 0850 0851 if (type != 0xff) { 0852 for (int c = 0; c < cellCount; c++) { 0853 int xc = (i + c) / documentHeight; 0854 int yc = (i + c) % documentHeight; 0855 m_pattern->stitches().addStitch(QPoint(xc, yc), stitchType[type], color - 1); // color-1 because PCStitch uses 1 based array 0856 } 0857 } 0858 } 0859 0860 quint32 extras; 0861 stream >> extras; 0862 0863 while (extras--) { 0864 qint16 x; 0865 qint16 y; 0866 quint8 color; 0867 quint8 type; 0868 0869 stream >> x; 0870 stream >> y; 0871 0872 for (int dx = 0; dx < 4; dx++) { 0873 stream >> color; 0874 stream >> type; 0875 0876 if (type != 0xff) { 0877 m_pattern->stitches().addStitch(QPoint(x - 1, y - 1), stitchType[type], color - 1); 0878 } 0879 } 0880 } 0881 0882 // read french knots 0883 0884 quint32 knots; 0885 stream >> knots; 0886 0887 while (knots--) { 0888 qint16 x; 0889 qint16 y; 0890 quint8 color; 0891 0892 stream >> x; 0893 stream >> y; 0894 stream >> color; 0895 m_pattern->stitches().addFrenchKnot(QPoint(x - 1, y - 1), color - 1); 0896 } 0897 0898 // read backstitches 0899 0900 qint32 backstitches; 0901 stream >> backstitches; 0902 0903 while (backstitches--) { 0904 qint16 sx; 0905 qint16 sy; 0906 qint16 sp; 0907 qint16 ex; 0908 qint16 ey; 0909 qint16 ep; 0910 quint16 color; 0911 stream >> sx >> sy >> sp >> ex >> ey >> ep >> color; 0912 m_pattern->stitches().addBackstitch(QPoint(--sx * 2 + ((sp - 1) % 3), --sy * 2 + ((sp - 1) / 3)), 0913 QPoint(--ex * 2 + ((ep - 1) % 3), --ey * 2 + ((ep - 1) / 3)), 0914 color - 1); 0915 } 0916 0917 if (stream.status() != QDataStream::Ok) { 0918 throw FailedReadFile(QString(i18n("Stream error"))); 0919 } 0920 } 0921 0922 void Document::readPCStitch7File(QDataStream &stream) 0923 { 0924 /* File Format 0925 uchar[256] // header 'PCStitch 7 Pattern File' 0926 // other information is contained here 0927 uchar[4] // unknown 0928 uchar[4] // unknown, there is something unique to each file here 0929 quint16 // pattern width 0930 quint16 // pattern height 0931 quint16 // cloth count width 0932 quint16 // cloth count height 0933 uchar[4] // RGBA - fabric colour 0934 quint16 // string length 0935 char[] // author 0936 quint16 // string length 0937 char[] // copyright 0938 quint16 // string length 0939 char[] // title 0940 quint16 // string length 0941 char[] // fabric 0942 quint16 // string length 0943 char[] // instructions 0944 quint16 // string length 0945 char[] // keywords 0946 quint16 // string length 0947 char[] // website 0948 uchar[4] // unknown - varies e.g. (0x02 0x00 0x02 0x00) (0x02 0x00 0x01 0x00) 0949 // possible default stitch / backstitch strands quint16 0950 char[25] // 'PCStitch Floss Palette!!!' 0951 uchar[4] // unknown 0952 quint16 // palette entries 0953 0954 [ 0955 other possible entries within the header may be 0956 company 0957 logo 0958 read only flag 0959 read only password 0960 stitches/inches flag - size maybe in inches 0961 square weave flag 0962 ] 0963 0964 struct paletteEntry { 0965 char[33] // scheme 0966 // palette allows for multiple schemes to be used 0967 // keycode used to identify source list 0968 char[10] // color name 0969 char[30] // color description 0970 uchar[4] // unknown 0971 uchar[4] // RGBA 0972 uchar[81] // unknown 0973 char[30] // symbol font 0974 uchar[7] // 0x00 0x00 0x42 0x00 0x00 0x00 0x00 - varies (symbols probably here, 3rd for stitches?) 0975 char[30] // color description 0976 uchar[4] // RGBA 0977 char[10] // color name 0978 uchar[7] // 0x00 0x00 0x00 0x00 0x00 0x01 0x00 0979 // possibly stitch strands (not sure of order, 6th possibly backstitch) 0x00 for default 0980 // Full, 3 quarter, quarter, petite, half, french, backstitches 0981 } repeated for the number of palette entries 0982 0983 struct stitches { 0984 quint16 // stitch count in columns from top left downward 0985 quint8 // color, 1 based index of color list, 0xFF for none 0986 quint8 // stitch type, 0xFF for none 0987 } repeated until sum of stitch count = width*height 0988 0989 uint32 extras 0990 struct extra { 0991 quint16 // x coordinate, 1 based index of cell 0992 quint16 // y coordinate, 1 based index of cell 0993 struct { 0994 quint8 // color, 1 based index of color list, 0xFF for none 0995 quint8 // stitch type, 0xFF for none 0996 } repeated 4 times 0997 } repeated for extras 0998 0999 uint32 knots 1000 struct knot { 1001 quint16 // x coordinate, 1 based index of snap points 1002 quint16 // y coordinate, 1 based index of snap points 1003 quint16 // color, 1 based index of color list 1004 } repeated for knotCount 1005 1006 uint32 backstitches 1007 struct backstitch { 1008 quint16 // start x, 1 based index of cell 1009 quint16 // start y, 1 based index of cell 1010 quint16 // start position, (1..9) based on snap points 1011 quint16 // end x, 1 based index of cell 1012 quint16 // end Y, 1 based index of cell 1013 quint16 // end position (1..9) based on snap points 1014 quint16 // color, 1 based index of color list 1015 } repeated for backstitches 1016 */ 1017 stream.setByteOrder(QDataStream::LittleEndian); 1018 stream.device()->seek(256); 1019 1020 quint32 unknown32; 1021 stream >> unknown32; 1022 stream >> unknown32; 1023 1024 quint16 width; 1025 quint16 height; 1026 stream >> width; 1027 stream >> height; 1028 1029 m_pattern->stitches().resize(width, height); 1030 setProperty(QStringLiteral("unitsFormat"), Configuration::EnumDocument_UnitsFormat::Stitches); 1031 1032 quint16 clothCount; 1033 stream >> clothCount; 1034 setProperty(QStringLiteral("horizontalClothCount"), double(clothCount)); 1035 stream >> clothCount; 1036 setProperty(QStringLiteral("verticalClothCount"), double(clothCount)); 1037 setProperty(QStringLiteral("clothCountUnits"), Configuration::EnumEditor_ClothCountUnits::Inches); 1038 1039 unsigned char r; 1040 unsigned char g; 1041 unsigned char b; 1042 unsigned char a; 1043 stream >> r >> g >> b >> a; 1044 setProperty(QStringLiteral("fabricColor"), QColor(r, g, b)); // alpha defaults to 255 1045 setProperty(QStringLiteral("author"), readPCStitchString(stream)); 1046 setProperty(QStringLiteral("copyright"), readPCStitchString(stream)); 1047 setProperty(QStringLiteral("title"), readPCStitchString(stream)); 1048 setProperty(QStringLiteral("fabric"), readPCStitchString(stream)); 1049 1050 QString instructions = readPCStitchString(stream); 1051 1052 if (!instructions.isEmpty()) { 1053 int index = instructions.indexOf(QLatin1String("}}")); // end of font defs 1054 index += 4; // skip paste }} and CR LF 1055 index = instructions.indexOf(QLatin1Char(' '), index); // find first space - end of text def 1056 index++; // and skip past it 1057 // index should now point to the first character of the instructions 1058 instructions = instructions.remove(0, index); 1059 instructions.truncate(instructions.length() - 10); 1060 } 1061 1062 setProperty(QStringLiteral("instructions"), instructions); 1063 1064 QString keywords(readPCStitchString(stream)); 1065 QString website(readPCStitchString(stream)); 1066 1067 quint16 defaultStitchStrands; 1068 quint16 defaultBackstitchStrands; 1069 stream >> defaultStitchStrands >> defaultBackstitchStrands; 1070 1071 char *buffer = new char[25]; 1072 stream.readRawData(buffer, 25); 1073 1074 if (strncmp(buffer, "PCStitch Floss Palette!!!", 25) == 0) { 1075 stream >> unknown32; 1076 1077 quint16 colors; 1078 stream >> colors; 1079 1080 m_pattern->palette().setSchemeName(QStringLiteral("DMC")); 1081 FlossScheme *scheme = SchemeManager::scheme(QStringLiteral("DMC")); 1082 1083 if (scheme == nullptr) { 1084 throw FailedReadFile(QString(i18n("The floss scheme DMC was not found"))); // this shouldn't happen because DMC should always be available 1085 } 1086 1087 for (int i = 0; i < colors; i++) { 1088 #pragma pack(push) 1089 #pragma pack(1) 1090 struct PALETTE_ENTRY { 1091 char scheme[33]; 1092 char colorName_1[10]; 1093 char colorDescription_1[30]; 1094 uchar unknown_1[4]; 1095 uchar RGBA_1[4]; 1096 uchar unknown_2[81]; 1097 char font[30]; 1098 uchar unknown_3[7]; 1099 char colorDescription_2[30]; 1100 uchar RGBA_2[4]; 1101 char colorName_2[10]; 1102 uchar unknown_4[7]; 1103 } paletteEntry; 1104 #pragma pack(pop) 1105 1106 stream.readRawData(reinterpret_cast<char *>(&paletteEntry), sizeof(struct PALETTE_ENTRY)); 1107 1108 QColor color = QColor(int(paletteEntry.RGBA_1[0]), int(paletteEntry.RGBA_1[1]), int(paletteEntry.RGBA_1[2])); 1109 QString colorName = QString::fromLatin1(paletteEntry.colorName_1, 10).trimmed(); // minus the white space 1110 1111 if (colorName == QLatin1String("White")) { 1112 colorName = QLatin1String("Blanc"); // fix colorName 1113 } 1114 1115 if (colorName == QLatin1String("5200")) { 1116 colorName = QLatin1String("B5200"); // fix colorName 1117 } 1118 1119 Floss *floss = scheme->find(colorName); 1120 1121 if (floss == nullptr) { 1122 floss = scheme->convert(color); // the name wasn't found so look for a similar color in DMC 1123 } 1124 1125 colorName = floss->name(); 1126 DocumentFloss *documentFloss = 1127 new DocumentFloss(colorName, m_pattern->palette().freeSymbol(), Qt::SolidLine, defaultStitchStrands, defaultBackstitchStrands); 1128 documentFloss->setFlossColor(floss->color()); 1129 m_pattern->palette().add(i, documentFloss); 1130 } 1131 } else { 1132 throw FailedReadFile(QString(i18n("Invalid data read."))); 1133 } 1134 1135 m_pattern->palette().setCurrentIndex(-1); 1136 1137 Stitch::Type stitchType[] = {Stitch::Delete, 1138 Stitch::Full, 1139 Stitch::TL3Qtr, 1140 Stitch::TR3Qtr, 1141 Stitch::BL3Qtr, 1142 Stitch::BR3Qtr, 1143 Stitch::TBHalf, 1144 Stitch::BTHalf, 1145 Stitch::Delete, 1146 Stitch::TLQtr, 1147 Stitch::TRQtr, 1148 Stitch::BLQtr, 1149 Stitch::BRQtr}; // conversion of PCStitch to KXStitch 1150 // TODO above needs to include petite stitches 1151 int documentWidth = m_pattern->stitches().width(); 1152 int documentHeight = m_pattern->stitches().height(); 1153 int cells = documentWidth * documentHeight; 1154 1155 quint16 cellCount; 1156 1157 for (int i = 0; i < cells; i += cellCount) { 1158 quint8 color; 1159 quint8 type; 1160 1161 stream >> cellCount; 1162 stream >> color; 1163 stream >> type; 1164 1165 if (type != 0xff) { 1166 for (int c = 0; c < cellCount; c++) { 1167 int xc = (i + c) / documentHeight; 1168 int yc = (i + c) % documentHeight; 1169 m_pattern->stitches().addStitch(QPoint(xc, yc), stitchType[type], color - 1); // color-1 because PCStitch uses 1 based array 1170 } 1171 } 1172 } 1173 1174 quint32 extras; 1175 stream >> extras; 1176 1177 while (extras--) { 1178 quint16 x; 1179 quint16 y; 1180 quint8 color; 1181 quint8 type; 1182 1183 stream >> x; 1184 stream >> y; 1185 1186 for (int dx = 0; dx < 4; dx++) { 1187 stream >> color; 1188 stream >> type; 1189 1190 if (type != 0xff) { 1191 m_pattern->stitches().addStitch(QPoint(x - 1, y - 1), stitchType[type], color - 1); 1192 } 1193 } 1194 } 1195 1196 // read french knots 1197 1198 quint32 knots; 1199 stream >> knots; 1200 1201 while (knots--) { 1202 quint16 x; 1203 quint16 y; 1204 quint16 color; 1205 1206 stream >> x; 1207 stream >> y; 1208 stream >> color; 1209 m_pattern->stitches().addFrenchKnot(QPoint(x - 1, y - 1), color - 1); 1210 } 1211 1212 // read backstitches 1213 1214 quint32 backstitches; 1215 stream >> backstitches; 1216 1217 while (backstitches--) { 1218 quint16 sx; 1219 quint16 sy; 1220 quint16 sp; 1221 quint16 ex; 1222 quint16 ey; 1223 quint16 ep; 1224 quint16 color; 1225 stream >> sx >> sy >> sp >> ex >> ey >> ep >> color; 1226 m_pattern->stitches().addBackstitch(QPoint(--sx * 2 + ((sp - 1) % 3), --sy * 2 + ((sp - 1) / 3)), 1227 QPoint(--ex * 2 + ((ep - 1) % 3), --ey * 2 + ((ep - 1) / 3)), 1228 color - 1); 1229 } 1230 1231 if (stream.status() != QDataStream::Ok) { 1232 throw FailedReadFile(QString(i18n("Stream error"))); 1233 } 1234 } 1235 1236 QString Document::readPCStitchString(QDataStream &stream) 1237 { 1238 char *buffer; 1239 quint16 stringSize; 1240 stream >> stringSize; 1241 buffer = new char[stringSize + 1]; 1242 stream.readRawData(buffer, stringSize); 1243 buffer[stringSize] = '\0'; 1244 QString string = QString::fromLatin1(buffer); 1245 delete[] buffer; 1246 1247 if (stream.status() != QDataStream::Ok) { 1248 throw FailedReadFile(QString(i18n("Stream error"))); 1249 } 1250 1251 return string; 1252 } 1253 1254 void Document::readKXStitchV2File(QDataStream &stream) 1255 { 1256 /* File format 1257 // header 1258 #QString("KXStitch") // read in the load function 1259 #qint16(FILE_FORMAT_VERSION) // read in the load function 1260 QString(title) 1261 QString(author) 1262 QString(fabric) 1263 QColor(fabricColor) // serialised format has changed over the various versions of qt. 1264 // for older versions this appears to be quint8 red, quint8 green quint8 blue, quint8 alpha 1265 qint16(index from flossscheme qcombobox) // unpredictable, palette stream will contain the scheme name 1266 qint16(inches) // boolean, true if the size displayed is in inches 1267 qint32(width) // width of pattern (is this in stitches or inches?) // discard in favour of stitchdata width 1268 qint32(height) // height of pattern (is this in stitches or inches?) // discard in favour of stitchdata height 1269 qint32(clothCount) // this needs to be converted to a double 1270 QString(instructions) 1271 1272 // palette 1273 qint32(current) // the current color selected 1274 qint32(colors) // number of colors in the palette 1275 QString(schemeName) 1276 QString(flossName) ] 1277 QString(flossDescription) ] Repeated for each 1278 QColor(flossColor) ] entry in the palette, note comment above regarding QColor 1279 qint16(flossSymbol) ] 1280 1281 // stitches 1282 qint32(width) // width in stitches // use instead of width from the header which might be in inches 1283 qint32(height) // height in stitches // use instead of height from the header which might be in inches 1284 qint8(stitches) ] 1285 qint8(type) ] Repeated for ] Repeated for 1286 qint16(colorIndex) ] each stitch ] each stitchqueue 1287 1288 // backstitches 1289 qint32(backstitches) // the number of backstitches 1290 QPoint(start) ] 1291 QPoint(end) ] Repeated for 1292 qint16(colorIndex) ] each backstitch 1293 1294 // there were no knots supported in this version 1295 */ 1296 1297 /* this is currently untested */ 1298 // read header 1299 QString title; 1300 QString author; 1301 QString fabric; 1302 stream >> title >> author >> fabric; 1303 setProperty(QStringLiteral("title"), title); 1304 setProperty(QStringLiteral("author"), author); 1305 setProperty(QStringLiteral("fabric"), fabric); 1306 1307 quint8 red; 1308 quint8 green; 1309 quint8 blue; 1310 quint8 alpha; 1311 stream >> red >> green >> blue >> alpha; 1312 setProperty(QStringLiteral("fabricColor"), QColor(red, green, blue, alpha)); 1313 1314 qint16 schemeIndex; 1315 stream >> schemeIndex; // discard 1316 1317 qint16 inches; 1318 stream >> inches; 1319 setProperty(QStringLiteral("unitsFormat"), 1320 (bool(inches)) ? Configuration::EnumDocument_UnitsFormat::Inches : Configuration::EnumDocument_UnitsFormat::Stitches); 1321 1322 qint32 width; 1323 qint32 height; 1324 stream >> width >> height; 1325 1326 qint32 clothCount; 1327 stream >> clothCount; 1328 setProperty(QStringLiteral("clothCountUnits"), Configuration::EnumEditor_ClothCountUnits::Inches); 1329 setProperty(QStringLiteral("horizontalClothCount"), double(clothCount)); 1330 setProperty(QStringLiteral("verticalClothCount"), double(clothCount)); 1331 setProperty(QStringLiteral("clothCountLink"), true); 1332 1333 QString instructions; 1334 stream >> instructions; 1335 setProperty(QStringLiteral("instructions"), instructions); 1336 1337 // read palette 1338 qint32 current; 1339 stream >> current; 1340 1341 qint32 colors; 1342 stream >> colors; 1343 1344 QString schemeName; 1345 stream >> schemeName; 1346 m_pattern->palette().setSchemeName(schemeName); 1347 1348 FlossScheme *flossScheme = SchemeManager::scheme(schemeName); 1349 1350 if (flossScheme == nullptr) { 1351 throw FailedReadFile(QString(i18n("The floss scheme %1 was not found", schemeName))); 1352 } 1353 1354 int colorIndex = 0; 1355 1356 while (colors--) { 1357 QString flossName; 1358 QString flossDescription; 1359 // QColor color - read as rgba instead 1360 qint16 symbol; 1361 1362 stream >> flossName >> flossDescription >> red >> green >> blue >> alpha >> symbol; 1363 1364 Floss *floss = flossScheme->find(flossName); 1365 1366 if (floss == nullptr) { 1367 throw FailedReadFile(QString(i18n("The floss name %1 was not found", flossName))); 1368 } 1369 1370 DocumentFloss *documentFloss = new DocumentFloss(flossName, 1371 m_pattern->palette().freeSymbol(), 1372 Qt::SolidLine, 1373 Configuration::palette_StitchStrands(), 1374 Configuration::palette_BackstitchStrands()); 1375 documentFloss->setFlossColor(floss->color()); 1376 m_pattern->palette().add(colorIndex++, documentFloss); 1377 } 1378 1379 // read stitches 1380 stream >> width >> height; 1381 qint32 cells = width * height; 1382 m_pattern->stitches().resize(width, height); 1383 1384 for (int i = 0; i < cells; i++) { 1385 qint8 stitches; 1386 stream >> stitches; 1387 1388 while (stitches--) { 1389 qint8 type; 1390 qint16 colorIndex; 1391 stream >> type >> colorIndex; 1392 1393 m_pattern->stitches().addStitch(QPoint(i % width, i / width), Stitch::Type(type), colorIndex); 1394 } 1395 } 1396 1397 qint32 backstitches; 1398 stream >> backstitches; 1399 1400 while (backstitches--) { 1401 QPoint start; 1402 QPoint end; 1403 qint16 colorIndex; 1404 stream >> start >> end >> colorIndex; 1405 1406 m_pattern->stitches().addBackstitch(start, end, colorIndex); 1407 } 1408 1409 if (stream.status() != QDataStream::Ok) { 1410 throw FailedReadFile(QString(i18n("Stream error"))); 1411 } 1412 } 1413 1414 void Document::readKXStitchV3File(QDataStream &stream) 1415 { 1416 /* File format 1417 // header 1418 #QString("KXStitch") // read in the load function 1419 #qint16(FILE_FORMAT_VERSION) // read in the load function 1420 QString(title) 1421 QString(author) 1422 QString(fabric) 1423 QColor(fabricColor) // serialised format has changed over the various versions of qt. 1424 // for older versions this appears to be quint8 red, quint8 green quint8 blue, quint8 alpha 1425 qint16(index from flossscheme qcombobox) // unpredictable, palette stream will contain the scheme name 1426 qint16(inches) // boolean, true if the size displayed is in inches 1427 qint32(width) // width of pattern (is this in stitches or inches?) // discard in favour of stitchdata width 1428 qint32(height) // height of pattern (is this in stitches or inches?) // discard in favour of stitchdata height 1429 qint32(clothCount) // this needs to be converted to a double 1430 QString(instructions) 1431 1432 // palette 1433 QString(schemeName) 1434 qint32(current) // the current color selected 1435 qint32(colors) // number of colors in the palette 1436 qint32(colorIndex) ] 1437 QString(flossName) ] Repeated for each 1438 qint16(flossSymbol) ] entry in the palette 1439 1440 // stitches 1441 qint32(width) // width in stitches // use instead of width from the header which might be in inches 1442 qint32(height) // height in stitches // use instead of height from the header which might be in inches 1443 qint8(stitches) ] 1444 qint8(type) ] Repeated for ] Repeated for 1445 qint16(colorIndex) ] each stitch ] each stitchqueue 1446 1447 // backstitches 1448 qint32(backstitches) // the number of backstitches 1449 QPoint(start) ] 1450 QPoint(end) ] Repeated for 1451 qint16(colorIndex) ] each backstitch 1452 1453 // there were no knots supported in this version 1454 */ 1455 1456 /* this is currently untested */ 1457 // read header 1458 QString title; 1459 QString author; 1460 QString fabric; 1461 stream >> title >> author >> fabric; 1462 setProperty(QStringLiteral("title"), title); 1463 setProperty(QStringLiteral("author"), author); 1464 setProperty(QStringLiteral("fabric"), fabric); 1465 1466 quint8 red; 1467 quint8 green; 1468 quint8 blue; 1469 quint8 alpha; 1470 stream >> red >> green >> blue >> alpha; 1471 setProperty(QStringLiteral("fabricColor"), QColor(red, green, blue, alpha)); 1472 1473 qint16 schemeIndex; 1474 stream >> schemeIndex; // discard 1475 1476 qint16 inches; 1477 stream >> inches; 1478 setProperty(QStringLiteral("unitsFormat"), 1479 (bool(inches)) ? Configuration::EnumDocument_UnitsFormat::Inches : Configuration::EnumDocument_UnitsFormat::Stitches); 1480 1481 qint32 width; 1482 qint32 height; 1483 stream >> width >> height; 1484 1485 qint32 clothCount; 1486 stream >> clothCount; 1487 setProperty(QStringLiteral("clothCountUnits"), Configuration::EnumEditor_ClothCountUnits::Inches); 1488 setProperty(QStringLiteral("horizontalClothCount"), double(clothCount)); 1489 setProperty(QStringLiteral("verticalClothCount"), double(clothCount)); 1490 setProperty(QStringLiteral("clothCountLink"), true); 1491 1492 QString instructions; 1493 stream >> instructions; 1494 setProperty(QStringLiteral("instructions"), instructions); 1495 1496 // read palette 1497 QString schemeName; 1498 stream >> schemeName; 1499 m_pattern->palette().setSchemeName(schemeName); 1500 1501 FlossScheme *flossScheme = SchemeManager::scheme(schemeName); 1502 1503 if (flossScheme == nullptr) { 1504 throw FailedReadFile(QString(i18n("The floss scheme %1 was not found", schemeName))); 1505 } 1506 1507 qint32 current; 1508 stream >> current; 1509 1510 qint32 colors; 1511 stream >> colors; 1512 1513 while (colors--) { 1514 qint32 colorIndex; 1515 QString flossName; 1516 qint16 symbol; 1517 1518 stream >> colorIndex >> flossName >> symbol; 1519 1520 Floss *floss = flossScheme->find(flossName); 1521 1522 if (floss == nullptr) { 1523 throw FailedReadFile(QString(i18n("The floss name %1 was not found", flossName))); 1524 } 1525 1526 DocumentFloss *documentFloss = new DocumentFloss(flossName, 1527 m_pattern->palette().freeSymbol(), 1528 Qt::SolidLine, 1529 Configuration::palette_StitchStrands(), 1530 Configuration::palette_BackstitchStrands()); 1531 documentFloss->setFlossColor(floss->color()); 1532 m_pattern->palette().add(colorIndex, documentFloss); 1533 } 1534 1535 // read stitches 1536 stream >> width >> height; 1537 qint32 cells = width * height; 1538 m_pattern->stitches().resize(width, height); 1539 1540 for (int i = 0; i < cells; i++) { 1541 qint8 stitches; 1542 stream >> stitches; 1543 1544 while (stitches--) { 1545 qint8 type; 1546 qint16 colorIndex; 1547 stream >> type >> colorIndex; 1548 1549 m_pattern->stitches().addStitch(QPoint(i % width, i / width), Stitch::Type(type), colorIndex); 1550 } 1551 } 1552 1553 qint32 backstitches; 1554 stream >> backstitches; 1555 1556 while (backstitches--) { 1557 QPoint start; 1558 QPoint end; 1559 qint16 colorIndex; 1560 stream >> start >> end >> colorIndex; 1561 1562 m_pattern->stitches().addBackstitch(start, end, colorIndex); 1563 } 1564 1565 if (stream.status() != QDataStream::Ok) { 1566 throw FailedReadFile(QString(i18n("Stream error"))); 1567 } 1568 } 1569 1570 void Document::readKXStitchV4File(QDataStream &stream) 1571 { 1572 // version 4 wasn't used in the release versions. 1573 // but was available in cvs 1574 /* File format 1575 // header 1576 #QString("KXStitch") // read in the load function 1577 #qint16(FILE_FORMAT_VERSION) // read in the load function 1578 QString(title) 1579 QString(author) 1580 QString(fabric) 1581 QColor(fabricColor) // serialised format has changed over the various versions of qt. 1582 // for older versions this appears to be quint8 red, quint8 green quint8 blue, quint8 alpha 1583 qint16(index from flossscheme qcombobox) // unpredictable, palette stream will contain the scheme name 1584 qint16(inches) // boolean, true if the size displayed is in inches 1585 qint32(width) // width of pattern (is this in stitches or inches?) // discard in favour of stitchdata width 1586 qint32(height) // height of pattern (is this in stitches or inches?) // discard in favour of stitchdata height 1587 qint32(clothCount) // this needs to be converted to a double 1588 QString(instructions) 1589 1590 // palette 1591 QString(schemeName) 1592 qint32(current) // the current color selected 1593 qint32(colors) // number of colors in the palette 1594 qint32(colorIndex) ] 1595 QString(flossName) ] Repeated for each 1596 qint16(flossSymbol) ] entry in the palette 1597 1598 // stitches 1599 qint32(width) // width in stitches // use instead of width from the header which might be in inches 1600 qint32(height) // height in stitches // use instead of height from the header which might be in inches 1601 qint8(stitches) ] 1602 qint8(type) ] Repeated for ] Repeated for 1603 qint16(colorIndex) ] each stitch ] each stitchqueue 1604 1605 // knots 1606 qint32(knots) // the number of knots 1607 QPoint(position) ] Repeated for 1608 qint16(colorIndex) ] each knot 1609 1610 // backstitches 1611 qint32(backstitches) // the number of backstitches 1612 QPoint(start) ] 1613 QPoint(end) ] Repeated for 1614 qint16(colorIndex) ] each backstitch 1615 */ 1616 1617 /* this is currently untested */ 1618 // read header 1619 QString title; 1620 QString author; 1621 QString fabric; 1622 stream >> title >> author >> fabric; 1623 setProperty(QStringLiteral("title"), title); 1624 setProperty(QStringLiteral("author"), author); 1625 setProperty(QStringLiteral("fabric"), fabric); 1626 1627 quint8 red; 1628 quint8 green; 1629 quint8 blue; 1630 quint8 alpha; 1631 stream >> red >> green >> blue >> alpha; 1632 setProperty(QStringLiteral("fabricColor"), QColor(red, green, blue, alpha)); 1633 1634 qint16 schemeIndex; 1635 stream >> schemeIndex; // discard 1636 1637 qint16 inches; 1638 stream >> inches; 1639 setProperty(QStringLiteral("unitsFormat"), 1640 (bool(inches)) ? Configuration::EnumDocument_UnitsFormat::Inches : Configuration::EnumDocument_UnitsFormat::Stitches); 1641 1642 qint32 width; 1643 qint32 height; 1644 stream >> width >> height; 1645 1646 qint32 clothCount; 1647 stream >> clothCount; 1648 setProperty(QStringLiteral("clothCountUnits"), Configuration::EnumEditor_ClothCountUnits::Inches); 1649 setProperty(QStringLiteral("horizontalClothCount"), double(clothCount)); 1650 setProperty(QStringLiteral("verticalClothCount"), double(clothCount)); 1651 setProperty(QStringLiteral("clothCountLink"), true); 1652 1653 QString instructions; 1654 stream >> instructions; 1655 setProperty(QStringLiteral("instructions"), instructions); 1656 1657 // read palette 1658 QString schemeName; 1659 stream >> schemeName; 1660 m_pattern->palette().setSchemeName(schemeName); 1661 1662 FlossScheme *flossScheme = SchemeManager::scheme(schemeName); 1663 1664 if (flossScheme == nullptr) { 1665 throw FailedReadFile(QString(i18n("The floss scheme %1 was not found", schemeName))); 1666 } 1667 1668 qint32 current; 1669 stream >> current; 1670 1671 qint32 colors; 1672 stream >> colors; 1673 1674 while (colors--) { 1675 qint32 colorIndex; 1676 QString flossName; 1677 qint16 symbol; 1678 1679 stream >> colorIndex >> flossName >> symbol; 1680 1681 Floss *floss = flossScheme->find(flossName); 1682 1683 if (floss == nullptr) { 1684 throw FailedReadFile(QString(i18n("The floss name %1 was not found", flossName))); 1685 } 1686 1687 DocumentFloss *documentFloss = new DocumentFloss(flossName, 1688 m_pattern->palette().freeSymbol(), 1689 Qt::SolidLine, 1690 Configuration::palette_StitchStrands(), 1691 Configuration::palette_BackstitchStrands()); 1692 documentFloss->setFlossColor(floss->color()); 1693 m_pattern->palette().add(colorIndex, documentFloss); 1694 } 1695 1696 // read stitches 1697 stream >> width >> height; 1698 qint32 cells = width * height; 1699 m_pattern->stitches().resize(width, height); 1700 1701 for (int i = 0; i < cells; i++) { 1702 qint8 stitches; 1703 stream >> stitches; 1704 1705 while (stitches--) { 1706 qint8 type; 1707 qint16 colorIndex; 1708 stream >> type >> colorIndex; 1709 1710 m_pattern->stitches().addStitch(QPoint(i % width, i / width), Stitch::Type(type), colorIndex); 1711 } 1712 } 1713 1714 qint32 knots; 1715 stream >> knots; 1716 1717 while (knots--) { 1718 QPoint position; 1719 qint16 colorIndex; 1720 stream >> position >> colorIndex; 1721 1722 m_pattern->stitches().addFrenchKnot(position, colorIndex); 1723 } 1724 1725 qint32 backstitches; 1726 stream >> backstitches; 1727 1728 while (backstitches--) { 1729 QPoint start; 1730 QPoint end; 1731 qint16 colorIndex; 1732 stream >> start >> end >> colorIndex; 1733 1734 m_pattern->stitches().addBackstitch(start, end, colorIndex); 1735 } 1736 1737 if (stream.status() != QDataStream::Ok) { 1738 throw FailedReadFile(QString(i18n("Stream error"))); 1739 } 1740 } 1741 1742 void Document::readKXStitchV5File(QDataStream &stream) 1743 { 1744 /* File format 1745 // header 1746 #QString("KXStitch") // read in the load function 1747 #qint16(FILE_FORMAT_VERSION) // read in the load function 1748 1749 // properties dialog 1750 QString(sizeUnits) 1751 qint32(width) // this is in stitches 1752 qint32(height) // this is in stitches 1753 double(clothCount) 1754 QString(clothCountUnits) 1755 QString(title) 1756 QString(author) 1757 QString(copyright) 1758 QString(fabric) 1759 QColor(fabricColor) // serialised format has changed over the various versions of qt. 1760 // for older versions this appears to be quint8 red, quint8 green quint8 blue, quint8 alpha 1761 QString(schemeName) 1762 QString(instructions) 1763 1764 // palette 1765 QString(schemeName) 1766 qint32(current) // the current color selected 1767 qint32(colors) // number of colors in the palette 1768 qint32(colorIndex) ] 1769 QString(flossName) ] Repeated for each 1770 qint16(flossSymbol) ] entry in the palette 1771 1772 // stitches 1773 qint32(width) // width in stitches // use instead of width from the header which might be in inches 1774 qint32(height) // height in stitches // use instead of height from the header which might be in inches 1775 qint8(stitches) ] 1776 qint8(type) ] Repeated for ] Repeated for 1777 qint16(colorIndex) ] each stitch ] each stitchqueue 1778 1779 // knots 1780 qint32(knots) // the number of knots 1781 QPoint(position) ] Repeated for 1782 qint16(colorIndex) ] each knot 1783 1784 // backstitches 1785 qint32(backstitches) // the number of backstitches 1786 QPoint(start) ] 1787 QPoint(end) ] Repeated for 1788 qint16(colorIndex) ] each backstitch 1789 */ 1790 1791 /* this is currently untested */ 1792 // read header 1793 QString sizeUnits; 1794 qint32 width; 1795 qint32 height; 1796 stream >> sizeUnits >> width >> height; 1797 1798 if (sizeUnits == i18n("Stitches")) { 1799 setProperty(QStringLiteral("unitsFormat"), Configuration::EnumDocument_UnitsFormat::Stitches); 1800 } 1801 1802 if (sizeUnits == i18n("CM")) { 1803 setProperty(QStringLiteral("unitsFormat"), Configuration::EnumDocument_UnitsFormat::Centimeters); 1804 } 1805 1806 if (sizeUnits == i18n("Inches")) { 1807 setProperty(QStringLiteral("unitsFormat"), Configuration::EnumDocument_UnitsFormat::Inches); 1808 } 1809 1810 double clothCount; 1811 QString clothCountUnits; 1812 stream >> clothCount >> clothCountUnits; 1813 setProperty(QStringLiteral("horizontalClothCount"), double(clothCount)); 1814 setProperty(QStringLiteral("verticalClothCount"), double(clothCount)); 1815 setProperty(QStringLiteral("clothCountLink"), true); 1816 1817 if (clothCountUnits == QLatin1String("/cm")) { 1818 setProperty(QStringLiteral("clothCountUnits"), Configuration::EnumEditor_ClothCountUnits::Centimeters); 1819 } 1820 1821 if (clothCountUnits == QLatin1String("/in")) { 1822 setProperty(QStringLiteral("clothCountUnits"), Configuration::EnumEditor_ClothCountUnits::Inches); 1823 } 1824 1825 QString title; 1826 QString author; 1827 QString copyright; 1828 QString fabric; 1829 stream >> title >> author >> copyright >> fabric; 1830 setProperty(QStringLiteral("title"), title); 1831 setProperty(QStringLiteral("author"), author); 1832 setProperty(QStringLiteral("copyright"), copyright); 1833 setProperty(QStringLiteral("fabric"), fabric); 1834 1835 quint8 red; 1836 quint8 green; 1837 quint8 blue; 1838 quint8 alpha; 1839 stream >> red >> green >> blue >> alpha; 1840 setProperty(QStringLiteral("fabricColor"), QColor(red, green, blue, alpha)); 1841 1842 QString schemeName; 1843 stream >> schemeName; // discard, also read in palette 1844 1845 QString instructions; 1846 stream >> instructions; 1847 setProperty(QStringLiteral("instructions"), instructions); 1848 1849 // read palette 1850 stream >> schemeName; 1851 m_pattern->palette().setSchemeName(schemeName); 1852 1853 FlossScheme *flossScheme = SchemeManager::scheme(schemeName); 1854 1855 if (flossScheme == nullptr) { 1856 throw FailedReadFile(QString(i18n("The floss scheme %1 was not found", schemeName))); 1857 } 1858 1859 qint32 current; 1860 stream >> current; 1861 1862 qint32 colors; 1863 stream >> colors; 1864 1865 while (colors--) { 1866 qint32 colorIndex; 1867 QString flossName; 1868 qint16 symbol; 1869 1870 stream >> colorIndex >> flossName >> symbol; 1871 1872 Floss *floss = flossScheme->find(flossName); 1873 1874 if (floss == nullptr) { 1875 throw FailedReadFile(QString(i18n("The floss name %1 was not found", flossName))); 1876 } 1877 1878 DocumentFloss *documentFloss = new DocumentFloss(flossName, 1879 m_pattern->palette().freeSymbol(), 1880 Qt::SolidLine, 1881 Configuration::palette_StitchStrands(), 1882 Configuration::palette_BackstitchStrands()); 1883 documentFloss->setFlossColor(floss->color()); 1884 m_pattern->palette().add(colorIndex, documentFloss); 1885 } 1886 1887 // read stitches 1888 stream >> width >> height; 1889 qint32 cells = width * height; 1890 m_pattern->stitches().resize(width, height); 1891 1892 for (int i = 0; i < cells; i++) { 1893 qint8 stitches; 1894 stream >> stitches; 1895 1896 while (stitches--) { 1897 qint8 type; 1898 qint16 colorIndex; 1899 stream >> type >> colorIndex; 1900 1901 m_pattern->stitches().addStitch(QPoint(i % width, i / width), Stitch::Type(type), colorIndex); 1902 } 1903 } 1904 1905 qint32 knots; 1906 stream >> knots; 1907 1908 while (knots--) { 1909 QPoint position; 1910 qint16 colorIndex; 1911 stream >> position >> colorIndex; 1912 1913 m_pattern->stitches().addFrenchKnot(position, colorIndex); 1914 } 1915 1916 qint32 backstitches; 1917 stream >> backstitches; 1918 1919 while (backstitches--) { 1920 QPoint start; 1921 QPoint end; 1922 qint16 colorIndex; 1923 stream >> start >> end >> colorIndex; 1924 1925 m_pattern->stitches().addBackstitch(start, end, colorIndex); 1926 } 1927 1928 if (stream.status() != QDataStream::Ok) { 1929 throw FailedReadFile(QString(i18n("Stream error"))); 1930 } 1931 } 1932 1933 void Document::readKXStitchV6File(QDataStream &stream) 1934 { 1935 /* File format 1936 // header 1937 #QString("KXStitch") // read in the load function 1938 #qint16(FILE_FORMAT_VERSION) // read in the load function 1939 1940 // properties dialog 1941 QString(sizeUnits) 1942 qint32(width) // this is in stitches 1943 qint32(height) // this is in stitches 1944 double(clothCount) 1945 QString(clothCountUnits) 1946 QString(title) 1947 QString(author) 1948 QString(copyright) 1949 QString(fabric) 1950 QColor(fabricColor) // serialised format has changed over the various versions of qt. 1951 // for older versions this appears to be quint8 red, quint8 green quint8 blue, quint8 alpha 1952 QString(schemeName) 1953 QString(instructions) 1954 1955 // palette 1956 QString(schemeName) 1957 qint32(current) // the current color selected 1958 qint32(colors) // number of colors in the palette 1959 qint32(colorIndex) ] 1960 QString(flossName) ] Repeated for each 1961 qint16(flossSymbol) ] entry in the palette 1962 qint8(stitchStrands) ] 1963 qint8(backstitchStrands) ] 1964 1965 // stitches 1966 qint32(width) // width in stitches // use instead of width from the header which might be in inches 1967 qint32(height) // height in stitches // use instead of height from the header which might be in inches 1968 qint8(stitches) ] 1969 qint8(type) ] Repeated for ] Repeated for 1970 qint16(colorIndex) ] each stitch ] each stitchqueue 1971 1972 // knots 1973 qint32(knots) // the number of knots 1974 QPoint(position) ] Repeated for 1975 qint16(colorIndex) ] each knot 1976 1977 // backstitches 1978 qint32(backstitches) // the number of backstitches 1979 QPoint(start) ] 1980 QPoint(end) ] Repeated for 1981 qint16(colorIndex) ] each backstitch 1982 */ 1983 1984 /* Working */ 1985 // read header 1986 QString sizeUnits; 1987 qint32 width; 1988 qint32 height; 1989 stream >> sizeUnits >> width >> height; 1990 1991 if (sizeUnits == i18n("Stitches")) { 1992 setProperty(QStringLiteral("unitsFormat"), Configuration::EnumDocument_UnitsFormat::Stitches); 1993 } 1994 1995 if (sizeUnits == i18n("CM")) { 1996 setProperty(QStringLiteral("unitsFormat"), Configuration::EnumDocument_UnitsFormat::Centimeters); 1997 } 1998 1999 if (sizeUnits == i18n("Inches")) { 2000 setProperty(QStringLiteral("unitsFormat"), Configuration::EnumDocument_UnitsFormat::Inches); 2001 } 2002 2003 double clothCount; 2004 QString clothCountUnits; 2005 stream >> clothCount >> clothCountUnits; 2006 setProperty(QStringLiteral("horizontalClothCount"), double(clothCount)); 2007 setProperty(QStringLiteral("verticalClothCount"), double(clothCount)); 2008 setProperty(QStringLiteral("clothCountLink"), true); 2009 2010 if (clothCountUnits == QLatin1String("/cm")) { 2011 setProperty(QStringLiteral("clothCountUnits"), Configuration::EnumEditor_ClothCountUnits::Centimeters); 2012 } 2013 2014 if (clothCountUnits == QLatin1String("/in")) { 2015 setProperty(QStringLiteral("clothCountUnits"), Configuration::EnumEditor_ClothCountUnits::Inches); 2016 } 2017 2018 QString title; 2019 QString author; 2020 QString copyright; 2021 QString fabric; 2022 stream >> title >> author >> copyright >> fabric; 2023 setProperty(QStringLiteral("title"), title); 2024 setProperty(QStringLiteral("author"), author); 2025 setProperty(QStringLiteral("copyright"), copyright); 2026 setProperty(QStringLiteral("fabric"), fabric); 2027 2028 quint8 red; 2029 quint8 green; 2030 quint8 blue; 2031 quint8 alpha; 2032 stream >> red >> green >> blue >> alpha; 2033 setProperty(QStringLiteral("fabricColor"), QColor(red, green, blue, alpha)); 2034 2035 QString schemeName; 2036 stream >> schemeName; // discard, also read in palette 2037 2038 QString instructions; 2039 stream >> instructions; 2040 setProperty(QStringLiteral("instructions"), instructions); 2041 2042 // read palette 2043 stream >> schemeName; 2044 m_pattern->palette().setSchemeName(schemeName); 2045 2046 FlossScheme *flossScheme = SchemeManager::scheme(schemeName); 2047 2048 if (flossScheme == nullptr) { 2049 throw FailedReadFile(QString(i18n("The floss scheme %1 was not found", schemeName))); 2050 } 2051 2052 qint32 current; 2053 stream >> current; 2054 2055 qint32 colors; 2056 stream >> colors; 2057 2058 while (colors--) { 2059 qint32 colorIndex; 2060 QString flossName; 2061 qint16 symbol; 2062 qint8 stitchStrands; 2063 qint8 backstitchStrands; 2064 2065 stream >> colorIndex >> flossName >> symbol >> stitchStrands >> backstitchStrands; 2066 2067 Floss *floss = flossScheme->find(flossName); 2068 2069 if (floss == nullptr) { 2070 throw FailedReadFile(QString(i18n("The floss name %1 was not found", flossName))); 2071 } 2072 2073 DocumentFloss *documentFloss = new DocumentFloss(flossName, m_pattern->palette().freeSymbol(), Qt::SolidLine, stitchStrands, backstitchStrands); 2074 documentFloss->setFlossColor(floss->color()); 2075 m_pattern->palette().add(colorIndex, documentFloss); 2076 } 2077 2078 // read stitches 2079 stream >> width >> height; 2080 qint32 cells = width * height; 2081 m_pattern->stitches().resize(width, height); 2082 2083 for (int i = 0; i < cells; i++) { 2084 qint8 stitches; 2085 stream >> stitches; 2086 2087 while (stitches--) { 2088 qint8 type; 2089 qint16 colorIndex; 2090 stream >> type >> colorIndex; 2091 2092 m_pattern->stitches().addStitch(QPoint(i % width, i / width), Stitch::Type(type), colorIndex); 2093 } 2094 } 2095 2096 qint32 knots; 2097 stream >> knots; 2098 2099 while (knots--) { 2100 QPoint position; 2101 qint16 colorIndex; 2102 stream >> position >> colorIndex; 2103 2104 m_pattern->stitches().addFrenchKnot(position, colorIndex); 2105 } 2106 2107 qint32 backstitches; 2108 stream >> backstitches; 2109 2110 while (backstitches--) { 2111 QPoint start; 2112 QPoint end; 2113 qint16 colorIndex; 2114 stream >> start >> end >> colorIndex; 2115 2116 m_pattern->stitches().addBackstitch(start, end, colorIndex); 2117 } 2118 2119 if (stream.status() != QDataStream::Ok) { 2120 throw FailedReadFile(QString(i18n("Stream error"))); 2121 } 2122 } 2123 2124 void Document::readKXStitchV7File(QDataStream &stream) 2125 { 2126 /* File format 2127 // header 2128 #QString("KXStitch") // read in the load function 2129 #qint16(FILE_FORMAT_VERSION) // read in the load function 2130 2131 // properties dialog 2132 qint32(sizeUnits) 2133 qint32(width) // this is in stitches 2134 qint32(height) // this is in stitches 2135 double(clothCount) 2136 qint32(clothCountUnits) 2137 QString(title) 2138 QString(author) 2139 QString(copyright) 2140 QString(fabric) 2141 QColor(fabricColor) // serialised format has changed over the various versions of qt. 2142 // for older versions this appears to be quint8 red, quint8 green quint8 blue, quint8 alpha 2143 QString(schemeName) 2144 QString(instructions) 2145 2146 // palette 2147 QString(schemeName) 2148 qint32(current) // the current color selected 2149 qint32(colors) // number of colors in the palette 2150 qint32(colorIndex) ] 2151 QString(flossName) ] Repeated for each 2152 qint16(flossSymbol) ] entry in the palette 2153 qint8(stitchStrands) ] 2154 qint8(backstitchStrands) ] 2155 2156 // stitches 2157 qint32(width) // width in stitches // use instead of width from the header which might be in inches 2158 qint32(height) // height in stitches // use instead of height from the header which might be in inches 2159 qint8(stitches) ] 2160 qint8(type) ] Repeated for ] Repeated for 2161 qint16(colorIndex) ] each stitch ] each stitchqueue 2162 2163 // knots 2164 qint32(knots) // the number of knots 2165 QPoint(position) ] Repeated for 2166 qint16(colorIndex) ] each knot 2167 2168 // backstitches 2169 qint32(backstitches) // the number of backstitches 2170 QPoint(start) ] 2171 QPoint(end) ] Repeated for 2172 qint16(colorIndex) ] each backstitch 2173 */ 2174 2175 /* Working */ 2176 Configuration::EnumDocument_UnitsFormat::type convertSizeUnits[] = {Configuration::EnumDocument_UnitsFormat::Stitches, 2177 Configuration::EnumDocument_UnitsFormat::Centimeters, // was MM 2178 Configuration::EnumDocument_UnitsFormat::Centimeters, 2179 Configuration::EnumDocument_UnitsFormat::Inches}; 2180 Configuration::EnumEditor_ClothCountUnits::type convertClothCountUnits[] = {Configuration::EnumEditor_ClothCountUnits::Inches, // was Stitches 2181 Configuration::EnumEditor_ClothCountUnits::Centimeters, 2182 Configuration::EnumEditor_ClothCountUnits::Inches}; 2183 // read header 2184 qint32 sizeUnits; 2185 qint32 width; 2186 qint32 height; 2187 stream >> sizeUnits >> width >> height; 2188 setProperty(QStringLiteral("unitsFormat"), convertSizeUnits[sizeUnits]); 2189 2190 double clothCount; 2191 qint32 clothCountUnits; 2192 stream >> clothCount >> clothCountUnits; 2193 setProperty(QStringLiteral("horizontalClothCount"), double(clothCount)); 2194 setProperty(QStringLiteral("verticalClothCount"), double(clothCount)); 2195 setProperty(QStringLiteral("clothCountLink"), true); 2196 setProperty(QStringLiteral("clothCountUnits"), convertClothCountUnits[clothCountUnits]); 2197 2198 QString title; 2199 QString author; 2200 QString copyright; 2201 QString fabric; 2202 stream >> title >> author >> copyright >> fabric; 2203 setProperty(QStringLiteral("title"), title); 2204 setProperty(QStringLiteral("author"), author); 2205 setProperty(QStringLiteral("copyright"), copyright); 2206 setProperty(QStringLiteral("fabric"), fabric); 2207 2208 quint8 red; 2209 quint8 green; 2210 quint8 blue; 2211 quint8 alpha; 2212 stream >> red >> green >> blue >> alpha; 2213 setProperty(QStringLiteral("fabricColor"), QColor(red, green, blue, alpha)); 2214 2215 QString schemeName; 2216 stream >> schemeName; // discard, also read in palette 2217 2218 QString instructions; 2219 stream >> instructions; 2220 setProperty(QStringLiteral("instructions"), instructions); 2221 2222 // read palette 2223 stream >> schemeName; 2224 m_pattern->palette().setSchemeName(schemeName); 2225 2226 FlossScheme *flossScheme = SchemeManager::scheme(schemeName); 2227 2228 if (flossScheme == nullptr) { 2229 throw FailedReadFile(QString(i18n("The floss scheme %1 was not found", schemeName))); 2230 } 2231 2232 qint32 current; 2233 stream >> current; 2234 2235 qint32 colors; 2236 stream >> colors; 2237 2238 while (colors--) { 2239 qint32 colorIndex; 2240 QString flossName; 2241 qint16 symbol; 2242 qint8 stitchStrands; 2243 qint8 backstitchStrands; 2244 2245 stream >> colorIndex >> flossName >> symbol >> stitchStrands >> backstitchStrands; 2246 2247 Floss *floss = flossScheme->find(flossName); 2248 2249 if (floss == nullptr) { 2250 throw FailedReadFile(QString(i18n("The floss name %1 was not found", flossName))); 2251 } 2252 2253 DocumentFloss *documentFloss = new DocumentFloss(flossName, m_pattern->palette().freeSymbol(), Qt::SolidLine, stitchStrands, backstitchStrands); 2254 documentFloss->setFlossColor(floss->color()); 2255 m_pattern->palette().add(colorIndex, documentFloss); 2256 } 2257 2258 // read stitches 2259 stream >> width >> height; 2260 qint32 cells = width * height; 2261 m_pattern->stitches().resize(width, height); 2262 2263 for (int i = 0; i < cells; i++) { 2264 qint8 stitches; 2265 stream >> stitches; 2266 2267 while (stitches--) { 2268 qint8 type; 2269 qint16 colorIndex; 2270 stream >> type >> colorIndex; 2271 2272 m_pattern->stitches().addStitch(QPoint(i % width, i / width), Stitch::Type(type), colorIndex); 2273 } 2274 } 2275 2276 qint32 knots; 2277 stream >> knots; 2278 2279 while (knots--) { 2280 QPoint position; 2281 qint16 colorIndex; 2282 stream >> position >> colorIndex; 2283 2284 m_pattern->stitches().addFrenchKnot(position, colorIndex); 2285 } 2286 2287 qint32 backstitches; 2288 stream >> backstitches; 2289 2290 while (backstitches--) { 2291 QPoint start; 2292 QPoint end; 2293 qint16 colorIndex; 2294 stream >> start >> end >> colorIndex; 2295 2296 m_pattern->stitches().addBackstitch(start, end, colorIndex); 2297 } 2298 2299 if (stream.status() != QDataStream::Ok) { 2300 throw FailedReadFile(QString(i18n("Stream error"))); 2301 } 2302 }