-
Notifications
You must be signed in to change notification settings - Fork 0
/
project_file.cpp
139 lines (111 loc) · 3.95 KB
/
project_file.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
#include "project_file.h"
#include <QDir>
#include <QSaveFile>
#include <QTemporaryFile>
// TODO: POC file format, should be improved
ProjectFile::ProjectFile() : _settings(0) {}
ProjectFile::~ProjectFile() {
delete _settings;
}
QSettings *ProjectFile::settings() {
if(!_settings) {
if(_dir.isValid()) {
_settings = new QSettings(_dir.path() + "/config.ini", QSettings::IniFormat);
} else {
return 0;
}
}
return _settings;
}
bool ProjectFile::addPixmap(const QString &id, const QPixmap &pix) const {
return pix.save(QString("%1/%2.png").arg(_dir.path()).arg(id), "png");
}
QPixmap ProjectFile::getPixmap(const QString &id) const {
if(id.isEmpty()) return QPixmap();
auto fileName = QString("%1/%2.png").arg(_dir.path()).arg(id);
return QPixmap(fileName, "png");
}
ProjectFile::ErrorCode ProjectFile::save(const QString &fileName) {
QSaveFile outFile(fileName);
if(!outFile.open(QFile::WriteOnly)) return IOError;
_settings->sync();
for(auto i : QDir(_dir.path()).entryInfoList(QDir::Files)) {
auto name = i.fileName().toUtf8();
qint32 nsize = name.size();
QByteArray data;
qint64 dsize;
if(i.suffix() == "ini") {
QFile file(i.absoluteFilePath());
if(!file.open(QFile::ReadOnly)) return IOError;
data = qCompress(file.readAll());
dsize = data.size();
} else {
QFile file(i.absoluteFilePath());
if(!file.open(QFile::ReadOnly)) return IOError;
dsize = i.size();
data = file.readAll();
}
if(outFile.write(reinterpret_cast<char*>(&nsize), sizeof(nsize)) < 0) return IOError;
if(outFile.write(reinterpret_cast<char*>(&dsize), sizeof(dsize)) < 0) return IOError;
if(outFile.write(name) < 0) return IOError;
if(outFile.write(data) < 0) return IOError;
}
return outFile.commit() ? NoError : IOError;
}
ProjectFile::ErrorCode ProjectFile::load(const QString &fileName) {
QFile inFile(fileName);
if(!inFile.open(QFile::ReadOnly)) return IOError;
QString name;
qint32 nsize = 0;
qint64 dsize = 0;
static const auto hsize = sizeof(nsize) + sizeof(dsize);
static const qint64 bufSize = 32 * 1024;
char buf[bufSize];
auto mode = Header;
while(!inFile.atEnd()) {
switch(mode) {
case Header:
if(inFile.read(buf, hsize) != hsize) {
return Corrupted;
}
nsize = *reinterpret_cast<qint32*>(buf);
dsize = *reinterpret_cast<qint64*>(buf + sizeof(nsize));
mode = Name;
break;
case Name:
if(nsize > bufSize) return Corrupted;
if(inFile.read(buf, nsize) != nsize) return IOError;
name = QString::fromUtf8(buf, nsize);
mode = Data;
break;
case Data: {
QTemporaryFile tmp;
if(!tmp.open()) return IOError;
while(dsize != 0) {
auto bytesRead = inFile.read(buf, qMin(dsize, bufSize));
if(bytesRead < 0) return IOError;
if(tmp.write(buf, bytesRead) != bytesRead) {
return IOError;
}
dsize -= bytesRead;
}
tmp.close();
if(name.endsWith(".ini")) {
if(!tmp.open()) return IOError;
QFile file(_dir.path() + "/" + name);
if(!file.open(QFile::WriteOnly)) return IOError;
if(file.write(qUncompress(tmp.readAll())) < 0) return IOError;
} else {
if(!QFile::copy(tmp.fileName(), _dir.path() + "/" + name)) return IOError;
}
mode = Header;
break;
}
default:
return Corrupted;
}
}
if(mode != Header) return Corrupted;
if(!QFile::exists(_dir.path() + "/config.ini")) return Corrupted;
return NoError;
}