95 } |
95 } |
96 |
96 |
97 QColor LDColor::edgeColor() const |
97 QColor LDColor::edgeColor() const |
98 { |
98 { |
99 if (isDirect()) |
99 if (isDirect()) |
100 return ::luma (faceColor()) < 48 ? Qt::white : Qt::black; |
100 return ::luma(faceColor()) < 48 ? Qt::white : Qt::black; |
101 else if (isLDConfigColor()) |
101 else if (isLDConfigColor()) |
102 return data().edgeColor; |
102 return data().edgeColor; |
103 else |
103 else |
104 return Qt::black; |
104 return Qt::black; |
105 } |
105 } |
106 |
106 |
107 int LDColor::luma() const |
107 int LDColor::luma() const |
108 { |
108 { |
109 return ::luma (faceColor()); |
109 return ::luma(faceColor()); |
110 } |
110 } |
111 |
111 |
112 int LDColor::edgeLuma() const |
112 int LDColor::edgeLuma() const |
113 { |
113 { |
114 return ::luma (edgeColor()); |
114 return ::luma(edgeColor()); |
115 } |
115 } |
116 |
116 |
117 qint32 LDColor::index() const |
117 qint32 LDColor::index() const |
118 { |
118 { |
119 return m_index; |
119 return m_index; |
120 } |
120 } |
121 |
121 |
122 QString LDColor::indexString() const |
122 QString LDColor::indexString() const |
123 { |
123 { |
124 if (isDirect()) |
124 if (isDirect()) |
125 return "0x" + QString::number (index(), 16).toUpper(); |
125 return "0x" + QString::number(index(), 16).toUpper(); |
126 |
126 |
127 return QString::number (index()); |
127 return QString::number(index()); |
128 } |
128 } |
129 |
129 |
130 bool LDColor::isDirect() const |
130 bool LDColor::isDirect() const |
131 { |
131 { |
132 return index() >= 0x02000000; |
132 return index() >= 0x02000000; |
133 } |
133 } |
134 |
134 |
135 int luma (const QColor& col) |
135 int luma(const QColor& col) |
136 { |
136 { |
137 return (0.2126f * col.red()) + (0.7152f * col.green()) + (0.0722f * col.blue()); |
137 return (0.2126f * col.red()) +(0.7152f * col.green()) +(0.0722f * col.blue()); |
138 } |
138 } |
139 |
139 |
140 ColorData::ColorData() |
140 ColorData::ColorData() |
141 { |
141 { |
142 if (colorData == nullptr) |
142 if (colorData == nullptr) |
158 { |
158 { |
159 if (colorData == this) |
159 if (colorData == this) |
160 colorData = nullptr; |
160 colorData = nullptr; |
161 } |
161 } |
162 |
162 |
163 bool ColorData::contains (int code) const |
163 bool ColorData::contains(int code) const |
164 { |
164 { |
165 return code >= 0 and code < EntryCount; |
165 return code >= 0 and code < EntryCount; |
166 } |
166 } |
167 |
167 |
168 const ColorData::Entry& ColorData::get (int code) const |
168 const ColorData::Entry& ColorData::get(int code) const |
169 { |
169 { |
170 if (not contains (code)) |
170 if (not contains(code)) |
171 throw std::runtime_error ("Attempted to get non-existant color information"); |
171 throw std::runtime_error("Attempted to get non-existant color information"); |
172 |
172 |
173 return m_data[code]; |
173 return m_data[code]; |
174 } |
174 } |
175 |
175 |
176 void ColorData::loadFromLdconfig() |
176 void ColorData::loadFromLdconfig() |
177 { |
177 { |
178 QString path = LDPaths::ldConfigPath(); |
178 QString path = LDPaths::ldConfigPath(); |
179 QFile fp (path); |
179 QFile fp(path); |
180 |
180 |
181 if (not fp.open (QIODevice::ReadOnly)) |
181 if (not fp.open(QIODevice::ReadOnly)) |
182 { |
182 { |
183 QMessageBox::critical (nullptr, "Error", "Unable to open LDConfig.ldr for parsing: " + fp.errorString()); |
183 QMessageBox::critical(nullptr, "Error", "Unable to open LDConfig.ldr for parsing: " + fp.errorString()); |
184 return; |
184 return; |
185 } |
185 } |
186 |
186 |
187 // TODO: maybe LDConfig can be loaded as a Document? Or would that be overkill? |
187 // TODO: maybe LDConfig can be loaded as a Document? Or would that be overkill? |
188 while (not fp.atEnd()) |
188 while (not fp.atEnd()) |
189 { |
189 { |
190 QString line = QString::fromUtf8 (fp.readLine()); |
190 QString line = QString::fromUtf8(fp.readLine()); |
191 |
191 |
192 if (line.isEmpty() or line[0] != '0') |
192 if (line.isEmpty() or line[0] != '0') |
193 continue; // empty or illogical |
193 continue; // empty or illogical |
194 |
194 |
195 line.remove ('\r'); |
195 line.remove('\r'); |
196 line.remove ('\n'); |
196 line.remove('\n'); |
197 |
197 |
198 // Parse the line |
198 // Parse the line |
199 LDConfigParser parser (line, ' '); |
199 LDConfigParser parser(line, ' '); |
200 QString name; |
200 QString name; |
201 QString facename; |
201 QString facename; |
202 QString edgename; |
202 QString edgename; |
203 QString codestring; |
203 QString codestring; |
204 |
204 |
205 // Check 0 !COLOUR, parse the name |
205 // Check 0 !COLOUR, parse the name |
206 if (not parser.compareToken (0, "0") or not parser.compareToken (1, "!COLOUR") or not parser.getToken (name, 2)) |
206 if (not parser.compareToken(0, "0") or not parser.compareToken(1, "!COLOUR") or not parser.getToken(name, 2)) |
207 continue; |
207 continue; |
208 |
208 |
209 // Replace underscores in the name with spaces for readability |
209 // Replace underscores in the name with spaces for readability |
210 name.replace ("_", " "); |
210 name.replace("_", " "); |
211 |
211 |
212 if (not parser.parseTag ("CODE", codestring)) |
212 if (not parser.parseTag("CODE", codestring)) |
213 continue; |
213 continue; |
214 |
214 |
215 bool ok; |
215 bool ok; |
216 int code = codestring.toShort (&ok); |
216 int code = codestring.toShort(&ok); |
217 |
217 |
218 if (not ok or not contains (code)) |
218 if (not ok or not contains(code)) |
219 continue; |
219 continue; |
220 |
220 |
221 if (not parser.parseTag ("VALUE", facename) or not parser.parseTag ("EDGE", edgename)) |
221 if (not parser.parseTag("VALUE", facename) or not parser.parseTag("EDGE", edgename)) |
222 continue; |
222 continue; |
223 |
223 |
224 // Ensure that our colors are correct |
224 // Ensure that our colors are correct |
225 QColor faceColor (facename); |
225 QColor faceColor(facename); |
226 QColor edgeColor (edgename); |
226 QColor edgeColor(edgename); |
227 |
227 |
228 if (not faceColor.isValid() or not edgeColor.isValid()) |
228 if (not faceColor.isValid() or not edgeColor.isValid()) |
229 continue; |
229 continue; |
230 |
230 |
231 Entry& entry = m_data[code]; |
231 Entry& entry = m_data[code]; |
232 entry.name = name; |
232 entry.name = name; |
233 entry.faceColor = faceColor; |
233 entry.faceColor = faceColor; |
234 entry.edgeColor = edgeColor; |
234 entry.edgeColor = edgeColor; |
235 entry.hexcode = facename; |
235 entry.hexcode = facename; |
236 |
236 |
237 if (parser.parseTag ("ALPHA", codestring)) |
237 if (parser.parseTag("ALPHA", codestring)) |
238 entry.faceColor.setAlpha (qBound (0, codestring.toInt(), 255)); |
238 entry.faceColor.setAlpha(qBound(0, codestring.toInt(), 255)); |
239 } |
239 } |
240 } |
240 } |
241 |
241 |
242 // ============================================================================= |
242 // ============================================================================= |
243 // |
243 // |
244 LDConfigParser::LDConfigParser (QString inText, char sep) |
244 LDConfigParser::LDConfigParser(QString inText, char sep) |
245 { |
245 { |
246 m_tokens = inText.split (sep, QString::SkipEmptyParts); |
246 m_tokens = inText.split(sep, QString::SkipEmptyParts); |
247 m_pos = -1; |
247 m_pos = -1; |
248 } |
248 } |
249 |
249 |
250 // ============================================================================= |
250 // ============================================================================= |
251 // |
251 // |
252 bool LDConfigParser::getToken (QString& val, const int pos) |
252 bool LDConfigParser::getToken(QString& val, const int pos) |
253 { |
253 { |
254 if (pos >= m_tokens.size()) |
254 if (pos >= m_tokens.size()) |
255 return false; |
255 return false; |
256 |
256 |
257 val = m_tokens[pos]; |
257 val = m_tokens[pos]; |
258 return true; |
258 return true; |
259 } |
259 } |
260 |
260 |
261 // ============================================================================= |
261 // ============================================================================= |
262 // |
262 // |
263 bool LDConfigParser::findToken (int& result, char const* needle, int args) |
263 bool LDConfigParser::findToken(int& result, char const* needle, int args) |
264 { |
264 { |
265 for (int i = 0; i < (m_tokens.size() - args); ++i) |
265 for (int i = 0; i <(m_tokens.size() - args); ++i) |
266 { |
266 { |
267 if (m_tokens[i] == needle) |
267 if (m_tokens[i] == needle) |
268 { |
268 { |
269 result = i; |
269 result = i; |
270 return true; |
270 return true; |
274 return false; |
274 return false; |
275 } |
275 } |
276 |
276 |
277 // ============================================================================= |
277 // ============================================================================= |
278 // |
278 // |
279 bool LDConfigParser::compareToken (int inPos, QString text) |
279 bool LDConfigParser::compareToken(int inPos, QString text) |
280 { |
280 { |
281 QString tok; |
281 QString tok; |
282 |
282 |
283 if (not getToken (tok, inPos)) |
283 if (not getToken(tok, inPos)) |
284 return false; |
284 return false; |
285 |
285 |
286 return (tok == text); |
286 return (tok == text); |
287 } |
287 } |
288 |
288 |
289 // ============================================================================= |
289 // ============================================================================= |
290 // |
290 // |
291 // Helper function for parseLDConfig |
291 // Helper function for parseLDConfig |
292 // |
292 // |
293 bool LDConfigParser::parseTag (char const* tag, QString& val) |
293 bool LDConfigParser::parseTag(char const* tag, QString& val) |
294 { |
294 { |
295 int pos; |
295 int pos; |
296 |
296 |
297 // Try find the token and get its position |
297 // Try find the token and get its position |
298 if (not findToken (pos, tag, 1)) |
298 if (not findToken(pos, tag, 1)) |
299 return false; |
299 return false; |
300 |
300 |
301 // Get the token after it and store it into val |
301 // Get the token after it and store it into val |
302 return getToken (val, pos + 1); |
302 return getToken(val, pos + 1); |
303 } |
303 } |