diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 419014eeb..985d23434 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -34,7 +34,7 @@ jobs: run: | QT_DIR=$(ls -d /Library/Developer/Qt-*-OpenSSL | tail -n 1) cmake \ - -DQt5_DIR=${QT_DIR}/lib/cmake/Qt5 \ + -DCMAKE_PREFIX_PATH=${QT_DIR} \ -DOPENSSL_ROOT_DIR=/Library/Developer/OpenSSL \ -DLDAP_ROOT=/Library/Developer/OpenLDAP \ -DCMAKE_OSX_ARCHITECTURES="x86_64;arm64" -B build -S . @@ -133,10 +133,9 @@ jobs: strategy: matrix: vcver: [141, 142, 143] - arch: [x86, x64] + arch: [x64] + qtver: [5.12.12] include: - - arch: x86 - qt: win32_msvc2017 - arch: x64 qt: win64_msvc2017_64 - vcver: 141 @@ -147,7 +146,20 @@ jobs: toolset: 14.29 - vcver: 143 image: windows-2022 - toolset: 14.31 + toolset: 14.32 + - vcver: 142 + arch: x86 + qtver: 5.12.12 + qt: win32_msvc2017 + image: windows-2019 + toolset: 14.29 + - vcver: 142 + arch: x64 + qtver: 6.3.0 + qtmodules: qt5compat + qt: win64_msvc2019_64 + image: windows-2019 + toolset: 14.29 env: VER_SUFFIX: .VS${{ matrix.vcver }} steps: @@ -176,8 +188,9 @@ jobs: - name: Install Qt uses: jurplel/install-qt-action@v2 with: - version: '5.12.12' + version: ${{ matrix.qtver }} arch: ${{ matrix.qt }} + modules: ${{ matrix.qtmodules }} - name: Setup dev env uses: ilammy/msvc-dev-cmd@v1 with: diff --git a/CMakeLists.txt b/CMakeLists.txt index fc9f5f6f4..f2a622288 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -4,7 +4,7 @@ if(POLICY CMP0074) endif() project(qdigidoc4 VERSION 4.2.12) -set(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake/modules") +set(CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake/modules) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(CMAKE_AUTOMOC ON) @@ -14,7 +14,8 @@ include( VersionInfo ) find_package( PKCS11 ) find_package( LibDigiDocpp 3.14.8 REQUIRED ) find_package( LDAP REQUIRED ) -find_package( Qt5 5.9.0 REQUIRED COMPONENTS Core Widgets Network PrintSupport Svg LinguistTools ) +find_package(QT NAMES Qt6 Qt5 COMPONENTS Core REQUIRED) +find_package(Qt${QT_VERSION_MAJOR} 5.9.0 REQUIRED COMPONENTS Core Widgets Network PrintSupport Svg LinguistTools) set_env( TSL_URL "https://ec.europa.eu/tools/lotl/eu-lotl.xml" CACHE STRING "TSL trust list primary URL" ) set_env( TSL_INCLUDE "EE" CACHE STRING "TSL list include in binary" ) diff --git a/client/Application.cpp b/client/Application.cpp index d7cdcafc5..8c39822d3 100644 --- a/client/Application.cpp +++ b/client/Application.cpp @@ -45,12 +45,14 @@ class MacMenuBar {}; #include +#include #include #include #include #include #include #include +#include #include #include #include @@ -61,7 +63,6 @@ class MacMenuBar {}; #include #include #include -#include #include #include #include @@ -163,7 +164,7 @@ class DigidocConf: public digidoc::XmlConfCurrent bool PKCS12Disable() const override { return s.value(QStringLiteral("PKCS12Disable"), digidoc::XmlConfCurrent::PKCS12Disable()).toBool(); } std::string TSLCache() const override - { return QStandardPaths::writableLocation(QStandardPaths::DataLocation).toStdString(); } + { return QStandardPaths::writableLocation(QStandardPaths::AppLocalDataLocation).toStdString(); } bool TSLOnlineDigest() const override { return s.value(QStringLiteral("TSLOnlineDigest"), digidoc::XmlConfCurrent::TSLOnlineDigest()).toBool(); } @@ -645,13 +646,13 @@ void Application::loadTranslation( const QString &lang ) return; QSettings().setValue(QStringLiteral("Language"), d->lang = lang); - if(lang == QStringLiteral("en")) QLocale::setDefault(QLocale(QLocale::English, QLocale::UnitedKingdom)); - else if(lang == QStringLiteral("ru")) QLocale::setDefault(QLocale( QLocale::Russian, QLocale::RussianFederation)); + if(lang == QLatin1String("en")) QLocale::setDefault(QLocale(QLocale::English, QLocale::UnitedKingdom)); + else if(lang == QLatin1String("ru")) QLocale::setDefault(QLocale( QLocale::Russian, QLocale::RussianFederation)); else QLocale::setDefault(QLocale(QLocale::Estonian, QLocale::Estonia)); - d->appTranslator.load(QStringLiteral(":/translations/") + lang); - d->commonTranslator.load(QStringLiteral(":/translations/common_") + lang); - d->qtTranslator.load(QStringLiteral(":/translations/qt_") + lang); + void(d->appTranslator.load(QStringLiteral(":/translations/") + lang)); + void(d->commonTranslator.load(QStringLiteral(":/translations/common_") + lang)); + void(d->qtTranslator.load(QStringLiteral(":/translations/qt_") + lang)); if( d->closeAction ) d->closeAction->setText( tr("Close Window") ); if( d->newClientAction ) d->newClientAction->setText( tr("New Window") ); if( d->newCryptoAction ) d->newCryptoAction->setText( tr("New Crypto window") ); @@ -676,7 +677,7 @@ void Application::mailTo( const QUrl &url ) doc.lpszFileName = PWSTR(fileName.utf16()); MapiMessageW message = {}; message.lpszSubject = PWSTR(subject.utf16()); - message.lpszNoteText = L""; + message.lpszNoteText = PWSTR(L""); message.nFileCount = 1; message.lpFiles = lpMapiFileDescW(&doc); switch( mapi( NULL, 0, &message, MAPI_LOGON_UI|MAPI_DIALOG, 0 ) ) @@ -699,7 +700,7 @@ void Application::mailTo( const QUrl &url ) doc.lpszFileName = LPSTR(fileName.constData()); MapiMessage message = {}; message.lpszSubject = LPSTR(subject.constData()); - message.lpszNoteText = ""; + message.lpszNoteText = LPSTR(""); message.nFileCount = 1; message.lpFiles = lpMapiFileDesc(&doc); switch( mapi( NULL, 0, &message, MAPI_LOGON_UI|MAPI_DIALOG, 0 ) ) @@ -953,8 +954,8 @@ void Application::openHelp() { QString lang = language(); QUrl u(QStringLiteral("https://www.id.ee/id-abikeskus/")); - if(lang == QStringLiteral("en")) u = QStringLiteral("https://www.id.ee/en/id-help/"); - if(lang == QStringLiteral("ru")) u = QStringLiteral("https://www.id.ee/ru/id-pomoshh/"); + if(lang == QLatin1String("en")) u = QStringLiteral("https://www.id.ee/en/id-help/"); + if(lang == QLatin1String("ru")) u = QStringLiteral("https://www.id.ee/ru/id-pomoshh/"); QDesktopServices::openUrl(u); } @@ -970,16 +971,16 @@ void Application::parseArgs( const QString &msg ) #endif { QUrl url( param, QUrl::StrictMode ); - params << (param != QStringLiteral("-crypto") && !url.toLocalFile().isEmpty() ? url.toLocalFile() : param); + params << (param != QLatin1String("-crypto") && !url.toLocalFile().isEmpty() ? url.toLocalFile() : param); } parseArgs( params ); } void Application::parseArgs( const QStringList &args ) { - bool crypto = args.contains(QStringLiteral("-crypto")); - bool sign = args.contains(QStringLiteral("-sign")); - bool newWindow = args.contains(QStringLiteral("-newWindow")); + bool crypto = args.contains(QLatin1String("-crypto")); + bool sign = args.contains(QLatin1String("-sign")); + bool newWindow = args.contains(QLatin1String("-newWindow")); QStringList params = args; params.removeAll(QStringLiteral("-sign")); params.removeAll(QStringLiteral("-crypto")); @@ -989,7 +990,7 @@ void Application::parseArgs( const QStringList &args ) params.removeAll(QStringLiteral("-pkcs11")); QString suffix = params.size() == 1 ? QFileInfo(params.value(0)).suffix() : QString(); - showClient(params, crypto || (suffix.compare(QStringLiteral("cdoc"), Qt::CaseInsensitive) == 0), sign, newWindow); + showClient(params, crypto || (suffix.compare(QLatin1String("cdoc"), Qt::CaseInsensitive) == 0), sign, newWindow); } uint Application::readTSLVersion(const QString &path) @@ -1000,7 +1001,7 @@ uint Application::readTSLVersion(const QString &path) QXmlStreamReader r(&f); while(!r.atEnd()) { - if(r.readNextStartElement() && r.name() == "TSLSequenceNumber") + if(r.readNextStartElement() && r.name() == QLatin1String("TSLSequenceNumber")) { r.readNext(); return r.text().toUInt(); diff --git a/client/CMakeLists.txt b/client/CMakeLists.txt index a3ae68888..151e77919 100644 --- a/client/CMakeLists.txt +++ b/client/CMakeLists.txt @@ -1,16 +1,18 @@ set_app_name( PROGNAME qdigidoc4 ) add_executable( TSLDownload TSLDownload.cpp ) -target_link_libraries( TSLDownload Qt5::Network ) +target_link_libraries(TSLDownload Qt${QT_VERSION_MAJOR}::Network) +get_target_property(qtCore_install_prefix Qt${QT_VERSION_MAJOR}::qmake IMPORTED_LOCATION) +get_filename_component(qtCore_install_prefix ${qtCore_install_prefix} DIRECTORY) add_custom_command( OUTPUT TSL.qrc DEPENDS TSLDownload COMMAND $ "${CMAKE_CURRENT_BINARY_DIR}" ${TSL_URL} ${TSL_INCLUDE} - WORKING_DIRECTORY ${_qt5Core_install_prefix}/bin + WORKING_DIRECTORY ${qtCore_install_prefix} ) configure_file( translations/tr.qrc tr.qrc COPYONLY ) -qt5_add_translation( SOURCES translations/en.ts translations/et.ts translations/ru.ts ) +qt_add_translation(SOURCES translations/en.ts translations/et.ts translations/ru.ts) add_executable( ${PROGNAME} WIN32 MACOSX_BUNDLE ${PROGNAME}.rc @@ -28,6 +30,7 @@ add_executable( ${PROGNAME} WIN32 MACOSX_BUNDLE Diagnostics.cpp DiagnosticsTask.cpp DocumentModel.cpp + IKValidator.cpp MainWindow.ui MainWindow.cpp MainWindow_MyEID.cpp @@ -102,6 +105,7 @@ add_executable( ${PROGNAME} WIN32 MACOSX_BUNDLE widgets/InfoStack.ui widgets/InfoStack.cpp widgets/LabelButton.cpp + widgets/LineEdit.cpp widgets/MainAction.ui widgets/MainAction.cpp widgets/NoCardInfo.ui @@ -123,11 +127,21 @@ add_executable( ${PROGNAME} WIN32 MACOSX_BUNDLE target_link_libraries( ${PROGNAME} qdigidoccommon - Qt5::PrintSupport - Qt5::Svg + Qt${QT_VERSION_MAJOR}::PrintSupport + Qt${QT_VERSION_MAJOR}::Svg ${LIBDIGIDOCPP_LIBRARY} ${LDAP_LIBRARIES} ) + +if(${QT_VERSION_MAJOR} STREQUAL "6") + find_package(Qt6 COMPONENTS Core5Compat SvgWidgets REQUIRED) + target_link_libraries(${PROGNAME} Qt6::Core5Compat Qt6::SvgWidgets) +elseif(WIN32) + find_package(Qt5 COMPONENTS WinExtras) + target_compile_definitions(${PROGNAME} PRIVATE QT_WIN_EXTRAS) + target_link_libraries(${PROGNAME} Qt5::WinExtras) +endif() + set_target_properties(${PROGNAME} PROPERTIES AUTOUIC ON AUTORCC ON @@ -156,7 +170,7 @@ if( APPLE ) COMMAND cp -a $ $/Library/QuickLook ) add_custom_target( macdeployqt DEPENDS ${PROGNAME} - COMMAND ${_qt5Core_install_prefix}/bin/macdeployqt $ + COMMAND ${qtCore_install_prefix}/macdeployqt $ COMMAND rm -rf $/PlugIns/bearer COMMAND cp -a /Library/Frameworks/digidocpp.framework $/Frameworks COMMAND rm $/Frameworks/digidocpp.framework/Resources/digidoc-tool @@ -197,8 +211,7 @@ elseif(WIN32) target_sources( ${PROGNAME} PRIVATE QCSP.cpp QCNG.cpp QWin.cpp CertStore.cpp Diagnostics_win.cpp) target_compile_options(${PROGNAME} PRIVATE "/guard:cf") target_link_options(${PROGNAME} PRIVATE "/guard:cf" $<$:/INTEGRITYCHECK>) - find_package( Qt5 COMPONENTS WinExtras ) - target_link_libraries( ${PROGNAME} Qt5::WinExtras NCrypt Crypt32 Cryptui ) + target_link_libraries(${PROGNAME} NCrypt Crypt32 Cryptui) get_filename_component(LIBS_PATH ${LIBDIGIDOCPP_LIBRARIES} DIRECTORY) if(CMAKE_SIZEOF_VOID_P EQUAL 8) set(PLATFORM x64) @@ -210,19 +223,20 @@ elseif(WIN32) set(MSI_FILE "Digidoc4_Client-${VERSION}$ENV{VER_SUFFIX}.${PLATFORM}") list(APPEND CANDLE_CMD "$ENV{WIX}bin\\candle.exe" -nologo -arch ${PLATFORM} -dMSI_VERSION=${VERSION} -dPlatform=${PLATFORM} -dlibs_path="${LIBS_PATH}" -dclient_path=$ -dico_path=${CMAKE_CURRENT_SOURCE_DIR}/images/digidoc.ico - -dqtconf=${CMAKE_SOURCE_DIR}/qt.conf -dschemasLocation=${LIBS_PATH}/schema SchemasFragment.wxs ${CMAKE_SOURCE_DIR}/qdigidoc4.wxs - ${CMAKE_MODULE_PATH}/WelcomeDlg2.wxs ${CMAKE_MODULE_PATH}/WixUI_Minimal2.wxs) + -dqtconf=${CMAKE_SOURCE_DIR}/qt.conf -dschemasLocation=${LIBS_PATH}/schema SchemasFragment.wxs + -dqt_ver_major=${QT_VERSION_MAJOR} -dqt_suffix=$<$:d> ${CMAKE_SOURCE_DIR}/qdigidoc4.wxs + ${CMAKE_SOURCE_DIR}/cmake/modules/WelcomeDlg2.wxs ${CMAKE_SOURCE_DIR}/cmake/modules/WixUI_Minimal2.wxs) list(APPEND LIGHT_CMD "$ENV{WIX}bin\\light.exe" -nologo -ext WixUIExtension qdigidoc4.wixobj SchemasFragment.wixobj WelcomeDlg2.wixobj WixUI_Minimal2.wixobj - -dWixUIDialogBmp=${CMAKE_MODULE_PATH}/dlgbmp.bmp - -dWixUIBannerBmp=${CMAKE_MODULE_PATH}/banner.bmp) + -dWixUIDialogBmp=${CMAKE_SOURCE_DIR}/cmake/modules/dlgbmp.bmp + -dWixUIBannerBmp=${CMAKE_SOURCE_DIR}/cmake/modules/banner.bmp) add_custom_target(msi DEPENDS ${PROGNAME} COMMAND "$ENV{WIX}bin\\heat.exe" dir ${LIBS_PATH}/schema -nologo -cg Schemas -gg -scom -sreg -sfrag -srd -dr SchemaFolder -var var.schemasLocation -out SchemasFragment.wxs COMMAND ${CANDLE_CMD} COMMAND ${LIGHT_CMD} -loc ${CMAKE_SOURCE_DIR}/qdigidoc4.en-US.wxl -cultures:en-US -o "${MSI_FILE}.en-US.msi" COMMAND ${LIGHT_CMD} -loc ${CMAKE_SOURCE_DIR}/qdigidoc4.et-EE.wxl -cultures:et-EE -o "${MSI_FILE}.et-EE.msi" #Build MSI with QT - COMMAND ${CANDLE_CMD} -dqt_path=${_qt5Core_install_prefix} + COMMAND ${CANDLE_CMD} -dqt_path=${qtCore_install_prefix} COMMAND ${LIGHT_CMD} -loc ${CMAKE_SOURCE_DIR}/qdigidoc4.en-US.wxl -cultures:en-US -o "${MSI_FILE}.en-US.qt.msi" COMMAND ${LIGHT_CMD} -loc ${CMAKE_SOURCE_DIR}/qdigidoc4.et-EE.wxl -cultures:et-EE -o "${MSI_FILE}.et-EE.qt.msi" WORKING_DIRECTORY ${CMAKE_BINARY_DIR} @@ -259,7 +273,7 @@ elseif(WIN32) COMMAND ${CMAKE_COMMAND} -E copy ${LIBS_PATH}/digidocpp.conf appx COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_SOURCE_DIR}/Assets appx/Assets COMMAND ${CMAKE_COMMAND} -E copy_directory ${LIBS_PATH}/schema appx/schema - COMMAND ${_qt5Core_install_prefix}/bin/windeployqt --no-translations --no-compiler-runtime --no-patchqt appx + COMMAND ${qtCore_install_prefix}/windeployqt --no-translations --no-compiler-runtime --no-patchqt appx COMMAND ${CMAKE_COMMAND} -E remove_directory appx/bearer COMMAND makeappx.exe pack -d appx -p ${MSI_FILE}.appx # https://msdn.microsoft.com/en-us/library/windows/desktop/jj835832(v=vs.85).aspx diff --git a/client/CryptoDoc.cpp b/client/CryptoDoc.cpp index 5c8b7ada6..4b28cc666 100644 --- a/client/CryptoDoc.cpp +++ b/client/CryptoDoc.cpp @@ -33,6 +33,7 @@ #include #include #include +#include #include #include #include @@ -82,7 +83,11 @@ class CryptoDoc::Private final: public QThread QByteArray crypto(const EVP_CIPHER *cipher, const QByteArray &data, bool encrypt); bool isEncryptedWarning(); +#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) + QByteArray fromBase64(const QStringView &data); +#else QByteArray fromBase64(const QStringRef &data); +#endif static bool opensslError(bool err); QByteArray readCDoc(QIODevice *cdoc, bool data); void readDDoc(QIODevice *ddoc); @@ -266,7 +271,11 @@ QByteArray CryptoDoc::Private::crypto(const EVP_CIPHER *cipher, const QByteArray return result; } -QByteArray CryptoDoc::Private::fromBase64( const QStringRef &data ) +#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) +QByteArray CryptoDoc::Private::fromBase64(const QStringView &data) +#else +QByteArray CryptoDoc::Private::fromBase64(const QStringRef &data) +#endif { unsigned int buf = 0; int nbits = 0; @@ -480,10 +489,10 @@ QByteArray CryptoDoc::Private::readCDoc(QIODevice *cdoc, bool data) if(data) { // EncryptedData/KeyInfo - if(xml.name() == "KeyInfo") + if(xml.name() == QStringLiteral("KeyInfo")) xml.skipCurrentElement(); // EncryptedData/CipherData/CipherValue - else if(xml.name() == "CipherValue") + else if(xml.name() == QStringLiteral("CipherValue")) { xml.readNext(); return fromBase64(xml.text()); @@ -492,16 +501,16 @@ QByteArray CryptoDoc::Private::readCDoc(QIODevice *cdoc, bool data) } // EncryptedData - if( xml.name() == "EncryptedData") + if(xml.name() == QStringLiteral("EncryptedData")) mime = xml.attributes().value(QStringLiteral("MimeType")).toString(); // EncryptedData/EncryptionProperties/EncryptionProperty - else if( xml.name() == "EncryptionProperty" ) + else if(xml.name() == QStringLiteral("EncryptionProperty")) { for( const QXmlStreamAttribute &attr: xml.attributes() ) { - if( attr.name() != "Name" ) + if(attr.name() != QStringLiteral("Name")) continue; - if( attr.value() == "orig_file" ) + if(attr.value() == QStringLiteral("orig_file")) { QStringList fileparts = xml.readElementText().split('|'); File file; @@ -516,10 +525,10 @@ QByteArray CryptoDoc::Private::readCDoc(QIODevice *cdoc, bool data) } } // EncryptedData/EncryptionMethod - else if( xml.name() == "EncryptionMethod" ) + else if(xml.name() == QStringLiteral("EncryptionMethod")) method = xml.attributes().value(QStringLiteral("Algorithm")).toString(); // EncryptedData/KeyInfo/EncryptedKey - else if( xml.name() == "EncryptedKey" ) + else if(xml.name() == QStringLiteral("EncryptedKey")) { CKey key; key.id = xml.attributes().value(QStringLiteral("Id")).toString(); @@ -718,7 +727,7 @@ void CryptoDoc::Private::writeCDoc(QIODevice *cdoc, const QByteArray &transportK writeBase64Element(w, DENC, QStringLiteral("CipherValue"), encryptedData); }); writeElement(w, DENC, QStringLiteral("EncryptionProperties"), [&]{ - for(QHash::const_iterator i = props.constBegin(); i != props.constEnd(); ++i) + for(QMultiHash::const_iterator i = props.constBegin(); i != props.constEnd(); ++i) writeElement(w, DENC, QStringLiteral("EncryptionProperty"), {{"Name", i.key()}}, [&]{ w.writeCharacters(i.value()); }); }); }); @@ -744,7 +753,7 @@ void CryptoDoc::Private::readDDoc(QIODevice *ddoc) default: continue; } - if(x.name() == "DataFile") + if(x.name() == QStringLiteral("DataFile")) { File file; file.name = x.attributes().value(QStringLiteral("Filename")).toString().normalized(QString::NormalizationForm_C); @@ -755,7 +764,7 @@ void CryptoDoc::Private::readDDoc(QIODevice *ddoc) file.size = FileDialog::fileSize(quint64(file.data.size())); files << file; } - else if(x.name() == "Signature") + else if(x.name() == QStringLiteral("Signature")) hasSignature = true; } qCDebug(CRYPTO) << "Container contains signature" << hasSignature; @@ -934,7 +943,25 @@ QString CDocumentModel::save(int row, const QString &path) const void CKey::setCert( const QSslCertificate &c ) { cert = c; - recipient = SslCertificate(c).friendlyName(); + recipient = [](const SslCertificate &c) { + QString cn = c.subjectInfo(QSslCertificate::CommonName); + QString o = c.subjectInfo(QSslCertificate::Organization); + + QRegularExpression rx("ESTEID \\((.*)\\)"); + QRegularExpressionMatch match = rx.match(o); + if(match.hasMatch()) + return QStringLiteral("%1,%2").arg(cn, match.captured(1)); + if(o == QStringLiteral("ESTEID")) + return QStringLiteral("%1,%2").arg(cn, CryptoDoc::tr("ID-CARD")); + int certType = c.type(); + if(certType & SslCertificate::EResidentSubType) + return QStringLiteral("%1,%2").arg(cn, CryptoDoc::tr("Digi-ID E-RESIDENT")); + if(certType & SslCertificate::DigiIDType) + return QStringLiteral("%1,%2").arg(cn, CryptoDoc::tr("Digi-ID")); + if(certType & SslCertificate::EstEidType) + return QStringLiteral("%1,%2").arg(cn, CryptoDoc::tr("ID-CARD")); + return cn; + }(c); } diff --git a/client/DigiDoc.h b/client/DigiDoc.h index 28d4fef10..b2f73fccc 100644 --- a/client/DigiDoc.h +++ b/client/DigiDoc.h @@ -29,7 +29,6 @@ class DigiDoc; class QDateTime; class QSslCertificate; -class QStringList; class DigiDocSignature { diff --git a/client/IKValidator.cpp b/client/IKValidator.cpp new file mode 100644 index 000000000..facef3c07 --- /dev/null +++ b/client/IKValidator.cpp @@ -0,0 +1,118 @@ +/* + * QEstEidCommon + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#include "IKValidator.h" + +#include +#include + +IKValidator::IKValidator(QObject *parent) + : QValidator(parent) +{} + +QDate IKValidator::birthDate(const QString &ik) +{ + if(ik.size() != 11) return {}; + + quint16 year = 0; + switch(ik.left(1).toUInt()) + { + case 1: case 2: year = 1800; break; + case 3: case 4: year = 1900; break; + case 5: case 6: year = 2000; break; + case 7: case 8: year = 2100; break; + default: return {}; + } + + QDate date( + ik.mid(1, 2).toUInt() + year, + ik.mid(3, 2).toUInt(), + ik.mid(5, 2).toUInt() ); + return date.isValid() ? date : QDate(); +} + +bool IKValidator::isValid(const QString &ik) +{ + if(ik.size() != 11) + return false; + + // Mobile-ID test IK-s + static const QStringList list { + QStringLiteral("14212128020"), + QStringLiteral("14212128021"), + QStringLiteral("14212128022"), + QStringLiteral("14212128023"), + QStringLiteral("14212128024"), + QStringLiteral("14212128025"), + QStringLiteral("14212128026"), + QStringLiteral("14212128027"), + QStringLiteral("38002240211"), + QStringLiteral("14212128029"), + }; + if(list.contains(ik)) + return true; + + // Validate date + if(birthDate(ik).isNull()) + return false; + + // Validate checksum + int sum1 = 0, sum2 = 0; + for(int i = 0, pos1 = 1, pos2 = 3; i < 10; ++i) + { + sum1 += ik.mid(i, 1).toUInt() * pos1; + sum2 += ik.mid(i, 1).toUInt() * pos2; + pos1 = pos1 == 9 ? 1 : pos1 + 1; + pos2 = pos2 == 9 ? 1 : pos2 + 1; + } + + int result; + if((result = sum1 % 11) >= 10 && + (result = sum2 % 11) >= 10) + result = 0; + + return ik.right( 1 ).toInt() == result; +} + +QValidator::State IKValidator::validate(QString &input, int &/*pos*/) const +{ + input = input.trimmed(); + if(input.size() > 11 || !QRegularExpression(QStringLiteral("\\d{0,11}")).match(input).hasMatch()) + return Invalid; + if(input.size() == 11) + return isValid(input) ? Acceptable : Invalid; + return Intermediate; +} + + + +NumberValidator::NumberValidator(QObject *parent) + : QValidator(parent) +{} + +NumberValidator::State NumberValidator::validate(QString &input, int & /*pos*/) const +{ + QString out; + QRegularExpression rx(QStringLiteral("(\\d+)")); + QRegularExpressionMatch match = rx.match(input); + for(int i = 0; i < match.lastCapturedIndex(); ++i) + out += match.captured(i); + input = out; + return Acceptable; +} diff --git a/client/IKValidator.h b/client/IKValidator.h new file mode 100644 index 000000000..f766a06ed --- /dev/null +++ b/client/IKValidator.h @@ -0,0 +1,44 @@ +/* + * QEstEidCommon + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#pragma once + +#include + +class IKValidator: public QValidator +{ + Q_OBJECT +public: + explicit IKValidator(QObject *parent); + + static QDate birthDate(const QString &ik); + static bool isValid(const QString &ik); + State validate(QString &input, int &pos) const; +}; + + + +class NumberValidator: public QValidator +{ + Q_OBJECT +public: + explicit NumberValidator(QObject *parent = 0); + + State validate(QString &input, int &pos) const; +}; diff --git a/client/LdapSearch.cpp b/client/LdapSearch.cpp index bc0063879..79b41ddce 100644 --- a/client/LdapSearch.cpp +++ b/client/LdapSearch.cpp @@ -148,7 +148,7 @@ void LdapSearch::search(const QString &search, const QVariantMap &userData) char *attrs[] = { const_cast("userCertificate;binary"), nullptr }; ULONG msg_id = 0; - int err = ldap_search_ext( d->ldap, "c=EE", LDAP_SCOPE_SUBTREE, + int err = ldap_search_ext( d->ldap, const_cast("c=EE"), LDAP_SCOPE_SUBTREE, const_cast(search.toLocal8Bit().constData()), attrs, 0, nullptr, nullptr, LDAP_NO_LIMIT, LDAP_NO_LIMIT, &msg_id); if(err) return setLastError( tr("Failed to init ldap search"), err ); diff --git a/client/MacMenuBar.h b/client/MacMenuBar.h index 6223fe20e..ae9488804 100644 --- a/client/MacMenuBar.h +++ b/client/MacMenuBar.h @@ -20,8 +20,9 @@ #pragma once #include +#include -class MacMenuBar: public QMenuBar +class MacMenuBar final: public QMenuBar { Q_OBJECT public: @@ -45,7 +46,7 @@ private slots: void activateWindow(QAction *a); private: - bool eventFilter(QObject *o, QEvent *e); + bool eventFilter(QObject *o, QEvent *e) final; QString title(QObject *o) const; QString typeName(ActionType type) const; diff --git a/client/MainWindow.cpp b/client/MainWindow.cpp index fc473906b..74e029370 100644 --- a/client/MainWindow.cpp +++ b/client/MainWindow.cpp @@ -50,6 +50,7 @@ #include #include #include +#include #include #include #include diff --git a/client/QCNG.cpp b/client/QCNG.cpp index 7021a7acc..980f748e4 100644 --- a/client/QCNG.cpp +++ b/client/QCNG.cpp @@ -161,7 +161,7 @@ QList QCNG::tokens() const { QString provider = QString::fromWCharArray(providers[i].pszName); qWarning() << "Found provider" << provider; - if(provider == MS_SMART_CARD_KEY_STORAGE_PROVIDER) + if(provider == QString::fromWCharArray(MS_SMART_CARD_KEY_STORAGE_PROVIDER)) { for( const QString &reader: QPCSC::instance().readers() ) { @@ -201,7 +201,7 @@ QByteArray QCNG::sign( int method, const QByteArray &digest ) const DWORD size = 0; QByteArray res; NCRYPT_KEY_HANDLE k = d->key(); - QString algo(5, 0); + QString algo(5, '\0'); SECURITY_STATUS err = NCryptGetProperty(k, NCRYPT_ALGORITHM_GROUP_PROPERTY, PBYTE(algo.data()), DWORD((algo.size() + 1) * 2), &size, 0); algo.resize(size/2 - 1); bool isRSA = algo == QStringLiteral("RSA"); diff --git a/client/QCSP.cpp b/client/QCSP.cpp index f1aca8eee..a2b45e303 100644 --- a/client/QCSP.cpp +++ b/client/QCSP.cpp @@ -263,7 +263,7 @@ QByteArray QCSP::sign(int method, const QByteArray &digest) const case CERT_NCRYPT_KEY_SPEC: { DWORD size = 0; - QString algo(5, 0); + QString algo(5, '\0'); err = NCryptGetProperty(key, NCRYPT_ALGORITHM_GROUP_PROPERTY, PBYTE(algo.data()), DWORD((algo.size() + 1) * 2), &size, 0); algo.resize(size/2 - 1); bool isRSA = algo == QStringLiteral("RSA"); diff --git a/client/QCardLock.cpp b/client/QCardLock.cpp index 8b0cf1828..17775ae58 100644 --- a/client/QCardLock.cpp +++ b/client/QCardLock.cpp @@ -20,12 +20,6 @@ #include "QCardLock.h" #include "QCardLock_p.h" - -QCardLockPrivate::QCardLockPrivate() -: readLock(QMutex::Recursive) -, exclusiveLock(QMutex::NonRecursive) -{} - QCardLock::QCardLock() : d(new QCardLockPrivate) { diff --git a/client/QCardLock_p.h b/client/QCardLock_p.h index dc5caf38b..e5bef6343 100644 --- a/client/QCardLock_p.h +++ b/client/QCardLock_p.h @@ -24,8 +24,10 @@ class QCardLockPrivate { public: - explicit QCardLockPrivate(); - - QMutex readLock; +#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) + QRecursiveMutex readLock; +#else + QMutex readLock{QMutex::Recursive}; +#endif QMutex exclusiveLock; }; diff --git a/client/QSigner.cpp b/client/QSigner.cpp index ae4b74b1e..adc624c55 100644 --- a/client/QSigner.cpp +++ b/client/QSigner.cpp @@ -34,6 +34,7 @@ #include #include +#include #include #include @@ -155,13 +156,15 @@ bool QSigner::cardsOrder(const TokenData &s1, const TokenData &s2) default: return 0; } }; - QRegExp r("(\\w{1,2})(\\d{7})"); - if(r.indexIn(s1.card()) == -1) + QRegularExpression reg(QStringLiteral("(\\w{1,2})(\\d{7})")); + QRegularExpressionMatch r1 = reg.match(s1.card()); + QRegularExpressionMatch r2 = reg.match(s2.card()); + if(r1.hasMatch() || r2.hasMatch()) return false; - QStringList cap1 = r.capturedTexts(); - if(r.indexIn(s2.card()) == -1) + QStringList cap1 = r1.capturedTexts(); + QStringList cap2 = r1.capturedTexts(); + if(cap1.isEmpty() || cap2.isEmpty()) return false; - QStringList cap2 = r.capturedTexts(); // new cards to front if(cap1[1].size() != cap2[1].size()) return cap1[1].size() > cap2[1].size(); diff --git a/client/QSmartCard.cpp b/client/QSmartCard.cpp index 80999e0b3..28be742bd 100644 --- a/client/QSmartCard.cpp +++ b/client/QSmartCard.cpp @@ -19,12 +19,12 @@ #include "QSmartCard_p.h" #include "QCardLock.h" +#include "IKValidator.h" #include "dialogs/PinPopup.h" #include "dialogs/PinUnblock.h" #include "Utils.h" #include -#include #include #include @@ -33,6 +33,7 @@ #include #include #include +#include Q_LOGGING_CATEGORY(CLog, "qdigidoc4.QSmartCard") diff --git a/client/QSmartCard_p.h b/client/QSmartCard_p.h index 8d43fe9d0..43f5e702e 100644 --- a/client/QSmartCard_p.h +++ b/client/QSmartCard_p.h @@ -25,12 +25,13 @@ #include #include -#include #include #define APDU QByteArray::fromHex +class QTextCodec; + class Card { public: diff --git a/client/SslCertificate.cpp b/client/SslCertificate.cpp index 09111fcdc..f94296016 100644 --- a/client/SslCertificate.cpp +++ b/client/SslCertificate.cpp @@ -30,6 +30,7 @@ #include #include #include +#include #include #include #include @@ -59,7 +60,11 @@ static QByteArray i2dDer(Func func, Arg arg) return der; } -uint qHash( const SslCertificate &cert ) { return qHash( cert.digest() ); } +#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) +size_t qHash(const SslCertificate &cert) { return qHash(cert.digest()); } +#else +uint qHash(const SslCertificate &cert) { return qHash(cert.digest()); } +#endif SslCertificate::SslCertificate() = default; @@ -151,25 +156,6 @@ QHash SslCertificate::enhancedKeyUsage return list; } -QString SslCertificate::friendlyName() const -{ - QString cn = subjectInfo(QSslCertificate::CommonName); - QString o = subjectInfo(QSslCertificate::Organization); - QRegExp rx("ESTEID \\((.*)\\)"); - if(rx.indexIn(o) != -1) - return QStringLiteral("%1,%2").arg(cn, rx.cap(1)); - if(o == QStringLiteral("ESTEID")) - return QStringLiteral("%1,%2").arg(cn, tr("ID-CARD")); - int certType = type(); - if(certType & SslCertificate::EResidentSubType) - return QStringLiteral("%1,%2").arg(cn, tr("Digi-ID E-RESIDENT")); - if(certType & SslCertificate::DigiIDType) - return QStringLiteral("%1,%2").arg(cn, tr("Digi-ID")); - if(certType & SslCertificate::EstEidType) - return QStringLiteral("%1,%2").arg(cn, tr("ID-CARD")); - return cn; -} - bool SslCertificate::isCA() const { auto cons = SCOPE(BASIC_CONSTRAINTS, extension(NID_basic_constraints)); @@ -300,14 +286,15 @@ QByteArray SslCertificate::toHex( const QByteArray &in, QChar separator ) QString SslCertificate::toString( const QString &format ) const { - QRegExp r( "[a-zA-Z]+" ); + QRegularExpression r(QStringLiteral("[a-zA-Z]+")); QString ret = format; + QRegularExpressionMatch match; int pos = 0; - while( (pos = r.indexIn( ret, pos )) != -1 ) - { - QString si = r.cap(0) == QStringLiteral("serialNumber") ? personalCode() : subjectInfo(r.cap(0).toLatin1()); - ret.replace( pos, r.cap(0).size(), si ); - pos += si.size(); + while((match = r.match(ret, pos)).hasMatch()) { + QString cap = match.captured(); + QString si = cap == QStringLiteral("serialNumber") ? personalCode() : subjectInfo(cap.toLatin1()); + ret.replace(match.capturedStart(), cap.size(), si); + pos = match.capturedStart() + si.size(); } return ret; } diff --git a/client/SslCertificate.h b/client/SslCertificate.h index 004d918c3..e0d98d4e3 100644 --- a/client/SslCertificate.h +++ b/client/SslCertificate.h @@ -87,7 +87,6 @@ class SslCertificate: public QSslCertificate QMultiHash authorityInfoAccess() const; QByteArray authorityKeyIdentifier() const; QHash enhancedKeyUsage() const; - QString friendlyName() const; bool isCA() const; inline bool isValid() const { const QDateTime currentTime = QDateTime::currentDateTime(); @@ -111,7 +110,11 @@ class SslCertificate: public QSslCertificate Qt::HANDLE extension( int nid ) const; }; -uint qHash( const SslCertificate &cert ); +#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) +size_t qHash(const SslCertificate &cert); +#else +uint qHash(const SslCertificate &cert); +#endif class PKCS12Certificate { diff --git a/client/TSLDownload.cpp b/client/TSLDownload.cpp index 0093def91..a4a6c9d0f 100644 --- a/client/TSLDownload.cpp +++ b/client/TSLDownload.cpp @@ -29,20 +29,18 @@ int main(int argc, char *argv[]) { QCoreApplication a(argc, argv); - QStringList territories = a.arguments(); - territories.removeFirst(); - QString path = territories.first(); - territories.removeFirst(); - QString url = territories.first(); + QStringList territories = QCoreApplication::arguments(); territories.removeFirst(); + QString path = territories.takeFirst(); + QString url = territories.takeFirst(); QNetworkAccessManager m; - QObject::connect(&m, &QNetworkAccessManager::sslErrors, [](QNetworkReply *r, const QList &errors){ + QObject::connect(&m, &QNetworkAccessManager::sslErrors, &m, [](QNetworkReply *r, const QList &errors){ r->ignoreSslErrors(errors); }); QNetworkReply *r = m.get(QNetworkRequest(QUrl(url))); - QObject::connect(r, &QNetworkReply::finished, [&](){ + QObject::connect(r, &QNetworkReply::finished, r, [&] { QFile f(path + "/" + r->request().url().fileName()); if(f.open(QFile::ReadWrite)) f.write(r->readAll()); @@ -54,16 +52,18 @@ int main(int argc, char *argv[]) { if(!xml.isStartElement()) continue; - if(xml.name() == "TSLLocation") + if(xml.name() == QLatin1String("TSLLocation")) url = xml.readElementText(); - else if( xml.name() == "SchemeTerritory") + else if( xml.name() == QLatin1String("SchemeTerritory")) territory = xml.readElementText(); - else if(xml.name() == "MimeType" && xml.readElementText() == "application/vnd.etsi.tsl+xml" && territories.contains(territory)) + else if(xml.name() == QLatin1String("MimeType") && + xml.readElementText() == QLatin1String("application/vnd.etsi.tsl+xml") && + territories.contains(territory)) { QNetworkReply *rt = m.get(QNetworkRequest(QUrl(url))); QEventLoop e; QObject::connect(rt, &QNetworkReply::finished, [&](){ - QFile t(path + "/" + territory + ".xml"); + QFile t(QStringLiteral("%1/%2.xml").arg(path, territory)); if(t.open(QFile::WriteOnly)) t.write(rt->readAll()); e.quit(); @@ -77,16 +77,16 @@ int main(int argc, char *argv[]) QFile o(path + "/TSL.qrc"); o.open(QFile::WriteOnly); QXmlStreamWriter w(&o); - w.writeStartElement("RCC"); - w.writeStartElement("qresource"); - w.writeAttribute("prefix", "TSL"); - w.writeTextElement("file", r->request().url().fileName()); + w.writeStartElement(QStringLiteral("RCC")); + w.writeStartElement(QStringLiteral("qresource")); + w.writeAttribute(QStringLiteral("prefix"), QStringLiteral("TSL")); + w.writeTextElement(QStringLiteral("file"), r->request().url().fileName()); for(const QString &territory: territories) - w.writeTextElement("file", territory + ".xml"); + w.writeTextElement(QStringLiteral("file"), territory + ".xml"); w.writeEndElement(); w.writeEndElement(); - a.quit(); + QCoreApplication::quit(); }); - return a.exec(); + return QCoreApplication::exec(); } diff --git a/client/dialogs/AccessCert.cpp b/client/dialogs/AccessCert.cpp index f950e86bb..3a4456367 100644 --- a/client/dialogs/AccessCert.cpp +++ b/client/dialogs/AccessCert.cpp @@ -160,7 +160,7 @@ bool AccessCert::installCert( const QByteArray &data, const QString &password ) SslCertificate cert(PKCS12Certificate(data, password).certificate()); if(cert.isNull()) return false; - QString path = QStandardPaths::writableLocation(QStandardPaths::DataLocation); + QString path = QStandardPaths::writableLocation(QStandardPaths::AppDataLocation); if ( !QDir( path ).exists() ) QDir().mkpath( path ); @@ -168,8 +168,7 @@ bool AccessCert::installCert( const QByteArray &data, const QString &password ) if ( !f.open( QIODevice::WriteOnly|QIODevice::Truncate ) ) { showWarning( tr("Failed to save server access certificate file to %1!\n%2") - .arg( f.fileName() ) - .arg( f.errorString() ) ); + .arg(f.fileName(), f.errorString())); return false; } f.write( data ); diff --git a/client/dialogs/AddRecipients.cpp b/client/dialogs/AddRecipients.cpp index ea872bd2c..d1b836c8a 100644 --- a/client/dialogs/AddRecipients.cpp +++ b/client/dialogs/AddRecipients.cpp @@ -24,6 +24,7 @@ #include "Application.h" #include "common_enums.h" #include "FileDialog.h" +#include "IKValidator.h" #include "LdapSearch.h" #include "QSigner.h" #include "Styles.h" @@ -32,7 +33,6 @@ #include "effects/Overlay.h" #include -#include #include #include @@ -99,12 +99,12 @@ AddRecipients::AddRecipients(ItemList* itemList, QWidget *parent) return; QXmlStreamReader xml( &f ); - if( !xml.readNextStartElement() || xml.name() != "History" ) + if(!xml.readNextStartElement() || xml.name() != QStringLiteral("History")) return; while( xml.readNextStartElement() ) { - if( xml.name() == "item" ) + if(xml.name() == QStringLiteral("item")) { historyCertData.append({ xml.attributes().value( "CN" ).toString(), @@ -317,7 +317,7 @@ QString AddRecipients::path() const QFileInfo f( s.fileName() ); return f.absolutePath() + "/" + f.baseName() + "/certhistory.xml"; #else - return QStandardPaths::writableLocation(QStandardPaths::DataLocation) + "/certhistory.xml"; + return QStandardPaths::writableLocation(QStandardPaths::AppDataLocation) + "/certhistory.xml"; #endif } @@ -394,14 +394,15 @@ void AddRecipients::search(const QString &term, bool select, const QString &type QApplication::setOverrideCursor(Qt::WaitCursor); ui->confirm->setDefault(false); ui->confirm->setAutoDefault(false); - QRegExp isDigit( "\\d*" ); QVariantMap userData { {"type", type}, {"select", select} }; QString cleanTerm = term.simplified(); - if(isDigit.exactMatch(cleanTerm) && (cleanTerm.size() == 11 || cleanTerm.size() == 8)) + bool isDigit = false; + cleanTerm.toULong(&isDigit); + if(isDigit && (cleanTerm.size() == 11 || cleanTerm.size() == 8)) { if(cleanTerm.size() == 11) { diff --git a/client/dialogs/FileDialog.cpp b/client/dialogs/FileDialog.cpp index 8b1070121..61a8be9f3 100644 --- a/client/dialogs/FileDialog.cpp +++ b/client/dialogs/FileDialog.cpp @@ -23,6 +23,7 @@ #include "dialogs/WarningDialog.h" #include +#include #include #include #include @@ -338,11 +339,11 @@ QString FileDialog::safeName(const QString &file) "LPT1", "LPT2", "LPT3", "LPT4", "LPT5", "LPT6", "LPT7", "LPT8", "LPT9" }; if(disabled.contains(info.baseName(), Qt::CaseInsensitive)) filename = QStringLiteral("___.") + info.suffix(); - filename.replace(QRegExp(QStringLiteral("[\\\\/*:?\"<>|]")), QStringLiteral("_")); + filename.replace(QRegularExpression(QStringLiteral("[\\\\/*:?\"<>|]")), QStringLiteral("_")); #elif defined(Q_OS_MAC) - filename.replace(QRegExp(QStringLiteral("[\\\\/:]")), QStringLiteral("_")); + filename.replace(QRegularExpression(QStringLiteral("[\\\\/:]")), QStringLiteral("_")); #else - filename.replace(QRegExp(QStringLiteral("[\\\\/]")), QStringLiteral("_")); + filename.replace(QRegularExpression(QStringLiteral("[\\\\/]")), QStringLiteral("_")); #endif return filename; } diff --git a/client/dialogs/MobileDialog.cpp b/client/dialogs/MobileDialog.cpp index a36bc7571..2117f6c30 100644 --- a/client/dialogs/MobileDialog.cpp +++ b/client/dialogs/MobileDialog.cpp @@ -19,14 +19,13 @@ #include "MobileDialog.h" #include "ui_MobileDialog.h" +#include "IKValidator.h" #include "Styles.h" #include "dialogs/SettingsDialog.h" #include "effects/Overlay.h" #include -#include - #define COUNTRY_CODE_EST QStringLiteral("372") #define COUNTRY_CODE_LTU QStringLiteral("370") @@ -61,12 +60,12 @@ MobileDialog::MobileDialog(QWidget *parent) : // Mobile ui->idCode->setValidator( new IKValidator( ui->idCode ) ); ui->idCode->setText(QSettings().value(QStringLiteral("MobileCode")).toString()); - ui->idCode->setAttribute(Qt::WA_MacShowFocusRect, 0); + ui->idCode->setAttribute(Qt::WA_MacShowFocusRect, false); ui->phoneNo->setValidator( new NumberValidator( ui->phoneNo ) ); ui->phoneNo->setText(QSettings().value(QStringLiteral("MobileNumber"), COUNTRY_CODE_EST).toString()); - ui->phoneNo->setAttribute(Qt::WA_MacShowFocusRect, 0); + ui->phoneNo->setAttribute(Qt::WA_MacShowFocusRect, false); ui->cbRemember->setChecked(QSettings().value(QStringLiteral("MobileSettings"), true).toBool()); - ui->cbRemember->setAttribute(Qt::WA_MacShowFocusRect, 0); + ui->cbRemember->setAttribute(Qt::WA_MacShowFocusRect, false); connect(ui->idCode, &QLineEdit::textEdited, this, &MobileDialog::enableSign); connect(ui->phoneNo, &QLineEdit::textEdited, this, &MobileDialog::enableSign); connect(ui->cbRemember, &QCheckBox::clicked, this, [=](bool checked) { diff --git a/client/dialogs/MobileDialog.ui b/client/dialogs/MobileDialog.ui index 069144515..43bf598bb 100644 --- a/client/dialogs/MobileDialog.ui +++ b/client/dialogs/MobileDialog.ui @@ -143,18 +143,13 @@ background-color: #BEDBED; - + 0 34 - - QWidget { - background-color: #FFFFFF; -} - 37254321 @@ -181,18 +176,13 @@ padding-top: 8px; - + 0 34 - - QWidget { - background-color: #FFFFFF; -} - 47101010033 @@ -306,6 +296,11 @@ padding-top: 8px; QCheckBox
widgets/CheckBox.h
+ + LineEdit + QLineEdit +
widgets/LineEdit.h
+
diff --git a/client/dialogs/MobileProgress.cpp b/client/dialogs/MobileProgress.cpp index c49d1ff3a..89512085a 100644 --- a/client/dialogs/MobileProgress.cpp +++ b/client/dialogs/MobileProgress.cpp @@ -41,7 +41,7 @@ #include #include #include -#ifdef Q_OS_WIN +#ifdef QT_WIN_EXTRAS #include #include #endif @@ -74,7 +74,7 @@ class MobileProgress::Private final: public QDialog, public Ui::MobileProgress QString NAME = QSettings().value(QStringLiteral("MIDNAME"), QStringLiteral("RIA DigiDoc")).toString(); bool useCustomUUID = QSettings().value(QStringLiteral("MIDUUID-CUSTOM"), QSettings().contains(QStringLiteral("MIDUUID"))).toBool(); QString UUID = useCustomUUID ? QSettings().value(QStringLiteral("MIDUUID")).toString() : QString(); -#ifdef Q_OS_WIN +#ifdef QT_WIN_EXTRAS QWinTaskbarButton *taskbar = nullptr; #endif WaitDialogHider hider; @@ -117,7 +117,7 @@ background-color: #007aff; d->statusTimer->setFrameRange(d->signProgressBar->minimum(), d->signProgressBar->maximum()); QObject::connect(d->statusTimer, &QTimeLine::frameChanged, d->signProgressBar, &QProgressBar::setValue); QObject::connect(d->statusTimer, &QTimeLine::finished, d, &QDialog::reject); -#ifdef Q_OS_WIN +#ifdef QT_WIN_EXTRAS d->taskbar = new QWinTaskbarButton(d); d->taskbar->setWindow(parent->windowHandle()); d->taskbar->progress()->setRange(d->signProgressBar->minimum(), d->signProgressBar->maximum()); @@ -385,7 +385,7 @@ std::vector MobileProgress::sign(const std::string &method, const void MobileProgress::stop() { d->statusTimer->stop(); -#ifdef Q_OS_WIN +#ifdef QT_WIN_EXTRAS d->taskbar->progress()->stop(); d->taskbar->progress()->hide(); #endif diff --git a/client/dialogs/PinPopup.cpp b/client/dialogs/PinPopup.cpp index b03f04d5f..dab7e1dd3 100644 --- a/client/dialogs/PinPopup.cpp +++ b/client/dialogs/PinPopup.cpp @@ -24,11 +24,11 @@ #include #include -#include +#include #include #include #include -#include +#include #include @@ -37,8 +37,8 @@ PinPopup::PinPopup(PinFlags flags, const SslCertificate &c, TokenFlags count, QW { if(c.type() & SslCertificate::TempelType) { - regexp.setPattern(QStringLiteral(".{4,}")); - ui->pin->setValidator(new QRegExpValidator(regexp, ui->pin)); + regexp.setPattern(QStringLiteral("^.{4,}$")); + ui->pin->setValidator(new QRegularExpressionValidator(regexp, ui->pin)); ui->pin->setMaxLength(32767); } } @@ -133,10 +133,10 @@ PinPopup::PinPopup(PinFlags flags, const QString &title, TokenFlags count, QWidg else if( !(flags & PinpadNoProgressFlag) ) { ui->pin->setFocus(); - ui->pin->setValidator( new QRegExpValidator( regexp, ui->pin ) ); + ui->pin->setValidator(new QRegularExpressionValidator(regexp, ui->pin)); ui->pin->setMaxLength( 12 ); connect(ui->pin, &QLineEdit::textEdited, this, [&](const QString &text) { - ui->ok->setEnabled(regexp.exactMatch(text)); + ui->ok->setEnabled(regexp.match(text).hasMatch()); }); ui->label->setBuddy( ui->pin ); ui->ok->setDisabled(true); @@ -151,7 +151,7 @@ PinPopup::~PinPopup() void PinPopup::setPinLen(unsigned long minLen, unsigned long maxLen) { QString charPattern = regexp.pattern().startsWith('.') ? QStringLiteral(".") : QStringLiteral("\\d"); - regexp.setPattern(QStringLiteral("%1{%2,%3}").arg(charPattern).arg(minLen).arg(maxLen)); + regexp.setPattern(QStringLiteral("^%1{%2,%3}$").arg(charPattern).arg(minLen).arg(maxLen)); } QString PinPopup::text() const { return ui->pin->text(); } diff --git a/client/dialogs/PinPopup.h b/client/dialogs/PinPopup.h index feeb878b4..f0172fc79 100644 --- a/client/dialogs/PinPopup.h +++ b/client/dialogs/PinPopup.h @@ -23,7 +23,7 @@ #include "WaitDialog.h" -#include +#include namespace Ui { class PinPopup; @@ -68,7 +68,7 @@ class PinPopup final : public QDialog private: Ui::PinPopup *ui; - QRegExp regexp; + QRegularExpression regexp; WaitDialogHider hider; }; diff --git a/client/dialogs/PinUnblock.cpp b/client/dialogs/PinUnblock.cpp index 8c822e1b0..502827870 100644 --- a/client/dialogs/PinUnblock.cpp +++ b/client/dialogs/PinUnblock.cpp @@ -25,7 +25,7 @@ #include #include -#include +#include PinUnblock::PinUnblock(WorkMode mode, QWidget *parent, QSmartCardData::PinType type, short leftAttempts, @@ -73,24 +73,24 @@ void PinUnblock::init( WorkMode mode, QSmartCardData::PinType type, short leftAt if( mode == PinUnblock::ChangePinWithPuk ) { ui->labelNameId->setText( tr("%1 code change").arg( QSmartCardData::typeString( type ) ) ); - regexpFirstCode.setPattern(QStringLiteral("\\d{8,12}")); - regexpNewCode.setPattern((type == QSmartCardData::Pin1Type) ? QStringLiteral("\\d{4,12}") : QStringLiteral("\\d{5,12}")); + regexpFirstCode.setPattern(QStringLiteral("^\\d{8,12}$")); + regexpNewCode.setPattern((type == QSmartCardData::Pin1Type) ? QStringLiteral("^\\d{4,12}$") : QStringLiteral("^\\d{5,12}$")); ui->unblock->setText( tr("CHANGE") ); } if( mode == PinUnblock::UnBlockPinWithPuk ) { ui->labelNameId->setText( tr("%1 unblocking").arg( QSmartCardData::typeString( type ) ) ); - regexpFirstCode.setPattern(QStringLiteral("\\d{8,12}")); - regexpNewCode.setPattern((type == QSmartCardData::Pin1Type) ? QStringLiteral("\\d{4,12}") : QStringLiteral("\\d{5,12}")); + regexpFirstCode.setPattern(QStringLiteral("^\\d{8,12}$")); + regexpNewCode.setPattern((type == QSmartCardData::Pin1Type) ? QStringLiteral("^\\d{4,12}$") : QStringLiteral("^\\d{5,12}$")); } else if( mode == PinUnblock::PinChange ) { ui->labelNameId->setText( tr("%1 code change").arg( QSmartCardData::typeString( type ) ) ); ui->labelPuk->setText( tr( "VALID %1 CODE").arg( QSmartCardData::typeString( type ) ) ); - regexpFirstCode.setPattern((type == QSmartCardData::Pin1Type) ? QStringLiteral("\\d{4,12}") : - (type == QSmartCardData::Pin2Type) ? QStringLiteral("\\d{5,12}") : QStringLiteral("\\d{8,12}")); - regexpNewCode.setPattern((type == QSmartCardData::Pin1Type) ? QStringLiteral("\\d{4,12}") : - (type == QSmartCardData::Pin2Type) ? QStringLiteral("\\d{5,12}") : QStringLiteral("\\d{8,12}")); + regexpFirstCode.setPattern((type == QSmartCardData::Pin1Type) ? QStringLiteral("^\\d{4,12}$") : + (type == QSmartCardData::Pin2Type) ? QStringLiteral("^\\d{5,12}$") : QStringLiteral("^\\d{8,12}$")); + regexpNewCode.setPattern((type == QSmartCardData::Pin1Type) ? QStringLiteral("^\\d{4,12}$") : + (type == QSmartCardData::Pin2Type) ? QStringLiteral("^\\d{5,12}$") : QStringLiteral("^\\d{8,12}$")); ui->unblock->setText( tr("CHANGE") ); } setWindowTitle(ui->labelNameId->text()); @@ -101,9 +101,9 @@ void PinUnblock::init( WorkMode mode, QSmartCardData::PinType type, short leftAt ui->puk->setAccessibleName(ui->labelPuk->text().toLower()); ui->unblock->setAccessibleName(ui->unblock->text().toLower()); - ui->puk->setValidator( new QRegExpValidator( regexpFirstCode, ui->puk ) ); - ui->pin->setValidator( new QRegExpValidator( regexpFirstCode, ui->pin ) ); - ui->repeat->setValidator( new QRegExpValidator( regexpFirstCode, ui->repeat ) ); + ui->puk->setValidator(new QRegularExpressionValidator(regexpFirstCode, ui->puk)); + ui->pin->setValidator(new QRegularExpressionValidator(regexpFirstCode, ui->pin)); + ui->repeat->setValidator(new QRegularExpressionValidator(regexpFirstCode, ui->repeat)); QFont condensed14(Styles::font(Styles::Condensed, 14)); QFont headerFont(Styles::font(Styles::Regular, 18)); @@ -124,12 +124,12 @@ void PinUnblock::init( WorkMode mode, QSmartCardData::PinType type, short leftAt initIntro(mode, type); connect(ui->puk, &QLineEdit::textChanged, this, [this](const QString &text) { - isFirstCodeOk = regexpFirstCode.exactMatch(text); + isFirstCodeOk = regexpFirstCode.match(text).hasMatch(); setUnblockEnabled(); }); connect(ui->pin, &QLineEdit::textChanged, this, [this, type, mode](const QString &text) { ui->labelPinValidation->hide(); - isNewCodeOk = regexpNewCode.exactMatch(text) && validatePin(text, type, mode); + isNewCodeOk = regexpNewCode.match(text).hasMatch() && validatePin(text, type, mode); isRepeatCodeOk = !text.isEmpty() && ui->pin->text() == ui->repeat->text(); setUnblockEnabled(); }); diff --git a/client/dialogs/PinUnblock.h b/client/dialogs/PinUnblock.h index e0a0a179d..9f409e5a5 100644 --- a/client/dialogs/PinUnblock.h +++ b/client/dialogs/PinUnblock.h @@ -21,6 +21,7 @@ #include "QSmartCard.h" +#include #include #include @@ -56,8 +57,8 @@ class PinUnblock final : public QDialog Ui::PinUnblock *ui; QDate birthDate; QString personalCode; - QRegExp regexpFirstCode; - QRegExp regexpNewCode; + QRegularExpression regexpFirstCode; + QRegularExpression regexpNewCode; bool isFirstCodeOk = false; bool isNewCodeOk = false; bool isRepeatCodeOk = false; diff --git a/client/dialogs/SettingsDialog.cpp b/client/dialogs/SettingsDialog.cpp index 261507d43..3b3dd8cac 100644 --- a/client/dialogs/SettingsDialog.cpp +++ b/client/dialogs/SettingsDialog.cpp @@ -47,6 +47,7 @@ #include #include #include +#include #include #include #include diff --git a/client/dialogs/SettingsDialog.ui b/client/dialogs/SettingsDialog.ui index 478ccef59..fbbe4287f 100644 --- a/client/dialogs/SettingsDialog.ui +++ b/client/dialogs/SettingsDialog.ui @@ -730,7 +730,7 @@ QPushButton {
- + false @@ -815,7 +815,7 @@ QPushButton { - + false @@ -1370,17 +1370,22 @@ QPushButton:disabled { + + CheckBox + QCheckBox +
widgets/CheckBox.h
+
+ + LineEdit + QLineEdit +
widgets/LineEdit.h
+
QSvgWidget QWidget
QSvgWidget
1
- - CheckBox - QCheckBox -
widgets/CheckBox.h
-
RadioButton QRadioButton diff --git a/client/dialogs/SmartIDDialog.cpp b/client/dialogs/SmartIDDialog.cpp index b5df39078..623ab6e3b 100644 --- a/client/dialogs/SmartIDDialog.cpp +++ b/client/dialogs/SmartIDDialog.cpp @@ -20,14 +20,13 @@ #include "SmartIDDialog.h" #include "ui_SmartIDDialog.h" +#include "IKValidator.h" #include "Styles.h" #include "dialogs/SettingsDialog.h" #include "effects/Overlay.h" #include -#include - SmartIDDialog::SmartIDDialog(QWidget *parent) : QDialog(parent) , ui(new Ui::SmartIDDialog) @@ -48,10 +47,10 @@ SmartIDDialog::SmartIDDialog(QWidget *parent) ui->labelCode->setFont(regularFont); ui->labelCountry->setFont(regularFont); ui->idCode->setFont(regularFont); - ui->idCode->setAttribute(Qt::WA_MacShowFocusRect, 0); + ui->idCode->setAttribute(Qt::WA_MacShowFocusRect, false); ui->idCountry->setFont(regularFont); ui->cbRemember->setFont(regularFont); - ui->cbRemember->setAttribute(Qt::WA_MacShowFocusRect, 0); + ui->cbRemember->setAttribute(Qt::WA_MacShowFocusRect, false); ui->sign->setFont(condensed); ui->cancel->setFont(condensed); diff --git a/client/dialogs/SmartIDDialog.ui b/client/dialogs/SmartIDDialog.ui index a9889864a..74b69b630 100644 --- a/client/dialogs/SmartIDDialog.ui +++ b/client/dialogs/SmartIDDialog.ui @@ -201,18 +201,13 @@ padding-top: 8px;
- + 0 34 - - QWidget { - background-color: #FFFFFF -} - 47101010033 @@ -365,6 +360,11 @@ QPushButton:disabled { QComboBox
widgets/ComboBox.h
+ + LineEdit + QLineEdit +
widgets/LineEdit.h
+
diff --git a/client/dialogs/SmartIDProgress.cpp b/client/dialogs/SmartIDProgress.cpp index 8d6f13813..7b5753218 100644 --- a/client/dialogs/SmartIDProgress.cpp +++ b/client/dialogs/SmartIDProgress.cpp @@ -42,7 +42,7 @@ #include #include #include -#ifdef Q_OS_WIN +#ifdef QT_WIN_EXTRAS #include #include #endif @@ -75,7 +75,7 @@ class SmartIDProgress::Private final: public QDialog, public Ui::MobileProgress QString NAME = QSettings().value(QStringLiteral("SIDNAME"), QStringLiteral("RIA DigiDoc")).toString(); bool useCustomUUID = QSettings().value(QStringLiteral("SIDUUID-CUSTOM"), QSettings().contains(QStringLiteral("SIDUUID"))).toBool(); QString UUID = useCustomUUID ? QSettings().value(QStringLiteral("SIDUUID")).toString() : QString(); -#ifdef Q_OS_WIN +#ifdef QT_WIN_EXTRAS QWinTaskbarButton *taskbar = nullptr; #endif WaitDialogHider hider; @@ -120,7 +120,7 @@ background-color: #007aff; d->statusTimer->setEasingCurve(QEasingCurve::Linear); d->statusTimer->setFrameRange(d->signProgressBar->minimum(), d->signProgressBar->maximum()); QObject::connect(d->statusTimer, &QTimeLine::frameChanged, d->signProgressBar, &QProgressBar::setValue); -#ifdef Q_OS_WIN +#ifdef QT_WIN_EXTRAS d->taskbar = new QWinTaskbarButton(d); d->taskbar->setWindow(parent->windowHandle()); d->taskbar->progress()->setRange(d->signProgressBar->minimum(), d->signProgressBar->maximum()); @@ -378,7 +378,7 @@ std::vector SmartIDProgress::sign(const std::string &method, cons void SmartIDProgress::stop() { d->statusTimer->stop(); -#ifdef Q_OS_WIN +#ifdef QT_WIN_EXTRAS d->taskbar->progress()->stop(); d->taskbar->progress()->hide(); #endif diff --git a/client/main.cpp b/client/main.cpp index 0fdbfe0a6..4c2e08461 100644 --- a/client/main.cpp +++ b/client/main.cpp @@ -22,6 +22,7 @@ #include "DiagnosticsTask.h" #include +#include #ifdef Q_OS_WIN32 #include @@ -30,6 +31,7 @@ int main( int argc, char *argv[] ) { +#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) QCoreApplication::setAttribute(Qt::AA_UseHighDpiPixmaps, true); #ifdef Q_OS_WIN32 SetProcessDPIAware(); @@ -42,22 +44,23 @@ int main( int argc, char *argv[] ) qDebug() << "Current DPI x: " << dpix << " y: " << dpiy << " setting scale:" << scale; #else QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling, true); +#endif #endif for(int i = 1; i < argc; ++i) { QString parameter(argv[i]); - if(parameter.startsWith("-diag")) + if(parameter.startsWith(QStringLiteral("-diag"))) { QCoreApplication qtApp( argc, argv ); qtApp.setApplicationName(QStringLiteral("qdigidoc4")); qtApp.setApplicationVersion(QStringLiteral("%1.%2.%3.%4") .arg(MAJOR_VER).arg(MINOR_VER).arg(RELEASE_VER).arg(BUILD_VER)); - qtApp.setOrganizationDomain("ria.ee"); - qtApp.setOrganizationName("RIA"); + qtApp.setOrganizationDomain(QStringLiteral("ria.ee")); + qtApp.setOrganizationName(QStringLiteral("RIA")); Application::initDiagnosticConf(); - DiagnosticsTask task(&qtApp, parameter.remove(QStringLiteral("-diag")).remove(QRegExp(QStringLiteral("^[:]*")))); + DiagnosticsTask task(&qtApp, parameter.remove(QStringLiteral("-diag")).remove(QRegularExpression(QStringLiteral("^[:]*")))); QObject::connect(&task, &DiagnosticsTask::finished, &qtApp, &QCoreApplication::quit); QObject::connect(&task, &DiagnosticsTask::failed, &qtApp, [] { QCoreApplication::exit(1); }); diff --git a/client/translations/en.ts b/client/translations/en.ts index b88e8ef96..63a1c9e07 100644 --- a/client/translations/en.ts +++ b/client/translations/en.ts @@ -648,6 +648,18 @@ No keys specified No recipients specified + + ID-CARD + ID-CARD + + + Digi-ID E-RESIDENT + Digi-ID E-RESIDENT + + + Digi-ID + Digi-ID + Diagnostics @@ -3138,10 +3150,6 @@ Additional licenses and components Decipher only Decipher only - - ID-CARD - ID-CARD - Unknown Unknown @@ -3154,14 +3162,6 @@ Additional licenses and components Ensures the identity of a remote computer Ensures the identity of a remote computer - - Digi-ID - Digi-ID - - - Digi-ID E-RESIDENT - Digi-ID E-RESIDENT - VerifyCert diff --git a/client/translations/et.ts b/client/translations/et.ts index 75e4d7d85..ed64bb1ad 100644 --- a/client/translations/et.ts +++ b/client/translations/et.ts @@ -648,6 +648,18 @@ No keys specified Ühtegi adressaati ei ole lisatud + + ID-CARD + ID-KAART + + + Digi-ID E-RESIDENT + Digi-ID E-RESIDENT + + + Digi-ID + Digi-ID + Diagnostics @@ -3138,10 +3150,6 @@ Täiendavad litsentsid ja komponendid Decipher only Ainult dekrüptimine - - ID-CARD - ID-KAART - Unknown Teadmata @@ -3154,14 +3162,6 @@ Täiendavad litsentsid ja komponendid Ensures the identity of a remote computer Tagab serverarvuti identiteedi - - Digi-ID - Digi-ID - - - Digi-ID E-RESIDENT - Digi-ID E-RESIDENT - VerifyCert diff --git a/client/translations/ru.ts b/client/translations/ru.ts index 3bc35edcd..6c9962da2 100644 --- a/client/translations/ru.ts +++ b/client/translations/ru.ts @@ -650,6 +650,18 @@ No keys specified Не выбрано ни одного получателя + + ID-CARD + ID-КАРТА + + + Digi-ID E-RESIDENT + Digi-ID E-RESIDENT + + + Digi-ID + Digi-ID + Diagnostics @@ -3141,10 +3153,6 @@ Additional licenses and components Decipher only Только разшифровка - - ID-CARD - ID-КАРТА - Unknown Неизвестно @@ -3157,14 +3165,6 @@ Additional licenses and components Ensures the identity of a remote computer Обеспечивается идентификация сервера - - Digi-ID - Digi-ID - - - Digi-ID E-RESIDENT - Digi-ID E-RESIDENT - VerifyCert diff --git a/client/widgets/ComboBox.cpp b/client/widgets/ComboBox.cpp index a5637ccf4..5204bedc7 100644 --- a/client/widgets/ComboBox.cpp +++ b/client/widgets/ComboBox.cpp @@ -41,7 +41,7 @@ void ComboBox::showPopup() popup->move(parentWidget()->mapToGlobal(geometry().topLeft())); QVBoxLayout *c = new QVBoxLayout(popup); - c->setMargin(0); + c->setContentsMargins(0, 0, 0, 0); c->setSpacing(0); QWidget *content = new QWidget(popup); @@ -49,7 +49,7 @@ void ComboBox::showPopup() c->addWidget(content); QVBoxLayout *l = new QVBoxLayout(content); - l->setMargin(0); + l->setContentsMargins(0, 0, 0, 0); l->setSpacing(0); auto addWidget = [=](const QString &text, int index) { QPushButton *b = new QPushButton(text, content); diff --git a/client/widgets/ItemList.ui b/client/widgets/ItemList.ui index 08f4e195c..bb9246ce6 100644 --- a/client/widgets/ItemList.ui +++ b/client/widgets/ItemList.ui @@ -281,7 +281,7 @@ border-width: 0px 0px 1px 0px; 0 - + 0 @@ -403,14 +403,20 @@ background-position: left bottom; } - LabelButton - QToolButton -
widgets/LabelButton.h
+ LineEdit + QLineEdit +
widgets/LineEdit.h
QSvgWidget QWidget
QSvgWidget
+ 1 +
+ + LabelButton + QToolButton +
widgets/LabelButton.h
diff --git a/client/widgets/LineEdit.cpp b/client/widgets/LineEdit.cpp new file mode 100644 index 000000000..a5b3de913 --- /dev/null +++ b/client/widgets/LineEdit.cpp @@ -0,0 +1,55 @@ +/* + * QDigiDoc4 + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#include "LineEdit.h" + +#include + +LineEdit::LineEdit(QWidget *parent) + : QLineEdit(parent) +{} + +void LineEdit::paintEvent(QPaintEvent *event) +{ +#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) + // Workaround QTBUG-92199 + if(text().isEmpty() && (!placeholderText().isEmpty() || !placeholder.isEmpty())) + { + if(!placeholderText().isEmpty()) + { + placeholder = placeholderText(); + setPlaceholderText(QString()); + } + QLineEdit::paintEvent(event); + + QPainter p(this); + QColor color = palette().color(QPalette::PlaceholderText); + color.setAlpha(63); + p.setPen(color); + QFontMetrics fm = fontMetrics(); + int minLB = qMax(0, -fm.minLeftBearing()); + QRect lineRect = this->rect(); + QRect ph = lineRect.adjusted(minLB + 3, 0, 0, 0); + QString elidedText = fm.elidedText(placeholder, Qt::ElideRight, ph.width()); + p.drawText(ph, Qt::AlignVCenter, elidedText); + return; + } +#endif + QLineEdit::paintEvent(event); +} diff --git a/client/widgets/LineEdit.h b/client/widgets/LineEdit.h new file mode 100644 index 000000000..8cf7d6970 --- /dev/null +++ b/client/widgets/LineEdit.h @@ -0,0 +1,34 @@ +/* + * QDigiDoc4 + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#pragma once + +#include + +class LineEdit: public QLineEdit +{ + Q_OBJECT +public: + explicit LineEdit(QWidget *parent = nullptr); + +private: + void paintEvent(QPaintEvent *event) override; + + QString placeholder; +}; diff --git a/client/widgets/MainAction.cpp b/client/widgets/MainAction.cpp index a46c193e3..56677d3a7 100644 --- a/client/widgets/MainAction.cpp +++ b/client/widgets/MainAction.cpp @@ -106,7 +106,6 @@ bool MainAction::eventFilter(QObject *watched, QEvent *event) QToolButton *button = qobject_cast(watched); QPainter painter(button); painter.setRenderHint(QPainter::Antialiasing); - painter.setRenderHint(QPainter::HighQualityAntialiasing); if(ui->otherCards->property("pressed").toBool()) painter.fillRect(button->rect(), QStringLiteral("#41B6E6")); else if(button->rect().contains(button->mapFromGlobal(QCursor::pos()))) diff --git a/client/widgets/PageIcon.cpp b/client/widgets/PageIcon.cpp index a76e8ee9a..aba93b6d9 100644 --- a/client/widgets/PageIcon.cpp +++ b/client/widgets/PageIcon.cpp @@ -23,6 +23,7 @@ #include "Styles.h" #include +#include using namespace ria::qdigidoc4; @@ -109,7 +110,11 @@ void PageIcon::activate( bool selected ) updateSelection(); } -void PageIcon::enterEvent( QEvent * /*ev*/ ) +#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) +void PageIcon::enterEvent(QEnterEvent * /*ev*/) +#else +void PageIcon::enterEvent(QEvent * /*ev*/) +#endif { if( !selected ) updateSelection(hover); diff --git a/client/widgets/PageIcon.h b/client/widgets/PageIcon.h index 3f5651e7a..7d60be2ce 100644 --- a/client/widgets/PageIcon.h +++ b/client/widgets/PageIcon.h @@ -22,14 +22,8 @@ #include "common_enums.h" #include -#include -#include -#include -#include -#include - -#include +class QSvgWidget; namespace Ui { class PageIcon; @@ -65,7 +59,11 @@ class PageIcon final : public QPushButton }; void changeEvent(QEvent *event) final; - void enterEvent(QEvent *event) final; +#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) + void enterEvent(QEnterEvent *ev) final; +#else + void enterEvent(QEvent *ev) final; +#endif void leaveEvent(QEvent *event) final; void updateIcon(); void updateSelection(); diff --git a/client/widgets/RadioButton.cpp b/client/widgets/RadioButton.cpp index c22911b42..3b3dcabdf 100644 --- a/client/widgets/RadioButton.cpp +++ b/client/widgets/RadioButton.cpp @@ -37,7 +37,6 @@ void RadioButton::paintEvent(QPaintEvent *event) rect.adjust(1, 1, -1, -1); QPainter painter(this); painter.setRenderHint(QPainter::Antialiasing); - painter.setRenderHint(QPainter::HighQualityAntialiasing); painter.fillRect(rect, Qt::white); painter.setPen(QStringLiteral("#AAADAD")); painter.drawEllipse(rect); diff --git a/client/widgets/SignatureItem.cpp b/client/widgets/SignatureItem.cpp index 01e1863e0..7427429e6 100644 --- a/client/widgets/SignatureItem.cpp +++ b/client/widgets/SignatureItem.cpp @@ -32,7 +32,7 @@ #include #include #include -#include +#include using namespace ria::qdigidoc4; diff --git a/client/widgets/StyledWidget.cpp b/client/widgets/StyledWidget.cpp index 70109c3c1..9a2ebea24 100644 --- a/client/widgets/StyledWidget.cpp +++ b/client/widgets/StyledWidget.cpp @@ -34,7 +34,7 @@ StyledWidget::~StyledWidget() = default; void StyledWidget::paintEvent(QPaintEvent */*ev*/) { QStyleOption opt; - opt.init(this); + opt.initFrom(this); QPainter p(this); style()->drawPrimitive(QStyle::PE_Widget, &opt, &p, this); } diff --git a/common b/common index 6be09d9da..7f10db50c 160000 --- a/common +++ b/common @@ -1 +1 @@ -Subproject commit 6be09d9dab2bd000011269920032521cf311349a +Subproject commit 7f10db50c9994a81f65817a895f9f2cafd7dac07 diff --git a/prepare_osx_build_environment.sh b/prepare_osx_build_environment.sh index 49db32faa..6f4bfa0d0 100755 --- a/prepare_osx_build_environment.sh +++ b/prepare_osx_build_environment.sh @@ -4,7 +4,7 @@ set -e ######### Versions of libraries/frameworks to be compiled -QT_VER="5.12.12" +QT_VER="6.3.0" OPENSSL_VER="1.1.1o" OPENLDAP_VER="2.6.2" REBUILD=false @@ -112,35 +112,24 @@ if [[ "$REBUILD" = true || ! -d ${QT_PATH} ]] ; then qt_ver_parts=( ${QT_VER//./ } ) QT_MINOR="${qt_ver_parts[0]}.${qt_ver_parts[1]}" echo -e "\n${ORANGE}##### Building Qt ${QT_VER} ${QT_PATH} #####${RESET}\n" - mkdir -p ${BUILD_PATH} && cd ${BUILD_PATH} - for ARCH in x86_64 arm64; do - for PACKAGE in qtbase-everywhere-src-${QT_VER} qtsvg-everywhere-src-${QT_VER} qttools-everywhere-src-${QT_VER}; do - if [ ! -f ${PACKAGE}.tar.xz ]; then - curl -O -L http://download.qt.io/official_releases/qt/${QT_MINOR}/${QT_VER}/submodules/${PACKAGE}.tar.xz - fi - rm -rf ${PACKAGE} - tar xf ${PACKAGE}.tar.xz - cd ${PACKAGE} - if [[ "${PACKAGE}" == *"qtbase"* ]] ; then - if [[ "${ARCH}" == "arm64" ]] ; then - CROSSCOMPILE="-device-option QMAKE_APPLE_DEVICE_ARCHS=${ARCH}" - fi - patch -Np1 -i ${SCRIPTPATH}/qt-macos12.patch - ./configure -prefix ${QT_PATH} -opensource -nomake tests -nomake examples -no-securetransport -openssl -openssl-linked -confirm-license OPENSSL_PREFIX=${OPENSSL_PATH} ${CROSSCOMPILE} - else - "${QT_PATH}"/bin/qmake - fi - make - make install - cd - - rm -rf ${PACKAGE} - done - mv ${QT_PATH} ${QT_PATH}.${ARCH} - done - cp -a ${QT_PATH}.x86_64 ${QT_PATH} - cd ${QT_PATH}.arm64 - for i in lib/Qt*.framework/Versions/Current/Qt* plugins/*/*.dylib; do - lipo -create ${QT_PATH}.x86_64/${i} ${i} -output ${QT_PATH}/${i} + mkdir -p ${BUILD_PATH} + cd ${BUILD_PATH} + for PACKAGE in qtbase-everywhere-src-${QT_VER} qtsvg-everywhere-src-${QT_VER} qttools-everywhere-src-${QT_VER} qt5compat-everywhere-src-${QT_VER}; do + if [ ! -f ${PACKAGE}.tar.xz ]; then + curl -O -L http://download.qt.io/official_releases/qt/${QT_MINOR}/${QT_VER}/submodules/${PACKAGE}.tar.xz + fi + rm -rf ${PACKAGE} + tar xf ${PACKAGE}.tar.xz + cd ${PACKAGE} + if [[ "${PACKAGE}" == *"qtbase"* ]] ; then + ./configure -prefix ${QT_PATH} -opensource -nomake tests -nomake examples -no-securetransport -openssl -openssl-linked -confirm-license -- -DOPENSSL_ROOT_DIR=${OPENSSL_PATH} -DCMAKE_OSX_ARCHITECTURES="x86_64;arm64" + else + ${QT_PATH}/bin/qt-configure-module . + fi + cmake --build . --parallel + cmake --build . --target install + cd - + rm -rf ${PACKAGE} done cd - else diff --git a/qdigidoc4.wxs b/qdigidoc4.wxs index b7469bda4..4f9c2696d 100644 --- a/qdigidoc4.wxs +++ b/qdigidoc4.wxs @@ -33,6 +33,12 @@ msiexec /a libdigidocpp-3.13.8.1378.msi /qn TARGETDIR=C:\target + + + + + + @@ -42,7 +48,6 @@ msiexec /a libdigidocpp-3.13.8.1378.msi /qn TARGETDIR=C:\target - @@ -125,64 +130,74 @@ msiexec /a libdigidocpp-3.13.8.1378.msi /qn TARGETDIR=C:\target - - - - - - + + + + + + - - - - + + + + + + - - - - - - - - - - - + + + + + + + + + + + + + + + + - - - - - + - + - - - + + + + - - - + + + + + + + + + + - + - - - + + + @@ -195,12 +210,15 @@ msiexec /a libdigidocpp-3.13.8.1378.msi /qn TARGETDIR=C:\target - + + + +