Charlie Jiang pushed to branch gsoc-2022-chariri-2 at FreeType / FreeType Demo Programs
Commits:
-
709ad8f1
by Charlie Jiang at 2022-07-22T16:25:35+08:00
-
c61eb3e5
by Charlie Jiang at 2022-07-23T18:05:33+08:00
12 changed files:
- src/ftinspect/CMakeLists.txt
- src/ftinspect/engine/engine.cpp
- src/ftinspect/engine/engine.hpp
- src/ftinspect/engine/fontfilemanager.cpp
- src/ftinspect/ftinspect.cpp
- src/ftinspect/maingui.cpp
- src/ftinspect/maingui.hpp
- src/ftinspect/meson.build
- src/ftinspect/panels/settingpanel.cpp
- src/ftinspect/panels/singular.cpp
- + src/ftinspect/widgets/tripletselector.cpp
- + src/ftinspect/widgets/tripletselector.hpp
Changes:
... | ... | @@ -37,6 +37,7 @@ add_executable(ftinspect |
37 | 37 | "widgets/customwidgets.cpp"
|
38 | 38 | "widgets/glyphindexselector.cpp"
|
39 | 39 | "widgets/fontsizeselector.cpp"
|
40 | + "widgets/tripletselector.cpp"
|
|
40 | 41 | |
41 | 42 | "models/customcomboboxmodels.cpp"
|
42 | 43 |
... | ... | @@ -175,11 +175,13 @@ Engine::numberOfFaces(int fontIndex) |
175 | 175 | FT_Face face;
|
176 | 176 | long numFaces = -1;
|
177 | 177 | |
178 | + if (fontIndex < 0)
|
|
179 | + return -1;
|
|
180 | + |
|
181 | + auto id = FaceID(fontIndex, 0, 0);
|
|
182 | + |
|
178 | 183 | // search triplet (fontIndex, 0, 0)
|
179 | - FTC_FaceID ftcFaceID = reinterpret_cast<FTC_FaceID>
|
|
180 | - (faceIDMap_.value(FaceID(fontIndex,
|
|
181 | - 0,
|
|
182 | - 0)));
|
|
184 | + FTC_FaceID ftcFaceID = reinterpret_cast<FTC_FaceID>(faceIDMap_.value(id));
|
|
183 | 185 | if (ftcFaceID)
|
184 | 186 | {
|
185 | 187 | // found
|
... | ... | @@ -190,14 +192,13 @@ Engine::numberOfFaces(int fontIndex) |
190 | 192 | {
|
191 | 193 | // not found; try to load triplet (fontIndex, 0, 0)
|
192 | 194 | ftcFaceID = reinterpret_cast<FTC_FaceID>(faceCounter_);
|
193 | - faceIDMap_.insert(FaceID(fontIndex, 0, 0),
|
|
194 | - faceCounter_++);
|
|
195 | + faceIDMap_.insert(id, faceCounter_++);
|
|
195 | 196 | |
196 | 197 | if (!FTC_Manager_LookupFace(cacheManager_, ftcFaceID, &face))
|
197 | 198 | numFaces = face->num_faces;
|
198 | 199 | else
|
199 | 200 | {
|
200 | - faceIDMap_.remove(FaceID(fontIndex, 0, 0));
|
|
201 | + faceIDMap_.remove(id);
|
|
201 | 202 | faceCounter_--;
|
202 | 203 | }
|
203 | 204 | }
|
... | ... | @@ -214,12 +215,12 @@ Engine::numberOfNamedInstances(int fontIndex, |
214 | 215 | // we return `n' named instances plus one;
|
215 | 216 | // instance index 0 represents a face without a named instance selected
|
216 | 217 | int numNamedInstances = -1;
|
218 | + if (fontIndex < 0)
|
|
219 | + return -1;
|
|
220 | + auto id = FaceID(fontIndex, faceIndex, 0);
|
|
217 | 221 | |
218 | 222 | // search triplet (fontIndex, faceIndex, 0)
|
219 | - FTC_FaceID ftcFaceID = reinterpret_cast<FTC_FaceID>
|
|
220 | - (faceIDMap_.value(FaceID(fontIndex,
|
|
221 | - faceIndex,
|
|
222 | - 0)));
|
|
223 | + FTC_FaceID ftcFaceID = reinterpret_cast<FTC_FaceID>(faceIDMap_.value(id));
|
|
223 | 224 | if (ftcFaceID)
|
224 | 225 | {
|
225 | 226 | // found
|
... | ... | @@ -230,14 +231,13 @@ Engine::numberOfNamedInstances(int fontIndex, |
230 | 231 | {
|
231 | 232 | // not found; try to load triplet (fontIndex, faceIndex, 0)
|
232 | 233 | ftcFaceID = reinterpret_cast<FTC_FaceID>(faceCounter_);
|
233 | - faceIDMap_.insert(FaceID(fontIndex, faceIndex, 0),
|
|
234 | - faceCounter_++);
|
|
234 | + faceIDMap_.insert(id, faceCounter_++);
|
|
235 | 235 | |
236 | 236 | if (!FTC_Manager_LookupFace(cacheManager_, ftcFaceID, &face))
|
237 | 237 | numNamedInstances = static_cast<int>((face->style_flags >> 16) + 1);
|
238 | 238 | else
|
239 | 239 | {
|
240 | - faceIDMap_.remove(FaceID(fontIndex, faceIndex, 0));
|
|
240 | + faceIDMap_.remove(id);
|
|
241 | 241 | faceCounter_--;
|
242 | 242 | }
|
243 | 243 | }
|
... | ... | @@ -246,6 +246,48 @@ Engine::numberOfNamedInstances(int fontIndex, |
246 | 246 | }
|
247 | 247 | |
248 | 248 | |
249 | +QString
|
|
250 | +Engine::namedInstanceName(int fontIndex, long faceIndex, int index)
|
|
251 | +{
|
|
252 | + FT_Face face;
|
|
253 | + QString name;
|
|
254 | + |
|
255 | + if (fontIndex < 0)
|
|
256 | + return QString();
|
|
257 | + |
|
258 | + auto id = FaceID(fontIndex, faceIndex, index);
|
|
259 | + |
|
260 | + // search triplet (fontIndex, faceIndex, 0)
|
|
261 | + FTC_FaceID ftcFaceID = reinterpret_cast<FTC_FaceID>(faceIDMap_.value(id));
|
|
262 | + if (ftcFaceID)
|
|
263 | + {
|
|
264 | + // found
|
|
265 | + if (!FTC_Manager_LookupFace(cacheManager_, ftcFaceID, &face))
|
|
266 | + name = QString("%1 %2")
|
|
267 | + .arg(face->family_name)
|
|
268 | + .arg(face->style_name);
|
|
269 | + }
|
|
270 | + else
|
|
271 | + {
|
|
272 | + // not found; try to load triplet (fontIndex, faceIndex, 0)
|
|
273 | + ftcFaceID = reinterpret_cast<FTC_FaceID>(faceCounter_);
|
|
274 | + faceIDMap_.insert(id, faceCounter_++);
|
|
275 | + |
|
276 | + if (!FTC_Manager_LookupFace(cacheManager_, ftcFaceID, &face))
|
|
277 | + name = QString("%1 %2")
|
|
278 | + .arg(face->family_name)
|
|
279 | + .arg(face->style_name);
|
|
280 | + else
|
|
281 | + {
|
|
282 | + faceIDMap_.remove(id);
|
|
283 | + faceCounter_--;
|
|
284 | + }
|
|
285 | + }
|
|
286 | + |
|
287 | + return name;
|
|
288 | +}
|
|
289 | + |
|
290 | + |
|
249 | 291 | int
|
250 | 292 | Engine::currentFontFirstUnicodeCharMap()
|
251 | 293 | {
|
... | ... | @@ -270,15 +312,15 @@ Engine::loadFont(int fontIndex, |
270 | 312 | // search triplet (fontIndex, faceIndex, namedInstanceIndex)
|
271 | 313 | scaler_.face_id = reinterpret_cast<FTC_FaceID>
|
272 | 314 | (faceIDMap_.value(FaceID(fontIndex,
|
273 | - faceIndex,
|
|
274 | - namedInstanceIndex)));
|
|
315 | + faceIndex,
|
|
316 | + namedInstanceIndex)));
|
|
275 | 317 | if (scaler_.face_id)
|
276 | 318 | {
|
277 | 319 | // found
|
278 | 320 | if (!FTC_Manager_LookupSize(cacheManager_, &scaler_, &ftSize_))
|
279 | 321 | numGlyphs = ftSize_->face->num_glyphs;
|
280 | 322 | }
|
281 | - else
|
|
323 | + else if (fontIndex >= 0)
|
|
282 | 324 | {
|
283 | 325 | // not found; try to load triplet
|
284 | 326 | // (fontIndex, faceIndex, namedInstanceIndex)
|
... | ... | @@ -107,17 +107,22 @@ public: |
107 | 107 | |
108 | 108 | FT_Library ftLibrary() const { return library_; }
|
109 | 109 | FTC_Manager cacheManager() { return cacheManager_; }
|
110 | + |
|
110 | 111 | int dpi() { return dpi_; }
|
111 | 112 | double pointSize() { return pointSize_; }
|
113 | + |
|
114 | + int numberOfOpenedFonts();
|
|
112 | 115 | int currentFontType() const { return fontType_; }
|
113 | 116 | const QString& currentFamilyName() { return curFamilyName_; }
|
114 | 117 | const QString& currentStyleName() { return curStyleName_; }
|
115 | 118 | int currentFontNumberOfGlyphs() { return curNumGlyphs_; }
|
116 | - int numberOfOpenedFonts();
|
|
119 | + |
|
117 | 120 | QString glyphName(int glyphIndex);
|
118 | 121 | long numberOfFaces(int fontIndex);
|
119 | 122 | int numberOfNamedInstances(int fontIndex,
|
120 | 123 | long faceIndex);
|
124 | + QString namedInstanceName(int fontIndex, long faceIndex, int index);
|
|
125 | + |
|
121 | 126 | int currentFontFirstUnicodeCharMap();
|
122 | 127 | // Note: the current font face must be properly set
|
123 | 128 | unsigned glyphIndexFromCharCode(int code, int charMapIndex);
|
... | ... | @@ -32,6 +32,7 @@ FontFileManager::append(QStringList newFileNames) |
32 | 32 | for (auto& name : newFileNames)
|
33 | 33 | {
|
34 | 34 | auto info = QFileInfo(name);
|
35 | + info.setCaching(false);
|
|
35 | 36 | |
36 | 37 | // Filter non-file elements
|
37 | 38 | if (!info.isFile())
|
... | ... | @@ -24,8 +24,6 @@ main(int argc, |
24 | 24 | Engine engine;
|
25 | 25 | MainGUI gui(&engine);
|
26 | 26 | |
27 | - gui.setDefaults();
|
|
28 | - |
|
29 | 27 | gui.show();
|
30 | 28 | |
31 | 29 | return app.exec();
|
... | ... | @@ -25,7 +25,6 @@ MainGUI::MainGUI(Engine* engine) |
25 | 25 | createConnections();
|
26 | 26 | createActions();
|
27 | 27 | createMenus();
|
28 | - createStatusBar();
|
|
29 | 28 | setupDragDrop();
|
30 | 29 | |
31 | 30 | readSettings();
|
... | ... | @@ -132,103 +131,13 @@ MainGUI::openFonts(QStringList const& fileNames) |
132 | 131 | int oldSize = engine_->numberOfOpenedFonts();
|
133 | 132 | engine_->openFonts(fileNames);
|
134 | 133 | |
135 | - // if we have new fonts, set the current index to the first new one
|
|
136 | - if (oldSize < engine_->numberOfOpenedFonts())
|
|
137 | - currentFontIndex_ = oldSize;
|
|
138 | - |
|
139 | - showFont();
|
|
140 | -}
|
|
141 | - |
|
142 | - |
|
143 | -void
|
|
144 | -MainGUI::closeFont()
|
|
145 | -{
|
|
146 | - if (currentFontIndex_ < engine_->numberOfOpenedFonts())
|
|
147 | - {
|
|
148 | - engine_->removeFont(currentFontIndex_);
|
|
149 | - }
|
|
150 | - |
|
151 | - // show next font after deletion, i.e., retain index if possible
|
|
152 | - int num = engine_->numberOfOpenedFonts();
|
|
153 | - if (num)
|
|
154 | - {
|
|
155 | - if (currentFontIndex_ >= num)
|
|
156 | - currentFontIndex_ = num - 1;
|
|
157 | - }
|
|
158 | - else
|
|
159 | - currentFontIndex_ = 0;
|
|
160 | - |
|
161 | - showFont();
|
|
162 | -}
|
|
163 | - |
|
164 | - |
|
165 | -void
|
|
166 | -MainGUI::watchCurrentFont()
|
|
167 | -{
|
|
168 | - showFont();
|
|
134 | + tripletSelector_->repopulateFonts();
|
|
169 | 135 | }
|
170 | 136 | |
171 | 137 | |
172 | 138 | void
|
173 | -MainGUI::showFont()
|
|
139 | +MainGUI::onTripletChanged()
|
|
174 | 140 | {
|
175 | - // we do lazy computation of FT_Face objects
|
|
176 | - |
|
177 | - if (currentFontIndex_ < engine_->numberOfOpenedFonts())
|
|
178 | - {
|
|
179 | - QFileInfo& fileInfo = engine_->fontFileManager()[currentFontIndex_];
|
|
180 | - QString fontName = fileInfo.fileName();
|
|
181 | - |
|
182 | - engine_->fontFileManager().updateWatching(currentFontIndex_);
|
|
183 | - if (fileInfo.isSymLink())
|
|
184 | - {
|
|
185 | - fontName.prepend("<i>");
|
|
186 | - fontName.append("</i>");
|
|
187 | - }
|
|
188 | - |
|
189 | - if (!fileInfo.exists())
|
|
190 | - {
|
|
191 | - // On Unix-like systems, the symlink's target gets opened; this
|
|
192 | - // implies that deletion of a symlink doesn't make `engine->loadFont'
|
|
193 | - // fail since it operates on a file handle pointing to the target.
|
|
194 | - // For this reason, we remove the font to enforce a reload.
|
|
195 | - engine_->removeFont(currentFontIndex_, false);
|
|
196 | - }
|
|
197 | - |
|
198 | - fontFilenameLabel_->setText(fontName);
|
|
199 | - }
|
|
200 | - else
|
|
201 | - fontFilenameLabel_->clear();
|
|
202 | - |
|
203 | - syncSettings();
|
|
204 | - currentNumberOfFaces_
|
|
205 | - = engine_->numberOfFaces(currentFontIndex_);
|
|
206 | - currentNumberOfNamedInstances_
|
|
207 | - = engine_->numberOfNamedInstances(currentFontIndex_,
|
|
208 | - currentFaceIndex_);
|
|
209 | - currentNumberOfGlyphs_
|
|
210 | - = engine_->loadFont(currentFontIndex_,
|
|
211 | - currentFaceIndex_,
|
|
212 | - currentNamedInstanceIndex_);
|
|
213 | - |
|
214 | - if (currentNumberOfGlyphs_ < 0)
|
|
215 | - {
|
|
216 | - // there might be various reasons why the current
|
|
217 | - // (file, face, instance) triplet is invalid or missing;
|
|
218 | - // we thus start our timer to periodically test
|
|
219 | - // whether the font starts working
|
|
220 | - if (currentFontIndex_ > 0
|
|
221 | - && currentFontIndex_ < engine_->numberOfOpenedFonts())
|
|
222 | - engine_->fontFileManager().timerStart();
|
|
223 | - }
|
|
224 | - |
|
225 | - fontNameLabel_->setText(QString("%1 %2")
|
|
226 | - .arg(engine_->currentFamilyName())
|
|
227 | - .arg(engine_->currentStyleName()));
|
|
228 | - |
|
229 | - checkCurrentFontIndex();
|
|
230 | - checkCurrentFaceIndex();
|
|
231 | - checkCurrentNamedInstanceIndex();
|
|
232 | 141 | auto state = settingPanel_->blockSignals(true);
|
233 | 142 | settingPanel_->checkHinting();
|
234 | 143 | settingPanel_->blockSignals(state);
|
... | ... | @@ -247,6 +156,7 @@ MainGUI::repaintCurrentTab() |
247 | 156 | void
|
248 | 157 | MainGUI::reloadCurrentTabFont()
|
249 | 158 | {
|
159 | + syncSettings();
|
|
250 | 160 | tabs_[tabWidget_->currentIndex()]->reloadFont();
|
251 | 161 | }
|
252 | 162 | |
... | ... | @@ -258,180 +168,17 @@ MainGUI::syncSettings() |
258 | 168 | }
|
259 | 169 | |
260 | 170 | |
261 | -void
|
|
262 | -MainGUI::clearStatusBar()
|
|
263 | -{
|
|
264 | - statusBar()->clearMessage();
|
|
265 | - statusBar()->setStyleSheet("");
|
|
266 | -}
|
|
267 | - |
|
268 | - |
|
269 | -void
|
|
270 | -MainGUI::checkCurrentFontIndex()
|
|
271 | -{
|
|
272 | - if (engine_->numberOfOpenedFonts() < 2)
|
|
273 | - {
|
|
274 | - previousFontButton_->setEnabled(false);
|
|
275 | - nextFontButton_->setEnabled(false);
|
|
276 | - }
|
|
277 | - else if (currentFontIndex_ == 0)
|
|
278 | - {
|
|
279 | - previousFontButton_->setEnabled(false);
|
|
280 | - nextFontButton_->setEnabled(true);
|
|
281 | - }
|
|
282 | - else if (currentFontIndex_ >= engine_->numberOfOpenedFonts() - 1)
|
|
283 | - {
|
|
284 | - previousFontButton_->setEnabled(true);
|
|
285 | - nextFontButton_->setEnabled(false);
|
|
286 | - }
|
|
287 | - else
|
|
288 | - {
|
|
289 | - previousFontButton_->setEnabled(true);
|
|
290 | - nextFontButton_->setEnabled(true);
|
|
291 | - }
|
|
292 | -}
|
|
293 | - |
|
294 | - |
|
295 | -void
|
|
296 | -MainGUI::checkCurrentFaceIndex()
|
|
297 | -{
|
|
298 | - if (currentNumberOfFaces_ < 2)
|
|
299 | - {
|
|
300 | - previousFaceButton_->setEnabled(false);
|
|
301 | - nextFaceButton_->setEnabled(false);
|
|
302 | - }
|
|
303 | - else if (currentFaceIndex_ == 0)
|
|
304 | - {
|
|
305 | - previousFaceButton_->setEnabled(false);
|
|
306 | - nextFaceButton_->setEnabled(true);
|
|
307 | - }
|
|
308 | - else if (currentFaceIndex_ >= currentNumberOfFaces_ - 1)
|
|
309 | - {
|
|
310 | - previousFaceButton_->setEnabled(true);
|
|
311 | - nextFaceButton_->setEnabled(false);
|
|
312 | - }
|
|
313 | - else
|
|
314 | - {
|
|
315 | - previousFaceButton_->setEnabled(true);
|
|
316 | - nextFaceButton_->setEnabled(true);
|
|
317 | - }
|
|
318 | -}
|
|
319 | - |
|
320 | - |
|
321 | -void
|
|
322 | -MainGUI::checkCurrentNamedInstanceIndex()
|
|
323 | -{
|
|
324 | - if (currentNumberOfNamedInstances_ < 2)
|
|
325 | - {
|
|
326 | - previousNamedInstanceButton_->setEnabled(false);
|
|
327 | - nextNamedInstanceButton_->setEnabled(false);
|
|
328 | - }
|
|
329 | - else if (currentNamedInstanceIndex_ == 0)
|
|
330 | - {
|
|
331 | - previousNamedInstanceButton_->setEnabled(false);
|
|
332 | - nextNamedInstanceButton_->setEnabled(true);
|
|
333 | - }
|
|
334 | - else if (currentNamedInstanceIndex_ >= currentNumberOfNamedInstances_ - 1)
|
|
335 | - {
|
|
336 | - previousNamedInstanceButton_->setEnabled(true);
|
|
337 | - nextNamedInstanceButton_->setEnabled(false);
|
|
338 | - }
|
|
339 | - else
|
|
340 | - {
|
|
341 | - previousNamedInstanceButton_->setEnabled(true);
|
|
342 | - nextNamedInstanceButton_->setEnabled(true);
|
|
343 | - }
|
|
344 | -}
|
|
345 | - |
|
346 | - |
|
347 | -void
|
|
348 | -MainGUI::previousFont()
|
|
349 | -{
|
|
350 | - if (currentFontIndex_ > 0)
|
|
351 | - {
|
|
352 | - currentFontIndex_--;
|
|
353 | - currentFaceIndex_ = 0;
|
|
354 | - currentNamedInstanceIndex_ = 0;
|
|
355 | - showFont();
|
|
356 | - }
|
|
357 | -}
|
|
358 | - |
|
359 | - |
|
360 | -void
|
|
361 | -MainGUI::nextFont()
|
|
362 | -{
|
|
363 | - if (currentFontIndex_ < engine_->numberOfOpenedFonts() - 1)
|
|
364 | - {
|
|
365 | - currentFontIndex_++;
|
|
366 | - currentFaceIndex_ = 0;
|
|
367 | - currentNamedInstanceIndex_ = 0;
|
|
368 | - showFont();
|
|
369 | - }
|
|
370 | -}
|
|
371 | - |
|
372 | - |
|
373 | -void
|
|
374 | -MainGUI::previousFace()
|
|
375 | -{
|
|
376 | - if (currentFaceIndex_ > 0)
|
|
377 | - {
|
|
378 | - currentFaceIndex_--;
|
|
379 | - currentNamedInstanceIndex_ = 0;
|
|
380 | - showFont();
|
|
381 | - }
|
|
382 | -}
|
|
383 | - |
|
384 | - |
|
385 | -void
|
|
386 | -MainGUI::nextFace()
|
|
387 | -{
|
|
388 | - if (currentFaceIndex_ < currentNumberOfFaces_ - 1)
|
|
389 | - {
|
|
390 | - currentFaceIndex_++;
|
|
391 | - currentNamedInstanceIndex_ = 0;
|
|
392 | - showFont();
|
|
393 | - }
|
|
394 | -}
|
|
395 | - |
|
396 | - |
|
397 | -void
|
|
398 | -MainGUI::previousNamedInstance()
|
|
399 | -{
|
|
400 | - if (currentNamedInstanceIndex_ > 0)
|
|
401 | - {
|
|
402 | - currentNamedInstanceIndex_--;
|
|
403 | - showFont();
|
|
404 | - }
|
|
405 | -}
|
|
406 | - |
|
407 | - |
|
408 | -void
|
|
409 | -MainGUI::nextNamedInstance()
|
|
410 | -{
|
|
411 | - if (currentNamedInstanceIndex_ < currentNumberOfNamedInstances_ - 1)
|
|
412 | - {
|
|
413 | - currentNamedInstanceIndex_++;
|
|
414 | - showFont();
|
|
415 | - }
|
|
416 | -}
|
|
417 | - |
|
418 | - |
|
419 | 171 | // XXX distances are specified in pixels,
|
420 | 172 | // making the layout dependent on the output device resolution
|
421 | 173 | void
|
422 | 174 | MainGUI::createLayout()
|
423 | 175 | {
|
424 | 176 | // left side
|
425 | - fontFilenameLabel_ = new QLabel(this);
|
|
426 | - |
|
427 | - infoLeftLayout_ = new QHBoxLayout;
|
|
428 | - infoLeftLayout_->addWidget(fontFilenameLabel_);
|
|
429 | - |
|
430 | 177 | settingPanel_ = new SettingPanel(this, engine_);
|
431 | 178 | |
432 | - leftLayout_ = new QVBoxLayout;
|
|
433 | - leftLayout_->addLayout(infoLeftLayout_);
|
|
179 | + leftLayout_ = new QVBoxLayout; // The only point is to set a margin->remove?
|
|
434 | 180 | leftLayout_->addWidget(settingPanel_);
|
181 | + leftLayout_->setContentsMargins(32, 32, 8, 16);
|
|
435 | 182 | |
436 | 183 | // we don't want to expand the left side horizontally;
|
437 | 184 | // to change the policy we have to use a widget wrapper
|
... | ... | @@ -446,8 +193,6 @@ MainGUI::createLayout() |
446 | 193 | leftWidget_->setSizePolicy(leftWidgetPolicy);
|
447 | 194 | |
448 | 195 | // right side
|
449 | - fontNameLabel_ = new QLabel(this);
|
|
450 | - |
|
451 | 196 | singularTab_ = new SingularTab(this, engine_);
|
452 | 197 | continuousTab_ = new ContinuousTab(this, engine_);
|
453 | 198 | |
... | ... | @@ -458,43 +203,33 @@ MainGUI::createLayout() |
458 | 203 | tabWidget_->addTab(singularTab_, tr("Singular Grid View"));
|
459 | 204 | tabs_.append(continuousTab_);
|
460 | 205 | tabWidget_->addTab(continuousTab_, tr("Continuous View"));
|
461 | - |
|
462 | - previousFontButton_ = new QPushButton(tr("Previous Font"), this);
|
|
463 | - nextFontButton_ = new QPushButton(tr("Next Font"), this);
|
|
464 | - previousFaceButton_ = new QPushButton(tr("Previous Face"), this);
|
|
465 | - nextFaceButton_ = new QPushButton(tr("Next Face"), this);
|
|
466 | - previousNamedInstanceButton_
|
|
467 | - = new QPushButton(tr("Previous Named Instance"), this);
|
|
468 | - nextNamedInstanceButton_ = new QPushButton(tr("Next Named Instance"), this);
|
|
469 | - |
|
470 | - fontLayout = new QGridLayout;
|
|
471 | - fontLayout->setColumnStretch(0, 2);
|
|
472 | - fontLayout->addWidget(nextFontButton_, 0, 1);
|
|
473 | - fontLayout->addWidget(previousFontButton_, 1, 1);
|
|
474 | - fontLayout->setColumnStretch(2, 1);
|
|
475 | - fontLayout->addWidget(nextFaceButton_, 0, 3);
|
|
476 | - fontLayout->addWidget(previousFaceButton_, 1, 3);
|
|
477 | - fontLayout->setColumnStretch(4, 1);
|
|
478 | - fontLayout->addWidget(nextNamedInstanceButton_, 0, 5);
|
|
479 | - fontLayout->addWidget(previousNamedInstanceButton_, 1, 5);
|
|
480 | - fontLayout->setColumnStretch(6, 2);
|
|
206 | +
|
|
207 | + tripletSelector_ = new TripletSelector(this, engine_);
|
|
481 | 208 | |
482 | 209 | rightLayout_ = new QVBoxLayout;
|
483 | - rightLayout_->addWidget(fontNameLabel_);
|
|
484 | - rightLayout_->addWidget(tabWidget_);
|
|
485 | - rightLayout_->addLayout(fontLayout);
|
|
210 | + //rightLayout_->addWidget(fontNameLabel_);
|
|
211 | + rightLayout_->addWidget(tabWidget_); // same for `leftLayout_`: Remove?
|
|
212 | + rightLayout_->setContentsMargins(8, 32, 32, 16);
|
|
486 | 213 | |
487 | 214 | // for symmetry with the left side use a widget also
|
488 | 215 | rightWidget_ = new QWidget(this);
|
489 | 216 | rightWidget_->setLayout(rightLayout_);
|
490 | 217 | |
491 | 218 | // the whole thing
|
492 | - ftinspectLayout_ = new QHBoxLayout;
|
|
493 | - ftinspectLayout_->addWidget(leftWidget_);
|
|
494 | - ftinspectLayout_->addWidget(rightWidget_);
|
|
219 | + mainPartLayout_ = new QHBoxLayout;
|
|
220 | + mainPartLayout_->addWidget(leftWidget_);
|
|
221 | + mainPartLayout_->addWidget(rightWidget_);
|
|
222 | + |
|
223 | + ftinspectLayout_ = new QVBoxLayout;
|
|
224 | + ftinspectLayout_->setSpacing(0);
|
|
225 | + ftinspectLayout_->addLayout(mainPartLayout_);
|
|
226 | + ftinspectLayout_->addWidget(tripletSelector_);
|
|
227 | + ftinspectLayout_->setContentsMargins(0, 0, 0, 0);
|
|
495 | 228 | |
496 | 229 | ftinspectWidget_ = new QWidget(this);
|
497 | 230 | ftinspectWidget_->setLayout(ftinspectLayout_);
|
231 | + |
|
232 | + statusBar()->hide(); // remove the extra space
|
|
498 | 233 | setCentralWidget(ftinspectWidget_);
|
499 | 234 | setWindowTitle("ftinspect");
|
500 | 235 | }
|
... | ... | @@ -504,28 +239,15 @@ void |
504 | 239 | MainGUI::createConnections()
|
505 | 240 | {
|
506 | 241 | connect(settingPanel_, &SettingPanel::fontReloadNeeded,
|
507 | - this, &MainGUI::showFont);
|
|
242 | + this, &MainGUI::reloadCurrentTabFont);
|
|
508 | 243 | connect(settingPanel_, &SettingPanel::repaintNeeded,
|
509 | 244 | this, &MainGUI::repaintCurrentTab);
|
510 | 245 | |
511 | 246 | connect(tabWidget_, &QTabWidget::currentChanged,
|
512 | 247 | this, &MainGUI::reloadCurrentTabFont);
|
513 | 248 | |
514 | - connect(previousFontButton_, &QPushButton::clicked,
|
|
515 | - this, &MainGUI::previousFont);
|
|
516 | - connect(nextFontButton_, &QPushButton::clicked,
|
|
517 | - this, &MainGUI::nextFont);
|
|
518 | - connect(previousFaceButton_, &QPushButton::clicked,
|
|
519 | - this, &MainGUI::previousFace);
|
|
520 | - connect(nextFaceButton_, &QPushButton::clicked,
|
|
521 | - this, &MainGUI::nextFace);
|
|
522 | - connect(previousNamedInstanceButton_, &QPushButton::clicked,
|
|
523 | - this, &MainGUI::previousNamedInstance);
|
|
524 | - connect(nextNamedInstanceButton_, &QPushButton::clicked,
|
|
525 | - this, &MainGUI::nextNamedInstance);
|
|
526 | - |
|
527 | - connect(&engine_->fontFileManager(), &FontFileManager::currentFileChanged,
|
|
528 | - this, &MainGUI::watchCurrentFont);
|
|
249 | + connect(tripletSelector_, &TripletSelector::tripletChanged,
|
|
250 | + this, &MainGUI::onTripletChanged);
|
|
529 | 251 | }
|
530 | 252 | |
531 | 253 | |
... | ... | @@ -538,7 +260,8 @@ MainGUI::createActions() |
538 | 260 | |
539 | 261 | closeFontAct_ = new QAction(tr("&Close Font"), this);
|
540 | 262 | closeFontAct_->setShortcuts(QKeySequence::Close);
|
541 | - connect(closeFontAct_, &QAction::triggered, this, &MainGUI::closeFont);
|
|
263 | + connect(closeFontAct_, &QAction::triggered,
|
|
264 | + tripletSelector_, &TripletSelector::closeCurrentFont);
|
|
542 | 265 | |
543 | 266 | exitAct_ = new QAction(tr("E&xit"), this);
|
544 | 267 | exitAct_->setShortcuts(QKeySequence::Quit);
|
... | ... | @@ -566,13 +289,6 @@ MainGUI::createMenus() |
566 | 289 | }
|
567 | 290 | |
568 | 291 | |
569 | -void
|
|
570 | -MainGUI::createStatusBar()
|
|
571 | -{
|
|
572 | - statusBar()->showMessage("");
|
|
573 | -}
|
|
574 | - |
|
575 | - |
|
576 | 292 | void
|
577 | 293 | MainGUI::setupDragDrop()
|
578 | 294 | {
|
... | ... | @@ -580,20 +296,6 @@ MainGUI::setupDragDrop() |
580 | 296 | }
|
581 | 297 | |
582 | 298 | |
583 | -void
|
|
584 | -MainGUI::setDefaults()
|
|
585 | -{
|
|
586 | - // the next four values always non-negative
|
|
587 | - currentFontIndex_ = 0;
|
|
588 | - currentFaceIndex_ = 0;
|
|
589 | - currentNamedInstanceIndex_ = 0;
|
|
590 | -
|
|
591 | - checkCurrentFontIndex();
|
|
592 | - checkCurrentFaceIndex();
|
|
593 | - checkCurrentNamedInstanceIndex();
|
|
594 | -}
|
|
595 | - |
|
596 | - |
|
597 | 299 | void
|
598 | 300 | MainGUI::readSettings()
|
599 | 301 | {
|
... | ... | @@ -6,9 +6,7 @@ |
6 | 6 | #pragma once
|
7 | 7 | |
8 | 8 | #include "engine/engine.hpp"
|
9 | -#include "widgets/customwidgets.hpp"
|
|
10 | -#include "widgets/glyphindexselector.hpp"
|
|
11 | -#include "models/customcomboboxmodels.hpp"
|
|
9 | +#include "widgets/tripletselector.hpp"
|
|
12 | 10 | #include "panels/settingpanel.hpp"
|
13 | 11 | #include "panels/singular.hpp"
|
14 | 12 | #include "panels/continuous.hpp"
|
... | ... | @@ -53,8 +51,6 @@ public: |
53 | 51 | MainGUI(Engine* engine);
|
54 | 52 | ~MainGUI() override;
|
55 | 53 | |
56 | - void setDefaults();
|
|
57 | - |
|
58 | 54 | friend class Engine;
|
59 | 55 | friend FT_Error faceRequester(FTC_FaceID,
|
60 | 56 | FT_Library,
|
... | ... | @@ -69,33 +65,15 @@ protected: |
69 | 65 | private slots:
|
70 | 66 | void about();
|
71 | 67 | void aboutQt();
|
72 | - void checkCurrentFaceIndex();
|
|
73 | - void checkCurrentFontIndex();
|
|
74 | - void checkCurrentNamedInstanceIndex();
|
|
75 | - void closeFont();
|
|
76 | - void showFont();
|
|
77 | 68 | void repaintCurrentTab();
|
78 | 69 | void reloadCurrentTabFont();
|
79 | 70 | void loadFonts();
|
80 | - void nextFace();
|
|
81 | - void nextFont();
|
|
82 | - void nextNamedInstance();
|
|
83 | - void previousFace();
|
|
84 | - void previousFont();
|
|
85 | - void previousNamedInstance();
|
|
86 | - void watchCurrentFont();
|
|
71 | + void onTripletChanged();
|
|
87 | 72 | |
88 | 73 | private:
|
89 | 74 | Engine* engine_;
|
90 | -
|
|
91 | - int currentFontIndex_;
|
|
92 | - |
|
93 | - long currentNumberOfFaces_;
|
|
94 | - long currentFaceIndex_;
|
|
95 | - |
|
96 | - int currentNumberOfNamedInstances_;
|
|
97 | - int currentNamedInstanceIndex_;
|
|
98 | 75 | |
76 | + FaceID currentTriplet_;
|
|
99 | 77 | int currentNumberOfGlyphs_;
|
100 | 78 | |
101 | 79 | // layout related stuff
|
... | ... | @@ -105,25 +83,15 @@ private: |
105 | 83 | QAction *exitAct_;
|
106 | 84 | QAction *loadFontsAct_;
|
107 | 85 | |
108 | - QGridLayout *fontLayout;
|
|
109 | - |
|
110 | - QHBoxLayout *ftinspectLayout_;
|
|
111 | - QHBoxLayout *infoLeftLayout_;
|
|
112 | - |
|
113 | - QLabel *fontFilenameLabel_;
|
|
114 | - QLabel *fontNameLabel_;
|
|
86 | + QVBoxLayout *ftinspectLayout_;
|
|
87 | + QHBoxLayout *mainPartLayout_;
|
|
115 | 88 | |
116 | 89 | QLocale *locale_;
|
117 | 90 | |
118 | 91 | QMenu *menuFile_;
|
119 | 92 | QMenu *menuHelp_;
|
120 | - |
|
121 | - QPushButton *nextFaceButton_;
|
|
122 | - QPushButton *nextFontButton_;
|
|
123 | - QPushButton *nextNamedInstanceButton_;
|
|
124 | - QPushButton *previousFaceButton_;
|
|
125 | - QPushButton *previousFontButton_;
|
|
126 | - QPushButton *previousNamedInstanceButton_;
|
|
93 | +
|
|
94 | + TripletSelector* tripletSelector_;
|
|
127 | 95 |
|
128 | 96 | QVBoxLayout *leftLayout_;
|
129 | 97 | QVBoxLayout *rightLayout_;
|
... | ... | @@ -142,13 +110,11 @@ private: |
142 | 110 | void openFonts(QStringList const& fileNames);
|
143 | 111 | |
144 | 112 | void syncSettings();
|
145 | - void clearStatusBar();
|
|
146 | 113 | |
147 | 114 | void createActions();
|
148 | 115 | void createConnections();
|
149 | 116 | void createLayout();
|
150 | 117 | void createMenus();
|
151 | - void createStatusBar();
|
|
152 | 118 | void setupDragDrop();
|
153 | 119 | |
154 | 120 | void readSettings();
|
... | ... | @@ -36,6 +36,7 @@ if qt5_dep.found() |
36 | 36 | 'widgets/customwidgets.cpp',
|
37 | 37 | 'widgets/glyphindexselector.cpp',
|
38 | 38 | 'widgets/fontsizeselector.cpp',
|
39 | + 'widgets/tripletselector.cpp',
|
|
39 | 40 | |
40 | 41 | 'models/customcomboboxmodels.cpp',
|
41 | 42 | |
... | ... | @@ -54,6 +55,7 @@ if qt5_dep.found() |
54 | 55 | 'widgets/customwidgets.hpp',
|
55 | 56 | 'widgets/glyphindexselector.hpp',
|
56 | 57 | 'widgets/fontsizeselector.hpp',
|
58 | + 'widgets/tripletselector.hpp',
|
|
57 | 59 | 'rendering/glyphcontinuous.hpp',
|
58 | 60 | 'models/customcomboboxmodels.hpp',
|
59 | 61 | 'panels/settingpanel.hpp',
|
... | ... | @@ -358,6 +358,8 @@ SettingPanel::createLayout() |
358 | 358 | mainLayout_ = new QVBoxLayout;
|
359 | 359 | mainLayout_->addWidget(tab_);
|
360 | 360 | setLayout(mainLayout_);
|
361 | + mainLayout_->setContentsMargins(0, 0, 0, 0);
|
|
362 | + setContentsMargins(0, 0, 0, 0);
|
|
361 | 363 | }
|
362 | 364 | |
363 | 365 |
... | ... | @@ -208,7 +208,7 @@ SingularTab::setGridVisible() |
208 | 208 | void
|
209 | 209 | SingularTab::showToolTip()
|
210 | 210 | {
|
211 | - QToolTip::showText(helpButton_->pos(),
|
|
211 | + QToolTip::showText(mapToGlobal(helpButton_->pos()),
|
|
212 | 212 | tr("Scroll: Grid Up/Down\n"
|
213 | 213 | "Alt + Scroll: Grid Left/Right\n"
|
214 | 214 | "Ctrl + Scroll: Adjust Zoom (Relative to cursor)\n"
|
1 | +// tripletselector.cpp
|
|
2 | + |
|
3 | +// Copyright (C) 2022 by Charlie Jiang.
|
|
4 | + |
|
5 | +#include "tripletselector.hpp"
|
|
6 | + |
|
7 | +#include "../engine/engine.hpp"
|
|
8 | + |
|
9 | +#include <functional>
|
|
10 | + |
|
11 | +TripletSelector::TripletSelector(QWidget* parent,
|
|
12 | + Engine* engine)
|
|
13 | +: QWidget(parent),
|
|
14 | + engine_(engine)
|
|
15 | +{
|
|
16 | + createLayout();
|
|
17 | + createConnections();
|
|
18 | + checkButtons();
|
|
19 | +}
|
|
20 | + |
|
21 | + |
|
22 | +TripletSelector::~TripletSelector()
|
|
23 | +{
|
|
24 | +}
|
|
25 | + |
|
26 | + |
|
27 | +void
|
|
28 | +TripletSelector::repopulateFonts()
|
|
29 | +{
|
|
30 | + auto oldSize = fontComboBox_->count();
|
|
31 | + auto oldIndex = fontComboBox_->currentIndex();
|
|
32 | + |
|
33 | + {
|
|
34 | + QSignalBlocker blk(fontComboBox_);
|
|
35 | + QSignalBlocker blk2(faceComboBox_);
|
|
36 | + QSignalBlocker blk3(niComboBox_);
|
|
37 | + fontComboBox_->clear();
|
|
38 | +
|
|
39 | + auto& ffm = engine_->fontFileManager();
|
|
40 | + auto newSize = ffm.size();
|
|
41 | + for (int i = 0; i < newSize; i++)
|
|
42 | + {
|
|
43 | + auto& info = ffm[i];
|
|
44 | + auto name = info.filePath();
|
|
45 | + auto displayName = info.fileName();
|
|
46 | + if (info.isSymbolicLink())
|
|
47 | + displayName += " [symlink]";
|
|
48 | + |
|
49 | + fontComboBox_->addItem(displayName, name);
|
|
50 | + }
|
|
51 | + |
|
52 | + if (newSize > oldSize)
|
|
53 | + {
|
|
54 | + // if we have new fonts, set the current index to the first new one
|
|
55 | + fontComboBox_->setCurrentIndex(oldSize);
|
|
56 | + }
|
|
57 | + else if (newSize < oldSize)
|
|
58 | + {
|
|
59 | + if (oldIndex >= newSize)
|
|
60 | + oldIndex = newSize - 1;
|
|
61 | + if (oldIndex < 0)
|
|
62 | + oldIndex = -1;
|
|
63 | + fontComboBox_->setCurrentIndex(oldIndex);
|
|
64 | + }
|
|
65 | + |
|
66 | + // Note no signal will be emitted from any combobox until this block ends
|
|
67 | + }
|
|
68 | + |
|
69 | + // This will check buttons & reload the triplet
|
|
70 | + repopulateFaces();
|
|
71 | +}
|
|
72 | + |
|
73 | + |
|
74 | +void
|
|
75 | +TripletSelector::repopulateFaces(bool fontSwitched)
|
|
76 | +{
|
|
77 | + // Avoid unnecessary recreating, to reduce interruption of user oper
|
|
78 | + auto needToRecreate = fontSwitched;
|
|
79 | + auto oldSize = faceComboBox_->count();
|
|
80 | + |
|
81 | + auto fontIndex = fontComboBox_->currentIndex();
|
|
82 | + auto newSize = engine_->numberOfFaces(fontIndex);
|
|
83 | + |
|
84 | + if (fontIndex < 0 || newSize < 0)
|
|
85 | + {
|
|
86 | + // Clear and go
|
|
87 | + faceComboBox_->clear();
|
|
88 | + repopulateNamedInstances(fontSwitched);
|
|
89 | + return;
|
|
90 | + }
|
|
91 | + |
|
92 | + if (newSize != oldSize)
|
|
93 | + needToRecreate = true;
|
|
94 | + |
|
95 | + std::vector<QString> newFaces;
|
|
96 | + newFaces.reserve(newSize);
|
|
97 | + for (long i = 0; i < newSize; i++)
|
|
98 | + {
|
|
99 | + newFaces.emplace_back(engine_->namedInstanceName(fontIndex, i, 0));
|
|
100 | + if (!needToRecreate && newFaces[i] != faceComboBox_->itemData(i))
|
|
101 | + needToRecreate = true;
|
|
102 | + }
|
|
103 | + |
|
104 | + if (!needToRecreate)
|
|
105 | + {
|
|
106 | + // no need to refersh the combobox
|
|
107 | + repopulateNamedInstances(fontSwitched);
|
|
108 | + return;
|
|
109 | + }
|
|
110 | + |
|
111 | + {
|
|
112 | + QSignalBlocker blk2(faceComboBox_);
|
|
113 | + QSignalBlocker blk3(niComboBox_);
|
|
114 | + faceComboBox_->clear();
|
|
115 | + |
|
116 | + for (long i = 0; i < newSize; i++)
|
|
117 | + {
|
|
118 | + auto& name = newFaces[i];
|
|
119 | + auto displayName = QString("%1: %2").arg(i).arg(name);
|
|
120 | + faceComboBox_->addItem(displayName, name);
|
|
121 | + }
|
|
122 | + |
|
123 | + faceComboBox_->setCurrentIndex(0);
|
|
124 | + // Note no signal will be emitted from any combobox until this block ends
|
|
125 | + }
|
|
126 | + |
|
127 | + // This will check buttons & reload the triplet
|
|
128 | + repopulateNamedInstances(true);
|
|
129 | +}
|
|
130 | + |
|
131 | + |
|
132 | +void
|
|
133 | +TripletSelector::repopulateNamedInstances(bool fontSwitched)
|
|
134 | +{
|
|
135 | + // Avoid unnecessary recreating, to reduce interruption of user oper
|
|
136 | + // Similar to `repopulateFaces`
|
|
137 | + auto needToRecreate = fontSwitched;
|
|
138 | + auto oldSize = niComboBox_->count();
|
|
139 | + |
|
140 | + auto fontIndex = fontComboBox_->currentIndex();
|
|
141 | + auto faceIndex = faceComboBox_->currentIndex();
|
|
142 | + auto newSize = engine_->numberOfNamedInstances(fontIndex, faceIndex);
|
|
143 | + |
|
144 | + if (fontIndex < 0 || faceIndex < 0 || newSize < 0)
|
|
145 | + {
|
|
146 | + // Clear and go
|
|
147 | + niComboBox_->clear();
|
|
148 | + checkButtons();
|
|
149 | + loadTriplet();
|
|
150 | + return;
|
|
151 | + }
|
|
152 | + |
|
153 | + if (newSize != oldSize)
|
|
154 | + needToRecreate = true;
|
|
155 | + |
|
156 | + std::vector<QString> newFaces;
|
|
157 | + newFaces.reserve(newSize);
|
|
158 | + for (long i = 0; i < newSize; i++)
|
|
159 | + {
|
|
160 | + newFaces.emplace_back(engine_->namedInstanceName(fontIndex, faceIndex, i));
|
|
161 | + if (!needToRecreate && newFaces[i] != niComboBox_->itemData(i))
|
|
162 | + needToRecreate = true;
|
|
163 | + }
|
|
164 | + |
|
165 | + if (!needToRecreate)
|
|
166 | + {
|
|
167 | + // no need to refersh the combobox
|
|
168 | + checkButtons();
|
|
169 | + loadTriplet();
|
|
170 | + return;
|
|
171 | + }
|
|
172 | + |
|
173 | + {
|
|
174 | + QSignalBlocker blk3(niComboBox_);
|
|
175 | + niComboBox_->clear();
|
|
176 | + |
|
177 | + for (long i = 0; i < newSize; i++)
|
|
178 | + {
|
|
179 | + auto& name = newFaces[i];
|
|
180 | + auto displayName = QString("%1: %2").arg(i).arg(name);
|
|
181 | + if (i == 0)
|
|
182 | + displayName = "* " + displayName;
|
|
183 | + niComboBox_->addItem(displayName, name);
|
|
184 | + }
|
|
185 | + |
|
186 | + niComboBox_->setCurrentIndex(0);
|
|
187 | + // Note no signal will be emitted from any combobox until this block ends
|
|
188 | + }
|
|
189 | + |
|
190 | + checkButtons();
|
|
191 | + loadTriplet();
|
|
192 | +}
|
|
193 | + |
|
194 | + |
|
195 | +void
|
|
196 | +TripletSelector::closeCurrentFont()
|
|
197 | +{
|
|
198 | + auto idx = fontComboBox_->currentIndex();
|
|
199 | + if (idx < 0)
|
|
200 | + return;
|
|
201 | + engine_->fontFileManager().remove(idx);
|
|
202 | + |
|
203 | + // show next font after deletion, i.e., retain index if possible
|
|
204 | + int num = engine_->numberOfOpenedFonts();
|
|
205 | + if (num)
|
|
206 | + {
|
|
207 | + if (idx >= num)
|
|
208 | + idx = num - 1;
|
|
209 | + }
|
|
210 | + else
|
|
211 | + idx = -1;
|
|
212 | + |
|
213 | + {
|
|
214 | + // Shut up when repopulating
|
|
215 | + QSignalBlocker blockerThis(this);
|
|
216 | + QSignalBlocker blockerComboBox(fontComboBox_);
|
|
217 | + repopulateFonts();
|
|
218 | + }
|
|
219 | + |
|
220 | + if (idx != -1)
|
|
221 | + faceComboBox_->setCurrentIndex(idx);
|
|
222 | + updateFont();
|
|
223 | +}
|
|
224 | + |
|
225 | + |
|
226 | +void
|
|
227 | +TripletSelector::updateFont()
|
|
228 | +{
|
|
229 | + auto idx = fontComboBox_->currentIndex();
|
|
230 | + auto num = engine_->numberOfOpenedFonts();
|
|
231 | + if (idx < 0)
|
|
232 | + {
|
|
233 | + faceComboBox_->clear();
|
|
234 | + niComboBox_->clear();
|
|
235 | + |
|
236 | + checkButtons();
|
|
237 | + loadTriplet();
|
|
238 | + return;
|
|
239 | + }
|
|
240 | + |
|
241 | + if (num <= 0 || idx >= num)
|
|
242 | + {
|
|
243 | + // out of sync: this shouldn't happen
|
|
244 | + repopulateFonts();
|
|
245 | + return;
|
|
246 | + }
|
|
247 | + |
|
248 | + // This will check buttons & reload the triplet
|
|
249 | + repopulateFaces();
|
|
250 | +}
|
|
251 | + |
|
252 | + |
|
253 | +void
|
|
254 | +TripletSelector::updateFace()
|
|
255 | +{
|
|
256 | + auto idx = faceComboBox_->currentIndex();
|
|
257 | + auto num = engine_->numberOfFaces(fontComboBox_->currentIndex());
|
|
258 | +
|
|
259 | + if (idx >= num)
|
|
260 | + {
|
|
261 | + // out of sync
|
|
262 | + repopulateFaces();
|
|
263 | + return;
|
|
264 | + }
|
|
265 | + |
|
266 | + // This will check buttons & reload the triplet
|
|
267 | + repopulateNamedInstances();
|
|
268 | +}
|
|
269 | + |
|
270 | + |
|
271 | +void
|
|
272 | +TripletSelector::updateNI()
|
|
273 | +{
|
|
274 | + auto idx = niComboBox_->currentIndex();
|
|
275 | + auto num = engine_->numberOfNamedInstances(fontComboBox_->currentIndex(),
|
|
276 | + faceComboBox_->currentIndex());
|
|
277 | +
|
|
278 | + if (idx >= num)
|
|
279 | + {
|
|
280 | + // out of sync
|
|
281 | + repopulateNamedInstances();
|
|
282 | + return;
|
|
283 | + }
|
|
284 | + |
|
285 | + checkButtons();
|
|
286 | + loadTriplet();
|
|
287 | +}
|
|
288 | + |
|
289 | + |
|
290 | +void
|
|
291 | +TripletSelector::checkButtons()
|
|
292 | +{
|
|
293 | + fontUpButton_->setEnabled(fontComboBox_->currentIndex() > 0);
|
|
294 | + fontDownButton_->setEnabled(fontComboBox_->currentIndex()
|
|
295 | + < fontComboBox_->count() - 1);
|
|
296 | + closeFontButton_->setEnabled(faceComboBox_->currentIndex() >= 0);
|
|
297 | + |
|
298 | + faceUpButton_->setEnabled(faceComboBox_->currentIndex() > 0);
|
|
299 | + faceDownButton_->setEnabled(faceComboBox_->currentIndex()
|
|
300 | + < faceComboBox_->count() - 1);
|
|
301 | + |
|
302 | + niUpButton_->setEnabled(niComboBox_->currentIndex() > 0);
|
|
303 | + niDownButton_->setEnabled(niComboBox_->currentIndex()
|
|
304 | + < niComboBox_->count() - 1);
|
|
305 | +}
|
|
306 | + |
|
307 | + |
|
308 | +void
|
|
309 | +TripletSelector::watchCurrentFont()
|
|
310 | +{
|
|
311 | + repopulateFaces(false);
|
|
312 | +}
|
|
313 | + |
|
314 | + |
|
315 | +void
|
|
316 | +TripletSelector::createLayout()
|
|
317 | +{
|
|
318 | + fontComboBox_ = new QComboBox(this);
|
|
319 | + faceComboBox_ = new QComboBox(this);
|
|
320 | + niComboBox_ = new QComboBox(this);
|
|
321 | + |
|
322 | + fontComboBox_->setPlaceholderText(tr("No font open"));
|
|
323 | + faceComboBox_->setPlaceholderText(tr("No face available"));
|
|
324 | + niComboBox_->setPlaceholderText(tr("No named instance available"));
|
|
325 | +
|
|
326 | + closeFontButton_ = new QToolButton(this);
|
|
327 | + fontUpButton_ = new QToolButton(this);
|
|
328 | + faceUpButton_ = new QToolButton(this);
|
|
329 | + niUpButton_ = new QToolButton(this);
|
|
330 | + fontDownButton_ = new QToolButton(this);
|
|
331 | + faceDownButton_ = new QToolButton(this);
|
|
332 | + niDownButton_ = new QToolButton(this);
|
|
333 | + |
|
334 | + closeFontButton_->setText(tr("Close"));
|
|
335 | + fontUpButton_ ->setText(tr("\xE2\x86\x91"));
|
|
336 | + faceUpButton_ ->setText(tr("\xE2\x86\x91"));
|
|
337 | + niUpButton_ ->setText(tr("\xE2\x86\x91"));
|
|
338 | + fontDownButton_ ->setText(tr("\xE2\x86\x93"));
|
|
339 | + faceDownButton_ ->setText(tr("\xE2\x86\x93"));
|
|
340 | + niDownButton_ ->setText(tr("\xE2\x86\x93"));
|
|
341 | +
|
|
342 | + fontComboBox_ ->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Expanding);
|
|
343 | + faceComboBox_ ->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Expanding);
|
|
344 | + niComboBox_ ->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Expanding);
|
|
345 | + closeFontButton_->setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Expanding);
|
|
346 | + fontUpButton_ ->setFixedSize(30, 30);
|
|
347 | + faceUpButton_ ->setFixedSize(30, 30);
|
|
348 | + niUpButton_ ->setFixedSize(30, 30);
|
|
349 | + fontDownButton_ ->setFixedSize(30, 30);
|
|
350 | + faceDownButton_ ->setFixedSize(30, 30);
|
|
351 | + niDownButton_ ->setFixedSize(30, 30);
|
|
352 | + |
|
353 | + layout_ = new QHBoxLayout;
|
|
354 | + layout_->setSpacing(0);
|
|
355 | + layout_->setContentsMargins(0, 0, 0, 0);
|
|
356 | + |
|
357 | + layout_->addWidget(fontComboBox_);
|
|
358 | + layout_->addWidget(fontUpButton_);
|
|
359 | + layout_->addWidget(fontDownButton_);
|
|
360 | + layout_->addWidget(closeFontButton_);
|
|
361 | + layout_->addWidget(faceComboBox_);
|
|
362 | + layout_->addWidget(faceUpButton_);
|
|
363 | + layout_->addWidget(faceDownButton_);
|
|
364 | + layout_->addWidget(niComboBox_);
|
|
365 | + layout_->addWidget(niUpButton_);
|
|
366 | + layout_->addWidget(niDownButton_);
|
|
367 | + |
|
368 | + setFixedHeight(30);
|
|
369 | + setLayout(layout_);
|
|
370 | + layout_->setContentsMargins(0, 0, 0, 0);
|
|
371 | + //setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Fixed);
|
|
372 | +}
|
|
373 | + |
|
374 | + |
|
375 | +void
|
|
376 | +TripletSelector::createConnections()
|
|
377 | +{
|
|
378 | + connect(fontComboBox_, QOverload<int>::of(&QComboBox::currentIndexChanged),
|
|
379 | + this, &TripletSelector::updateFont);
|
|
380 | + connect(faceComboBox_, QOverload<int>::of(&QComboBox::currentIndexChanged),
|
|
381 | + this, &TripletSelector::updateFace);
|
|
382 | + connect(niComboBox_, QOverload<int>::of(&QComboBox::currentIndexChanged),
|
|
383 | + this, &TripletSelector::updateNI);
|
|
384 | + |
|
385 | + connect(closeFontButton_, &QToolButton::clicked,
|
|
386 | + this, &TripletSelector::closeCurrentFont);
|
|
387 | + connect(fontUpButton_ , &QToolButton::clicked,
|
|
388 | + this,
|
|
389 | + std::bind(&TripletSelector::previousComboBoxItem, fontComboBox_));
|
|
390 | + connect(faceUpButton_ , &QToolButton::clicked,
|
|
391 | + this,
|
|
392 | + std::bind(&TripletSelector::previousComboBoxItem, faceComboBox_));
|
|
393 | + connect(niUpButton_ , &QToolButton::clicked,
|
|
394 | + this,
|
|
395 | + std::bind(&TripletSelector::previousComboBoxItem, niComboBox_));
|
|
396 | + connect(fontDownButton_ , &QToolButton::clicked,
|
|
397 | + this,
|
|
398 | + std::bind(&TripletSelector::nextComboBoxItem, fontComboBox_));
|
|
399 | + connect(faceDownButton_ , &QToolButton::clicked,
|
|
400 | + this,
|
|
401 | + std::bind(&TripletSelector::nextComboBoxItem, faceComboBox_));
|
|
402 | + connect(niDownButton_ , &QToolButton::clicked,
|
|
403 | + this,
|
|
404 | + std::bind(&TripletSelector::nextComboBoxItem, niComboBox_));
|
|
405 | + |
|
406 | + connect(&engine_->fontFileManager(), &FontFileManager::currentFileChanged,
|
|
407 | + this, &TripletSelector::watchCurrentFont);
|
|
408 | +}
|
|
409 | + |
|
410 | + |
|
411 | +std::vector<QString>
|
|
412 | +TripletSelector::extractUserDatas(QComboBox* comboBox)
|
|
413 | +{
|
|
414 | + auto count = comboBox->count();
|
|
415 | + std::vector<QString> vec;
|
|
416 | + vec.resize(count);
|
|
417 | + for (long i = 0; i < count; i++)
|
|
418 | + {
|
|
419 | + auto role = comboBox->itemData(i);
|
|
420 | + if (role.canConvert<QString>())
|
|
421 | + vec[i] = role.toString();
|
|
422 | + else
|
|
423 | + vec[i] = QString();
|
|
424 | + }
|
|
425 | + return vec;
|
|
426 | +}
|
|
427 | + |
|
428 | + |
|
429 | +void
|
|
430 | +TripletSelector::loadTriplet()
|
|
431 | +{
|
|
432 | + // we do lazy computation of FT_Face objects
|
|
433 | + |
|
434 | + // TODO really?
|
|
435 | + auto fontIndex = fontComboBox_->currentIndex();
|
|
436 | + auto faceIndex = faceComboBox_->currentIndex();
|
|
437 | + auto instanceIndex = niComboBox_->currentIndex();
|
|
438 | + |
|
439 | + if (fontIndex >= 0 && fontIndex < engine_->numberOfOpenedFonts())
|
|
440 | + {
|
|
441 | + QFileInfo& fileInfo = engine_->fontFileManager()[fontIndex];
|
|
442 | + engine_->fontFileManager().updateWatching(fontIndex);
|
|
443 | + |
|
444 | + if (!fileInfo.exists())
|
|
445 | + {
|
|
446 | + // On Unix-like systems, the symlink's target gets opened; this
|
|
447 | + // implies that deletion of a symlink doesn't make `engine->loadFont'
|
|
448 | + // fail since it operates on a file handle pointing to the target.
|
|
449 | + // For this reason, we remove the font to enforce a reload.
|
|
450 | + engine_->removeFont(fontIndex, false);
|
|
451 | + }
|
|
452 | + }
|
|
453 | + |
|
454 | + auto number = engine_->loadFont(fontIndex, faceIndex, instanceIndex);
|
|
455 | + |
|
456 | + if (number < 0)
|
|
457 | + {
|
|
458 | + // there might be various reasons why the current
|
|
459 | + // (file, face, instance) triplet is invalid or missing;
|
|
460 | + // we thus start our timer to periodically test
|
|
461 | + // whether the font starts working
|
|
462 | + if (faceIndex >= 0 && faceIndex < engine_->numberOfOpenedFonts())
|
|
463 | + engine_->fontFileManager().timerStart();
|
|
464 | + }
|
|
465 | + |
|
466 | + emit tripletChanged();
|
|
467 | +}
|
|
468 | + |
|
469 | + |
|
470 | +void
|
|
471 | +TripletSelector::nextComboBoxItem(QComboBox* c)
|
|
472 | +{
|
|
473 | + if (c->currentIndex() < 0 || c->currentIndex() >= c->count() - 1)
|
|
474 | + return;
|
|
475 | + // No need to handle further steps, the event handler will take care of these
|
|
476 | + c->setCurrentIndex(c->currentIndex() + 1);
|
|
477 | +}
|
|
478 | + |
|
479 | + |
|
480 | +void
|
|
481 | +TripletSelector::previousComboBoxItem(QComboBox* c)
|
|
482 | +{
|
|
483 | + if (c->currentIndex() <= 0)
|
|
484 | + return;
|
|
485 | + // No need to handle further steps, the event handler will take care of these
|
|
486 | + c->setCurrentIndex(c->currentIndex() - 1);
|
|
487 | +}
|
|
488 | + |
|
489 | + |
|
490 | +// end of tripletselector.cpp |
1 | +// QPushButton.hpp
|
|
2 | + |
|
3 | +// Copyright (C) 2022 by Charlie Jiang.
|
|
4 | + |
|
5 | +#pragma once
|
|
6 | + |
|
7 | +#include <vector>
|
|
8 | +#include <QWidget>
|
|
9 | +#include <QComboBox>
|
|
10 | +#include <QPushButton>
|
|
11 | +#include <QToolButton>
|
|
12 | +#include <QBoxLayout>
|
|
13 | + |
|
14 | +class Engine;
|
|
15 | +class TripletSelector
|
|
16 | +: public QWidget
|
|
17 | +{
|
|
18 | + Q_OBJECT
|
|
19 | + |
|
20 | +public:
|
|
21 | + TripletSelector(QWidget* parent,
|
|
22 | + Engine* engine);
|
|
23 | + ~TripletSelector() override;
|
|
24 | + |
|
25 | + void repopulateFonts();
|
|
26 | + void repopulateFaces(bool fontSwitched = true);
|
|
27 | + void repopulateNamedInstances(bool fontSwitched = true);
|
|
28 | + void closeCurrentFont();
|
|
29 | + void updateFont();
|
|
30 | + void updateFace();
|
|
31 | + void updateNI();
|
|
32 | + void loadTriplet();
|
|
33 | + |
|
34 | +signals:
|
|
35 | + void tripletChanged();
|
|
36 | + |
|
37 | +private:
|
|
38 | + Engine* engine_;
|
|
39 | + |
|
40 | + QComboBox* fontComboBox_;
|
|
41 | + QComboBox* faceComboBox_;
|
|
42 | + QComboBox* niComboBox_;
|
|
43 | + |
|
44 | + QToolButton* closeFontButton_;
|
|
45 | + |
|
46 | + QToolButton* fontUpButton_;
|
|
47 | + QToolButton* fontDownButton_;
|
|
48 | + QToolButton* faceUpButton_;
|
|
49 | + QToolButton* faceDownButton_;
|
|
50 | + QToolButton* niUpButton_;
|
|
51 | + QToolButton* niDownButton_;
|
|
52 | + |
|
53 | + QHBoxLayout* layout_;
|
|
54 | + |
|
55 | + void checkButtons();
|
|
56 | + void watchCurrentFont();
|
|
57 | + |
|
58 | + void createLayout();
|
|
59 | + void createConnections();
|
|
60 | + |
|
61 | + std::vector<QString> extractUserDatas(QComboBox* comboBox);
|
|
62 | + |
|
63 | + static void nextComboBoxItem(QComboBox* c);
|
|
64 | + static void previousComboBoxItem(QComboBox* c);
|
|
65 | +};
|
|
66 | + |
|
67 | + |
|
68 | +// end of QPushButton.hpp |