/************************************************************************ ** ** @file def.cpp ** @author Roman Telezhynskyi ** @date 11 6, 2015 ** ** @brief ** @copyright ** This source code is part of the Valentina project, a pattern making ** program, whose allow create and modeling patterns of clothing. ** Copyright (C) 2015 Valentina project ** All Rights Reserved. ** ** Valentina is free software: you can redistribute it and/or modify ** it under the terms of the GNU General Public License as published by ** the Free Software Foundation, either version 3 of the License, or ** (at your option) any later version. ** ** Valentina is distributed in the hope that it will be useful, ** but WITHOUT ANY WARRANTY; without even the implied warranty of ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ** GNU General Public License for more details. ** ** You should have received a copy of the GNU General Public License ** along with Valentina. If not, see . ** *************************************************************************/ #include "def.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "vabstractapplication.h" #if QT_VERSION < QT_VERSION_CHECK(5, 14, 0) # include "vdatastreamenum.h" #endif #include "../ifc/exception/vexception.h" #include "literals.h" #if QT_VERSION < QT_VERSION_CHECK(5, 5, 0) #include "../vmisc/diagnostic.h" #endif // QT_VERSION < QT_VERSION_CHECK(5, 5, 0) //--------------------------------------------------------------------------------------------------------------------- QPixmap QPixmapFromCache(const QString &pixmapPath) { QPixmap pixmap; if (not QPixmapCache::find(pixmapPath, &pixmap)) { pixmap = QPixmap(pixmapPath); QPixmapCache::insert(pixmapPath, pixmap); } return pixmap; } //--------------------------------------------------------------------------------------------------------------------- void SetItemOverrideCursor(QGraphicsItem *item, const QString &pixmapPath, int hotX, int hotY) { #ifndef QT_NO_CURSOR SCASSERT(item != nullptr) item->setCursor(QCursor(QPixmapFromCache(pixmapPath), hotX, hotY)); #else Q_UNUSED(item) Q_UNUSED(pixmapPath) Q_UNUSED(hotX) Q_UNUSED(hotY) #endif } //--------------------------------------------------------------------------------------------------------------------- QStringList SupportedLocales() { return QStringList { "uk_UA", "de_DE", "cs_CZ", "he_IL", "fr_FR", "it_IT", "nl_NL", "id_ID", "es_ES", "fi_FI", "en_US", "en_CA", "en_IN", "ro_RO", "zh_CN", "pt_BR", "el_GR", "pl_PL" }; } //--------------------------------------------------------------------------------------------------------------------- /** * @brief strippedName the function call around curFile to exclude the path to the file. * @param fullFileName full path to the file. * @return file name. */ QString StrippedName(const QString &fullFileName) { return QFileInfo(fullFileName).fileName(); } //--------------------------------------------------------------------------------------------------------------------- QString RelativeMPath(const QString &patternPath, const QString &absoluteMPath) { if (patternPath.isEmpty() || absoluteMPath.isEmpty()) { return absoluteMPath; } if (QFileInfo(absoluteMPath).isRelative()) { return absoluteMPath; } return QFileInfo(patternPath).absoluteDir().relativeFilePath(absoluteMPath); } //--------------------------------------------------------------------------------------------------------------------- QString AbsoluteMPath(const QString &patternPath, const QString &relativeMPath) { if (patternPath.isEmpty() || relativeMPath.isEmpty()) { return relativeMPath; } if (QFileInfo(relativeMPath).isAbsolute()) { return relativeMPath; } return QFileInfo(QFileInfo(patternPath).absoluteDir(), relativeMPath).absoluteFilePath(); } //--------------------------------------------------------------------------------------------------------------------- QMarginsF GetMinPrinterFields(const QSharedPointer &printer) { QPageLayout layout = printer->pageLayout(); layout.setUnits(QPageLayout::Millimeter); const QMarginsF minMargins = layout.minimumMargins(); QMarginsF min; min.setLeft(UnitConvertor(minMargins.left(), Unit::Mm, Unit::Px)); min.setRight(UnitConvertor(minMargins.right(), Unit::Mm, Unit::Px)); min.setTop(UnitConvertor(minMargins.top(), Unit::Mm, Unit::Px)); min.setBottom(UnitConvertor(minMargins.bottom(), Unit::Mm, Unit::Px)); return min; } //--------------------------------------------------------------------------------------------------------------------- auto GetPrinterFields(const QSharedPointer &printer) -> QMarginsF { if (printer.isNull()) { return {}; } // We can't use Unit::Px because our dpi in most cases is different const QMarginsF m = printer->pageLayout().margins(QPageLayout::Millimeter); QMarginsF def; def.setLeft(UnitConvertor(m.left(), Unit::Mm, Unit::Px)); def.setRight(UnitConvertor(m.right(), Unit::Mm, Unit::Px)); def.setTop(UnitConvertor(m.top(), Unit::Mm, Unit::Px)); def.setBottom(UnitConvertor(m.bottom(), Unit::Mm, Unit::Px)); return def; } //--------------------------------------------------------------------------------------------------------------------- QPixmap darkenPixmap(const QPixmap &pixmap) { QImage img = pixmap.toImage().convertToFormat(QImage::Format_ARGB32); const int imgh = img.height(); const int imgw = img.width(); for (int y = 0; y < imgh; ++y) { for (int x = 0; x < imgw; ++x) { int h, s, v; QRgb pixel = img.pixel(x, y); const int a = qAlpha(pixel); QColor hsvColor(pixel); hsvColor.getHsv(&h, &s, &v); s = qMin(100, s * 2); v = v / 2; hsvColor.setHsv(h, s, v); pixel = hsvColor.rgb(); img.setPixel(x, y, qRgba(qRed(pixel), qGreen(pixel), qBlue(pixel), a)); } } return QPixmap::fromImage(img); } //--------------------------------------------------------------------------------------------------------------------- void ShowInGraphicalShell(const QString &filePath) { #ifdef Q_OS_MAC QStringList args{ "-e", "tell application \"Finder\"", "-e", "activate", "-e", "select POSIX file \""+filePath+"\"", "-e", "end tell" }; QProcess::startDetached(QStringLiteral("osascript"), args); #elif defined(Q_OS_WIN) QProcess::startDetached(QStringLiteral("explorer"), QStringList{"/select", QDir::toNativeSeparators(filePath)}); #else const int timeout = 1000; // ms QString command = QStringLiteral("dbus-send --reply-timeout=%1 --session --dest=org.freedesktop.FileManager1 " "--type=method_call /org/freedesktop/FileManager1 " "org.freedesktop.FileManager1.ShowItems array:string:\"%2\" string:\"\"") .arg(timeout).arg(QUrl::fromLocalFile(filePath).toString()); // Sending message through dbus will highlighting file QProcess dbus; #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) // This approach works too. dbus.start(command, QStringList()); // clazy:exclude=qt6-deprecated-api-fixes #else dbus.startCommand(command); #endif if (not dbus.waitForStarted(timeout)) { // This way will open only window without highlighting file QDesktopServices::openUrl(QUrl::fromLocalFile(QFileInfo(filePath).path())); return; } if (not dbus.waitForFinished(timeout)) { // This way will open only window without highlighting file QDesktopServices::openUrl(QUrl::fromLocalFile(QFileInfo(filePath).path())); return; } #endif } //--------------------------------------------------------------------------------------------------------------------- bool IsOptionSet(int argc, char *argv[], const char *option) { for (int i = 1; i < argc; ++i) { if (!qstrcmp(argv[i], option)) { return true; } } return false; } //--------------------------------------------------------------------------------------------------------------------- // See issue #624. https://bitbucket.org/dismine/valentina/issues/624 void InitHighDpiScaling(int argc, char *argv[]) { /* For more info see: http://doc.qt.io/qt-5/highdpi.html */ if (IsOptionSet(argc, argv, qPrintable(QLatin1String("--") + LONG_OPTION_NO_HDPI_SCALING))) { #if QT_VERSION >= QT_VERSION_CHECK(5, 6, 0) #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) QCoreApplication::setAttribute(Qt::AA_DisableHighDpiScaling); #endif #else qputenv("QT_DEVICE_PIXEL_RATIO", QByteArray("1")); #endif } else { #if QT_VERSION >= QT_VERSION_CHECK(5, 6, 0) #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) QApplication::setAttribute(Qt::AA_EnableHighDpiScaling); // DPI support #endif #else qputenv("QT_AUTO_SCREEN_SCALE_FACTOR", QByteArray("1")); #endif } } Q_GLOBAL_STATIC_WITH_ARGS(const QString, strTMark, (QLatin1String("tMark"))) // NOLINT Q_GLOBAL_STATIC_WITH_ARGS(const QString, strVMark, (QLatin1String("vMark"))) // NOLINT Q_GLOBAL_STATIC_WITH_ARGS(const QString, strVMark2, (QLatin1String("vMark2"))) // NOLINT Q_GLOBAL_STATIC_WITH_ARGS(const QString, strUMark, (QLatin1String("uMark"))) // NOLINT Q_GLOBAL_STATIC_WITH_ARGS(const QString, strBoxMark, (QLatin1String("boxMark"))) // NOLINT //--------------------------------------------------------------------------------------------------------------------- QString PassmarkLineTypeToString(PassmarkLineType type) { switch(type) { case PassmarkLineType::OneLine: return strOne; case PassmarkLineType::TwoLines: return strTwo; case PassmarkLineType::ThreeLines: return strThree; case PassmarkLineType::TMark: return *strTMark; case PassmarkLineType::VMark: return *strVMark; case PassmarkLineType::VMark2: return *strVMark2; case PassmarkLineType::UMark: return *strUMark; case PassmarkLineType::BoxMark: return *strBoxMark; default: break; } return strOne; } //--------------------------------------------------------------------------------------------------------------------- PassmarkLineType StringToPassmarkLineType(const QString &value) { const QStringList values{strOne, strTwo, strThree, *strTMark, *strVMark, *strVMark2, *strUMark, *strBoxMark}; switch(values.indexOf(value)) { case 0: // strOne return PassmarkLineType::OneLine; case 1: // strTwo return PassmarkLineType::TwoLines; case 2: // strThree return PassmarkLineType::ThreeLines; case 3: // strTMark return PassmarkLineType::TMark; case 4: // strVMark return PassmarkLineType::VMark; case 5: // strVMark2 return PassmarkLineType::VMark2; case 6: // strUMark return PassmarkLineType::UMark; case 7: // strBoxMark return PassmarkLineType::BoxMark; default: break; } return PassmarkLineType::OneLine; } //--------------------------------------------------------------------------------------------------------------------- QString PassmarkAngleTypeToString(PassmarkAngleType type) { switch(type) { case PassmarkAngleType::Straightforward: return strStraightforward; case PassmarkAngleType::Bisector: return strBisector; case PassmarkAngleType::Intersection: return strIntersection; case PassmarkAngleType::IntersectionOnlyLeft: return strIntersectionOnlyLeft; case PassmarkAngleType::IntersectionOnlyRight: return strIntersectionOnlyRight; case PassmarkAngleType::Intersection2: return strIntersection2; case PassmarkAngleType::Intersection2OnlyLeft: return strIntersection2OnlyLeft; case PassmarkAngleType::Intersection2OnlyRight: return strIntersection2OnlyRight; default: break; } return strStraightforward; } //--------------------------------------------------------------------------------------------------------------------- PassmarkAngleType StringToPassmarkAngleType(const QString &value) { const QStringList values = QStringList() << strStraightforward << strBisector << strIntersection << strIntersectionOnlyLeft << strIntersectionOnlyRight << strIntersection2 << strIntersection2OnlyLeft << strIntersection2OnlyRight; switch(values.indexOf(value)) { case 0: return PassmarkAngleType::Straightforward; case 1: return PassmarkAngleType::Bisector; case 2: return PassmarkAngleType::Intersection; case 3: return PassmarkAngleType::IntersectionOnlyLeft; case 4: return PassmarkAngleType::IntersectionOnlyRight; case 5: return PassmarkAngleType::Intersection2; case 6: return PassmarkAngleType::Intersection2OnlyLeft; case 7: return PassmarkAngleType::Intersection2OnlyRight; default: break; } return PassmarkAngleType::Straightforward; } //--------------------------------------------------------------------------------------------------------------------- Unit StrToUnits(const QString &unit) { const QStringList units = QStringList() << unitMM << unitCM << unitINCH << unitPX; Unit result = Unit::Cm; switch (units.indexOf(unit)) { case 0:// mm result = Unit::Mm; break; case 2:// inch result = Unit::Inch; break; case 3:// px result = Unit::Px; break; case 1:// cm default: result = Unit::Cm; break; } return result; } //--------------------------------------------------------------------------------------------------------------------- /** * @brief UnitsToStr translate unit to string. * * This method used when need write unit in xml file and for showing unit in dialogs. * @param unit curent unit * @param translate true if need show translated name. Default value false. * @return string reprezantation for unit. */ QString UnitsToStr(const Unit &unit, const bool translate) { QString result; switch (unit) { case Unit::Mm: translate ? result = QObject::tr("mm") : result = unitMM; break; case Unit::Inch: translate ? result = QObject::tr("inch") : result = unitINCH; break; case Unit::Px: translate ? result = QObject::tr("px") : result = unitPX; break; case Unit::LAST_UNIT_DO_NOT_USE: break; case Unit::Cm: default: translate ? result = QObject::tr("cm") : result = unitCM; break; } return result; } //--------------------------------------------------------------------------------------------------------------------- void InitLanguages(QComboBox *combobox) { SCASSERT(combobox != nullptr) combobox->clear(); QStringList fileNames; QDirIterator it(VAbstractApplication::translationsPath(), QStringList("valentina_*.qm"), QDir::Files, QDirIterator::Subdirectories); while (it.hasNext()) { it.next(); fileNames.append(it.fileName()); } bool englishUS = false; const QString en_US = QStringLiteral("en_US"); for (auto locale : fileNames) { // get locale extracted by filename "valentina_de_De.qm" locale.truncate(locale.lastIndexOf('.')); // "valentina_de_De" locale.remove(0, locale.indexOf('_') + 1); // "de_De" if (locale.startsWith(QLatin1String("ru"))) { continue; } if (not englishUS) { englishUS = (en_US == locale); } QLocale loc = QLocale(locale); QString lang = loc.nativeLanguageName(); // Since Qt 5.12 country names have spaces QString country = QLocale::countryToString(loc.country()).remove(' '); if (country == QLatin1String("Czechia")) { country = QLatin1String("CzechRepublic"); } QIcon ico(QString("://flags/%1.png").arg(country)); combobox->addItem(ico, lang, locale); } if (combobox->count() == 0 || not englishUS) { // English language is internal and doens't have own *.qm file. // Since Qt 5.12 country names have spaces QIcon ico(QString("://flags/%1.png").arg(QLocale::countryToString(QLocale::UnitedStates).remove(' '))); QString lang = QLocale(en_US).nativeLanguageName(); combobox->addItem(ico, lang, en_US); } // set default translators and language checked qint32 index = combobox->findData(VAbstractApplication::VApp()->Settings()->GetLocale()); if (index != -1) { combobox->setCurrentIndex(index); } } const quint32 CustomSARecord::streamHeader = 0xEBFF7586; // CRC-32Q string "CustomSARecord" const quint16 CustomSARecord::classVersion = 1; // Friend functions //--------------------------------------------------------------------------------------------------------------------- QDataStream &operator<<(QDataStream &out, const CustomSARecord &record) { out << CustomSARecord::streamHeader << CustomSARecord::classVersion; // Added in classVersion = 1 out << record.startPoint; out << record.path; out << record.endPoint; out << record.reverse; out << record.includeType; // Added in classVersion = 2 return out; } //--------------------------------------------------------------------------------------------------------------------- QDataStream &operator>>(QDataStream &in, CustomSARecord &record) { quint32 actualStreamHeader = 0; in >> actualStreamHeader; if (actualStreamHeader != CustomSARecord::streamHeader) { QString message = QCoreApplication::tr("CustomSARecord prefix mismatch error: actualStreamHeader = 0x%1 " "and streamHeader = 0x%2") .arg(actualStreamHeader, 8, 0x10, QChar('0')) .arg(CustomSARecord::streamHeader, 8, 0x10, QChar('0')); throw VException(message); } quint16 actualClassVersion = 0; in >> actualClassVersion; if (actualClassVersion > CustomSARecord::classVersion) { QString message = QCoreApplication::tr("CustomSARecord compatibility error: actualClassVersion = %1 and " "classVersion = %2") .arg(actualClassVersion).arg(CustomSARecord::classVersion); throw VException(message); } in >> record.startPoint; in >> record.path; in >> record.endPoint; in >> record.reverse; in >> record.includeType; // if (actualClassVersion >= 2) // { // } return in; } //--------------------------------------------------------------------------------------------------------------------- QString IncrementTypeToString(IncrementType type) { switch(type) { case IncrementType::Increment: return strTypeIncrement; case IncrementType::Separator: return strTypeSeparator; default: break; } return strTypeIncrement; } //--------------------------------------------------------------------------------------------------------------------- IncrementType StringToIncrementType(const QString &value) { const QStringList values { strTypeIncrement, strTypeSeparator }; switch(values.indexOf(value)) { case 0: return IncrementType::Increment; case 1: return IncrementType::Separator; default: break; } return IncrementType::Increment; } //--------------------------------------------------------------------------------------------------------------------- QString MeasurementTypeToString(MeasurementType type) { switch(type) { case MeasurementType::Measurement: return strTypeMeasurement; case MeasurementType::Separator: return strTypeSeparator; default: break; } return strTypeIncrement; } //--------------------------------------------------------------------------------------------------------------------- MeasurementType StringToMeasurementType(const QString &value) { const QStringList values { strTypeMeasurement, strTypeSeparator }; switch(values.indexOf(value)) { case 0: return MeasurementType::Measurement; case 1: return MeasurementType::Separator; default: break; } return MeasurementType::Measurement; } //--------------------------------------------------------------------------------------------------------------------- QStringList SplitFilePaths(const QString &path) { QStringList result; QString subPath = QDir::cleanPath(path); QString lastFileName; do { QFileInfo fileInfo(subPath); lastFileName = fileInfo.fileName(); if (not lastFileName.isEmpty()) { result.prepend(lastFileName); subPath = fileInfo.path(); } } while(not lastFileName.isEmpty()); return result; }