• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In
Build has been canceled!

ossia / score / 30758591572

02 Aug 2026 05:18PM UTC coverage: 15.263%. Remained the same
30758591572

Pull #2163

github

web-flow
Merge 0acd683c5 into 5988aecb3
Pull Request #2163: Fix backwards playback for audio plug-ins (VST, VST3, LV2, JSFX)

0 of 57 new or added lines in 5 files covered. (0.0%)

276 existing lines in 3 files now uncovered.

30463 of 199585 relevant lines covered (15.26%)

1075.25 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

74.43
/src/lib/score/widgets/SetIcons.cpp
1
// This is an open source non-commercial project. Dear PVS-Studio, please check
2
// it. PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
3
#include "SetIcons.hpp"
4

5
#include <score/application/ApplicationContext.hpp>
6
#include <score/widgets/Pixmap.hpp>
7

8
#include <core/application/ApplicationSettings.hpp>
9

10
#include <ossia/detail/hash_map.hpp>
11

12
#include <QDebug>
13
#include <QDirIterator>
14
#include <QFile>
15
#include <QGuiApplication>
16
#include <QScreen>
17
// QtSvg is an optional Qt module (see src/lib/CMakeLists.txt). Guard on the
18
// header so score still builds against a Qt without it (e.g. a minimal wasm SDK).
19
#if __has_include(<QSvgRenderer>)
20
#include <QSvgRenderer>
21
#include <QtSvg>
22
#define SCORE_HAS_QTSVG 1
23
#else
24
#define SCORE_HAS_QTSVG 0
25
#endif
26

27
namespace std
28
{
29
template <>
30
struct hash<std::pair<QString, QString>>
31
{
32
  std::size_t operator()(const std::pair<QString, QString>& p) const noexcept
33
  {
34
    return qHash(p);
35
  }
36
};
37

38
template <>
39
struct hash<std::tuple<QString, QString, QString, QString>>
40
{
41
  std::size_t
42
  operator()(const std::tuple<QString, QString, QString, QString>& p) const noexcept
2,725✔
43
  {
44
    return qHash(std::get<0>(p)) ^ qHash(std::get<1>(p)) ^ qHash(std::get<2>(p))
5,450✔
45
           ^ qHash(std::get<3>(p));
2,725✔
46
  }
47
};
48
}
49
static auto& iconMap()
973✔
50
{
51
  static ossia::hash_map<std::tuple<QString, QString, QString, QString>, QIcon> icons;
973✔
52
  return icons;
973✔
53
}
×
54

55
void setIcons(
74✔
56
    QAction* action, const QString& iconOn, const QString& iconOff,
57
    const QString& iconDisable, bool enableHover)
58
{
59
  auto& map = iconMap();
74✔
60
  auto pair = std::make_tuple(iconOn, iconOff, iconDisable, QString{});
74✔
61
  auto it = map.find(pair);
74✔
62
  if(it != map.end())
74✔
63
  {
64
    action->setIcon(it->second);
7✔
65
  }
7✔
66
  else
67
  {
68
    QIcon icon;
67✔
69
    QPixmap on = score::get_pixmap(iconOn);
67✔
70
    QPixmap off = score::get_pixmap(iconOff);
67✔
71
    QPixmap disable = score::get_pixmap(iconDisable);
67✔
72
    icon.addPixmap(on, QIcon::Mode::Selected);
67✔
73
    if(enableHover)
67✔
74
    {
75
      icon.addPixmap(on, QIcon::Mode::Active);
35✔
76
      icon.addPixmap(on, QIcon::Mode::Active, QIcon::State::On);
35✔
77
    }
35✔
78
    icon.addPixmap(on, QIcon::Mode::Normal, QIcon::State::On);
67✔
79
    icon.addPixmap(disable, QIcon::Mode::Disabled);
67✔
80
    icon.addPixmap(off, QIcon::Mode::Normal);
67✔
81
    action->setIcon(icon);
67✔
82

83
    map.insert(std::make_pair(std::move(pair), std::move(icon)));
67✔
84
  }
67✔
85
}
74✔
86
void setIcons(
679✔
87
    QAction* action, const QString& iconOn, const QString& iconHover,
88
    const QString& iconOff, const QString& iconDisable)
89
{
90
  auto& map = iconMap();
679✔
91
  auto pair = std::make_tuple(iconOn, iconOff, iconDisable, QString{});
679✔
92
  auto it = map.find(pair);
679✔
93
  if(it != map.end())
679✔
94
  {
95
    action->setIcon(it->second);
209✔
96
  }
209✔
97
  else
98
  {
99
    QIcon icon;
470✔
100
    QPixmap on = score::get_pixmap(iconOn);
470✔
101
    QPixmap off = score::get_pixmap(iconOff);
470✔
102
    QPixmap disable = score::get_pixmap(iconDisable);
470✔
103
    QPixmap hover = score::get_pixmap(iconHover);
470✔
104
    icon.addPixmap(on, QIcon::Mode::Selected);
470✔
105
    icon.addPixmap(hover, QIcon::Mode::Active);
470✔
106
    icon.addPixmap(hover, QIcon::Mode::Active, QIcon::State::On);
470✔
107
    icon.addPixmap(on, QIcon::Mode::Normal, QIcon::State::On);
470✔
108
    icon.addPixmap(disable, QIcon::Mode::Disabled);
470✔
109
    icon.addPixmap(off, QIcon::Mode::Normal);
470✔
110
    action->setIcon(icon);
470✔
111

112
    map.insert(std::make_pair(std::move(pair), std::move(icon)));
470✔
113
  }
470✔
114
}
679✔
115

116
QIcon makeIcon(const QString& icon)
165✔
117
{
118
  return genIconFromPixmaps(icon, icon, icon);
165✔
119
}
120

121
QIcon makeIcons(
53✔
122
    const QString& iconOn, const QString& iconOff, const QString& iconDisabled)
123
{
124
  return genIconFromPixmaps(iconOn, iconOff, iconDisabled);
53✔
125
}
126

127
QIcon makeIcons(
2✔
128
    const QString& iconOn, const QString& iconHover, const QString& iconOff,
129
    const QString& iconDisabled)
130
{
131
  return genIconFromPixmaps(iconOn, iconHover, iconOff, iconDisabled);
2✔
132
}
133

134
QIcon genIconFromPixmaps(
218✔
135
    const QString& iconOn, const QString& iconOff, const QString& iconDisabled)
136
{
137
  auto& map = iconMap();
218✔
138
  auto pair = std::make_tuple(iconOn, iconOff, iconDisabled, QString{});
218✔
139
  auto it = map.find(pair);
218✔
140
  if(it != map.end())
218✔
141
  {
142
    return it->second;
27✔
143
  }
144
  else
145
  {
146
    QIcon icon;
191✔
147
    QPixmap on(score::get_pixmap(iconOn));
191✔
148
    QPixmap off(score::get_pixmap(iconOff));
191✔
149
    QPixmap disabled(score::get_pixmap(iconDisabled));
191✔
150

151
    icon.addPixmap(on, QIcon::Mode::Selected);
191✔
152
    icon.addPixmap(on, QIcon::Mode::Active);
191✔
153
    icon.addPixmap(on, QIcon::Mode::Normal, QIcon::State::On);
191✔
154
    icon.addPixmap(on, QIcon::Mode::Selected, QIcon::State::On);
191✔
155
    icon.addPixmap(on, QIcon::Mode::Active, QIcon::State::On);
191✔
156
    icon.addPixmap(off, QIcon::Mode::Normal);
191✔
157
    icon.addPixmap(disabled, QIcon::Mode::Disabled);
191✔
158

159
    map.insert(std::make_pair(std::move(pair), icon));
191✔
160
    return icon;
191✔
161
  }
191✔
162
}
218✔
163

164
QIcon genIconFromPixmaps(
2✔
165
    const QString& iconOn, const QString& iconHover, const QString& iconOff,
166
    const QString& iconDisabled)
167
{
168
  auto& map = iconMap();
2✔
169
  auto pair = std::make_tuple(iconOn, iconOff, iconDisabled, iconHover);
2✔
170
  auto it = map.find(pair);
2✔
171
  if(it != map.end())
2✔
172
  {
173
    return it->second;
×
174
  }
175
  else
176
  {
177
    QIcon icon;
2✔
178
    QPixmap on(score::get_pixmap(iconOn));
2✔
179
    QPixmap off(score::get_pixmap(iconOff));
2✔
180
    QPixmap disabled(score::get_pixmap(iconDisabled));
2✔
181
    QPixmap hover(score::get_pixmap(iconHover));
2✔
182

183
    icon.addPixmap(on, QIcon::Mode::Selected);
2✔
184
    icon.addPixmap(hover, QIcon::Mode::Active);
2✔
185
    icon.addPixmap(hover, QIcon::Mode::Active, QIcon::State::On);
2✔
186
    icon.addPixmap(on, QIcon::Mode::Normal, QIcon::State::On);
2✔
187
    icon.addPixmap(on, QIcon::Mode::Selected, QIcon::State::On);
2✔
188
    icon.addPixmap(off, QIcon::Mode::Normal);
2✔
189
    icon.addPixmap(disabled, QIcon::Mode::Disabled);
2✔
190

191
    map.insert(std::make_pair(std::move(pair), icon));
2✔
192
    return icon;
2✔
193
  }
2✔
194
}
2✔
195
namespace score
196
{
197
static ossia::hash_map<QString, QString> svg_pixmap_map{};
44✔
198
static void init_svgmap()
2,834✔
199
{
200
  if(svg_pixmap_map.empty())
2,834✔
201
  {
202
    QDirIterator d{
32✔
203
        ":/",
32✔
204
        {"*.svg"},
32✔
205
        QDir::Files | QDir::NoDotAndDotDot,
32✔
206
        QDirIterator::Subdirectories};
32✔
207
    while(d.hasNext())
12,661✔
208
    {
209
      const auto& file = d.nextFileInfo();
12,629✔
210
      svg_pixmap_map[file.baseName()] = file.absoluteFilePath();
12,629✔
211
    }
12,629✔
212
  }
32✔
213
}
2,834✔
214

215
static QPixmap render_svg(const QString& svg, double scaleFactor)
2,809✔
216
{
217
#if SCORE_HAS_QTSVG
218
  QSvgRenderer renderer{svg};
2,809✔
219

220
  QSize baseSize = renderer.defaultSize();
2,809✔
221
  QSize targetSize = baseSize * scaleFactor;
2,809✔
222
  QPixmap img{targetSize};
2,809✔
223
  img.fill(Qt::transparent);
2,809✔
224

225
  QPainter painter{&img};
2,809✔
226
  painter.setRenderHint(QPainter::Antialiasing);
2,809✔
227
  renderer.render(&painter);
2,809✔
228
  painter.end();
2,809✔
229

230
  img.setDevicePixelRatio(scaleFactor);
2,809✔
231

232
  return img;
2,809✔
233
#else
234
  return {};
235
#endif
236
}
2,809✔
237

238
static QImage render_svg_image(const QString& svg, double scaleFactor)
×
239
{
240
#if SCORE_HAS_QTSVG
241
  QSvgRenderer renderer{svg};
×
242

243
  QSize baseSize = renderer.defaultSize();
×
244
  QSize targetSize = baseSize * scaleFactor;
×
245
  QImage img{targetSize, QImage::Format_ARGB32_Premultiplied};
×
246
  img.fill(Qt::transparent);
×
247

248
  QPainter painter{&img};
×
249
  painter.setRenderHint(QPainter::Antialiasing);
×
250
  renderer.render(&painter);
×
251
  painter.end();
×
252

253
  img.setDevicePixelRatio(scaleFactor);
×
254

255
  return img;
×
256
#else
257
  return {};
258
#endif
259
}
×
260

261
QPixmap get_pixmap(QString str, QString svg)
2,834✔
262
{
263
  init_svgmap();
2,834✔
264

265
  QPixmap img;
2,834✔
266
  static const auto& appSettings = score::AppContext().applicationSettings;
2,834✔
267
  if(!appSettings.gui)
2,834✔
268
    return img;
×
269

270
  if(appSettings.vector_gui)
2,834✔
271
  {
272
    if(QFile::exists(svg))
2,834✔
273
    {
274
      return render_svg(svg, 4.);
×
275
    }
276
    else
277
    {
278
      QFileInfo f{str};
2,834✔
279
      if(auto it = svg_pixmap_map.find(f.baseName()); it != svg_pixmap_map.end())
2,834✔
280
      {
281
        img.load(it->second);
2,809✔
282
        return render_svg(it->second, 4.);
2,809✔
283
      }
284
    }
2,834✔
285
  }
25✔
286

287
  if(appSettings.vector_gui || qGuiApp->devicePixelRatio() >= 1.5)
25✔
288
  {
289
    auto newstr = str;
25✔
290
    newstr.replace(".png", "@2x.png", Qt::CaseInsensitive);
25✔
291
    if(QFile::exists(newstr))
25✔
292
    {
293
      img.setDevicePixelRatio(2.);
25✔
294
      str = newstr;
25✔
295
    }
25✔
296
    else
297
    {
298
      qDebug() << "hidpi pixmap not found: " << newstr;
×
299
    }
300
  }
25✔
301
  img.load(str);
25✔
302
  return img;
25✔
303
}
2,834✔
304

305
QCursor get_cursor(QString str, double hotspot_x, double hotspot_y)
396✔
306
{
307
  QCursor cur;
396✔
308
  static const auto& appSettings = score::AppContext().applicationSettings;
396✔
309
  if(!appSettings.gui)
396✔
310
    return cur;
×
311

312
  // Here we don't care about the vector gui thing as cursors are never scaled
313
  QPixmap img;
396✔
314
  if(qGuiApp->devicePixelRatio() >= 1.5)
396✔
315
  {
316
    auto newstr = str;
×
317
    newstr.replace(".png", "@2x.png", Qt::CaseInsensitive);
×
318
    if(QFile::exists(newstr))
×
319
    {
320
      str = newstr;
×
321
      img.load(str);
×
322
      img.setDevicePixelRatio(2.);
×
323
    }
×
324
    else
325
    {
326
      qDebug() << "hidpi pixmap not found: " << newstr;
×
327
      img.load(str);
×
328
    }
329
  }
×
330
  else
331
  {
332
    img.load(str);
396✔
333
  }
334
  double hotspot_scale = 1.;
396✔
335
  if(QGuiApplication::platformName() == QLatin1String("xcb"))
396✔
336
    hotspot_scale = img.devicePixelRatio();
120✔
337

338
  cur = QCursor{img, (int)(hotspot_x * hotspot_scale), (int)(hotspot_y * hotspot_scale)};
396✔
339
  return cur;
396✔
340
}
396✔
341

342
QImage get_image(QString str, QString svg)
×
343
{
344
  init_svgmap();
×
345

UNCOV
346
  QImage img;
×
347
  static const auto& appSettings = score::AppContext().applicationSettings;
×
UNCOV
348
  if(!appSettings.gui)
×
349
    return img;
×
350

351
  if(appSettings.vector_gui)
×
352
  {
UNCOV
353
    if(QFile::exists(svg))
×
354
    {
355
      return render_svg_image(svg, 4.);
×
356
    }
357
    else
358
    {
359
      QFileInfo f{str};
×
UNCOV
360
      if(auto it = svg_pixmap_map.find(f.baseName()); it != svg_pixmap_map.end())
×
361
      {
362
        img.load(it->second);
×
UNCOV
363
        return render_svg_image(it->second, 4.);
×
364
      }
UNCOV
365
    }
×
366
  }
×
367

368
  if(appSettings.vector_gui || qGuiApp->devicePixelRatio() >= 2.0)
×
369
  {
370
    auto newstr = str;
×
371
    newstr.replace(".png", "@2x.png", Qt::CaseInsensitive);
×
372
    if(QFile::exists(newstr))
×
373
    {
UNCOV
374
      img.setDevicePixelRatio(2.);
×
375
      str = newstr;
×
UNCOV
376
    }
×
377
    else
378
    {
379
      qDebug() << "hidpi pixmap not found: " << newstr;
×
380
    }
UNCOV
381
  }
×
UNCOV
382
  img.load(str);
×
UNCOV
383
  return img;
×
UNCOV
384
}
×
385
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE TRIAL · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc