freetype-commit
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Git][freetype/freetype-demos][gsoc-2022-chariri-2] [ftinspect] WIP: New


From: Charlie Jiang (@cqjjjzr)
Subject: [Git][freetype/freetype-demos][gsoc-2022-chariri-2] [ftinspect] WIP: New Font/Face/Named Instance selector.
Date: Sat, 23 Jul 2022 10:36:08 +0000

Charlie Jiang pushed to branch gsoc-2022-chariri-2 at FreeType / FreeType Demo Programs

Commits:

  • fbfba14a
    by Charlie Jiang at 2022-07-23T18:35:44+08:00
    [ftinspect] WIP: New Font/Face/Named Instance selector.
    
    (Commit message WIP)
    
    TODO: Crashes when using symlink and delete the link when the font is being
    inspected.
    

11 changed files:

Changes:

  • src/ftinspect/CMakeLists.txt
    ... ... @@ -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
     
    

  • src/ftinspect/engine/engine.cpp
    ... ... @@ -99,13 +99,14 @@ faceRequester(FTC_FaceID ftcFaceID,
    99 99
       if (faceID.fontIndex < 0
    
    100 100
           || faceID.fontIndex >= engine->numberOfOpenedFonts())
    
    101 101
         return FT_Err_Invalid_Argument;
    
    102
    -
    
    102
    +  
    
    103 103
       QString font = engine->fontFileManager_[faceID.fontIndex].filePath();
    
    104 104
       long faceIndex = faceID.faceIndex;
    
    105 105
     
    
    106 106
       if (faceID.namedInstanceIndex > 0)
    
    107 107
         faceIndex += faceID.namedInstanceIndex << 16;
    
    108 108
     
    
    109
    +  *faceP = NULL;
    
    109 110
       return FT_New_Face(library,
    
    110 111
                          qPrintable(font),
    
    111 112
                          faceIndex,
    
    ... ... @@ -175,11 +176,13 @@ Engine::numberOfFaces(int fontIndex)
    175 176
       FT_Face face;
    
    176 177
       long numFaces = -1;
    
    177 178
     
    
    179
    +  if (fontIndex < 0)
    
    180
    +    return -1;
    
    181
    +
    
    182
    +  auto id = FaceID(fontIndex, 0, 0);
    
    183
    +
    
    178 184
       // search triplet (fontIndex, 0, 0)
    
    179
    -  FTC_FaceID ftcFaceID = reinterpret_cast<FTC_FaceID>
    
    180
    -                           (faceIDMap_.value(FaceID(fontIndex,
    
    181
    -                                                   0,
    
    182
    -                                                   0)));
    
    185
    +  FTC_FaceID ftcFaceID = reinterpret_cast<FTC_FaceID>(faceIDMap_.value(id));
    
    183 186
       if (ftcFaceID)
    
    184 187
       {
    
    185 188
         // found
    
    ... ... @@ -190,14 +193,13 @@ Engine::numberOfFaces(int fontIndex)
    190 193
       {
    
    191 194
         // not found; try to load triplet (fontIndex, 0, 0)
    
    192 195
         ftcFaceID = reinterpret_cast<FTC_FaceID>(faceCounter_);
    
    193
    -    faceIDMap_.insert(FaceID(fontIndex, 0, 0),
    
    194
    -                     faceCounter_++);
    
    196
    +    faceIDMap_.insert(id, faceCounter_++);
    
    195 197
     
    
    196 198
         if (!FTC_Manager_LookupFace(cacheManager_, ftcFaceID, &face))
    
    197 199
           numFaces = face->num_faces;
    
    198 200
         else
    
    199 201
         {
    
    200
    -      faceIDMap_.remove(FaceID(fontIndex, 0, 0));
    
    202
    +      faceIDMap_.remove(id);
    
    201 203
           faceCounter_--;
    
    202 204
         }
    
    203 205
       }
    
    ... ... @@ -214,12 +216,12 @@ Engine::numberOfNamedInstances(int fontIndex,
    214 216
       // we return `n' named instances plus one;
    
    215 217
       // instance index 0 represents a face without a named instance selected
    
    216 218
       int numNamedInstances = -1;
    
    219
    +  if (fontIndex < 0)
    
    220
    +    return -1;
    
    221
    +  auto id = FaceID(fontIndex, faceIndex, 0);
    
    217 222
     
    
    218 223
       // search triplet (fontIndex, faceIndex, 0)
    
    219
    -  FTC_FaceID ftcFaceID = reinterpret_cast<FTC_FaceID>
    
    220
    -                           (faceIDMap_.value(FaceID(fontIndex,
    
    221
    -                                                   faceIndex,
    
    222
    -                                                   0)));
    
    224
    +  FTC_FaceID ftcFaceID = reinterpret_cast<FTC_FaceID>(faceIDMap_.value(id));
    
    223 225
       if (ftcFaceID)
    
    224 226
       {
    
    225 227
         // found
    
    ... ... @@ -230,14 +232,13 @@ Engine::numberOfNamedInstances(int fontIndex,
    230 232
       {
    
    231 233
         // not found; try to load triplet (fontIndex, faceIndex, 0)
    
    232 234
         ftcFaceID = reinterpret_cast<FTC_FaceID>(faceCounter_);
    
    233
    -    faceIDMap_.insert(FaceID(fontIndex, faceIndex, 0),
    
    234
    -                     faceCounter_++);
    
    235
    +    faceIDMap_.insert(id, faceCounter_++);
    
    235 236
     
    
    236 237
         if (!FTC_Manager_LookupFace(cacheManager_, ftcFaceID, &face))
    
    237 238
           numNamedInstances = static_cast<int>((face->style_flags >> 16) + 1);
    
    238 239
         else
    
    239 240
         {
    
    240
    -      faceIDMap_.remove(FaceID(fontIndex, faceIndex, 0));
    
    241
    +      faceIDMap_.remove(id);
    
    241 242
           faceCounter_--;
    
    242 243
         }
    
    243 244
       }
    
    ... ... @@ -246,6 +247,48 @@ Engine::numberOfNamedInstances(int fontIndex,
    246 247
     }
    
    247 248
     
    
    248 249
     
    
    250
    +QString
    
    251
    +Engine::namedInstanceName(int fontIndex, long faceIndex, int index)
    
    252
    +{
    
    253
    +  FT_Face face;
    
    254
    +  QString name;
    
    255
    +
    
    256
    +  if (fontIndex < 0)
    
    257
    +    return QString();
    
    258
    +
    
    259
    +  auto id = FaceID(fontIndex, faceIndex, index);
    
    260
    +
    
    261
    +  // search triplet (fontIndex, faceIndex, 0)
    
    262
    +  FTC_FaceID ftcFaceID = reinterpret_cast<FTC_FaceID>(faceIDMap_.value(id));
    
    263
    +  if (ftcFaceID)
    
    264
    +  {
    
    265
    +    // found
    
    266
    +    if (!FTC_Manager_LookupFace(cacheManager_, ftcFaceID, &face))
    
    267
    +      name = QString("%1 %2")
    
    268
    +               .arg(face->family_name)
    
    269
    +               .arg(face->style_name);
    
    270
    +  }
    
    271
    +  else
    
    272
    +  {
    
    273
    +    // not found; try to load triplet (fontIndex, faceIndex, 0)
    
    274
    +    ftcFaceID = reinterpret_cast<FTC_FaceID>(faceCounter_);
    
    275
    +    faceIDMap_.insert(id, faceCounter_++);
    
    276
    +
    
    277
    +    if (!FTC_Manager_LookupFace(cacheManager_, ftcFaceID, &face))
    
    278
    +      name = QString("%1 %2")
    
    279
    +               .arg(face->family_name)
    
    280
    +               .arg(face->style_name);
    
    281
    +    else
    
    282
    +    {
    
    283
    +      faceIDMap_.remove(id);
    
    284
    +      faceCounter_--;
    
    285
    +    }
    
    286
    +  }
    
    287
    +
    
    288
    +  return name;
    
    289
    +}
    
    290
    +
    
    291
    +
    
    249 292
     int
    
    250 293
     Engine::currentFontFirstUnicodeCharMap()
    
    251 294
     {
    
    ... ... @@ -270,15 +313,15 @@ Engine::loadFont(int fontIndex,
    270 313
       // search triplet (fontIndex, faceIndex, namedInstanceIndex)
    
    271 314
       scaler_.face_id = reinterpret_cast<FTC_FaceID>
    
    272 315
                          (faceIDMap_.value(FaceID(fontIndex,
    
    273
    -                                             faceIndex,
    
    274
    -                                             namedInstanceIndex)));
    
    316
    +                                              faceIndex,
    
    317
    +                                              namedInstanceIndex)));
    
    275 318
       if (scaler_.face_id)
    
    276 319
       {
    
    277 320
         // found
    
    278 321
         if (!FTC_Manager_LookupSize(cacheManager_, &scaler_, &ftSize_))
    
    279 322
           numGlyphs = ftSize_->face->num_glyphs;
    
    280 323
       }
    
    281
    -  else
    
    324
    +  else if (fontIndex >= 0)
    
    282 325
       {
    
    283 326
         // not found; try to load triplet
    
    284 327
         // (fontIndex, faceIndex, namedInstanceIndex)
    

  • src/ftinspect/engine/engine.hpp
    ... ... @@ -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);
    

  • src/ftinspect/engine/fontfilemanager.cpp
    ... ... @@ -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())
    

  • src/ftinspect/ftinspect.cpp
    ... ... @@ -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();
    

  • src/ftinspect/maingui.cpp
    ... ... @@ -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
     {
    

  • src/ftinspect/maingui.hpp
    ... ... @@ -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();
    

  • src/ftinspect/meson.build
    ... ... @@ -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',
    

  • src/ftinspect/panels/settingpanel.cpp
    ... ... @@ -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
     
    

  • src/ftinspect/widgets/tripletselector.cpp
    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
    +  niComboBox_->setEnabled(newSize > 1);
    
    166
    +
    
    167
    +  if (!needToRecreate)
    
    168
    +  {
    
    169
    +    // no need to refersh the combobox
    
    170
    +    checkButtons();
    
    171
    +    loadTriplet();
    
    172
    +    return;
    
    173
    +  }
    
    174
    +
    
    175
    +  {
    
    176
    +    QSignalBlocker blk3(niComboBox_);
    
    177
    +    niComboBox_->clear();
    
    178
    +
    
    179
    +    for (long i = 0; i < newSize; i++)
    
    180
    +    {
    
    181
    +      auto& name = newFaces[i];
    
    182
    +      auto displayName = QString("%1: %2").arg(i).arg(name);
    
    183
    +      if (i == 0)
    
    184
    +        displayName = "* " + displayName;
    
    185
    +      niComboBox_->addItem(displayName, name);
    
    186
    +    }
    
    187
    +
    
    188
    +    niComboBox_->setCurrentIndex(0);
    
    189
    +    // Note no signal will be emitted from any combobox until this block ends
    
    190
    +  }
    
    191
    +
    
    192
    +  checkButtons();
    
    193
    +  loadTriplet();
    
    194
    +}
    
    195
    +
    
    196
    +
    
    197
    +void
    
    198
    +TripletSelector::closeCurrentFont()
    
    199
    +{
    
    200
    +  auto idx = fontComboBox_->currentIndex();
    
    201
    +  if (idx < 0)
    
    202
    +    return;
    
    203
    +  engine_->fontFileManager().remove(idx);
    
    204
    +
    
    205
    +  // show next font after deletion, i.e., retain index if possible
    
    206
    +  int num = engine_->numberOfOpenedFonts();
    
    207
    +  if (num)
    
    208
    +  {
    
    209
    +    if (idx >= num)
    
    210
    +      idx = num - 1;
    
    211
    +  }
    
    212
    +  else
    
    213
    +    idx = -1;
    
    214
    +
    
    215
    +  {
    
    216
    +    // Shut up when repopulating
    
    217
    +    QSignalBlocker blockerThis(this);
    
    218
    +    QSignalBlocker blockerComboBox(fontComboBox_);
    
    219
    +    repopulateFonts();
    
    220
    +  }
    
    221
    +
    
    222
    +  if (idx != -1)
    
    223
    +    faceComboBox_->setCurrentIndex(idx);
    
    224
    +  updateFont();
    
    225
    +}
    
    226
    +
    
    227
    +
    
    228
    +void
    
    229
    +TripletSelector::updateFont()
    
    230
    +{
    
    231
    +  auto idx = fontComboBox_->currentIndex();
    
    232
    +  auto num = engine_->numberOfOpenedFonts();
    
    233
    +  if (idx < 0)
    
    234
    +  {
    
    235
    +    faceComboBox_->clear();
    
    236
    +    niComboBox_->clear();
    
    237
    +
    
    238
    +    checkButtons();
    
    239
    +    loadTriplet();
    
    240
    +    return;
    
    241
    +  }
    
    242
    +
    
    243
    +  if (num <= 0 || idx >= num)
    
    244
    +  {
    
    245
    +    // out of sync: this shouldn't happen
    
    246
    +    repopulateFonts();
    
    247
    +    return;
    
    248
    +  }
    
    249
    +
    
    250
    +  // This will check buttons & reload the triplet
    
    251
    +  repopulateFaces();
    
    252
    +}
    
    253
    +
    
    254
    +
    
    255
    +void
    
    256
    +TripletSelector::updateFace()
    
    257
    +{
    
    258
    +  auto idx = faceComboBox_->currentIndex();
    
    259
    +  auto num = engine_->numberOfFaces(fontComboBox_->currentIndex());
    
    260
    +  
    
    261
    +  if (idx >= num)
    
    262
    +  {
    
    263
    +    // out of sync
    
    264
    +    repopulateFaces();
    
    265
    +    return;
    
    266
    +  }
    
    267
    +
    
    268
    +  // This will check buttons & reload the triplet
    
    269
    +  repopulateNamedInstances();
    
    270
    +}
    
    271
    +
    
    272
    +
    
    273
    +void
    
    274
    +TripletSelector::updateNI()
    
    275
    +{
    
    276
    +  auto idx = niComboBox_->currentIndex();
    
    277
    +  auto num = engine_->numberOfNamedInstances(fontComboBox_->currentIndex(),
    
    278
    +                                             faceComboBox_->currentIndex());
    
    279
    +  
    
    280
    +  if (idx >= num)
    
    281
    +  {
    
    282
    +    // out of sync
    
    283
    +    repopulateNamedInstances();
    
    284
    +    return;
    
    285
    +  }
    
    286
    +
    
    287
    +  checkButtons();
    
    288
    +  loadTriplet();
    
    289
    +}
    
    290
    +
    
    291
    +
    
    292
    +void
    
    293
    +TripletSelector::checkButtons()
    
    294
    +{
    
    295
    +  fontUpButton_->setEnabled(fontComboBox_->currentIndex() > 0);
    
    296
    +  fontDownButton_->setEnabled(fontComboBox_->currentIndex()
    
    297
    +                              < fontComboBox_->count() - 1);
    
    298
    +  closeFontButton_->setEnabled(faceComboBox_->currentIndex() >= 0);
    
    299
    +
    
    300
    +  faceUpButton_->setEnabled(faceComboBox_->currentIndex() > 0);
    
    301
    +  faceDownButton_->setEnabled(faceComboBox_->currentIndex()
    
    302
    +                              < faceComboBox_->count() - 1);
    
    303
    +
    
    304
    +  niUpButton_->setEnabled(niComboBox_->currentIndex() > 0);
    
    305
    +  niDownButton_->setEnabled(niComboBox_->currentIndex()
    
    306
    +                            < niComboBox_->count() - 1);
    
    307
    +}
    
    308
    +
    
    309
    +
    
    310
    +void
    
    311
    +TripletSelector::watchCurrentFont()
    
    312
    +{
    
    313
    +  repopulateFaces(false);
    
    314
    +}
    
    315
    +
    
    316
    +
    
    317
    +void
    
    318
    +TripletSelector::createLayout()
    
    319
    +{
    
    320
    +  fontComboBox_ = new QComboBox(this);
    
    321
    +  faceComboBox_ = new QComboBox(this);
    
    322
    +  niComboBox_    = new QComboBox(this);
    
    323
    +
    
    324
    +  fontComboBox_->setPlaceholderText(tr("No font open"));
    
    325
    +  faceComboBox_->setPlaceholderText(tr("No face available"));
    
    326
    +  niComboBox_->setPlaceholderText(tr("No named instance available"));
    
    327
    +  
    
    328
    +  closeFontButton_ = new QToolButton(this);
    
    329
    +  fontUpButton_    = new QToolButton(this);
    
    330
    +  faceUpButton_    = new QToolButton(this);
    
    331
    +  niUpButton_      = new QToolButton(this);
    
    332
    +  fontDownButton_  = new QToolButton(this);
    
    333
    +  faceDownButton_  = new QToolButton(this);
    
    334
    +  niDownButton_    = new QToolButton(this);
    
    335
    +
    
    336
    +  closeFontButton_->setText(tr("Close"));
    
    337
    +  fontUpButton_   ->setText(tr("\xE2\x86\x91"));
    
    338
    +  faceUpButton_   ->setText(tr("\xE2\x86\x91"));
    
    339
    +  niUpButton_     ->setText(tr("\xE2\x86\x91"));
    
    340
    +  fontDownButton_ ->setText(tr("\xE2\x86\x93"));
    
    341
    +  faceDownButton_ ->setText(tr("\xE2\x86\x93"));
    
    342
    +  niDownButton_   ->setText(tr("\xE2\x86\x93"));
    
    343
    +  
    
    344
    +  fontComboBox_   ->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Expanding);
    
    345
    +  faceComboBox_   ->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Expanding);
    
    346
    +  niComboBox_     ->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Expanding);
    
    347
    +  closeFontButton_->setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Expanding);
    
    348
    +  fontUpButton_   ->setFixedSize(30, 30);
    
    349
    +  faceUpButton_   ->setFixedSize(30, 30);
    
    350
    +  niUpButton_     ->setFixedSize(30, 30);
    
    351
    +  fontDownButton_ ->setFixedSize(30, 30);
    
    352
    +  faceDownButton_ ->setFixedSize(30, 30);
    
    353
    +  niDownButton_   ->setFixedSize(30, 30);
    
    354
    +
    
    355
    +  layout_ = new QHBoxLayout;
    
    356
    +  layout_->setSpacing(0);
    
    357
    +  layout_->setContentsMargins(0, 0, 0, 0);
    
    358
    +
    
    359
    +  layout_->addWidget(fontComboBox_);
    
    360
    +  layout_->addWidget(fontUpButton_);
    
    361
    +  layout_->addWidget(fontDownButton_);
    
    362
    +  layout_->addWidget(closeFontButton_);
    
    363
    +  layout_->addWidget(faceComboBox_);
    
    364
    +  layout_->addWidget(faceUpButton_);
    
    365
    +  layout_->addWidget(faceDownButton_);
    
    366
    +  layout_->addWidget(niComboBox_);
    
    367
    +  layout_->addWidget(niUpButton_);
    
    368
    +  layout_->addWidget(niDownButton_);
    
    369
    +
    
    370
    +  setFixedHeight(30);
    
    371
    +  setLayout(layout_);
    
    372
    +  layout_->setContentsMargins(0, 0, 0, 0);
    
    373
    +  //setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Fixed);
    
    374
    +}
    
    375
    +
    
    376
    +
    
    377
    +void
    
    378
    +TripletSelector::createConnections()
    
    379
    +{
    
    380
    +  connect(fontComboBox_, QOverload<int>::of(&QComboBox::currentIndexChanged),
    
    381
    +          this, &TripletSelector::updateFont);
    
    382
    +  connect(faceComboBox_, QOverload<int>::of(&QComboBox::currentIndexChanged),
    
    383
    +          this, &TripletSelector::updateFace);
    
    384
    +  connect(niComboBox_, QOverload<int>::of(&QComboBox::currentIndexChanged),
    
    385
    +          this, &TripletSelector::updateNI);
    
    386
    +
    
    387
    +  connect(closeFontButton_, &QToolButton::clicked, 
    
    388
    +          this, &TripletSelector::closeCurrentFont);
    
    389
    +  connect(fontUpButton_   , &QToolButton::clicked, 
    
    390
    +          this, 
    
    391
    +          std::bind(&TripletSelector::previousComboBoxItem, fontComboBox_));
    
    392
    +  connect(faceUpButton_   , &QToolButton::clicked, 
    
    393
    +          this, 
    
    394
    +          std::bind(&TripletSelector::previousComboBoxItem, faceComboBox_));
    
    395
    +  connect(niUpButton_     , &QToolButton::clicked, 
    
    396
    +          this, 
    
    397
    +          std::bind(&TripletSelector::previousComboBoxItem, niComboBox_));
    
    398
    +  connect(fontDownButton_ , &QToolButton::clicked, 
    
    399
    +          this, 
    
    400
    +          std::bind(&TripletSelector::nextComboBoxItem, fontComboBox_));
    
    401
    +  connect(faceDownButton_ , &QToolButton::clicked, 
    
    402
    +          this,
    
    403
    +          std::bind(&TripletSelector::nextComboBoxItem, faceComboBox_));
    
    404
    +  connect(niDownButton_   , &QToolButton::clicked, 
    
    405
    +          this, 
    
    406
    +          std::bind(&TripletSelector::nextComboBoxItem, niComboBox_));
    
    407
    +
    
    408
    +  connect(&engine_->fontFileManager(), &FontFileManager::currentFileChanged,
    
    409
    +          this, &TripletSelector::watchCurrentFont);
    
    410
    +}
    
    411
    +
    
    412
    +
    
    413
    +std::vector<QString>
    
    414
    +TripletSelector::extractUserDatas(QComboBox* comboBox)
    
    415
    +{
    
    416
    +  auto count = comboBox->count();
    
    417
    +  std::vector<QString> vec;
    
    418
    +  vec.resize(count);
    
    419
    +  for (long i = 0; i < count; i++)
    
    420
    +  {
    
    421
    +    auto role = comboBox->itemData(i);
    
    422
    +    if (role.canConvert<QString>())
    
    423
    +      vec[i] = role.toString();
    
    424
    +    else
    
    425
    +      vec[i] = QString();
    
    426
    +  }
    
    427
    +  return vec;
    
    428
    +}
    
    429
    +
    
    430
    +
    
    431
    +void
    
    432
    +TripletSelector::loadTriplet()
    
    433
    +{
    
    434
    +  // we do lazy computation of FT_Face objects
    
    435
    +
    
    436
    +  // TODO really?
    
    437
    +  auto fontIndex = fontComboBox_->currentIndex();
    
    438
    +  auto faceIndex = faceComboBox_->currentIndex();
    
    439
    +  auto instanceIndex = niComboBox_->currentIndex();
    
    440
    +
    
    441
    +  if (fontIndex >= 0 && fontIndex < engine_->numberOfOpenedFonts())
    
    442
    +  {
    
    443
    +    QFileInfo& fileInfo = engine_->fontFileManager()[fontIndex];
    
    444
    +    engine_->fontFileManager().updateWatching(fontIndex);
    
    445
    +
    
    446
    +    if (!fileInfo.exists())
    
    447
    +    {
    
    448
    +      // On Unix-like systems, the symlink's target gets opened; this
    
    449
    +      // implies that deletion of a symlink doesn't make `engine->loadFont'
    
    450
    +      // fail since it operates on a file handle pointing to the target.
    
    451
    +      // For this reason, we remove the font to enforce a reload.
    
    452
    +      engine_->removeFont(fontIndex, false);
    
    453
    +    }
    
    454
    +  }
    
    455
    +
    
    456
    +  auto number = engine_->loadFont(fontIndex, faceIndex, instanceIndex);
    
    457
    +
    
    458
    +  if (number < 0)
    
    459
    +  {
    
    460
    +    // there might be various reasons why the current
    
    461
    +    // (file, face, instance) triplet is invalid or missing;
    
    462
    +    // we thus start our timer to periodically test
    
    463
    +    // whether the font starts working
    
    464
    +    if (faceIndex >= 0 && faceIndex < engine_->numberOfOpenedFonts())
    
    465
    +      engine_->fontFileManager().timerStart();
    
    466
    +  }
    
    467
    +
    
    468
    +  emit tripletChanged();
    
    469
    +}
    
    470
    +
    
    471
    +
    
    472
    +void
    
    473
    +TripletSelector::nextComboBoxItem(QComboBox* c)
    
    474
    +{
    
    475
    +  if (c->currentIndex() < 0 || c->currentIndex() >= c->count() - 1)
    
    476
    +    return;
    
    477
    +  // No need to handle further steps, the event handler will take care of these
    
    478
    +  c->setCurrentIndex(c->currentIndex() + 1);
    
    479
    +}
    
    480
    +
    
    481
    +
    
    482
    +void
    
    483
    +TripletSelector::previousComboBoxItem(QComboBox* c)
    
    484
    +{
    
    485
    +  if (c->currentIndex() <= 0)
    
    486
    +    return;
    
    487
    +  // No need to handle further steps, the event handler will take care of these
    
    488
    +  c->setCurrentIndex(c->currentIndex() - 1);
    
    489
    +}
    
    490
    +
    
    491
    +
    
    492
    +// end of tripletselector.cpp

  • src/ftinspect/widgets/tripletselector.hpp
    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


  • reply via email to

    [Prev in Thread] Current Thread [Next in Thread]