1
2
3 #include "toonzqt/gutil.h"
4 #include "toonz/preferences.h"
5
6 // TnzQt includes
7 #include "toonzqt/dvdialog.h"
8
9 // TnzCore includes
10 #include "traster.h"
11 #include "tpixelutils.h"
12 #include "tfilepath.h"
13 #include "tfiletype.h"
14 #include "tstroke.h"
15 #include "tcurves.h"
16 #include "trop.h"
17 #include "tmsgcore.h"
18
19 // Qt includes
20 #include <QPixmap>
21 #include <QImage>
22 #include <QPainter>
23 #include <QPainterPath>
24 #include <QIcon>
25 #include <QString>
26 #include <QApplication>
27 #include <QMouseEvent>
28 #include <QTabletEvent>
29 #include <QKeyEvent>
30 #include <QUrl>
31 #include <QFileInfo>
32 #include <QDesktopWidget>
33 #include <QSvgRenderer>
34
35 using namespace DVGui;
36
37 //-----------------------------------------------------------------------------
38
fileSizeString(qint64 size,int precision)39 QString fileSizeString(qint64 size, int precision) {
40 if (size < 1024)
41 return QString::number(size) + " Bytes";
42 else if (size < 1024 * 1024)
43 return QString::number(size / (1024.0), 'f', precision) + " KB";
44 else if (size < 1024 * 1024 * 1024)
45 return QString::number(size / (1024 * 1024.0), 'f', precision) + " MB";
46 else
47 return QString::number(size / (1024 * 1024 * 1024.0), 'f', precision) +
48 " GB";
49 }
50
51 //----------------------------------------------------------------
52
rasterToQImage(const TRasterP & ras,bool premultiplied,bool mirrored)53 QImage rasterToQImage(const TRasterP &ras, bool premultiplied, bool mirrored) {
54 if (TRaster32P ras32 = ras) {
55 QImage image(ras->getRawData(), ras->getLx(), ras->getLy(),
56 premultiplied ? QImage::Format_ARGB32_Premultiplied
57 : QImage::Format_ARGB32);
58 if (mirrored) return image.mirrored();
59 return image;
60 } else if (TRasterGR8P ras8 = ras) {
61 QImage image(ras->getRawData(), ras->getLx(), ras->getLy(), ras->getWrap(),
62 QImage::Format_Indexed8);
63 static QVector<QRgb> colorTable;
64 if (colorTable.size() == 0) {
65 int i;
66 for (i = 0; i < 256; i++) colorTable.append(QColor(i, i, i).rgb());
67 }
68 image.setColorTable(colorTable);
69 if (mirrored) return image.mirrored();
70 return image;
71 }
72 return QImage();
73 }
74
75 //-----------------------------------------------------------------------------
76
rasterToQPixmap(const TRaster32P & ras,bool premultiplied,bool setDevPixRatio)77 QPixmap rasterToQPixmap(const TRaster32P &ras, bool premultiplied,
78 bool setDevPixRatio) {
79 QPixmap pixmap = QPixmap::fromImage(rasterToQImage(ras, premultiplied));
80 if (setDevPixRatio) {
81 pixmap.setDevicePixelRatio(getDevPixRatio());
82 }
83 return pixmap;
84 }
85
86 //-----------------------------------------------------------------------------
87
rasterFromQImage(QImage image,bool premultiply,bool mirror)88 TRaster32P rasterFromQImage(
89 QImage image, bool premultiply,
90 bool mirror) // no need of const& - Qt uses implicit sharing...
91 {
92 QImage copyImage = mirror ? image.mirrored() : image;
93 TRaster32P ras(image.width(), image.height(), image.width(),
94 (TPixelRGBM32 *)copyImage.bits(), false);
95 if (premultiply) TRop::premultiply(ras);
96 return ras->clone();
97 }
98
99 //-----------------------------------------------------------------------------
100
rasterFromQPixmap(QPixmap pixmap,bool premultiply,bool mirror)101 TRaster32P rasterFromQPixmap(
102 QPixmap pixmap, bool premultiply,
103 bool mirror) // no need of const& - Qt uses implicit sharing...
104 {
105 QImage image = pixmap.toImage();
106 return rasterFromQImage(image, premultiply, mirror);
107 }
108
109 //-----------------------------------------------------------------------------
110
drawPolygon(QPainter & p,const std::vector<QPointF> & points,bool fill,const QColor colorFill,const QColor colorLine)111 void drawPolygon(QPainter &p, const std::vector<QPointF> &points, bool fill,
112 const QColor colorFill, const QColor colorLine) {
113 if (points.size() == 0) return;
114 p.setPen(colorLine);
115 QPolygonF E0Polygon;
116 int i = 0;
117 for (i = 0; i < (int)points.size(); i++) E0Polygon << QPointF(points[i]);
118 E0Polygon << QPointF(points[0]);
119
120 QPainterPath E0Path;
121 E0Path.addPolygon(E0Polygon);
122 if (fill) p.fillPath(E0Path, QBrush(colorFill));
123 p.drawPath(E0Path);
124 }
125
126 //-----------------------------------------------------------------------------
127
drawArrow(QPainter & p,const QPointF a,const QPointF b,const QPointF c,bool fill,const QColor colorFill,const QColor colorLine)128 void drawArrow(QPainter &p, const QPointF a, const QPointF b, const QPointF c,
129 bool fill, const QColor colorFill, const QColor colorLine) {
130 std::vector<QPointF> pts;
131 pts.push_back(a);
132 pts.push_back(b);
133 pts.push_back(c);
134 drawPolygon(p, pts, fill, colorFill, colorLine);
135 }
136
137 //-----------------------------------------------------------------------------
138
scalePixmapKeepingAspectRatio(QPixmap pixmap,QSize size,QColor color)139 QPixmap scalePixmapKeepingAspectRatio(QPixmap pixmap, QSize size,
140 QColor color) {
141 if (pixmap.isNull()) return pixmap;
142 if (pixmap.devicePixelRatio() > 1.0) size *= pixmap.devicePixelRatio();
143 if (pixmap.size() == size) return pixmap;
144 QPixmap scaledPixmap =
145 pixmap.scaled(size.width(), size.height(), Qt::KeepAspectRatio,
146 Qt::SmoothTransformation);
147 QPixmap newPixmap(size);
148 newPixmap.fill(color);
149 QPainter painter(&newPixmap);
150 painter.drawPixmap(double(size.width() - scaledPixmap.width()) * 0.5,
151 double(size.height() - scaledPixmap.height()) * 0.5,
152 scaledPixmap);
153 newPixmap.setDevicePixelRatio(pixmap.devicePixelRatio());
154 return newPixmap;
155 }
156
157 //-----------------------------------------------------------------------------
158
svgToPixmap(const QString & svgFilePath,const QSize & size,Qt::AspectRatioMode aspectRatioMode,QColor bgColor)159 QPixmap svgToPixmap(const QString &svgFilePath, const QSize &size,
160 Qt::AspectRatioMode aspectRatioMode, QColor bgColor) {
161 static int devPixRatio = getDevPixRatio();
162 QSvgRenderer svgRenderer(svgFilePath);
163 QSize pixmapSize;
164 QRectF renderRect;
165 if (size.isEmpty()) {
166 pixmapSize = svgRenderer.defaultSize() * devPixRatio;
167 renderRect = QRectF(QPointF(), QSizeF(pixmapSize));
168 } else {
169 pixmapSize = size * devPixRatio;
170 if (aspectRatioMode == Qt::KeepAspectRatio ||
171 aspectRatioMode == Qt::KeepAspectRatioByExpanding) {
172 QSize imgSize = svgRenderer.defaultSize();
173 QPointF scaleFactor((float)pixmapSize.width() / (float)imgSize.width(),
174 (float)pixmapSize.height() / (float)imgSize.height());
175 float factor = (aspectRatioMode == Qt::KeepAspectRatio)
176 ? std::min(scaleFactor.x(), scaleFactor.y())
177 : std::max(scaleFactor.x(), scaleFactor.y());
178 QSizeF renderSize(factor * (float)imgSize.width(),
179 factor * (float)imgSize.height());
180 QPointF topLeft(
181 ((float)pixmapSize.width() - renderSize.width()) * 0.5f,
182 ((float)pixmapSize.height() - renderSize.height()) * 0.5f);
183 renderRect = QRectF(topLeft, renderSize);
184 } else { // Qt::IgnoreAspectRatio:
185 renderRect = QRectF(QPointF(), QSizeF(pixmapSize));
186 }
187 }
188 QPixmap pixmap(pixmapSize);
189 QPainter painter;
190 pixmap.fill(bgColor);
191 painter.begin(&pixmap);
192 svgRenderer.render(&painter, renderRect);
193 painter.end();
194 pixmap.setDevicePixelRatio(devPixRatio);
195 return pixmap;
196 }
197
198 //-----------------------------------------------------------------------------
199
getDevPixRatio()200 int getDevPixRatio() {
201 static int devPixRatio = QApplication::desktop()->devicePixelRatio();
202 return devPixRatio;
203 }
204
205 //-----------------------------------------------------------------------------
206
getIconThemePath(const QString & fileSVGPath)207 QString getIconThemePath(const QString &fileSVGPath) {
208 // Use as follows:
209 // QPixmap pixmapIcon = getIconThemePath("path/to/file.svg");
210 // Is equal to: :icons/*theme*/path/to/file.svg
211
212 // Set themeable directory
213 static QString theme = Preferences::instance()->getIconTheme()
214 ? ":icons/dark/"
215 : ":icons/light/";
216
217 // If no file in light icon theme directory, fallback to dark directory
218 if (!QFile::exists(QString(theme + fileSVGPath))) theme = ":icons/dark/";
219
220 return theme + fileSVGPath;
221 }
222
223 //-----------------------------------------------------------------------------
224
compositePixmap(QPixmap pixmap,const qreal & opacity,const QSize & size,const int leftAdj,const int topAdj,QColor bgColor)225 QPixmap compositePixmap(QPixmap pixmap, const qreal &opacity, const QSize &size,
226 const int leftAdj, const int topAdj, QColor bgColor) {
227 static int devPixRatio = getDevPixRatio();
228
229 // Sets size of destination pixmap for source to be drawn onto, if size is
230 // empty use source pixmap size, else use custom size.
231 QPixmap destination(size.isEmpty() ? pixmap.size() : size * devPixRatio);
232 destination.setDevicePixelRatio(devPixRatio);
233 destination.fill(bgColor);
234
235 if (!pixmap.isNull()) {
236 QPainter p(&destination);
237 pixmap = pixmap.scaled(pixmap.size(), Qt::KeepAspectRatio);
238 pixmap.setDevicePixelRatio(devPixRatio);
239 p.setBackgroundMode(Qt::TransparentMode);
240 p.setBackground(QBrush(Qt::transparent));
241 p.eraseRect(pixmap.rect());
242 p.setOpacity(opacity);
243 p.drawPixmap(leftAdj, topAdj, pixmap);
244 }
245 return destination;
246 }
247
248 //-----------------------------------------------------------------------------
249
recolorPixmap(QPixmap pixmap,QColor color)250 QPixmap recolorPixmap(QPixmap pixmap, QColor color) {
251 // Change black pixels to any chosen color
252 QImage img = pixmap.toImage().convertToFormat(QImage::Format_ARGB32);
253 for (int y = 0; y < img.height(); y++) {
254 QRgb *pixel = reinterpret_cast<QRgb *>(img.scanLine(y));
255 QRgb *end = pixel + img.width();
256 for (; pixel != end; pixel++) {
257 // Only recolor zero value (black) pixels
258 if (QColor::fromRgba(*pixel).value() == 0)
259 *pixel =
260 QColor(color.red(), color.green(), color.blue(), qAlpha(*pixel))
261 .rgba();
262 }
263 }
264 pixmap = QPixmap::fromImage(img);
265 return pixmap;
266 }
267
268 //-----------------------------------------------------------------------------
269
createQIcon(const char * iconSVGName,bool useFullOpacity,bool isForMenuItem)270 QIcon createQIcon(const char *iconSVGName, bool useFullOpacity,
271 bool isForMenuItem) {
272 static int devPixRatio = getDevPixRatio();
273
274 QIcon themeIcon = QIcon::fromTheme(iconSVGName);
275
276 // Get icon dimensions
277 QSize iconSize(0, 0);
278 for (QList<QSize> sizes = themeIcon.availableSizes(); !sizes.isEmpty();
279 sizes.removeFirst())
280 if (sizes.first().width() > iconSize.width())
281 iconSize = sizes.first() * devPixRatio;
282
283 // Control lightness of the icons
284 const qreal activeOpacity = 1;
285 const qreal baseOpacity = useFullOpacity ? 1 : 0.8;
286 const qreal disabledOpacity = 0.15;
287
288 // Psuedo state name strings
289 QString overStr = QString(iconSVGName) + "_over";
290 QString onStr = QString(iconSVGName) + "_on";
291
292 //----------
293
294 // Base pixmap
295 QPixmap themeIconPixmap(recolorPixmap(themeIcon.pixmap(iconSize)));
296 if (!themeIconPixmap.isNull()) { // suppress message
297 themeIconPixmap.setDevicePixelRatio(devPixRatio);
298 themeIconPixmap = themeIconPixmap.scaled(iconSize, Qt::KeepAspectRatio,
299 Qt::SmoothTransformation);
300 }
301
302 // Over pixmap
303 QPixmap overPixmap(recolorPixmap(QIcon::fromTheme(overStr).pixmap(iconSize)));
304 if (!overPixmap.isNull()) { // suppress message
305 overPixmap.setDevicePixelRatio(devPixRatio);
306 overPixmap = overPixmap.scaled(iconSize, Qt::KeepAspectRatio,
307 Qt::SmoothTransformation);
308 }
309
310 // On pixmap
311 QPixmap onPixmap(recolorPixmap(QIcon::fromTheme(onStr).pixmap(iconSize)));
312 if (!onPixmap.isNull()) { // suppress message
313 onPixmap.setDevicePixelRatio(devPixRatio);
314 onPixmap = onPixmap.scaled(iconSize, Qt::KeepAspectRatio,
315 Qt::SmoothTransformation);
316 }
317
318 //----------
319
320 QIcon icon;
321
322 #ifdef _WIN32
323 bool showIconInMenu = Preferences::instance()->getBoolValue(showIconsInMenu);
324 // set transparent icon
325 if (isForMenuItem &&
326 themeIconPixmap.size() == QSize(16 * devPixRatio, 16 * devPixRatio) &&
327 !showIconInMenu) {
328 static QPixmap emptyPm(16 * devPixRatio, 16 * devPixRatio);
329 emptyPm.fill(Qt::transparent);
330
331 icon.addPixmap(emptyPm, QIcon::Normal, QIcon::Off);
332 icon.addPixmap(emptyPm, QIcon::Normal, QIcon::On);
333 icon.addPixmap(emptyPm, QIcon::Disabled, QIcon::Off);
334 icon.addPixmap(emptyPm, QIcon::Disabled, QIcon::On);
335 icon.addPixmap(emptyPm, QIcon::Active);
336 } else
337 #endif
338 {
339 // Base icon
340 icon.addPixmap(compositePixmap(themeIconPixmap, baseOpacity), QIcon::Normal,
341 QIcon::Off);
342 icon.addPixmap(compositePixmap(themeIconPixmap, disabledOpacity),
343 QIcon::Disabled, QIcon::Off);
344
345 // Over icon
346 icon.addPixmap(!overPixmap.isNull()
347 ? compositePixmap(overPixmap, activeOpacity)
348 : compositePixmap(themeIconPixmap, activeOpacity),
349 QIcon::Active);
350
351 // On icon
352 if (!onPixmap.isNull()) {
353 icon.addPixmap(compositePixmap(onPixmap, activeOpacity), QIcon::Normal,
354 QIcon::On);
355 icon.addPixmap(compositePixmap(onPixmap, disabledOpacity),
356 QIcon::Disabled, QIcon::On);
357 } else {
358 icon.addPixmap(compositePixmap(themeIconPixmap, activeOpacity),
359 QIcon::Normal, QIcon::On);
360 icon.addPixmap(compositePixmap(themeIconPixmap, disabledOpacity),
361 QIcon::Disabled, QIcon::On);
362 }
363 }
364 //----------
365
366 // For icons intended for menus that are 16x16 in dimensions, to repurpose
367 // them for use in toolbars that are set for 20x20 we want to draw them onto a
368 // 20x20 pixmap so they don't get resized in the GUI, they will be loaded into
369 // the icon along with the original 16x16 pixmap.
370
371 if (themeIconPixmap.size() == QSize(16 * devPixRatio, 16 * devPixRatio)) {
372 const QSize drawOnSize(20, 20);
373 const int x = (drawOnSize.width() - 16) / 2; // left adjust
374 const int y = (drawOnSize.height() - 16) / 2; // top adjust
375
376 // Base icon
377 icon.addPixmap(
378 compositePixmap(themeIconPixmap, baseOpacity, drawOnSize, x, y),
379 QIcon::Normal, QIcon::Off);
380 icon.addPixmap(
381 compositePixmap(themeIconPixmap, disabledOpacity, drawOnSize, x, y),
382 QIcon::Disabled, QIcon::Off);
383
384 // Over icon
385 icon.addPixmap(
386 !overPixmap.isNull()
387 ? compositePixmap(overPixmap, activeOpacity, drawOnSize, x, y)
388 : compositePixmap(themeIconPixmap, activeOpacity, drawOnSize, x, y),
389 QIcon::Active);
390
391 // On icon
392 if (!onPixmap.isNull()) {
393 icon.addPixmap(compositePixmap(onPixmap, activeOpacity, drawOnSize, x, y),
394 QIcon::Normal, QIcon::On);
395 icon.addPixmap(
396 compositePixmap(onPixmap, disabledOpacity, drawOnSize, x, y),
397 QIcon::Disabled, QIcon::On);
398 } else {
399 icon.addPixmap(
400 compositePixmap(themeIconPixmap, activeOpacity, drawOnSize, x, y),
401 QIcon::Normal, QIcon::On);
402 icon.addPixmap(
403 compositePixmap(themeIconPixmap, disabledOpacity, drawOnSize, x, y),
404 QIcon::Disabled, QIcon::On);
405 }
406 }
407
408 return icon;
409 }
410
411 //-----------------------------------------------------------------------------
412
createQIconPNG(const char * iconPNGName)413 QIcon createQIconPNG(const char *iconPNGName) {
414 QString normal = QString(":Resources/") + iconPNGName + ".png";
415 QString click = QString(":Resources/") + iconPNGName + "_click.png";
416 QString over = QString(":Resources/") + iconPNGName + "_over.png";
417
418 QIcon icon;
419 icon.addFile(normal, QSize(), QIcon::Normal, QIcon::Off);
420 icon.addFile(click, QSize(), QIcon::Normal, QIcon::On);
421 icon.addFile(over, QSize(), QIcon::Active);
422
423 return icon;
424 }
425
426 //-----------------------------------------------------------------------------
427
createQIconOnOffPNG(const char * iconPNGName,bool withOver)428 QIcon createQIconOnOffPNG(const char *iconPNGName, bool withOver) {
429 QString on = QString(":Resources/") + iconPNGName + "_on.png";
430 QString off = QString(":Resources/") + iconPNGName + "_off.png";
431 QString over = QString(":Resources/") + iconPNGName + "_over.png";
432
433 QIcon icon;
434 icon.addFile(off, QSize(), QIcon::Normal, QIcon::Off);
435 icon.addFile(on, QSize(), QIcon::Normal, QIcon::On);
436 if (withOver)
437 icon.addFile(over, QSize(), QIcon::Active);
438 else
439 icon.addFile(on, QSize(), QIcon::Active);
440
441 return icon;
442 }
443
444 //-----------------------------------------------------------------------------
445
createTemporaryIconFromName(const char * commandName)446 QIcon createTemporaryIconFromName(const char *commandName) {
447 const int visibleIconSize = 20;
448 const int menubarIconSize = 16;
449 const qreal activeOpacity = 1;
450 const qreal baseOpacity = 0.8;
451 const qreal disabledOpacity = 0.15;
452 QString name(commandName);
453 QList<QChar> iconChar;
454
455 for (int i = 0; i < name.length(); i++) {
456 QChar c = name.at(i);
457 if (c.isUpper() && iconChar.size() < 2)
458 iconChar.append(c);
459 else if (c.isDigit()) {
460 if (iconChar.isEmpty())
461 iconChar.append(c);
462 else if (iconChar.size() <= 2) {
463 if (iconChar.size() == 2) iconChar.removeLast();
464 iconChar.append(c);
465 break;
466 }
467 }
468 }
469
470 if (iconChar.isEmpty()) iconChar.append(name.at(0));
471
472 QString iconStr;
473 for (auto c : iconChar) iconStr.append(c);
474
475 QIcon icon;
476 // prepare for both normal and high dpi
477 for (int devPixelRatio = 1; devPixelRatio <= 2; devPixelRatio++) {
478 QPixmap transparentPm(menubarIconSize * devPixelRatio,
479 menubarIconSize * devPixelRatio);
480 transparentPm.fill(Qt::transparent);
481
482 int pxSize = visibleIconSize * devPixelRatio;
483
484 QPixmap pixmap(pxSize, pxSize);
485 QPainter painter;
486 pixmap.fill(Qt::transparent);
487 painter.begin(&pixmap);
488
489 painter.setPen(Preferences::instance()->getIconTheme() ? Qt::black
490 : Qt::white);
491
492 QRect rect(0, -2, pxSize, pxSize);
493 if (iconStr.size() == 2) {
494 painter.scale(0.6, 1.0);
495 rect.setRight(pxSize / 0.6);
496 }
497 QFont font = painter.font();
498 font.setPixelSize(pxSize);
499 painter.setFont(font);
500
501 painter.drawText(rect, Qt::AlignCenter, iconStr);
502
503 painter.end();
504
505 // For menu only
506 icon.addPixmap(transparentPm, QIcon::Normal, QIcon::Off);
507 icon.addPixmap(transparentPm, QIcon::Active);
508 icon.addPixmap(transparentPm, QIcon::Normal, QIcon::On);
509 icon.addPixmap(transparentPm, QIcon::Disabled, QIcon::Off);
510 icon.addPixmap(transparentPm, QIcon::Disabled, QIcon::On);
511
512 // For toolbars
513 icon.addPixmap(compositePixmap(pixmap, baseOpacity), QIcon::Normal,
514 QIcon::Off);
515 icon.addPixmap(compositePixmap(pixmap, disabledOpacity), QIcon::Disabled,
516 QIcon::Off);
517 icon.addPixmap(compositePixmap(pixmap, activeOpacity), QIcon::Active);
518 icon.addPixmap(compositePixmap(pixmap, activeOpacity), QIcon::Normal,
519 QIcon::On);
520 icon.addPixmap(compositePixmap(pixmap, disabledOpacity), QIcon::Disabled,
521 QIcon::On);
522 }
523 return icon;
524 }
525
526 //-----------------------------------------------------------------------------
527
toQString(const TFilePath & path)528 QString toQString(const TFilePath &path) {
529 return QString::fromStdWString(path.getWideString());
530 }
531
532 //-----------------------------------------------------------------------------
533
isSpaceString(const QString & str)534 bool isSpaceString(const QString &str) {
535 int i;
536 QString space(" ");
537 for (i = 0; i < str.size(); i++)
538 if (str.at(i) != space.at(0)) return false;
539 return true;
540 }
541
542 //-----------------------------------------------------------------------------
543
isValidFileName(const QString & fileName)544 bool isValidFileName(const QString &fileName) {
545 if (fileName.isEmpty() || fileName.contains(":") || fileName.contains("\\") ||
546 fileName.contains("/") || fileName.contains(">") ||
547 fileName.contains("<") || fileName.contains("*") ||
548 fileName.contains("|") || fileName.contains("\"") ||
549 fileName.contains("?") || fileName.trimmed().isEmpty())
550 return false;
551 return true;
552 }
553
554 //-----------------------------------------------------------------------------
555
isValidFileName_message(const QString & fileName)556 bool isValidFileName_message(const QString &fileName) {
557 return isValidFileName(fileName)
558 ? true
559 : (DVGui::error(
560 QObject::tr("The file name cannot be empty or contain any "
561 "of the following "
562 "characters: (new line) \\ / : * ? \" |")),
563 false);
564 }
565
566 //-----------------------------------------------------------------------------
567
isReservedFileName(const QString & fileName)568 bool isReservedFileName(const QString &fileName) {
569 #ifdef _WIN32
570 std::vector<QString> invalidNames{
571 "AUX", "CON", "NUL", "PRN", "COM1", "COM2", "COM3", "COM4",
572 "COM5", "COM6", "COM7", "COM8", "COM9", "LPT1", "LPT2", "LPT3",
573 "LPT4", "LPT5", "LPT6", "LPT7", "LPT8", "LPT9"};
574
575 if (std::find(invalidNames.begin(), invalidNames.end(), fileName) !=
576 invalidNames.end())
577 return true;
578 #endif
579
580 return false;
581 }
582
583 //-----------------------------------------------------------------------------
584
isReservedFileName_message(const QString & fileName)585 bool isReservedFileName_message(const QString &fileName) {
586 return isReservedFileName(fileName)
587 ? (DVGui::error(QObject::tr(
588 "That is a reserved file name and cannot be used.")),
589 true)
590 : false;
591 }
592
593 //-----------------------------------------------------------------------------
594
elideText(const QString & srcText,const QFont & font,int width)595 QString elideText(const QString &srcText, const QFont &font, int width) {
596 QFontMetrics metrix(font);
597 int srcWidth = metrix.width(srcText);
598 if (srcWidth < width) return srcText;
599 int tilde = metrix.width("~");
600 int block = (width - tilde) / 2;
601 QString text("");
602 int i;
603 for (i = 0; i < srcText.size(); i++) {
604 text += srcText.at(i);
605 if (metrix.width(text) > block) break;
606 }
607 text[i] = '~';
608 QString endText("");
609 for (i = srcText.size() - 1; i >= 0; i--) {
610 endText.push_front(srcText.at(i));
611 if (metrix.width(endText) > block) break;
612 }
613 endText.remove(0, 1);
614 text += endText;
615 return text;
616 }
617
618 //-----------------------------------------------------------------------------
619
elideText(const QString & srcText,const QFontMetrics & fm,int width,const QString & elideSymbol)620 QString elideText(const QString &srcText, const QFontMetrics &fm, int width,
621 const QString &elideSymbol) {
622 QString text(srcText);
623
624 for (int i = text.size(); i > 1 && fm.width(text) > width;)
625 text = srcText.left(--i).append(elideSymbol);
626
627 return text;
628 }
629
630 //-----------------------------------------------------------------------------
631
pathToUrl(const TFilePath & path)632 QUrl pathToUrl(const TFilePath &path) {
633 return QUrl::fromLocalFile(QString::fromStdWString(path.getWideString()));
634 }
635
636 //-----------------------------------------------------------------------------
637
isResource(const QString & path)638 bool isResource(const QString &path) {
639 const TFilePath fp(path.toStdWString());
640 TFileType::Type type = TFileType::getInfo(fp);
641
642 return (TFileType::isViewable(type) || type & TFileType::MESH_IMAGE ||
643 type == TFileType::AUDIO_LEVEL || type == TFileType::TABSCENE ||
644 type == TFileType::TOONZSCENE || fp.getType() == "tpl");
645 }
646
647 //-----------------------------------------------------------------------------
648
isResource(const QUrl & url)649 bool isResource(const QUrl &url) { return isResource(url.toLocalFile()); }
650
651 //-----------------------------------------------------------------------------
652
isResourceOrFolder(const QUrl & url)653 bool isResourceOrFolder(const QUrl &url) {
654 struct locals {
655 static inline bool isDir(const QString &path) {
656 return QFileInfo(path).isDir();
657 }
658 }; // locals
659
660 const QString &path = url.toLocalFile();
661 return (isResource(path) || locals::isDir(path));
662 }
663
664 //-----------------------------------------------------------------------------
665
acceptResourceDrop(const QList<QUrl> & urls)666 bool acceptResourceDrop(const QList<QUrl> &urls) {
667 int count = 0;
668 for (const QUrl &url : urls) {
669 if (isResource(url))
670 ++count;
671 else
672 return false;
673 }
674
675 return (count > 0);
676 }
677
678 //-----------------------------------------------------------------------------
679
acceptResourceOrFolderDrop(const QList<QUrl> & urls)680 bool acceptResourceOrFolderDrop(const QList<QUrl> &urls) {
681 int count = 0;
682 for (const QUrl &url : urls) {
683 if (isResourceOrFolder(url))
684 ++count;
685 else
686 return false;
687 }
688
689 return (count > 0);
690 }
691
692 //-----------------------------------------------------------------------------
693
strokeToPainterPath(TStroke * stroke)694 QPainterPath strokeToPainterPath(TStroke *stroke) {
695 QPainterPath path;
696 int i, chunkSize = stroke->getChunkCount();
697 for (i = 0; i < chunkSize; i++) {
698 const TThickQuadratic *q = stroke->getChunk(i);
699 if (i == 0) path.moveTo(toQPointF(q->getThickP0()));
700 path.quadTo(toQPointF(q->getThickP1()), toQPointF(q->getThickP2()));
701 }
702 return path;
703 }
704
705 //=============================================================================
706 // TabBarContainter
707 //-----------------------------------------------------------------------------
708
TabBarContainter(QWidget * parent)709 TabBarContainter::TabBarContainter(QWidget *parent) : QFrame(parent) {
710 setObjectName("TabBarContainer");
711 setFrameStyle(QFrame::StyledPanel);
712 }
713
714 //-----------------------------------------------------------------------------
715
paintEvent(QPaintEvent * event)716 void TabBarContainter::paintEvent(QPaintEvent *event) {
717 QPainter p(this);
718 p.setPen(getBottomAboveLineColor());
719 p.drawLine(0, height() - 2, width(), height() - 2);
720 p.setPen(getBottomBelowLineColor());
721 p.drawLine(0, height() - 1, width(), height() - 1);
722 }
723
724 //=============================================================================
725 // ToolBarContainer
726 //-----------------------------------------------------------------------------
727
ToolBarContainer(QWidget * parent)728 ToolBarContainer::ToolBarContainer(QWidget *parent) : QFrame(parent) {
729 setObjectName("ToolBarContainer");
730 setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Fixed);
731 }
732
733 //-----------------------------------------------------------------------------
734
paintEvent(QPaintEvent * event)735 void ToolBarContainer::paintEvent(QPaintEvent *event) { QPainter p(this); }
736
737 //=============================================================================
738
operator +(const QString & a,const TFilePath & fp)739 QString operator+(const QString &a, const TFilePath &fp) {
740 return a + QString::fromStdWString(fp.getWideString());
741 }
742