File indexing completed on 2024-04-28 04:32:02
0001 /* 0002 * Copyright (C) 2003-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 "LibraryFile.h" 0012 0013 #include <QDataStream> 0014 #include <QFile> 0015 #include <QFileInfo> 0016 #include <QProgressDialog> 0017 0018 #include <KLocalizedString> 0019 #include <KMessageBox> 0020 0021 #include <stdlib.h> 0022 0023 #include "LibraryPattern.h" 0024 0025 LibraryFile::LibraryFile(const QString &path) 0026 : m_read(false) 0027 , m_path(path) 0028 { 0029 m_exists = QFile::exists(localFile()); 0030 } 0031 0032 LibraryFile::~LibraryFile() 0033 { 0034 if (hasChanged()) { 0035 writeFile(); 0036 } 0037 0038 qDeleteAll(m_libraryPatterns); 0039 } 0040 0041 QString LibraryFile::path() const 0042 { 0043 return m_path; 0044 } 0045 0046 bool LibraryFile::isWritable() const 0047 { 0048 return QFileInfo(m_path).isWritable(); 0049 } 0050 0051 void LibraryFile::addPattern(LibraryPattern *libraryPattern) 0052 { 0053 m_libraryPatterns.append(libraryPattern); 0054 writeFile(); 0055 } 0056 0057 void LibraryFile::deletePattern(LibraryPattern *libraryPattern) 0058 { 0059 if (m_libraryPatterns.removeOne(libraryPattern)) { 0060 delete libraryPattern; 0061 writeFile(); 0062 } 0063 } 0064 0065 LibraryPattern *LibraryFile::first() 0066 { 0067 if (!m_read) { 0068 readFile(); 0069 } 0070 0071 m_current = 0; 0072 0073 if (m_current < m_libraryPatterns.count()) { 0074 return m_libraryPatterns.at(m_current++); 0075 } 0076 0077 return nullptr; 0078 } 0079 0080 LibraryPattern *LibraryFile::next() 0081 { 0082 if (m_current < m_libraryPatterns.count()) { 0083 return m_libraryPatterns.at(m_current++); 0084 } 0085 0086 return nullptr; 0087 } 0088 0089 void LibraryFile::readFile() 0090 { 0091 if (m_exists) { 0092 bool ok = true; 0093 QFile file(localFile()); 0094 0095 if (file.open(QIODevice::ReadOnly)) { 0096 QDataStream stream(&file); 0097 char header[11]; 0098 stream.readRawData(header, 11); 0099 0100 if (strncmp(header, "KXStitchLib", 11) == 0) { 0101 qint16 version; 0102 qint32 count; 0103 qint32 key; // version 1 of library format 0104 qint32 modifier; // version 1 of library format 0105 qint16 baseline; // version 1 of library format 0106 quint16 checksum; // version 1 of library format 0107 ok = true; 0108 QByteArray data; 0109 LibraryPattern *libraryPattern; 0110 0111 QProgressDialog progress(nullptr); 0112 progress.setLabelText(i18n("Loading Library %1", file.fileName())); 0113 0114 stream >> version; 0115 0116 switch (version) { 0117 case 1: 0118 progress.setRange(file.pos(), file.size()); 0119 progress.setValue(0); 0120 progress.show(); 0121 0122 while (!file.atEnd() && ok) { 0123 stream >> key; 0124 stream >> modifier; 0125 stream >> baseline; 0126 stream >> checksum; // no longer used 0127 stream >> data; 0128 Qt::KeyboardModifiers replacedModifiers; 0129 0130 if (modifier & 0x0100) { 0131 replacedModifiers |= Qt::ShiftModifier; 0132 } 0133 0134 if (modifier & 0x0200) { 0135 replacedModifiers |= Qt::ControlModifier; 0136 } 0137 0138 if (modifier & 0x0400) { 0139 replacedModifiers |= Qt::AltModifier; 0140 } 0141 0142 if (modifier & 0x0800) { 0143 replacedModifiers |= Qt::MetaModifier; 0144 } 0145 0146 if (checksum == qChecksum(data.data(), data.size())) { 0147 m_libraryPatterns.append(new LibraryPattern(data, key, replacedModifiers, baseline)); 0148 } else { 0149 KMessageBox::error(nullptr, 0150 i18n("Failed to read a pattern from the library %1.\n%2", localFile(), file.errorString()), 0151 i18n("Failed to read library.")); 0152 ok = false; 0153 } 0154 0155 progress.setValue(file.pos()); 0156 } 0157 0158 break; 0159 0160 case 100: 0161 stream >> count; 0162 progress.setRange(0, count); 0163 progress.setValue(0); 0164 progress.show(); 0165 0166 while (count--) { 0167 libraryPattern = new LibraryPattern; 0168 stream >> *libraryPattern; 0169 m_libraryPatterns.append(libraryPattern); 0170 progress.setValue(progress.value() + 1); 0171 } 0172 0173 break; 0174 0175 default: 0176 // not supported 0177 // throw exception 0178 break; 0179 } 0180 } 0181 0182 file.close(); 0183 m_read = true; 0184 } else { 0185 KMessageBox::error(nullptr, i18n("The file %1\ncould not be opened for reading.\n%2", localFile(), file.errorString()), i18n("Error opening file")); 0186 } 0187 } 0188 } 0189 0190 void LibraryFile::writeFile() 0191 { 0192 QFile file(localFile()); 0193 0194 if (file.open(QIODevice::WriteOnly)) { // truncates the file 0195 QDataStream stream(&file); 0196 stream.writeRawData("KXStitchLib", 11); 0197 stream << qint16(version); 0198 stream << qint32(m_libraryPatterns.count()); 0199 QListIterator<LibraryPattern *> iterator(m_libraryPatterns); 0200 0201 while (iterator.hasNext()) { 0202 LibraryPattern *libraryPattern = iterator.next(); 0203 stream << *libraryPattern; 0204 } 0205 0206 file.close(); 0207 m_read = true; 0208 } else { 0209 KMessageBox::error(nullptr, i18n("The file %1\ncould not be opened for writing.\n%2", localFile(), file.errorString()), i18n("Error opening file")); 0210 } 0211 } 0212 0213 QString LibraryFile::localFile() const 0214 { 0215 QFileInfo path(m_path); 0216 0217 if (path.isDir()) { 0218 return m_path + QLatin1String("/kxstitch.library"); 0219 } else { 0220 return m_path; 0221 } 0222 } 0223 0224 bool LibraryFile::hasChanged() 0225 { 0226 bool changed = false; 0227 0228 QListIterator<LibraryPattern *> libraryPatternIterator(m_libraryPatterns); 0229 0230 while (libraryPatternIterator.hasNext()) { 0231 changed = changed | libraryPatternIterator.next()->hasChanged(); 0232 } 0233 0234 return changed; 0235 }