diff --git a/.github/actions/create-package/action.yml b/.github/actions/create-package/action.yml index aa3420ddbb..989fb4a96b 100644 --- a/.github/actions/create-package/action.yml +++ b/.github/actions/create-package/action.yml @@ -3,6 +3,9 @@ inputs: arch: description: Architecture required: true + qt: + description: Qt Version + required: true outputs: output-basename: description: Output basename @@ -17,4 +20,5 @@ runs: env: RUNNER_OS: ${{runner.os}} INPUT_ARCH: ${{inputs.arch}} + INPUT_QT: ${{inputs.qt}} IS_RELEASE: ${{ github.ref == 'refs/heads/release' }} diff --git a/.github/actions/create-package/create-package.sh b/.github/actions/create-package/create-package.sh index edd252288d..7c6405f2c9 100755 --- a/.github/actions/create-package/create-package.sh +++ b/.github/actions/create-package/create-package.sh @@ -39,12 +39,13 @@ platforms/libqwayland-xcomposite-egl.so,platforms/libqwayland-xcomposite-glx.so, wayland-decoration-client,wayland-graphics-integration-client,wayland-shell-integration \ ${update_info} \ -appimage - local output_name="pencil2d-linux-$1-$(date +%F)" + local qtsuffix="-qt${INPUT_QT}" + local output_name="pencil2d${qtsuffix/-qt5/}-linux-$1-$(date +%F)" mv Pencil2D*.AppImage "$output_name.AppImage" mv Pencil2D*.AppImage.zsync "$output_name.AppImage.zsync" \ && sed -i '1,/^$/s/^\(Filename\|URL\): .*$/\1: '"$output_name.AppImage/" "$output_name.AppImage.zsync" \ || true - echo "::set-output name=output-basename::$output_name" + echo "output-basename=$output_name" >> "${GITHUB_OUTPUT}" echo "::endgroup::" } @@ -67,8 +68,9 @@ create_package_macos() { rm ffmpeg.7z ffmpeg.7z.sig echo "::endgroup::" - echo "Deploy Qt libraries" + echo "::group::Deploy Qt libraries" macdeployqt Pencil2D.app + echo "::endgroup::" echo "::group::Apply macdeployqt fix" curl -fsSLO https://github.com/aurelien-rainone/macdeployqtfix/archive/master.zip bsdtar xf master.zip @@ -80,8 +82,9 @@ create_package_macos() { rm -rf macdeployqtfix-master master.zip popd >/dev/null echo "Create ZIP" - bsdtar caf "pencil2d-mac-$1-$(date +%F).zip" Pencil2D - echo "::set-output name=output-basename::pencil2d-mac-$1-$(date +%F)" + local qtsuffix="-qt${INPUT_QT}" + bsdtar caf "pencil2d${qtsuffix/-qt5/}-mac-$1-$(date +%F).zip" Pencil2D + echo "output-basename=pencil2d${qtsuffix/-qt5/}-mac-$1-$(date +%F)" > "${GITHUB_OUTPUT}" } create_package_windows() { @@ -105,8 +108,9 @@ create_package_windows() { local _xbits="_x${platform#win}" cp "${IQTA_TOOLS}\\OpenSSL\\Win${_xbits/32/86}\\bin\\lib"{ssl,crypto}"-1_1${xbits/-x32/}.dll" Pencil2D/ echo "Create ZIP" - "${WINDIR}\\System32\\tar" caf "pencil2d-${platform}-$1-$(date +%F).zip" Pencil2D - echo "::set-output name=output-basename::pencil2d-${platform}-$1-$(date +%F)" + local qtsuffix="-qt${INPUT_QT}" + "${WINDIR}\\System32\\tar" caf "pencil2d${qtsuffix/-qt5/}-${platform}-$1-$(date +%F).zip" Pencil2D + echo "output-basename=pencil2d${qtsuffix/-qt5/}-${platform}-$1-$(date +%F)" > "${GITHUB_OUTPUT}" } "create_package_$(echo $RUNNER_OS | tr '[A-Z]' '[a-z]')" "${GITHUB_RUN_NUMBER}" diff --git a/.github/actions/install-dependencies/action.yml b/.github/actions/install-dependencies/action.yml index 91df7a19ef..a1d840d269 100644 --- a/.github/actions/install-dependencies/action.yml +++ b/.github/actions/install-dependencies/action.yml @@ -3,6 +3,9 @@ inputs: arch: description: Architecture required: true + qt: + description: Qt Version + required: true runs: using: composite steps: @@ -11,8 +14,11 @@ runs: env: RUNNER_OS: ${{runner.os}} INPUT_ARCH: ${{inputs.arch}} + INPUT_QT: ${{inputs.qt}} - if: runner.os == 'Windows' uses: jurplel/install-qt-action@v3 with: arch: ${{inputs.arch}} tools: tools_openssl_x${{endsWith(inputs.arch, '_64') && '64' || '86'}} + version: ${{matrix.qt == 6 && '6.4.2' || '5.15.2'}} + modules: ${{matrix.qt == 6 && 'qtmultimedia' || ''}} diff --git a/.github/actions/install-dependencies/install-dependencies.sh b/.github/actions/install-dependencies/install-dependencies.sh index b199caff3a..d078452584 100755 --- a/.github/actions/install-dependencies/install-dependencies.sh +++ b/.github/actions/install-dependencies/install-dependencies.sh @@ -8,9 +8,12 @@ setup_linux() { echo "::group::Add APT sources" for ppa in ppa:ubuntu-toolchain-r/test ppa:ubuntu-sdk-team/ppa \ - ppa:git-core/ppa ppa:beineri/opt-qt-5.15.2-xenial; do + ppa:git-core/ppa; do apt-add-repository -y "${ppa}" done + if [ "${INPUT_QT}" -eq 5 ]; then + apt-add-repository -y ppa:beineri/opt-qt-5.15.2-xenial + fi echo "::endgroup::" echo "::group::Fetch APT updates" @@ -18,12 +21,21 @@ setup_linux() { echo "::endgroup::" echo "::group::Install APT packages" - apt-get install -yq --no-install-suggests --no-install-recommends \ - build-essential qt515tools qt515base qt515multimedia qt515svg \ - qt515xmlpatterns qt515wayland libgl1-mesa-dev bsdtar ffmpeg \ - gstreamer1.0-plugins-base gstreamer1.0-plugins-good \ - gstreamer1.0-plugins-bad gstreamer1.0-plugins-ugly gstreamer1.0-alsa \ - gstreamer1.0-pulseaudio git curl libfuse2 + if [ "${INPUT_QT}" -eq 5 ]; then + apt-get install -yq --no-install-suggests --no-install-recommends \ + build-essential qt515tools qt515base qt515multimedia qt515svg \ + qt515wayland libgl1-mesa-dev bsdtar ffmpeg gstreamer1.0-plugins-base \ + gstreamer1.0-plugins-good gstreamer1.0-plugins-bad \ + gstreamer1.0-plugins-ugly gstreamer1.0-alsa gstreamer1.0-pulseaudio git \ + curl libfuse2 + else + apt-get install -yq --no-install-suggests --no-install-recommends \ + build-essential qt6-l10n-tools qt6-base-dev qt6-multimedia-dev \ + libqt6svg6-dev qt6-wayland-dev libgl1-mesa-dev libarchive-tools ffmpeg \ + gstreamer1.0-plugins-base gstreamer1.0-plugins-good \ + gstreamer1.0-plugins-bad gstreamer1.0-plugins-ugly gstreamer1.0-alsa \ + gstreamer1.0-pulseaudio git curl libfuse2 + fi echo "::endgroup::" } @@ -32,8 +44,8 @@ setup_macos() { brew update echo "::endgroup::" echo "::group::Install Homebrew packages" - brew install libarchive qt@5 - brew link qt@5 --force + brew install libarchive qt@${INPUT_QT} + brew link qt@${INPUT_QT} --force echo "/usr/local/opt/libarchive/bin" >> "${GITHUB_PATH}" echo "::endgroup::" } diff --git a/.github/actions/setup-environment/setup-environment.sh b/.github/actions/setup-environment/setup-environment.sh index fcb4db2d84..37236bb955 100755 --- a/.github/actions/setup-environment/setup-environment.sh +++ b/.github/actions/setup-environment/setup-environment.sh @@ -5,7 +5,9 @@ setup_linux() { # Our container image uses the non-Unicode C locale by default echo "LANG=C.UTF-8" >> "${GITHUB_ENV}" # Set up Qt environment variables and export them to the GitHub Actions workflow - (printenv; (. /opt/qt515/bin/qt515-env.sh; printenv)) | sort -st= -k1,1 | uniq -u >> "${GITHUB_ENV}" + if [ -f /opt/qt515/bin/qt515-env.sh ]; then + (printenv; (. /opt/qt515/bin/qt515-env.sh; printenv)) | sort -st= -k1,1 | uniq -u >> "${GITHUB_ENV}" + fi } setup_macos() { diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index fadad09ab5..70196cd4fa 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -24,23 +24,43 @@ jobs: fail-fast: false matrix: include: - - name: Linux x86_64 + - name: Qt 5 / Linux x86_64 os: ubuntu-latest # XXX: --privileged is sort of a brute-force solution to get FUSE # working inside Docker, however so far I haven’t been able to # figure out precisely *which* privileges are needed. container: { image: "ubuntu:16.04", options: --privileged } - - name: macOS x86_64 + qt: 5 + - name: Qt 5 / macOS x86_64 os: macos-latest container: - - name: Windows x86 + qt: 5 + - name: Qt 5 / Windows x86 os: windows-2019 arch: win32_msvc2019 container: - - name: Windows x86_64 + qt: 5 + - name: Qt 5 / Windows x86_64 os: windows-2019 arch: win64_msvc2019_64 container: + qt: 5 + - name: Qt 6 / Linux x86_64 + os: ubuntu-latest + # XXX: --privileged is sort of a brute-force solution to get FUSE + # working inside Docker, however so far I haven’t been able to + # figure out precisely *which* privileges are needed. + container: { image: "ubuntu:22.04", options: --privileged } + qt: 6 + - name: Qt 6 / macOS x86_64 + os: macos-latest + container: + qt: 6 + - name: Qt 6 / Windows x86_64 + os: windows-2019 + arch: win64_msvc2019_64 + container: + qt: 6 name: ${{matrix.name}} runs-on: ${{matrix.os}} @@ -63,6 +83,7 @@ jobs: uses: ./.github/actions/install-dependencies with: arch: ${{matrix.arch}} + qt: ${{matrix.qt}} - name: Set up environment uses: ./.github/actions/setup-environment @@ -70,8 +91,10 @@ jobs: arch: ${{matrix.arch}} - name: Configure build - run: mkdir build; qmake -o build PREFIX=/usr CONFIG+=release CONFIG+=GIT + run: mkdir build; ${{runner.os == 'Linux' && matrix.qt == 6 && 'qmake6' || 'qmake'}} + -o build PREFIX=/usr CONFIG+=release CONFIG+=GIT CONFIG+=PENCIL2D_${{github.ref == 'refs/heads/release' && 'RELEASE' || 'NIGHTLY'}} + ${{matrix.qt == 6 && 'CONFIG+=c++17 QMAKE_CXX_FLAGS+=-std=c++17' || ''}} - name: Build Pencil2D working-directory: build @@ -83,11 +106,14 @@ jobs: - name: Create package id: package + if: runner.os != 'Linux' || matrix.qt == 5 uses: ./.github/actions/create-package with: arch: ${{matrix.arch}} + qt: ${{matrix.qt}} - name: Upload package + if: runner.os != 'Linux' || matrix.qt == 5 uses: actions/upload-artifact@v3 with: name: ${{steps.package.outputs.output-basename}} diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml index de5c077c1c..ae372cbed1 100644 --- a/.github/workflows/docs.yml +++ b/.github/workflows/docs.yml @@ -30,7 +30,7 @@ jobs: - name: Retrieve Qt tagfiles working-directory: util/docs run: | - for i in core gui network svg testlib widgets xml xmlpatterns; do + for i in core gui network svg testlib widgets xml; do curl -fsSLO "https://doc.qt.io/qt-5/qt${i}.tags" done diff --git a/Doxyfile b/Doxyfile index dc73fff5e3..a537ef8061 100644 --- a/Doxyfile +++ b/Doxyfile @@ -2373,7 +2373,6 @@ TAGFILES = util/docs/qtcore.tags=https://doc.qt.io/qt-5/ \ util/docs/qttestlib.tags=https://doc.qt.io/qt-5/ \ util/docs/qtwidgets.tags=https://doc.qt.io/qt-5/ \ util/docs/qtxml.tags=https://doc.qt.io/qt-5/ \ - util/docs/qtxmlpatterns.tags=https://doc.qt.io/qt-5/ \ /usr/share/qt5/doc/qtcore/qtcore.tags=/usr/share/qt5/doc/qtcore/ \ /usr/share/qt5/doc/qtgui/qtgui.tags=/usr/share/qt5/doc/qtgui/ \ /usr/share/qt5/doc/qtnetwork/qtnetwork.tags=/usr/share/qt5/doc/qtnetwork/ \ @@ -2381,7 +2380,6 @@ TAGFILES = util/docs/qtcore.tags=https://doc.qt.io/qt-5/ \ /usr/share/qt5/doc/qttestlib/qttestlib.tags=/usr/share/qt5/doc/qttestlib/ \ /usr/share/qt5/doc/qtwidgets/qtwidgets.tags=/usr/share/qt5/doc/qtwidgets/ \ /usr/share/qt5/doc/qtxml/qtxml.tags=/usr/share/qt5/doc/qtxml/ \ - /usr/share/qt5/doc/qtxmlpatterns/qtxmlpatterns.tags=/usr/share/qt5/doc/qtxmlpatterns/ \ /usr/share/doc/qt/qtcore/qtcore.tags=/usr/share/doc/qt/qtcore/ \ /usr/share/doc/qt/qtgui/qtgui.tags=/usr/share/doc/qt/qtgui/ \ /usr/share/doc/qt/qtnetwork/qtnetwork.tags=/usr/share/doc/qt/qtnetwork/ \ @@ -2389,7 +2387,6 @@ TAGFILES = util/docs/qtcore.tags=https://doc.qt.io/qt-5/ \ /usr/share/doc/qt/qttestlib/qttestlib.tags=/usr/share/doc/qt/qttestlib/ \ /usr/share/doc/qt/qtwidgets/qtwidgets.tags=/usr/share/doc/qt/qtwidgets/ \ /usr/share/doc/qt/qtxml/qtxml.tags=/usr/share/doc/qt/qtxml/ \ - /usr/share/doc/qt/qtxmlpatterns/qtxmlpatterns.tags=/usr/share/doc/qt/qtxmlpatterns/ # Currently Qt Multimedia isn't configured to generate a tagfile, see # https://github.com/qt/qtmultimedia/blob/5.9/src/multimedia/doc/qtmultimedia.qdocconf diff --git a/app/app.pro b/app/app.pro index e798529727..714312b77f 100644 --- a/app/app.pro +++ b/app/app.pro @@ -12,7 +12,7 @@ TEMPLATE = app TARGET = pencil2d QMAKE_APPLICATION_BUNDLE_NAME = Pencil2D -CONFIG += qt precompile_header lrelease embed_translations +CONFIG += precompile_header lrelease embed_translations DESTDIR = ../bin MOC_DIR = .moc diff --git a/app/src/basedockwidget.cpp b/app/src/basedockwidget.cpp index a99a30c8d8..d052dd1cc1 100644 --- a/app/src/basedockwidget.cpp +++ b/app/src/basedockwidget.cpp @@ -53,7 +53,9 @@ void BaseDockWidget::resizeEvent(QResizeEvent *event) #ifdef __APPLE__ // For some reason the behavior of minimumSize and the margin changes on mac when floating, so we need to do this #else - minHeight += layout()->margin()*2; + int top, bottom; + layout()->getContentsMargins(nullptr, &top, nullptr, &bottom); + minHeight += top + bottom; #endif setMinimumSize(QSize(layout()->minimumSize().width(), minHeight)); } diff --git a/app/src/checkupdatesdialog.cpp b/app/src/checkupdatesdialog.cpp index 0a2dc13567..8723062da2 100644 --- a/app/src/checkupdatesdialog.cpp +++ b/app/src/checkupdatesdialog.cpp @@ -25,6 +25,7 @@ GNU General Public License for more details. #include #include #include +#include #include #include @@ -204,15 +205,15 @@ QString CheckUpdatesDialog::getVersionNumberFromXml(QString xml) while (!xmlReader.atEnd() && !xmlReader.hasError()) { QXmlStreamReader::TokenType tokenType = xmlReader.readNext(); - if (tokenType == QXmlStreamReader::StartElement && xmlReader.name() == "entry") + if (tokenType == QXmlStreamReader::StartElement && xmlReader.name() == QLatin1String("entry")) { while (!xmlReader.atEnd() && !xmlReader.hasError()) { xmlReader.readNext(); - if (xmlReader.name() == "title") + if (xmlReader.name() == QLatin1String("title")) { QString titleTag = xmlReader.readElementText(); - return titleTag.remove(QRegExp("^v")); // remove the leading 'v' + return titleTag.remove(QRegularExpression("^v")); // remove the leading 'v' } } } diff --git a/app/src/colorinspector.cpp b/app/src/colorinspector.cpp index 3196090fae..6b8c72cdfe 100644 --- a/app/src/colorinspector.cpp +++ b/app/src/colorinspector.cpp @@ -67,11 +67,11 @@ void ColorInspector::initUI() ui->hsvAlphaSlider->init(ColorSlider::ColorSpecType::HSV, ColorSlider::ColorType::ALPHA, mCurrentColor, 0.0, 255.0); QPalette p1 = ui->colorWrapper->palette(); - p1.setBrush(QPalette::Background, QBrush(QImage(":/background/checkerboard.png"))); + p1.setBrush(QPalette::Window, QBrush(QImage(":/background/checkerboard.png"))); ui->colorWrapper->setPalette(p1); QPalette p2 = ui->color->palette(); - p2.setColor(QPalette::Background, mCurrentColor); + p2.setColor(QPalette::Window, mCurrentColor); ui->color->setPalette(p2); connect(ui->colorSpecTabWidget, &QTabWidget::currentChanged, this, &ColorInspector::onColorSpecChanged); @@ -180,7 +180,7 @@ void ColorInspector::updateControls() ui->hsvAlphaSpinBox->setValue(qRound(mCurrentColor.alpha() / 2.55)); QPalette p = ui->color->palette(); - p.setColor(QPalette::Background, mCurrentColor); + p.setColor(QPalette::Window, mCurrentColor); ui->color->setPalette(p); update(); diff --git a/app/src/commandlineexporter.cpp b/app/src/commandlineexporter.cpp index 2b258f4490..e4851a395a 100644 --- a/app/src/commandlineexporter.cpp +++ b/app/src/commandlineexporter.cpp @@ -29,6 +29,12 @@ GNU General Public License for more details. #include "commandlineexporter.h" +#if QT_VERSION >= QT_VERSION_CHECK(5, 14, 0) +const auto qEndl = Qt::endl; +#else +const auto qEndl = endl; +#endif + CommandLineExporter::CommandLineExporter(Editor *editor) : mEditor(editor), mOut(stdout, QIODevice::WriteOnly), @@ -50,16 +56,16 @@ bool CommandLineExporter::process(const QString &inputPath, if(inputPath.isEmpty()) { - mErr << tr("Error: No input file specified. An input project file argument is required when output path(s) are specified.") << endl; + mErr << tr("Error: No input file specified. An input project file argument is required when output path(s) are specified.") << qEndl; return false; } Status s = mEditor->openObject(inputPath, [](int){}, [](int){}); if (!s.ok()) { - mErr << endl << endl << s.title() << endl << endl; - mErr << s.description() << endl << endl; - mErr << s.details().str() << endl << endl; + mErr << qEndl << qEndl << s.title() << qEndl << qEndl; + mErr << s.description() << qEndl << qEndl; + mErr << s.details().str() << qEndl << qEndl; return false; } @@ -69,7 +75,7 @@ bool CommandLineExporter::process(const QString &inputPath, cameraLayer = dynamic_cast(layerManager->findLayerByName(camera, Layer::CAMERA)); if (cameraLayer == nullptr) { - mErr << tr("Warning: the specified camera layer %1 was not found, ignoring.").arg(camera) << endl; + mErr << tr("Warning: the specified camera layer %1 was not found, ignoring.").arg(camera) << qEndl; } } if (cameraLayer == nullptr) @@ -101,7 +107,7 @@ bool CommandLineExporter::process(const QString &inputPath, QString format = detectFormatByFileNameExtension(outputPath); if (format.isNull()) { - mErr << tr("Warning: Output format is not specified or unsupported. Using PNG.", "Command line warning") << endl; + mErr << tr("Warning: Output format is not specified or unsupported. Using PNG.", "Command line warning") << qEndl; format = "PNG"; } @@ -126,10 +132,10 @@ void CommandLineExporter::exportMovie(const QString &outputPath, { if (transparency) { - mErr << tr("Warning: Transparency is not currently supported in movie files", "Command line warning") << endl; + mErr << tr("Warning: Transparency is not currently supported in movie files", "Command line warning") << qEndl; } - mOut << tr("Exporting movie...", "Command line task progress") << endl; + mOut << tr("Exporting movie...", "Command line task progress") << qEndl; ExportMovieDesc desc; desc.strFileName = outputPath; @@ -141,7 +147,7 @@ void CommandLineExporter::exportMovie(const QString &outputPath, MovieExporter ex; ex.run(mEditor->object(), desc, [](float, float){}, [](float){}, [](const QString &){}); - mOut << tr("Done.", "Command line task done") << endl; + mOut << tr("Done.", "Command line task done") << qEndl; } void CommandLineExporter::exportImageSequence(const QString &outputPath, @@ -152,7 +158,7 @@ void CommandLineExporter::exportImageSequence(const QString &outputPath, int endFrame, bool transparency) { - mOut << tr("Exporting image sequence...", "Command line task progress") << endl; + mOut << tr("Exporting image sequence...", "Command line task progress") << qEndl; mEditor->object()->exportFrames(startFrame, endFrame, cameraLayer, @@ -165,5 +171,5 @@ void CommandLineExporter::exportImageSequence(const QString &outputPath, true, nullptr, 0); - mOut << tr("Done.", "Command line task done") << endl; + mOut << tr("Done.", "Command line task done") << qEndl; } diff --git a/app/src/commandlineparser.cpp b/app/src/commandlineparser.cpp index dc8e8e0dd0..3685da12c9 100644 --- a/app/src/commandlineparser.cpp +++ b/app/src/commandlineparser.cpp @@ -19,6 +19,12 @@ GNU General Public License for more details. #include +#if QT_VERSION >= QT_VERSION_CHECK(5, 14, 0) +const auto qEndl = Qt::endl; +#else +const auto qEndl = endl; +#endif + CommandLineParser::CommandLineParser() : mParser(), mInputPath(), mOutputPaths(), mCamera() { mParser.setApplicationDescription(tr("Pencil2D is an animation/drawing software for Mac OS X, Windows, and Linux. " @@ -96,7 +102,7 @@ void CommandLineParser::process(QStringList arguments) mWidth = mParser.value("width").toInt(&ok); if (!ok) { - err << tr("Warning: width value %1 is not an integer, ignoring.").arg(mParser.value("width")) << endl; + err << tr("Warning: width value %1 is not an integer, ignoring.").arg(mParser.value("width")) << qEndl; mWidth = -1; } } @@ -107,7 +113,7 @@ void CommandLineParser::process(QStringList arguments) mHeight = mParser.value("height").toInt(&ok); if (!ok) { - err << tr("Warning: height value %1 is not an integer, ignoring.").arg(mParser.value("height")) << endl; + err << tr("Warning: height value %1 is not an integer, ignoring.").arg(mParser.value("height")) << qEndl; mHeight = -1; } } @@ -118,12 +124,12 @@ void CommandLineParser::process(QStringList arguments) mStartFrame = mParser.value("start").toInt(&ok); if (!ok) { - err << tr("Warning: start value %1 is not an integer, ignoring.").arg(mParser.value("start")) << endl; + err << tr("Warning: start value %1 is not an integer, ignoring.").arg(mParser.value("start")) << qEndl; mStartFrame = 1; } if (mStartFrame < 1) { - err << tr("Warning: start value must be at least 1, ignoring.") << endl; + err << tr("Warning: start value must be at least 1, ignoring.") << qEndl; mStartFrame = 1; } } @@ -144,13 +150,13 @@ void CommandLineParser::process(QStringList arguments) mEndFrame = mParser.value("end").toInt(&ok); if (!ok) { - err << tr("Warning: end value %1 is not an integer, last or last-sound, ignoring.").arg(mParser.value("end")) << endl; + err << tr("Warning: end value %1 is not an integer, last or last-sound, ignoring.").arg(mParser.value("end")) << qEndl; mEndFrame = -1; } } if (mEndFrame > -1 && mEndFrame < mStartFrame) { - err << tr("Warning: end value %1 is smaller than start value %2, ignoring.").arg(mEndFrame).arg(mStartFrame) << endl; + err << tr("Warning: end value %1 is smaller than start value %2, ignoring.").arg(mEndFrame).arg(mStartFrame) << qEndl; mEndFrame = mStartFrame; } } diff --git a/app/src/generalpage.cpp b/app/src/generalpage.cpp index 07a2038011..ff0406835a 100644 --- a/app/src/generalpage.cpp +++ b/app/src/generalpage.cpp @@ -92,7 +92,7 @@ GeneralPage::GeneralPage() : ui(new Ui::GeneralPage) ui->backgroundButtons->setId(ui->dotsBackgroundButton, 4); ui->backgroundButtons->setId(ui->weaveBackgroundButton, 5); - auto buttonClicked = static_cast(&QButtonGroup::buttonClicked); + auto buttonClicked = static_cast(&QButtonGroup::buttonClicked); auto curIndexChanged = static_cast(&QComboBox::currentIndexChanged); auto spinValueChanged = static_cast(&QSpinBox::valueChanged); connect(ui->languageCombo, curIndexChanged, this, &GeneralPage::languageChanged); @@ -196,19 +196,15 @@ void GeneralPage::languageChanged(int i) tr("The language change will take effect after a restart of Pencil2D")); } -void GeneralPage::backgroundChanged(int value) +void GeneralPage::backgroundChanged(QAbstractButton* button) { QString brushName = "white"; - switch (value) - { - case 1: brushName = "checkerboard"; break; - case 2: brushName = "white"; break; - case 3: brushName = "grey"; break; - case 4: brushName = "dots"; break; - case 5: brushName = "weave"; break; - default: - break; - } + if (button == ui->checkerBackgroundButton) brushName = "checkerboard"; + else if (button == ui->whiteBackgroundButton) brushName = "white"; + else if (button == ui->greyBackgroundButton) brushName = "grey"; + else if (button == ui->dotsBackgroundButton) brushName = "dots"; + else if (button == ui->weaveBackgroundButton) brushName = "weave"; + else Q_UNREACHABLE(); mManager->set(SETTING::BACKGROUND_STYLE, brushName); } diff --git a/app/src/generalpage.h b/app/src/generalpage.h index cdfdac6341..239e6b8b9f 100644 --- a/app/src/generalpage.h +++ b/app/src/generalpage.h @@ -18,6 +18,7 @@ GNU General Public License for more details. #ifndef GENERALPAGE_H #define GENERALPAGE_H +class QAbstractButton; class PreferenceManager; namespace Ui { @@ -54,7 +55,7 @@ private slots: void highResCheckboxStateChanged(int b); void gridCheckBoxStateChanged(int b); void curveSmoothingChanged(int value); - void backgroundChanged(int value); + void backgroundChanged(QAbstractButton* button); void frameCacheNumberChanged(int value); void invertScrollDirectionBoxStateChanged(int b); diff --git a/app/src/importimageseqdialog.cpp b/app/src/importimageseqdialog.cpp index a4ac70378b..896067a889 100644 --- a/app/src/importimageseqdialog.cpp +++ b/app/src/importimageseqdialog.cpp @@ -364,7 +364,7 @@ Status ImportImageSeqDialog::validateFiles(const QStringList &filepaths) for (int i = 0; i < filepaths.count(); i++) { - QFileInfo file = filepaths.at(i); + QFileInfo file(filepaths.at(i)); if (!file.exists()) failedPathsString += filepaths.at(i) + "\n"; } diff --git a/app/src/mainwindow2.cpp b/app/src/mainwindow2.cpp index bbe92fea03..14fec8f622 100644 --- a/app/src/mainwindow2.cpp +++ b/app/src/mainwindow2.cpp @@ -20,6 +20,7 @@ GNU General Public License for more details. #include "ui_mainwindow2.h" // Qt headers +#include #include #include #include @@ -185,7 +186,9 @@ void MainWindow2::createDockWidgets() for (BaseDockWidget* pWidget : mDockWidgets) { pWidget->setAllowedAreas(Qt::AllDockWidgetAreas); - pWidget->setFeatures(QDockWidget::AllDockWidgetFeatures); + pWidget->setFeatures(QDockWidget::DockWidgetFeature::DockWidgetClosable | + QDockWidget::DockWidgetFeature::DockWidgetMovable | + QDockWidget::DockWidgetFeature::DockWidgetFloatable); pWidget->setFocusPolicy(Qt::NoFocus); pWidget->setEditor(mEditor); @@ -1003,7 +1006,11 @@ void MainWindow2::importGIF() void MainWindow2::lockWidgets(bool shouldLock) { - QDockWidget::DockWidgetFeatures feat = shouldLock ? QDockWidget::NoDockWidgetFeatures : QDockWidget::AllDockWidgetFeatures; + QDockWidget::DockWidgetFeatures feat = shouldLock + ? QDockWidget::NoDockWidgetFeatures + : (QDockWidget::DockWidgetFeature::DockWidgetClosable | + QDockWidget::DockWidgetFeature::DockWidgetMovable | + QDockWidget::DockWidgetFeature::DockWidgetFloatable); for (QDockWidget* d : mDockWidgets) { diff --git a/app/src/pencil2d.cpp b/app/src/pencil2d.cpp index 3c52edf809..d7c40e9dde 100644 --- a/app/src/pencil2d.cpp +++ b/app/src/pencil2d.cpp @@ -150,7 +150,11 @@ void Pencil2D::installTranslators() #endif std::unique_ptr qtTranslator(new QTranslator(this)); +#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) + if (qtTranslator->load(locale, "qt", "_", QLibraryInfo::path(QLibraryInfo::TranslationsPath))) +#else if (qtTranslator->load(locale, "qt", "_", QLibraryInfo::location(QLibraryInfo::TranslationsPath))) +#endif { installTranslator(qtTranslator.release()); } diff --git a/app/src/shortcutspage.cpp b/app/src/shortcutspage.cpp index 0eab0dc7b7..3cc3e47980 100644 --- a/app/src/shortcutspage.cpp +++ b/app/src/shortcutspage.cpp @@ -18,7 +18,6 @@ GNU General Public License for more details. #include "ui_shortcutspage.h" #include -#include #include #include #include diff --git a/app/src/spinslider.cpp b/app/src/spinslider.cpp index b7efb602c6..a9bf226277 100644 --- a/app/src/spinslider.cpp +++ b/app/src/spinslider.cpp @@ -51,7 +51,7 @@ void SpinSlider::init(QString text, GROWTH_TYPE type, VALUE_TYPE dataType, qreal mSlider->setMaximumWidth(500); QGridLayout* layout = new QGridLayout(); - layout->setMargin(2); + layout->setContentsMargins(2, 2, 2, 2); layout->setSpacing(2); layout->addWidget(mLabel, 0, 0, 1, 1); diff --git a/app/src/statusbar.cpp b/app/src/statusbar.cpp index 73ace9bd0d..a34e51d279 100644 --- a/app/src/statusbar.cpp +++ b/app/src/statusbar.cpp @@ -62,7 +62,11 @@ StatusBar::StatusBar(QWidget *parent) : QStatusBar(parent) mZoomBox->setMaxCount(mZoomBox->count() + 1); mZoomBox->setEditable(true); mZoomBox->lineEdit()->setAlignment(Qt::AlignRight); +#if QT_VERSION >= QT_VERSION_CHECK(5, 14, 0) + connect(mZoomBox, &QComboBox::textActivated, [=](const QString ¤tText) +#else connect(mZoomBox, static_cast(&QComboBox::activated), [=](const QString ¤tText) +#endif { if (mZoomBox->count() == mZoomBox->maxCount()) { diff --git a/app/src/timeline.cpp b/app/src/timeline.cpp index 77baecc4d5..af5bd22c18 100644 --- a/app/src/timeline.cpp +++ b/app/src/timeline.cpp @@ -92,7 +92,7 @@ void TimeLine::initUI() layerButtons->setFixedHeight(30); QHBoxLayout* leftToolBarLayout = new QHBoxLayout(); - leftToolBarLayout->setMargin(0); + leftToolBarLayout->setContentsMargins(0, 0, 0, 0); leftToolBarLayout->addWidget(layerButtons); leftToolBar->setLayout(leftToolBarLayout); @@ -112,7 +112,7 @@ void TimeLine::initUI() QGridLayout* leftLayout = new QGridLayout(); leftLayout->addWidget(leftToolBar, 0, 0); leftLayout->addWidget(mLayerList, 1, 0); - leftLayout->setMargin(0); + leftLayout->setContentsMargins(0, 0, 0, 0); leftLayout->setSpacing(0); leftWidget->setLayout(leftLayout); @@ -167,14 +167,14 @@ void TimeLine::initUI() rightToolBarLayout->addWidget(timelineButtons); rightToolBarLayout->setAlignment(Qt::AlignLeft); rightToolBarLayout->addWidget(mTimeControls); - rightToolBarLayout->setMargin(0); + rightToolBarLayout->setContentsMargins(0, 0, 0, 0); rightToolBarLayout->setSpacing(0); rightToolBar->setLayout(rightToolBarLayout); QGridLayout* rightLayout = new QGridLayout(); rightLayout->addWidget(rightToolBar, 0, 0); rightLayout->addWidget(mTracks, 1, 0); - rightLayout->setMargin(0); + rightLayout->setContentsMargins(0, 0, 0, 0); rightLayout->setSpacing(0); rightWidget->setLayout(rightLayout); @@ -189,7 +189,7 @@ void TimeLine::initUI() lay->addWidget(splitter, 0, 0); lay->addWidget(mVScrollbar, 0, 1); lay->addWidget(mHScrollbar, 1, 0); - lay->setMargin(0); + lay->setContentsMargins(0, 0, 0, 0); lay->setSpacing(0); timeLineContent->setLayout(lay); setWidget(timeLineContent); diff --git a/app/src/timelinecells.cpp b/app/src/timelinecells.cpp index a37a6400a4..a25805aab3 100644 --- a/app/src/timelinecells.cpp +++ b/app/src/timelinecells.cpp @@ -21,6 +21,7 @@ GNU General Public License for more details. #include #include #include +#include #include #include "camerapropertiesdialog.h" @@ -859,7 +860,7 @@ void TimeLineCells::mousePressEvent(QMouseEvent* event) } break; case TIMELINE_CELL_TYPE::Tracks: - if (event->button() == Qt::MidButton) + if (event->button() == Qt::MiddleButton) { mLastFrameNumber = getFrameNumber(event->pos().x()); } @@ -993,7 +994,7 @@ void TimeLineCells::mouseMoveEvent(QMouseEvent* event) } else if (mType == TIMELINE_CELL_TYPE::Tracks) { - if (primaryButton == Qt::MidButton) + if (primaryButton == Qt::MiddleButton) { mFrameOffset = qMin(qMax(0, mFrameLength - width() / getFrameSize()), qMax(0, mFrameOffset + mLastFrameNumber - mFramePosMoveX)); update(); @@ -1050,7 +1051,7 @@ void TimeLineCells::mouseReleaseEvent(QMouseEvent* event) if (frameNumber < 1) frameNumber = 1; int layerNumber = getLayerNumber(event->pos().y()); - if (mType == TIMELINE_CELL_TYPE::Tracks && mCurrentLayerNumber != -1 && primaryButton != Qt::MidButton) + if (mType == TIMELINE_CELL_TYPE::Tracks && mCurrentLayerNumber != -1 && primaryButton != Qt::MiddleButton) { // We should affect the current layer based on what's selected, not where the mouse currently is. Layer* currentLayer = mEditor->layers()->getLayer(mCurrentLayerNumber); @@ -1155,7 +1156,7 @@ void TimeLineCells::editLayerProperties(Layer *layer) const void TimeLineCells::editLayerProperties(LayerCamera* cameraLayer) const { - QRegExp regex("([\\xFFEF-\\xFFFF])+"); + QRegularExpression regex("([\\x{FFEF}-\\x{FFFF}])+"); CameraPropertiesDialog dialog(cameraLayer->name(), cameraLayer->getViewRect().width(), cameraLayer->getViewRect().height()); @@ -1178,7 +1179,7 @@ void TimeLineCells::editLayerProperties(LayerCamera* cameraLayer) const void TimeLineCells::editLayerName(Layer* layer) const { - QRegExp regex("([\\xFFEF-\\xFFFF])+"); + QRegularExpression regex("([\\x{FFEF}-\\x{FFFF}])+"); bool ok; QString name = QInputDialog::getText(nullptr, tr("Layer Properties"), diff --git a/core_lib/core_lib.pro b/core_lib/core_lib.pro index e928b977f8..2b25e8d863 100644 --- a/core_lib/core_lib.pro +++ b/core_lib/core_lib.pro @@ -6,10 +6,10 @@ ! include( ../util/common.pri ) { error( Could not find the common.pri file! ) } -QT += core widgets gui xml xmlpatterns multimedia svg +QT += core widgets gui xml multimedia svg TEMPLATE = lib -CONFIG += qt staticlib precompile_header +CONFIG += staticlib precompile_header RESOURCES += data/core_lib.qrc diff --git a/core_lib/src/external/linux/linux.cpp b/core_lib/src/external/linux/linux.cpp index 2b0f3e665c..16e86c17d9 100644 --- a/core_lib/src/external/linux/linux.cpp +++ b/core_lib/src/external/linux/linux.cpp @@ -49,6 +49,7 @@ namespace PlatformHandler } } +#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) // Temporary solution for high DPI displays // EnableHighDpiScaling is a just in case mechanism in the event that we // want to disable this without recompiling, see #922 @@ -60,5 +61,6 @@ namespace PlatformHandler // Only works on Windows & X11 QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling); } +#endif // QT_VERSION < QT_VERSION_CHECK(6, 0, 0) } } diff --git a/core_lib/src/external/win32/win32.cpp b/core_lib/src/external/win32/win32.cpp index 82222e592b..eef2c17377 100644 --- a/core_lib/src/external/win32/win32.cpp +++ b/core_lib/src/external/win32/win32.cpp @@ -29,6 +29,7 @@ namespace PlatformHandler bool isDarkMode() { return false; }; void initialise() { +#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) // Temporary solution for high DPI displays // EnableHighDpiScaling is a just in case mechanism in the event that we // want to disable this without recompiling, see #922 @@ -40,5 +41,6 @@ namespace PlatformHandler // Only works on Windows & X11 QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling); } +#endif // QT_VERSION < QT_VERSION_CHECK(6, 0, 0) }; } diff --git a/core_lib/src/graphics/vector/beziercurve.cpp b/core_lib/src/graphics/vector/beziercurve.cpp index 5410d5eef4..97c2a79d64 100644 --- a/core_lib/src/graphics/vector/beziercurve.cpp +++ b/core_lib/src/graphics/vector/beziercurve.cpp @@ -860,7 +860,11 @@ bool BezierCurve::findIntersection(BezierCurve curve1, int i1, BezierCurve curve QPointF intersectionPoint = QPointF(50.0, 50.0); // bogus point QPointF* cubicIntersection = &intersectionPoint; +#if QT_VERSION >= QT_VERSION_CHECK(5, 14, 0) + if ( R1.intersects(R2) || L2.intersects(L1, cubicIntersection) == QLineF::BoundedIntersection ) +#else if ( R1.intersects(R2) || L2.intersect(L1, cubicIntersection) == QLineF::BoundedIntersection ) +#endif { //if (L2.intersect(L1, intersection) == QLineF::BoundedIntersection) { //qDebug() << " FOUND rectangle intersection "; @@ -880,7 +884,11 @@ bool BezierCurve::findIntersection(BezierCurve curve1, int i1, BezierCurve curve Q2 = curve2.getPointOnCubic(i2, t); L1 = QLineF(P1, Q1); L2 = QLineF(P2, Q2); +#if QT_VERSION >= QT_VERSION_CHECK(5, 14, 0) + if (L2.intersects(L1, cubicIntersection) == QLineF::BoundedIntersection) +#else if (L2.intersect(L1, cubicIntersection) == QLineF::BoundedIntersection) +#endif { QPointF intersectionPoint = *cubicIntersection; if (intersectionPoint != curve1.getVertex(i1-1) && intersectionPoint != curve1.getVertex(i1)) diff --git a/core_lib/src/graphics/vector/vertexref.cpp b/core_lib/src/graphics/vector/vertexref.cpp index 307873f2f2..b31765d1f1 100644 --- a/core_lib/src/graphics/vector/vertexref.cpp +++ b/core_lib/src/graphics/vector/vertexref.cpp @@ -27,17 +27,17 @@ VertexRef::VertexRef(int curveN, int vertexN) vertexNumber = vertexN; } -VertexRef VertexRef::nextVertex() +VertexRef VertexRef::nextVertex() const { return VertexRef(curveNumber, vertexNumber+1); } -VertexRef VertexRef::prevVertex() +VertexRef VertexRef::prevVertex() const { return VertexRef(curveNumber, vertexNumber-1); } -bool VertexRef::operator==(VertexRef vertexRef1) +bool VertexRef::operator==(VertexRef vertexRef1) const { if ( (curveNumber == vertexRef1.curveNumber) && (vertexNumber == vertexRef1.vertexNumber)) { @@ -49,7 +49,7 @@ bool VertexRef::operator==(VertexRef vertexRef1) } } -bool VertexRef::operator!=(VertexRef vertexRef1) +bool VertexRef::operator!=(VertexRef vertexRef1) const { if ( (curveNumber != vertexRef1.curveNumber) || (vertexNumber != vertexRef1.vertexNumber)) { diff --git a/core_lib/src/graphics/vector/vertexref.h b/core_lib/src/graphics/vector/vertexref.h index 8e5c487602..3959fa2bde 100644 --- a/core_lib/src/graphics/vector/vertexref.h +++ b/core_lib/src/graphics/vector/vertexref.h @@ -23,10 +23,10 @@ class VertexRef public: VertexRef(); VertexRef(int curveN, int vertexN); - VertexRef nextVertex(); - VertexRef prevVertex(); - bool operator==(VertexRef vertexRef1); - bool operator!=(VertexRef vertexRef1); + VertexRef nextVertex() const; + VertexRef prevVertex() const; + bool operator==(VertexRef vertexRef1) const; + bool operator!=(VertexRef vertexRef1) const; int curveNumber = -1; int vertexNumber = -1; diff --git a/core_lib/src/interface/backgroundwidget.cpp b/core_lib/src/interface/backgroundwidget.cpp index bb17b39972..ebee13a2b6 100644 --- a/core_lib/src/interface/backgroundwidget.cpp +++ b/core_lib/src/interface/backgroundwidget.cpp @@ -69,7 +69,7 @@ void BackgroundWidget::settingUpdated(SETTING setting) void BackgroundWidget::paintEvent(QPaintEvent *) { QStyleOption opt; - opt.init(this); + opt.initFrom(this); QPainter painter(this); style()->drawPrimitive(QStyle::PE_Widget, &opt, &painter, this); diff --git a/core_lib/src/interface/editor.h b/core_lib/src/interface/editor.h index e2700bf4a1..0b5723d3db 100644 --- a/core_lib/src/interface/editor.h +++ b/core_lib/src/interface/editor.h @@ -24,6 +24,18 @@ GNU General Public License for more details. #include "pencilerror.h" #include "pencildef.h" +#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) +Q_MOC_INCLUDE("colormanager.h") +Q_MOC_INCLUDE("toolmanager.h") +Q_MOC_INCLUDE("layermanager.h") +Q_MOC_INCLUDE("playbackmanager.h") +Q_MOC_INCLUDE("viewmanager.h") +Q_MOC_INCLUDE("preferencemanager.h") +Q_MOC_INCLUDE("selectionmanager.h") +Q_MOC_INCLUDE("soundmanager.h") +Q_MOC_INCLUDE("overlaymanager.h") +Q_MOC_INCLUDE("clipboardmanager.h") +#endif class QClipboard; class QTemporaryDir; diff --git a/core_lib/src/interface/flowlayout.cpp b/core_lib/src/interface/flowlayout.cpp index de2c5f96eb..032f065c81 100644 --- a/core_lib/src/interface/flowlayout.cpp +++ b/core_lib/src/interface/flowlayout.cpp @@ -116,7 +116,7 @@ QLayoutItem *FlowLayout::takeAt(int index) Qt::Orientations FlowLayout::expandingDirections() const { - return 0; + return {}; } bool FlowLayout::hasHeightForWidth() const @@ -147,8 +147,9 @@ QSize FlowLayout::minimumSize() const QLayoutItem *item; foreach (item, itemList) size = size.expandedTo(item->minimumSize()); - - size += QSize(2*margin(), 2*margin()); + int left, top, right, bottom; + getContentsMargins(&left, &top, &right, &bottom); + size += QSize(left + right, top + bottom); return size; } diff --git a/core_lib/src/interface/scribblearea.cpp b/core_lib/src/interface/scribblearea.cpp index fc9bcee7a6..998c398978 100644 --- a/core_lib/src/interface/scribblearea.cpp +++ b/core_lib/src/interface/scribblearea.cpp @@ -531,7 +531,11 @@ void ScribbleArea::wheelEvent(QWheelEvent* event) static const bool isX11 = QGuiApplication::platformName() == "xcb"; const QPoint pixels = event->pixelDelta(); const QPoint angle = event->angleDelta(); +#if QT_VERSION >= QT_VERSION_CHECK(5, 14, 0) + const QPointF offset = mEditor->view()->mapScreenToCanvas(event->position()); +#else const QPointF offset = mEditor->view()->mapScreenToCanvas(event->posF()); +#endif const qreal currentScale = mEditor->view()->scaling(); // From the pixelDelta documentation: On X11 this value is driver-specific and unreliable, use angleDelta() instead @@ -559,7 +563,11 @@ void ScribbleArea::tabletEvent(QTabletEvent *e) { PointerEvent event(e); +#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) + if (event.pointerType() == QPointingDevice::PointerType::Eraser) +#else if (event.pointerType() == QTabletEvent::Eraser) +#endif { editor()->tools()->tabletSwitchToEraser(); } @@ -634,7 +642,7 @@ void ScribbleArea::tabletEvent(QTabletEvent *e) void ScribbleArea::pointerPressEvent(PointerEvent* event) { bool isCameraLayer = mEditor->layers()->currentLayer()->type() == Layer::CAMERA; - if ((currentTool()->type() != HAND || isCameraLayer) && (event->button() != Qt::RightButton) && (event->button() != Qt::MidButton || isCameraLayer)) + if ((currentTool()->type() != HAND || isCameraLayer) && (event->button() != Qt::RightButton) && (event->button() != Qt::MiddleButton || isCameraLayer)) { Layer* layer = mEditor->layers()->currentLayer(); if (!layer->visible()) @@ -647,7 +655,7 @@ void ScribbleArea::pointerPressEvent(PointerEvent* event) } } - if (event->buttons() & (Qt::MidButton | Qt::RightButton) && + if (event->buttons() & (Qt::MiddleButton | Qt::RightButton) && editor()->tools()->setTemporaryTool(HAND, event->buttons())) { currentTool()->pointerPressEvent(event); diff --git a/core_lib/src/movieexporter.cpp b/core_lib/src/movieexporter.cpp index 08d52898ce..a32726a409 100644 --- a/core_lib/src/movieexporter.cpp +++ b/core_lib/src/movieexporter.cpp @@ -27,6 +27,7 @@ GNU General Public License for more details. #include #include #include +#include #include "object.h" #include "layercamera.h" @@ -34,6 +35,12 @@ GNU General Public License for more details. #include "soundclip.h" #include "util.h" +#if QT_VERSION >= QT_VERSION_CHECK(5, 14, 0) +using Qt::SplitBehaviorFlags; +#else +using SplitBehaviorFlags = QString::SplitBehavior; +#endif + MovieExporter::MovieExporter() { } @@ -352,7 +359,7 @@ Status MovieExporter::generateMovie( // Run FFmpeg command - STATUS_CHECK(executeFFMpegPipe(ffmpegPath, args, progress, [&](QProcess& ffmpeg, int framesProcessed) + Status status = executeFFMpegPipe(ffmpegPath, args, progress, [&](QProcess& ffmpeg, int framesProcessed) { if(framesProcessed < 0) { @@ -377,10 +384,13 @@ Status MovieExporter::generateMovie( obj->paintImage(painter, currentFrame, false, true); painter.end(); - // Should use sizeInBytes instead of byteCount to support large images, - // but this is only supported in QT 5.10+ +#if QT_VERSION >= QT_VERSION_CHECK(5, 10, 0) + int bytesWritten = ffmpeg.write(reinterpret_cast(imageToExport.constBits()), imageToExport.sizeInBytes()); + Q_ASSERT(bytesWritten == imageToExport.sizeInBytes()); +#else int bytesWritten = ffmpeg.write(reinterpret_cast(imageToExport.constBits()), imageToExport.byteCount()); Q_ASSERT(bytesWritten == imageToExport.byteCount()); +#endif currentFrame++; failCounter = 0; @@ -388,7 +398,8 @@ Status MovieExporter::generateMovie( } return false; - })); + }); + STATUS_CHECK(status); return Status::OK; } @@ -468,7 +479,7 @@ Status MovieExporter::generateGif( // Run FFmpeg command - STATUS_CHECK(executeFFMpegPipe(ffmpegPath, args, progress, [&](QProcess& ffmpeg, int framesProcessed) + Status status = executeFFMpegPipe(ffmpegPath, args, progress, [&](QProcess& ffmpeg, int framesProcessed) { /* The GIF FFmpeg command requires the entires stream to be * written before FFmpeg can encode the GIF. This is because @@ -494,13 +505,19 @@ Status MovieExporter::generateGif( obj->paintImage(painter, currentFrame, false, true); +#if QT_VERSION >= QT_VERSION_CHECK(5, 10, 0) + bytesWritten = ffmpeg.write(reinterpret_cast(imageToExport.constBits()), imageToExport.sizeInBytes()); + Q_ASSERT(bytesWritten == imageToExport.sizeInBytes()); +#else bytesWritten = ffmpeg.write(reinterpret_cast(imageToExport.constBits()), imageToExport.byteCount()); Q_ASSERT(bytesWritten == imageToExport.byteCount()); +#endif currentFrame++; return true; - })); + }); + STATUS_CHECK(status); return Status::OK; } @@ -541,7 +558,7 @@ Status MovieExporter::executeFFmpeg(const QString& cmd, const QStringList& args, if(!ffmpeg.waitForReadyRead()) break; QString output(ffmpeg.readAll()); - QStringList sList = output.split(QRegExp("[\r\n]"), QString::SkipEmptyParts); + QStringList sList = output.split(QRegularExpression("[\r\n]"), SplitBehaviorFlags::SkipEmptyParts); for (const QString& s : sList) { qDebug() << "[ffmpeg]" << s; @@ -565,7 +582,7 @@ Status MovieExporter::executeFFmpeg(const QString& cmd, const QStringList& args, } QString output(ffmpeg.readAll()); - QStringList sList = output.split(QRegExp("[\r\n]"), QString::SkipEmptyParts); + QStringList sList = output.split(QRegularExpression("[\r\n]"), SplitBehaviorFlags::SkipEmptyParts); for (const QString& s : sList) { qDebug() << "[ffmpeg]" << s; @@ -671,7 +688,7 @@ Status MovieExporter::executeFFMpegPipe(const QString& cmd, const QStringList& a if(ffmpeg.waitForReadyRead(10)) { QString output(ffmpeg.readAll()); - QStringList sList = output.split(QRegExp("[\r\n]"), QString::SkipEmptyParts); + QStringList sList = output.split(QRegularExpression("[\r\n]"), SplitBehaviorFlags::SkipEmptyParts); for (const QString& s : sList) { qDebug() << "[ffmpeg]" << s; @@ -702,7 +719,7 @@ Status MovieExporter::executeFFMpegPipe(const QString& cmd, const QStringList& a } QString output(ffmpeg.readAll()); - QStringList sList = output.split(QRegExp("[\r\n]"), QString::SkipEmptyParts); + QStringList sList = output.split(QRegularExpression("[\r\n]"), SplitBehaviorFlags::SkipEmptyParts); for (const QString& s : sList) { qDebug() << "[ffmpeg]" << s; diff --git a/core_lib/src/movieimporter.cpp b/core_lib/src/movieimporter.cpp index e4cdd89ca7..d9389bf5ae 100644 --- a/core_lib/src/movieimporter.cpp +++ b/core_lib/src/movieimporter.cpp @@ -19,6 +19,7 @@ GNU General Public License for more details. #include #include #include +#include #include #include #include @@ -121,7 +122,11 @@ Status MovieImporter::estimateFrames(const QString &filePath, int fps, int *fram if (!ffmpeg.waitForReadyRead()) break; QString output(ffmpeg.readAll()); - QStringList sList = output.split(QRegExp("[\r\n]"), QString::SkipEmptyParts); +#if QT_VERSION >= QT_VERSION_CHECK(5, 14, 0) + QStringList sList = output.split(QRegularExpression("[\r\n]"), Qt::SkipEmptyParts); +#else + QStringList sList = output.split(QRegularExpression("[\r\n]"), QString::SkipEmptyParts); +#endif for (const QString& s : sList) { index = s.indexOf("Duration: "); diff --git a/core_lib/src/soundplayer.cpp b/core_lib/src/soundplayer.cpp index 278c4abcc6..6120b67b03 100644 --- a/core_lib/src/soundplayer.cpp +++ b/core_lib/src/soundplayer.cpp @@ -15,6 +15,7 @@ GNU General Public License for more details. */ #include "soundplayer.h" +#include #include #include #include "soundclip.h" @@ -44,7 +45,12 @@ void SoundPlayer::init(SoundClip* clip) mBuffer.setData(file.readAll()); mBuffer.open(QBuffer::ReadOnly); +#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) + mMediaPlayer->setAudioOutput(new QAudioOutput(this)); + mMediaPlayer->setSourceDevice(&mBuffer, QUrl::fromLocalFile(clip->fileName())); +#else mMediaPlayer->setMedia(QUrl::fromLocalFile(clip->fileName()), &mBuffer); +#endif makeConnections(); clip->attachPlayer(this); @@ -107,8 +113,12 @@ void SoundPlayer::setMediaPlayerPosition(qint64 pos) void SoundPlayer::makeConnections() { +#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) + connect(mMediaPlayer, &QMediaPlayer::errorOccurred, this, [](QMediaPlayer::Error err, const QString&) +#else auto errorSignal = static_cast(&QMediaPlayer::error); connect(mMediaPlayer, errorSignal, this, [](QMediaPlayer::Error err) +#endif { qDebug() << "MediaPlayer Error: " << err; }); diff --git a/core_lib/src/structure/filemanager.cpp b/core_lib/src/structure/filemanager.cpp index a24db42fdf..ae9ddd1127 100644 --- a/core_lib/src/structure/filemanager.cpp +++ b/core_lib/src/structure/filemanager.cpp @@ -51,7 +51,6 @@ Object* FileManager::load(const QString& sFileName) // Test file format: new zipped .pclx or old .pcl? bool isArchive = isArchiveFormat(sFileName); - QString isArchiveStr = "Is archive: " + QString(isArchive); if (!isArchive) { @@ -837,7 +836,7 @@ Status FileManager::recoverObject(Object* object) file.close(); QDomDocument xmlDoc; - mainXmlOK &= xmlDoc.setContent(&file); + mainXmlOK &= !!xmlDoc.setContent(&file); QDomDocumentType type = xmlDoc.doctype(); mainXmlOK &= (type.name() == "PencilDocument" || type.name() == "MyObject"); @@ -846,7 +845,7 @@ Status FileManager::recoverObject(Object* object) mainXmlOK &= (!root.isNull()); QDomElement objectTag = root.firstChildElement("object"); - mainXmlOK &= (objectTag.isNull() == false); + mainXmlOK &= (!objectTag.isNull()); if (mainXmlOK == false) { diff --git a/core_lib/src/structure/layercamera.cpp b/core_lib/src/structure/layercamera.cpp index 1ff1fbc354..c41507f5b1 100644 --- a/core_lib/src/structure/layercamera.cpp +++ b/core_lib/src/structure/layercamera.cpp @@ -306,14 +306,18 @@ void LayerCamera::mergeControlPointIfNeeded(int frame) const const QLineF& interpolatedLinePC = QLineF(-camPrev->translation(), camPrev->getPathControlPoint()); QPointF mergedCPoint; +#if QT_VERSION >= QT_VERSION_CHECK(5, 14, 0) + auto intersection = interpolatedLinePC.intersects(interpolatedLineCN, &mergedCPoint); +#else auto intersection = interpolatedLinePC.intersect(interpolatedLineCN, &mergedCPoint); +#endif // Try to recover the control point if the distance is within the threshold, otherwise do nothing - if (intersection == QLineF::IntersectType::UnboundedIntersection && + if (intersection == QLineF::UnboundedIntersection && QLineF(camFrame->getPathControlPoint(), mergedCPoint).length() < mControlPointMergeThreshold) { camPrev->setPathControlPoint(mergedCPoint); camPrev->setPathControlPointMoved(true); - } else if (intersection == QLineF::IntersectType::NoIntersection) { + } else if (intersection == QLineF::NoIntersection) { camPrev->setPathControlPointMoved(false); } } diff --git a/core_lib/src/structure/object.cpp b/core_lib/src/structure/object.cpp index 0a5871853a..30391fed51 100644 --- a/core_lib/src/structure/object.cpp +++ b/core_lib/src/structure/object.cpp @@ -25,6 +25,7 @@ GNU General Public License for more details. #include #include #include +#include #include "layer.h" #include "layerbitmap.h" @@ -303,7 +304,11 @@ bool Object::swapLayers(int i, int j) if (i != j) { +#if QT_VERSION >= QT_VERSION_CHECK(5, 13, 0) + mLayers.swapItemsAt(i, j); +#else mLayers.swap(i, j); +#endif } return true; } @@ -571,8 +576,11 @@ void Object::importPaletteGPL(QFile& file) int countInLine = 0; QString name = ""; - - for(const QString& snip : line.split(QRegExp("\\s|\\t"), QString::SkipEmptyParts)) +#if QT_VERSION >= QT_VERSION_CHECK(5, 14, 0) + for(const QString& snip : line.split(QRegularExpression("\\s|\\t"), Qt::SkipEmptyParts)) +#else + for(const QString& snip : line.split(QRegularExpression("\\s|\\t"), QString::SkipEmptyParts)) +#endif { switch (countInLine) { diff --git a/core_lib/src/tool/basetool.cpp b/core_lib/src/tool/basetool.cpp index 56bd359bc7..c6029edce8 100644 --- a/core_lib/src/tool/basetool.cpp +++ b/core_lib/src/tool/basetool.cpp @@ -164,7 +164,7 @@ QPixmap BaseTool::canvasCursor(float width, float feather, bool useFeather, floa cursorPixmap.fill(QColor(255, 255, 255, 0)); QPainter cursorPainter(&cursorPixmap); QPen cursorPen = cursorPainter.pen(); - cursorPainter.setRenderHint(QPainter::HighQualityAntialiasing); + cursorPainter.setRenderHint(QPainter::Antialiasing); // Draw cross in center cursorPen.setStyle(Qt::SolidLine); diff --git a/core_lib/src/tool/movetool.cpp b/core_lib/src/tool/movetool.cpp index 20f459382c..8ddc3a3da0 100644 --- a/core_lib/src/tool/movetool.cpp +++ b/core_lib/src/tool/movetool.cpp @@ -367,7 +367,7 @@ QCursor MoveTool::cursor(MoveMode mode) const cursorPixmap.fill(QColor(255, 255, 255, 0)); QPainter cursorPainter(&cursorPixmap); - cursorPainter.setRenderHint(QPainter::HighQualityAntialiasing); + cursorPainter.setRenderHint(QPainter::Antialiasing); switch(mode) { diff --git a/core_lib/src/tool/selecttool.cpp b/core_lib/src/tool/selecttool.cpp index 6b9d8725df..df24930ae2 100644 --- a/core_lib/src/tool/selecttool.cpp +++ b/core_lib/src/tool/selecttool.cpp @@ -43,14 +43,14 @@ void SelectTool::loadSettings() QCursor SelectTool::cursor() { // Don't update cursor while we're moving the selection - if (mScribbleArea->isPointerInUse()) { return mCursorPixmap; } + if (mScribbleArea->isPointerInUse()) { return QCursor(mCursorPixmap); } mEditor->select()->setMoveModeForAnchorInRange(getCurrentPoint()); MoveMode mode = mEditor->select()->getMoveMode(); mCursorPixmap.fill(QColor(255, 255, 255, 0)); QPainter cursorPainter(&mCursorPixmap); - cursorPainter.setRenderHint(QPainter::HighQualityAntialiasing); + cursorPainter.setRenderHint(QPainter::Antialiasing); switch(mode) { @@ -79,7 +79,7 @@ QCursor SelectTool::cursor() default: Q_UNREACHABLE(); } - return mCursorPixmap; + return QCursor(mCursorPixmap); } void SelectTool::resetToDefault() diff --git a/core_lib/src/util/pointerevent.cpp b/core_lib/src/util/pointerevent.cpp index 3bef76394f..b65c720ac8 100644 --- a/core_lib/src/util/pointerevent.cpp +++ b/core_lib/src/util/pointerevent.cpp @@ -234,6 +234,28 @@ PointerEvent::InputType PointerEvent::inputType() const return InputType::Unknown; } +#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) + +QInputDevice::DeviceType PointerEvent::device() const +{ + if (mTabletEvent) + { + return mTabletEvent->deviceType(); + } + return QInputDevice::DeviceType::Unknown; +} + +QPointingDevice::PointerType PointerEvent::pointerType() const +{ + if (mTabletEvent) + { + return mTabletEvent->pointerType(); + } + return QPointingDevice::PointerType::Unknown; +} + +#else // QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) + QTabletEvent::TabletDevice PointerEvent::device() const { if (mTabletEvent) @@ -252,4 +274,4 @@ QTabletEvent::PointerType PointerEvent::pointerType() const return QTabletEvent::PointerType::UnknownPointer; } -//QEvent::device +#endif // QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) diff --git a/core_lib/src/util/pointerevent.h b/core_lib/src/util/pointerevent.h index d22c6b4837..871fe69a14 100644 --- a/core_lib/src/util/pointerevent.h +++ b/core_lib/src/util/pointerevent.h @@ -73,8 +73,13 @@ class PointerEvent QEvent::Type eventType() const; InputType inputType() const; +#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) + QInputDevice::DeviceType device() const; + QPointingDevice::PointerType pointerType() const; +#else QTabletEvent::TabletDevice device() const; QTabletEvent::PointerType pointerType() const; +#endif private: QTabletEvent* mTabletEvent = nullptr; diff --git a/docs/build_linux.md b/docs/build_linux.md index 930b4fc1c6..f86ccda827 100644 --- a/docs/build_linux.md +++ b/docs/build_linux.md @@ -3,7 +3,7 @@ Building Pencil2D on Linux {#build_linux} These are instructions for building Pencil2D on Linux. If you are using Windows go [here](@ref build_windows), and macOS go [here](@ref build_macos). This guide is primarily targeted towards developers. If you just want to use the latest version you can just download one of our [nightly builds](https://www.pencil2d.org/download/nightly/). -This tutorial was made with Ubuntu Xenial Xerus (16.04) and Arch Linux in mind, however you should be able to adapt this guide to other versions or distributions if necessary. +This tutorial was made with Ubuntu and Arch Linux in mind, however you should be able to adapt this guide to other distributions if necessary. ## Installing Dependencies @@ -26,9 +26,15 @@ Pencil2D relies on the %Qt application framework so you must install it before y ##### Command-line method -Pencil2D must be built with the %Qt 5 framework. To install %Qt 5, run this command: +Pencil2D must be built with the %Qt framework, version 5.6 or newer. Therefore, you will need at least Ubuntu 16.10 (Yakkety Yak) to use this method, as Canonical does not provide recent enough versions of Qt for older versions of Ubuntu. To install %Qt 5, run this command: - sudo apt install qt5-default qt5-qmake libqt5xmlpatterns5-dev libqt5svg5-dev qtmultimedia5-dev + sudo apt install qt5-default qtbase5-dev qtmultimedia5-dev qttools5-dev-tools libqt5svg5-dev + +@note If you are using Ubuntu 20.04 (Focal Fossa) or newer, you can omit qt5-default from the command above. + +If you are using Ubuntu 22.04 (Jammy Jellyfish) or later, you can alternatively install %Qt 6 by running this command: + + sudo apt install qt6-base-dev qt6-l10n-tools qt6-multimedia-dev libqt6svg6-dev For a more pleasant development experience, you might want to install %Qt Creator as well (recommended). To do so, run the following command: @@ -36,9 +42,11 @@ For a more pleasant development experience, you might want to install %Qt Creato #### Arch Linux -Pencil uses version 5 of the %Qt framework. To install all required components of %Qt, run this command: +Pencil uses the %Qt framework, version 5.6 or newer. To install all required components of %Qt 5, run this command: + + sudo pacman -S --needed qt5-base qt5-multimedia qt5-svg qt5-tools qt-gstreamer - sudo pacman -S --needed qt5-multimedia qt5-svg qt5-xmlpatterns qt-gstreamer +If you would like to use %Qt 6 instead, simply replace the version number in the command above. For a more pleasant development experience, you might want to install %Qt Creator as well (recommended). To do so, run the following command: @@ -46,7 +54,7 @@ For a more pleasant development experience, you might want to install %Qt Creato ### Make and GCC/Clang -You will need GNU Make and either GCC or CLANG to build Pencil2D. +You will need GNU Make and either GCC or Clang to build Pencil2D. #### Ubuntu @@ -60,6 +68,7 @@ These are usually installed by default, so you don't have to worry about them. I sudo apt install make clang + #### Arch Linux On most Arch systems, these are installed early on, but if your system does not have them yet, you can install them by running the following commands. @@ -72,6 +81,7 @@ On most Arch systems, these are installed early on, but if your system does not sudo pacman -S --needed make clang + # Get the source code - Simply download a [source code archive](https://github.com/pencil2d/pencil/archive/master.zip), or @@ -103,6 +113,8 @@ Substitute \ for the mkspec of your desired configuration and run the c mkdir build; pushd build; qmake -r -spec CONFIG+=debug ..; popd +@note In order to use %Qt 6, you might need to replace `qmake` with `qmake6`. + Next you have to use GNU Make to actually compile the source code. Run the command: make -C build diff --git a/docs/build_mac.md b/docs/build_mac.md index 1252dac939..7ce2127a94 100644 --- a/docs/build_mac.md +++ b/docs/build_mac.md @@ -50,7 +50,11 @@ A dialog should pop up asking if you want to install the command line developer If you have `Homebrew` installed, you can install %Qt 5 framework via Homebrew as well. Run this command: - brew install qt5 + brew install qt@5 + +If you would like to use %Qt 6 instead, simply replace the version number in the command above. + +@warning Please note that there are known issues with the Homebrew build of Qt 6 which may cause Pencil2D to crash. As a workaround, you can try disabling the "Add build library search path to DYLD_LIBRARY_PATH and DYLD_FRAMEWORK_PATH" option in your run configuration after configuring the project in Qt Creator. Otherwise, please use the official builds instead (see above), as they are not affected. For more details, see [this discussion](https://github.com/orgs/Homebrew/discussions/4362). And also run the following commands to install %Qt Creator: diff --git a/tests/tests.pro b/tests/tests.pro index c0a5a8224b..9bba5c9f3e 100644 --- a/tests/tests.pro +++ b/tests/tests.pro @@ -6,7 +6,7 @@ ! include( ../util/common.pri ) { error( Could not find the common.pri file! ) } -QT += core widgets gui xml xmlpatterns multimedia svg testlib +QT += core widgets gui xml multimedia svg testlib TEMPLATE = app