1 /************************************************************************
2 **
3 ** @file def.cpp
4 ** @author Roman Telezhynskyi <dismine(at)gmail.com>
5 ** @date 11 6, 2015
6 **
7 ** @brief
8 ** @copyright
9 ** This source code is part of the Valentina project, a pattern making
10 ** program, whose allow create and modeling patterns of clothing.
11 ** Copyright (C) 2015 Valentina project
12 ** <https://gitlab.com/smart-pattern/valentina> All Rights Reserved.
13 **
14 ** Valentina is free software: you can redistribute it and/or modify
15 ** it under the terms of the GNU General Public License as published by
16 ** the Free Software Foundation, either version 3 of the License, or
17 ** (at your option) any later version.
18 **
19 ** Valentina is distributed in the hope that it will be useful,
20 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
21 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 ** GNU General Public License for more details.
23 **
24 ** You should have received a copy of the GNU General Public License
25 ** along with Valentina. If not, see <http://www.gnu.org/licenses/>.
26 **
27 *************************************************************************/
28
29 #include "def.h"
30
31 #include <QApplication>
32 #include <QChar>
33 #include <QColor>
34 #include <QComboBox>
35 #include <QCursor>
36 #include <QDir>
37 #include <QDirIterator>
38 #include <QFileInfo>
39 #include <QGuiApplication>
40 #include <QImage>
41 #include <QLatin1Char>
42 #include <QList>
43 #include <QMap>
44 #include <QMessageLogger>
45 #include <QObject>
46 #include <QPixmap>
47 #include <QPrinterInfo>
48 #include <QProcess>
49 #include <QRgb>
50 #include <QStaticStringData>
51 #include <QStringData>
52 #include <QStringDataPtr>
53 #include <QtDebug>
54 #include <QPixmapCache>
55 #include <QGraphicsItem>
56 #include <QGlobalStatic>
57 #include <QDesktopServices>
58 #include <QUrl>
59
60 #include "vabstractapplication.h"
61 #if QT_VERSION < QT_VERSION_CHECK(5, 14, 0)
62 # include "vdatastreamenum.h"
63 #endif
64 #include "../ifc/exception/vexception.h"
65
66 const qreal defCurveApproximationScale = 0.5;
67 const qreal minCurveApproximationScale = 0.2;
68 const qreal maxCurveApproximationScale = 10.0;
69
70 const int minLabelFontSize = 5;
71 const int maxLabelFontSize = 100;
72
73 //functions
74 const QString degTorad_F = QStringLiteral("degTorad");
75 const QString radTodeg_F = QStringLiteral("radTodeg");
76 const QString sin_F = QStringLiteral("sin");
77 const QString cos_F = QStringLiteral("cos");
78 const QString tan_F = QStringLiteral("tan");
79 const QString asin_F = QStringLiteral("asin");
80 const QString acos_F = QStringLiteral("acos");
81 const QString atan_F = QStringLiteral("atan");
82 const QString sinh_F = QStringLiteral("sinh");
83 const QString cosh_F = QStringLiteral("cosh");
84 const QString tanh_F = QStringLiteral("tanh");
85 const QString asinh_F = QStringLiteral("asinh");
86 const QString acosh_F = QStringLiteral("acosh");
87 const QString atanh_F = QStringLiteral("atanh");
88 const QString sinD_F = QStringLiteral("sinD");
89 const QString cosD_F = QStringLiteral("cosD");
90 const QString tanD_F = QStringLiteral("tanD");
91 const QString asinD_F = QStringLiteral("asinD");
92 const QString acosD_F = QStringLiteral("acosD");
93 const QString atanD_F = QStringLiteral("atanD");
94 const QString log2_F = QStringLiteral("log2");
95 const QString log10_F = QStringLiteral("log10");
96 const QString log_F = QStringLiteral("log");
97 const QString ln_F = QStringLiteral("ln");
98 const QString exp_F = QStringLiteral("exp");
99 const QString sqrt_F = QStringLiteral("sqrt");
100 const QString sign_F = QStringLiteral("sign");
101 const QString rint_F = QStringLiteral("rint");
102 const QString r2cm_F = QStringLiteral("r2cm");
103 const QString csrCm_F = QStringLiteral("csrCm");
104 const QString csrInch_F = QStringLiteral("csrInch");
105 const QString abs_F = QStringLiteral("abs");
106 const QString min_F = QStringLiteral("min");
107 const QString max_F = QStringLiteral("max");
108 const QString sum_F = QStringLiteral("sum");
109 const QString avg_F = QStringLiteral("avg");
110 const QString fmod_F = QStringLiteral("fmod");
111 const QString warning_F = QStringLiteral("warning");
112
113 const QStringList builInFunctions
114 {
115 degTorad_F, radTodeg_F,
116 sin_F, cos_F, tan_F,
117 asin_F, acos_F, atan_F,
118 sinh_F, cosh_F, tanh_F,
119 asinh_F, acosh_F, atanh_F,
120 sinD_F, cosD_F, tanD_F,
121 asinD_F, acosD_F, atanD_F,
122 log2_F, log10_F, log_F,
123 ln_F,
124 exp_F,
125 sqrt_F,
126 sign_F,
127 rint_F, r2cm_F,
128 csrCm_F, csrInch_F,
129 abs_F,
130 min_F, max_F,
131 sum_F,
132 avg_F,
133 fmod_F,
134 warning_F
135 };
136
137 const QString pl_size = QStringLiteral("size");
138 const QString pl_height = QStringLiteral("height");
139 const QString pl_hip = QStringLiteral("hip");
140 const QString pl_waist = QStringLiteral("waist");
141 const QString pl_sizeLabel = QStringLiteral("sizeLabel");
142 const QString pl_heightLabel = QStringLiteral("heightLabel");
143 const QString pl_hipLabel = QStringLiteral("hipLabel");
144 const QString pl_waistLabel = QStringLiteral("waistLabel");
145 const QString pl_date = QStringLiteral("date");
146 const QString pl_time = QStringLiteral("time");
147 const QString pl_birthDate = QStringLiteral("birthDate");
148 const QString pl_patternName = QStringLiteral("patternName");
149 const QString pl_patternNumber = QStringLiteral("patternNumber");
150 const QString pl_author = QStringLiteral("author");
151 const QString pl_customer = QStringLiteral("customer");
152 const QString pl_email = QStringLiteral("email");
153 const QString pl_userMaterial = QStringLiteral("userMaterial");
154 const QString pl_pExt = QStringLiteral("pExt");
155 const QString pl_pUnits = QStringLiteral("pUnits");
156 const QString pl_pFileName = QStringLiteral("pFileName");
157 const QString pl_mFileName = QStringLiteral("mFileName");
158 const QString pl_mExt = QStringLiteral("mExt");
159 const QString pl_mUnits = QStringLiteral("mUnits");
160 const QString pl_mSizeUnits = QStringLiteral("mSizeUnits");
161 const QString pl_pLetter = QStringLiteral("pLetter");
162 const QString pl_pAnnotation = QStringLiteral("pAnnotation");
163 const QString pl_pOrientation = QStringLiteral("pOrientation");
164 const QString pl_pRotation = QStringLiteral("pRotation");
165 const QString pl_pTilt = QStringLiteral("pTilt");
166 const QString pl_pFoldPosition = QStringLiteral("pFoldPosition");
167 const QString pl_pName = QStringLiteral("pName");
168 const QString pl_pQuantity = QStringLiteral("pQuantity");
169 const QString pl_mFabric = QStringLiteral("mFabric");
170 const QString pl_mLining = QStringLiteral("mLining");
171 const QString pl_mInterfacing = QStringLiteral("mInterfacing");
172 const QString pl_mInterlining = QStringLiteral("mInterlining");
173 const QString pl_wCut = QStringLiteral("wCut");
174 const QString pl_wOnFold = QStringLiteral("wOnFold");
175 const QString pl_measurement = QStringLiteral("measurement_");
176 const QString pl_finalMeasurement = QStringLiteral("finalMeasurement_");
177
178 const QString cursorArrowOpenHand = QStringLiteral("://cursor/cursor-arrow-openhand.png");
179 const QString cursorArrowCloseHand = QStringLiteral("://cursor/cursor-arrow-closehand.png");
180
181 const QString unitMM = QStringLiteral("mm");
182 const QString unitCM = QStringLiteral("cm");
183 const QString unitINCH = QStringLiteral("inch");
184 const QString unitPX = QStringLiteral("px");
185
186 const QString valentinaNamespace = QStringLiteral("valentina");
187
188 //---------------------------------------------------------------------------------------------------------------------
QPixmapFromCache(const QString & pixmapPath)189 QPixmap QPixmapFromCache(const QString &pixmapPath)
190 {
191 QPixmap pixmap;
192
193 if (not QPixmapCache::find(pixmapPath, &pixmap))
194 {
195 pixmap = QPixmap(pixmapPath);
196 QPixmapCache::insert(pixmapPath, pixmap);
197 }
198 return pixmap;
199 }
200
201 //---------------------------------------------------------------------------------------------------------------------
SetItemOverrideCursor(QGraphicsItem * item,const QString & pixmapPath,int hotX,int hotY)202 void SetItemOverrideCursor(QGraphicsItem *item, const QString &pixmapPath, int hotX, int hotY)
203 {
204 #ifndef QT_NO_CURSOR
205 SCASSERT(item != nullptr)
206 item->setCursor(QCursor(QPixmapFromCache(pixmapPath), hotX, hotY));
207 #else
208 Q_UNUSED(item)
209 Q_UNUSED(pixmapPath)
210 Q_UNUSED(hotX)
211 Q_UNUSED(hotY)
212 #endif
213 }
214
215 //---------------------------------------------------------------------------------------------------------------------
SupportedLocales()216 QStringList SupportedLocales()
217 {
218 return QStringList
219 {
220 "ru_RU",
221 "uk_UA",
222 "de_DE",
223 "cs_CZ",
224 "he_IL",
225 "fr_FR",
226 "it_IT",
227 "nl_NL",
228 "id_ID",
229 "es_ES",
230 "fi_FI",
231 "en_US",
232 "en_CA",
233 "en_IN",
234 "ro_RO",
235 "zh_CN",
236 "pt_BR",
237 "el_GR",
238 "pl_PL"
239 };
240 }
241
242 //---------------------------------------------------------------------------------------------------------------------
243 /**
244 * @brief strippedName the function call around curFile to exclude the path to the file.
245 * @param fullFileName full path to the file.
246 * @return file name.
247 */
StrippedName(const QString & fullFileName)248 QString StrippedName(const QString &fullFileName)
249 {
250 return QFileInfo(fullFileName).fileName();
251 }
252
253 //---------------------------------------------------------------------------------------------------------------------
RelativeMPath(const QString & patternPath,const QString & absoluteMPath)254 QString RelativeMPath(const QString &patternPath, const QString &absoluteMPath)
255 {
256 if (patternPath.isEmpty() || absoluteMPath.isEmpty())
257 {
258 return absoluteMPath;
259 }
260
261 if (QFileInfo(absoluteMPath).isRelative())
262 {
263 return absoluteMPath;
264 }
265
266 return QFileInfo(patternPath).absoluteDir().relativeFilePath(absoluteMPath);
267 }
268
269 //---------------------------------------------------------------------------------------------------------------------
AbsoluteMPath(const QString & patternPath,const QString & relativeMPath)270 QString AbsoluteMPath(const QString &patternPath, const QString &relativeMPath)
271 {
272 if (patternPath.isEmpty() || relativeMPath.isEmpty())
273 {
274 return relativeMPath;
275 }
276
277 if (QFileInfo(relativeMPath).isAbsolute())
278 {
279 return relativeMPath;
280 }
281
282 return QFileInfo(QFileInfo(patternPath).absoluteDir(), relativeMPath).absoluteFilePath();
283 }
284
285 //---------------------------------------------------------------------------------------------------------------------
GetMinPrinterFields(const QSharedPointer<QPrinter> & printer)286 QMarginsF GetMinPrinterFields(const QSharedPointer<QPrinter> &printer)
287 {
288 QPageLayout layout = printer->pageLayout();
289 layout.setUnits(QPageLayout::Millimeter);
290 const QMarginsF minMargins = layout.minimumMargins();
291
292 QMarginsF min;
293 min.setLeft(UnitConvertor(minMargins.left(), Unit::Mm, Unit::Px));
294 min.setRight(UnitConvertor(minMargins.right(), Unit::Mm, Unit::Px));
295 min.setTop(UnitConvertor(minMargins.top(), Unit::Mm, Unit::Px));
296 min.setBottom(UnitConvertor(minMargins.bottom(), Unit::Mm, Unit::Px));
297 return min;
298 }
299
300 //---------------------------------------------------------------------------------------------------------------------
GetPrinterFields(const QSharedPointer<QPrinter> & printer)301 auto GetPrinterFields(const QSharedPointer<QPrinter> &printer) -> QMarginsF
302 {
303 if (printer.isNull())
304 {
305 return {};
306 }
307
308 // We can't use Unit::Px because our dpi in most cases is different
309 const QMarginsF m = printer->pageLayout().margins(QPageLayout::Millimeter);
310
311 QMarginsF def;
312 def.setLeft(UnitConvertor(m.left(), Unit::Mm, Unit::Px));
313 def.setRight(UnitConvertor(m.right(), Unit::Mm, Unit::Px));
314 def.setTop(UnitConvertor(m.top(), Unit::Mm, Unit::Px));
315 def.setBottom(UnitConvertor(m.bottom(), Unit::Mm, Unit::Px));
316 return def;
317 }
318
319 //---------------------------------------------------------------------------------------------------------------------
darkenPixmap(const QPixmap & pixmap)320 QPixmap darkenPixmap(const QPixmap &pixmap)
321 {
322 QImage img = pixmap.toImage().convertToFormat(QImage::Format_ARGB32);
323 const int imgh = img.height();
324 const int imgw = img.width();
325 for (int y = 0; y < imgh; ++y)
326 {
327 for (int x = 0; x < imgw; ++x)
328 {
329 int h, s, v;
330 QRgb pixel = img.pixel(x, y);
331 const int a = qAlpha(pixel);
332 QColor hsvColor(pixel);
333 hsvColor.getHsv(&h, &s, &v);
334 s = qMin(100, s * 2);
335 v = v / 2;
336 hsvColor.setHsv(h, s, v);
337 pixel = hsvColor.rgb();
338 img.setPixel(x, y, qRgba(qRed(pixel), qGreen(pixel), qBlue(pixel), a));
339 }
340 }
341 return QPixmap::fromImage(img);
342 }
343
344 //---------------------------------------------------------------------------------------------------------------------
ShowInGraphicalShell(const QString & filePath)345 void ShowInGraphicalShell(const QString &filePath)
346 {
347 #ifdef Q_OS_MAC
348 QStringList args{
349 "-e", "tell application \"Finder\"",
350 "-e", "activate",
351 "-e", "select POSIX file \""+filePath+"\"",
352 "-e", "end tell"
353 };
354 QProcess::startDetached(QStringLiteral("osascript"), args);
355 #elif defined(Q_OS_WIN)
356 QProcess::startDetached(QStringLiteral("explorer"), QStringList{"/select", QDir::toNativeSeparators(filePath)});
357 #else
358 // we cannot select a file here, because no file browser really supports it...
359 QDesktopServices::openUrl(QUrl::fromLocalFile(QFileInfo(filePath).path()));
360 #endif
361 }
362
363 //---------------------------------------------------------------------------------------------------------------------
IsOptionSet(int argc,char * argv[],const char * option)364 bool IsOptionSet(int argc, char *argv[], const char *option)
365 {
366 for (int i = 1; i < argc; ++i)
367 {
368 if (!qstrcmp(argv[i], option))
369 {
370 return true;
371 }
372 }
373 return false;
374 }
375
376 //---------------------------------------------------------------------------------------------------------------------
377 // See issue #624. https://bitbucket.org/dismine/valentina/issues/624
InitHighDpiScaling(int argc,char * argv[])378 void InitHighDpiScaling(int argc, char *argv[])
379 {
380 /* For more info see: http://doc.qt.io/qt-5/highdpi.html */
381 if (IsOptionSet(argc, argv, qPrintable(QLatin1String("--") + LONG_OPTION_NO_HDPI_SCALING)))
382 {
383 #if QT_VERSION >= QT_VERSION_CHECK(5, 6, 0)
384 QCoreApplication::setAttribute(Qt::AA_DisableHighDpiScaling);
385 #else
386 qputenv("QT_DEVICE_PIXEL_RATIO", QByteArray("1"));
387 #endif
388 }
389 else
390 {
391 #if QT_VERSION >= QT_VERSION_CHECK(5, 6, 0)
392 QApplication::setAttribute(Qt::AA_EnableHighDpiScaling); // DPI support
393 #else
394 qputenv("QT_AUTO_SCREEN_SCALE_FACTOR", QByteArray("1"));
395 #endif
396 }
397 }
398
399 const QString strOne = QStringLiteral("one");
400 const QString strTwo = QStringLiteral("two");
401 const QString strThree = QStringLiteral("three");
402
403 Q_GLOBAL_STATIC_WITH_ARGS(const QString, strTMark, (QLatin1String("tMark")))
404 Q_GLOBAL_STATIC_WITH_ARGS(const QString, strVMark, (QLatin1String("vMark")))
405 Q_GLOBAL_STATIC_WITH_ARGS(const QString, strVMark2, (QLatin1String("vMark2")))
406 Q_GLOBAL_STATIC_WITH_ARGS(const QString, strUMark, (QLatin1String("uMark")))
407 Q_GLOBAL_STATIC_WITH_ARGS(const QString, strBoxMark, (QLatin1String("boxMark")))
408
409 //---------------------------------------------------------------------------------------------------------------------
PassmarkLineTypeToString(PassmarkLineType type)410 QString PassmarkLineTypeToString(PassmarkLineType type)
411 {
412 switch(type)
413 {
414 case PassmarkLineType::OneLine:
415 return strOne;
416 case PassmarkLineType::TwoLines:
417 return strTwo;
418 case PassmarkLineType::ThreeLines:
419 return strThree;
420 case PassmarkLineType::TMark:
421 return *strTMark;
422 case PassmarkLineType::VMark:
423 return *strVMark;
424 case PassmarkLineType::VMark2:
425 return *strVMark2;
426 case PassmarkLineType::UMark:
427 return *strUMark;
428 case PassmarkLineType::BoxMark:
429 return *strBoxMark;
430 default:
431 break;
432 }
433
434 return strOne;
435 }
436
437 //---------------------------------------------------------------------------------------------------------------------
StringToPassmarkLineType(const QString & value)438 PassmarkLineType StringToPassmarkLineType(const QString &value)
439 {
440 const QStringList values{strOne, strTwo, strThree, *strTMark, *strVMark, *strVMark2, *strUMark, *strBoxMark};
441
442 switch(values.indexOf(value))
443 {
444 case 0: // strOne
445 return PassmarkLineType::OneLine;
446 case 1: // strTwo
447 return PassmarkLineType::TwoLines;
448 case 2: // strThree
449 return PassmarkLineType::ThreeLines;
450 case 3: // strTMark
451 return PassmarkLineType::TMark;
452 case 4: // strVMark
453 return PassmarkLineType::VMark;
454 case 5: // strVMark2
455 return PassmarkLineType::VMark2;
456 case 6: // strUMark
457 return PassmarkLineType::UMark;
458 case 7: // strBoxMark
459 return PassmarkLineType::BoxMark;
460 default:
461 break;
462 }
463 return PassmarkLineType::OneLine;
464 }
465
466 const QString strStraightforward = QStringLiteral("straightforward");
467 const QString strBisector = QStringLiteral("bisector");
468 const QString strIntersection = QStringLiteral("intersection");
469 const QString strIntersectionOnlyLeft = QStringLiteral("intersectionLeft");
470 const QString strIntersectionOnlyRight = QStringLiteral("intersectionRight");
471 const QString strIntersection2 = QStringLiteral("intersection2");
472 const QString strIntersection2OnlyLeft = QStringLiteral("intersection2Left");
473 const QString strIntersection2OnlyRight = QStringLiteral("intersection2Right");
474 const QString strTypeIncrement = QStringLiteral("increment");
475 const QString strTypeSeparator = QStringLiteral("separator");
476
477 //---------------------------------------------------------------------------------------------------------------------
PassmarkAngleTypeToString(PassmarkAngleType type)478 QString PassmarkAngleTypeToString(PassmarkAngleType type)
479 {
480 switch(type)
481 {
482 case PassmarkAngleType::Straightforward:
483 return strStraightforward;
484 case PassmarkAngleType::Bisector:
485 return strBisector;
486 case PassmarkAngleType::Intersection:
487 return strIntersection;
488 case PassmarkAngleType::IntersectionOnlyLeft:
489 return strIntersectionOnlyLeft;
490 case PassmarkAngleType::IntersectionOnlyRight:
491 return strIntersectionOnlyRight;
492 case PassmarkAngleType::Intersection2:
493 return strIntersection2;
494 case PassmarkAngleType::Intersection2OnlyLeft:
495 return strIntersection2OnlyLeft;
496 case PassmarkAngleType::Intersection2OnlyRight:
497 return strIntersection2OnlyRight;
498 default:
499 break;
500 }
501
502 return strStraightforward;
503 }
504
505 //---------------------------------------------------------------------------------------------------------------------
StringToPassmarkAngleType(const QString & value)506 PassmarkAngleType StringToPassmarkAngleType(const QString &value)
507 {
508 const QStringList values = QStringList() << strStraightforward
509 << strBisector
510 << strIntersection
511 << strIntersectionOnlyLeft
512 << strIntersectionOnlyRight
513 << strIntersection2
514 << strIntersection2OnlyLeft
515 << strIntersection2OnlyRight;
516
517 switch(values.indexOf(value))
518 {
519 case 0:
520 return PassmarkAngleType::Straightforward;
521 case 1:
522 return PassmarkAngleType::Bisector;
523 case 2:
524 return PassmarkAngleType::Intersection;
525 case 3:
526 return PassmarkAngleType::IntersectionOnlyLeft;
527 case 4:
528 return PassmarkAngleType::IntersectionOnlyRight;
529 case 5:
530 return PassmarkAngleType::Intersection2;
531 case 6:
532 return PassmarkAngleType::Intersection2OnlyLeft;
533 case 7:
534 return PassmarkAngleType::Intersection2OnlyRight;
535 default:
536 break;
537 }
538 return PassmarkAngleType::Straightforward;
539 }
540
541
542 //---------------------------------------------------------------------------------------------------------------------
StrToUnits(const QString & unit)543 Unit StrToUnits(const QString &unit)
544 {
545 const QStringList units = QStringList() << unitMM << unitCM << unitINCH << unitPX;
546 Unit result = Unit::Cm;
547 switch (units.indexOf(unit))
548 {
549 case 0:// mm
550 result = Unit::Mm;
551 break;
552 case 2:// inch
553 result = Unit::Inch;
554 break;
555 case 3:// px
556 result = Unit::Px;
557 break;
558 case 1:// cm
559 default:
560 result = Unit::Cm;
561 break;
562 }
563 return result;
564 }
565
566 //---------------------------------------------------------------------------------------------------------------------
567 /**
568 * @brief UnitsToStr translate unit to string.
569 *
570 * This method used when need write unit in xml file and for showing unit in dialogs.
571 * @param unit curent unit
572 * @param translate true if need show translated name. Default value false.
573 * @return string reprezantation for unit.
574 */
UnitsToStr(const Unit & unit,const bool translate)575 QString UnitsToStr(const Unit &unit, const bool translate)
576 {
577 QString result;
578 switch (unit)
579 {
580 case Unit::Mm:
581 translate ? result = QObject::tr("mm") : result = unitMM;
582 break;
583 case Unit::Inch:
584 translate ? result = QObject::tr("inch") : result = unitINCH;
585 break;
586 case Unit::Px:
587 translate ? result = QObject::tr("px") : result = unitPX;
588 break;
589 case Unit::LAST_UNIT_DO_NOT_USE:
590 break;
591 case Unit::Cm:
592 default:
593 translate ? result = QObject::tr("cm") : result = unitCM;
594 break;
595 }
596 return result;
597 }
598
599 //---------------------------------------------------------------------------------------------------------------------
InitLanguages(QComboBox * combobox)600 void InitLanguages(QComboBox *combobox)
601 {
602 SCASSERT(combobox != nullptr)
603 combobox->clear();
604
605 QStringList fileNames;
606 QDirIterator it(VAbstractApplication::VApp()->translationsPath(), QStringList("valentina_*.qm"), QDir::Files,
607 QDirIterator::Subdirectories);
608 while (it.hasNext())
609 {
610 it.next();
611 fileNames.append(it.fileName());
612 }
613
614 bool englishUS = false;
615 const QString en_US = QStringLiteral("en_US");
616
617 for (auto locale : fileNames)
618 {
619 // get locale extracted by filename "valentina_de_De.qm"
620 locale.truncate(locale.lastIndexOf('.')); // "valentina_de_De"
621 locale.remove(0, locale.indexOf('_') + 1); // "de_De"
622
623 if (not englishUS)
624 {
625 englishUS = (en_US == locale);
626 }
627
628 QLocale loc = QLocale(locale);
629 QString lang = loc.nativeLanguageName();
630 // Since Qt 5.12 country names have spaces
631 QIcon ico(QString("://flags/%1.png").arg(QLocale::countryToString(loc.country()).remove(' ')));
632
633 combobox->addItem(ico, lang, locale);
634 }
635
636 if (combobox->count() == 0 || not englishUS)
637 {
638 // English language is internal and doens't have own *.qm file.
639 // Since Qt 5.12 country names have spaces
640 QIcon ico(QString("://flags/%1.png").arg(QLocale::countryToString(QLocale::UnitedStates).remove(' ')));
641 QString lang = QLocale(en_US).nativeLanguageName();
642 combobox->addItem(ico, lang, en_US);
643 }
644
645 // set default translators and language checked
646 qint32 index = combobox->findData(VAbstractApplication::VApp()->Settings()->GetLocale());
647 if (index != -1)
648 {
649 combobox->setCurrentIndex(index);
650 }
651 }
652
653 const quint32 CustomSARecord::streamHeader = 0xEBFF7586; // CRC-32Q string "CustomSARecord"
654 const quint16 CustomSARecord::classVersion = 1;
655
656 // Friend functions
657 //---------------------------------------------------------------------------------------------------------------------
operator <<(QDataStream & out,const CustomSARecord & record)658 QDataStream &operator<<(QDataStream &out, const CustomSARecord &record)
659 {
660 out << CustomSARecord::streamHeader << CustomSARecord::classVersion;
661
662 // Added in classVersion = 1
663 out << record.startPoint;
664 out << record.path;
665 out << record.endPoint;
666 out << record.reverse;
667 out << record.includeType;
668
669 // Added in classVersion = 2
670
671 return out;
672 }
673
674 //---------------------------------------------------------------------------------------------------------------------
operator >>(QDataStream & in,CustomSARecord & record)675 QDataStream &operator>>(QDataStream &in, CustomSARecord &record)
676 {
677 quint32 actualStreamHeader = 0;
678 in >> actualStreamHeader;
679
680 if (actualStreamHeader != CustomSARecord::streamHeader)
681 {
682 QString message = QCoreApplication::tr("CustomSARecord prefix mismatch error: actualStreamHeader = 0x%1 "
683 "and streamHeader = 0x%2")
684 .arg(actualStreamHeader, 8, 0x10, QChar('0'))
685 .arg(CustomSARecord::streamHeader, 8, 0x10, QChar('0'));
686 throw VException(message);
687 }
688
689 quint16 actualClassVersion = 0;
690 in >> actualClassVersion;
691
692 if (actualClassVersion > CustomSARecord::classVersion)
693 {
694 QString message = QCoreApplication::tr("CustomSARecord compatibility error: actualClassVersion = %1 and "
695 "classVersion = %2")
696 .arg(actualClassVersion).arg(CustomSARecord::classVersion);
697 throw VException(message);
698 }
699
700 in >> record.startPoint;
701 in >> record.path;
702 in >> record.endPoint;
703 in >> record.reverse;
704 in >> record.includeType;
705
706 // if (actualClassVersion >= 2)
707 // {
708
709 // }
710
711 return in;
712 }
713
714 //---------------------------------------------------------------------------------------------------------------------
IncrementTypeToString(IncrementType type)715 QString IncrementTypeToString(IncrementType type)
716 {
717 switch(type)
718 {
719 case IncrementType::Increment:
720 return strTypeIncrement;
721 case IncrementType::Separator:
722 return strTypeSeparator;
723 default:
724 break;
725 }
726
727 return strTypeIncrement;
728 }
729
730 //---------------------------------------------------------------------------------------------------------------------
StringToIncrementType(const QString & value)731 IncrementType StringToIncrementType(const QString &value)
732 {
733 const QStringList values { strTypeIncrement, strTypeSeparator };
734
735 switch(values.indexOf(value))
736 {
737 case 0:
738 return IncrementType::Increment;
739 case 1:
740 return IncrementType::Separator;
741 default:
742 break;
743 }
744 return IncrementType::Increment;
745 }
746
747 //---------------------------------------------------------------------------------------------------------------------
SplitFilePaths(const QString & path)748 QStringList SplitFilePaths(const QString &path)
749 {
750 QStringList result;
751 QString subPath = QDir::cleanPath(path);
752 QString lastFileName;
753
754 do
755 {
756 QFileInfo fileInfo(subPath);
757 lastFileName = fileInfo.fileName();
758 if (not lastFileName.isEmpty())
759 {
760 result.prepend(lastFileName);
761 subPath = fileInfo.path();
762 }
763 }
764 while(not lastFileName.isEmpty());
765
766 return result;
767 }
768