2022-08-19 15:59:36 +02:00
|
|
|
// Copyright (C) 2020 The Qt Company Ltd.
|
2022-12-21 10:12:09 +01:00
|
|
|
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
|
2020-10-11 15:33:23 +02:00
|
|
|
|
2022-10-06 17:53:35 +02:00
|
|
|
#include "androidtr.h"
|
2020-10-11 15:33:23 +02:00
|
|
|
#include "splashscreencontainerwidget.h"
|
|
|
|
|
#include "splashscreenwidget.h"
|
|
|
|
|
|
|
|
|
|
#include <texteditor/textdocument.h>
|
|
|
|
|
#include <texteditor/texteditor.h>
|
2021-08-17 16:19:15 +02:00
|
|
|
|
|
|
|
|
#include <utils/filepath.h>
|
2020-10-11 15:33:23 +02:00
|
|
|
#include <utils/utilsicons.h>
|
|
|
|
|
|
|
|
|
|
#include <QCheckBox>
|
|
|
|
|
#include <QColorDialog>
|
|
|
|
|
#include <QComboBox>
|
|
|
|
|
#include <QHBoxLayout>
|
|
|
|
|
#include <QFileDialog>
|
|
|
|
|
#include <QFileInfo>
|
|
|
|
|
#include <QFormLayout>
|
|
|
|
|
#include <QGroupBox>
|
|
|
|
|
#include <QTabWidget>
|
|
|
|
|
#include <QToolButton>
|
|
|
|
|
#include <QVBoxLayout>
|
2022-05-24 00:40:44 +02:00
|
|
|
#include <QXmlStreamReader>
|
|
|
|
|
#include <QXmlStreamWriter>
|
2020-10-11 15:33:23 +02:00
|
|
|
|
2021-08-17 16:19:15 +02:00
|
|
|
using namespace Utils;
|
|
|
|
|
|
2020-10-11 15:33:23 +02:00
|
|
|
namespace Android {
|
|
|
|
|
namespace Internal {
|
|
|
|
|
|
2021-05-28 18:22:44 +03:00
|
|
|
const char extraExtraExtraHighDpiImagePath[] = "/res/drawable-xxxhdpi/";
|
|
|
|
|
const char extraExtraHighDpiImagePath[] = "/res/drawable-xxhdpi/";
|
|
|
|
|
const char extraHighDpiImagePath[] = "/res/drawable-xhdpi/";
|
|
|
|
|
const char highDpiImagePath[] = "/res/drawable-hdpi/";
|
|
|
|
|
const char mediumDpiImagePath[] = "/res/drawable-mdpi/";
|
|
|
|
|
const char lowDpiImagePath[] = "/res/drawable-ldpi/";
|
|
|
|
|
const char splashscreenName[] = "splashscreen";
|
|
|
|
|
const char splashscreenPortraitName[] = "splashscreen_port";
|
|
|
|
|
const char splashscreenLandscapeName[] = "splashscreen_land";
|
|
|
|
|
const char splashscreenFileName[] = "logo";
|
|
|
|
|
const char splashscreenPortraitFileName[] = "logo_port";
|
|
|
|
|
const char splashscreenLandscapeFileName[] = "logo_land";
|
|
|
|
|
const char imageSuffix[] = ".png";
|
2023-02-10 14:44:09 +01:00
|
|
|
const QString fileDialogImageFiles = Tr::tr("Images (*.png *.jpg *.jpeg)"); // TODO: Implement a centralized images filter string
|
2020-10-11 15:33:23 +02:00
|
|
|
const QSize lowDpiImageSize{200, 320};
|
|
|
|
|
const QSize mediumDpiImageSize{320, 480};
|
|
|
|
|
const QSize highDpiImageSize{480, 800};
|
|
|
|
|
const QSize extraHighDpiImageSize{720, 1280};
|
|
|
|
|
const QSize extraExtraHighDpiImageSize{960, 1600};
|
|
|
|
|
const QSize extraExtraExtraHighDpiImageSize{1280, 1920};
|
|
|
|
|
const QSize displaySize{48, 72};
|
|
|
|
|
const QSize landscapeDisplaySize{72, 48};
|
|
|
|
|
// https://developer.android.com/training/multiscreen/screendensities#TaskProvideAltBmp
|
|
|
|
|
const int extraExtraExtraHighDpiScalingRatio = 16;
|
|
|
|
|
const int extraExtraHighDpiScalingRatio = 12;
|
|
|
|
|
const int extraHighDpiScalingRatio = 8;
|
|
|
|
|
const int highDpiScalingRatio = 6;
|
|
|
|
|
const int mediumDpiScalingRatio = 4;
|
|
|
|
|
const int lowDpiScalingRatio = 3;
|
|
|
|
|
|
2021-08-17 16:19:15 +02:00
|
|
|
static FilePath manifestDir(TextEditor::TextEditorWidget *textEditorWidget)
|
2020-10-11 15:33:23 +02:00
|
|
|
{
|
|
|
|
|
// Get the manifest file's directory from its filepath.
|
2021-08-17 16:19:15 +02:00
|
|
|
return textEditorWidget->textDocument()->filePath().absolutePath();
|
2020-10-11 15:33:23 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static SplashScreenWidget *addWidgetToPage(QWidget *page,
|
|
|
|
|
const QSize &size, const QSize &screenSize,
|
|
|
|
|
const QString &title, const QString &tooltip,
|
|
|
|
|
TextEditor::TextEditorWidget *textEditorWidget,
|
|
|
|
|
const QString &splashScreenPath,
|
|
|
|
|
int scalingRatio, int maxScalingRatio,
|
|
|
|
|
QHBoxLayout *pageLayout,
|
|
|
|
|
QVector<SplashScreenWidget *> &widgetContainer)
|
|
|
|
|
{
|
|
|
|
|
auto splashScreenWidget = new SplashScreenWidget(page,
|
|
|
|
|
size,
|
|
|
|
|
screenSize,
|
|
|
|
|
title,
|
|
|
|
|
tooltip,
|
|
|
|
|
splashScreenPath,
|
|
|
|
|
scalingRatio,
|
|
|
|
|
maxScalingRatio,
|
|
|
|
|
textEditorWidget);
|
|
|
|
|
pageLayout->addWidget(splashScreenWidget);
|
|
|
|
|
widgetContainer.push_back(splashScreenWidget);
|
|
|
|
|
return splashScreenWidget;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static QWidget *createPage(TextEditor::TextEditorWidget *textEditorWidget,
|
|
|
|
|
QVector<SplashScreenWidget *> &widgetContainer,
|
|
|
|
|
QVector<SplashScreenWidget *> &portraitWidgetContainer,
|
|
|
|
|
QVector<SplashScreenWidget *> &landscapeWidgetContainer,
|
|
|
|
|
int scalingRatio,
|
|
|
|
|
const QSize &size,
|
|
|
|
|
const QSize &portraitSize,
|
|
|
|
|
const QSize &landscapeSize,
|
|
|
|
|
const QString &path)
|
|
|
|
|
{
|
|
|
|
|
auto sizeToStr = [](const QSize &size) { return QString(" (%1x%2)").arg(size.width()).arg(size.height()); };
|
|
|
|
|
QWidget *page = new QWidget();
|
|
|
|
|
auto pageLayout = new QHBoxLayout(page);
|
|
|
|
|
auto genericWidget= addWidgetToPage(page,
|
|
|
|
|
displaySize, size,
|
2022-10-06 17:53:35 +02:00
|
|
|
Tr::tr("Splash screen"),
|
|
|
|
|
Tr::tr("Select splash screen image")
|
2020-10-11 15:33:23 +02:00
|
|
|
+ sizeToStr(size),
|
|
|
|
|
textEditorWidget,
|
|
|
|
|
path,
|
|
|
|
|
scalingRatio, extraExtraExtraHighDpiScalingRatio,
|
|
|
|
|
pageLayout,
|
|
|
|
|
widgetContainer);
|
|
|
|
|
|
|
|
|
|
auto portraitWidget = addWidgetToPage(page,
|
|
|
|
|
displaySize, portraitSize,
|
2022-10-06 17:53:35 +02:00
|
|
|
Tr::tr("Portrait splash screen"),
|
|
|
|
|
Tr::tr("Select portrait splash screen image")
|
2020-10-11 15:33:23 +02:00
|
|
|
+ sizeToStr(portraitSize),
|
|
|
|
|
textEditorWidget,
|
|
|
|
|
path,
|
|
|
|
|
scalingRatio, extraExtraExtraHighDpiScalingRatio,
|
|
|
|
|
pageLayout,
|
|
|
|
|
portraitWidgetContainer);
|
|
|
|
|
|
|
|
|
|
auto landscapeWidget = addWidgetToPage(page,
|
|
|
|
|
landscapeDisplaySize, landscapeSize,
|
2022-10-06 17:53:35 +02:00
|
|
|
Tr::tr("Landscape splash screen"),
|
|
|
|
|
Tr::tr("Select landscape splash screen image")
|
2020-10-11 15:33:23 +02:00
|
|
|
+ sizeToStr(landscapeSize),
|
|
|
|
|
textEditorWidget,
|
|
|
|
|
path,
|
|
|
|
|
scalingRatio, extraExtraExtraHighDpiScalingRatio,
|
|
|
|
|
pageLayout,
|
|
|
|
|
landscapeWidgetContainer);
|
|
|
|
|
|
|
|
|
|
auto clearButton = new QToolButton(page);
|
2022-10-06 17:53:35 +02:00
|
|
|
clearButton->setText(Tr::tr("Clear All"));
|
2020-10-11 15:33:23 +02:00
|
|
|
pageLayout->addWidget(clearButton);
|
|
|
|
|
pageLayout->setAlignment(clearButton, Qt::AlignVCenter);
|
|
|
|
|
SplashScreenContainerWidget::connect(clearButton, &QAbstractButton::clicked,
|
|
|
|
|
genericWidget, &SplashScreenWidget::clearImage);
|
|
|
|
|
SplashScreenContainerWidget::connect(clearButton, &QAbstractButton::clicked,
|
|
|
|
|
portraitWidget, &SplashScreenWidget::clearImage);
|
|
|
|
|
SplashScreenContainerWidget::connect(clearButton, &QAbstractButton::clicked,
|
|
|
|
|
landscapeWidget, &SplashScreenWidget::clearImage);
|
|
|
|
|
return page;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
SplashScreenContainerWidget::SplashScreenContainerWidget(
|
|
|
|
|
QWidget *parent,
|
|
|
|
|
TextEditor::TextEditorWidget *textEditorWidget)
|
|
|
|
|
: QStackedWidget(parent),
|
|
|
|
|
m_textEditorWidget(textEditorWidget)
|
|
|
|
|
{
|
|
|
|
|
auto noSplashscreenWidget = new QWidget(this);
|
|
|
|
|
auto splashscreenWidget = new QWidget(this);
|
|
|
|
|
auto layout = new QHBoxLayout(this);
|
|
|
|
|
auto settingsLayout = new QVBoxLayout(this);
|
|
|
|
|
auto noSplashscreenLayout = new QVBoxLayout(this);
|
|
|
|
|
auto formLayout = new QFormLayout(this);
|
|
|
|
|
QTabWidget *tab = new QTabWidget(this);
|
|
|
|
|
|
|
|
|
|
m_stickyCheck = new QCheckBox(this);
|
2022-10-06 17:53:35 +02:00
|
|
|
m_stickyCheck->setToolTip(Tr::tr("A non-sticky splash screen is hidden automatically when an activity is drawn.\n"
|
|
|
|
|
"To hide a sticky splash screen, invoke QtAndroid::hideSplashScreen()."));
|
|
|
|
|
formLayout->addRow(Tr::tr("Sticky splash screen:"), m_stickyCheck);
|
2020-10-11 15:33:23 +02:00
|
|
|
|
|
|
|
|
m_imageShowMode = new QComboBox(this);
|
2022-10-06 17:53:35 +02:00
|
|
|
formLayout->addRow(Tr::tr("Image show mode:"), m_imageShowMode);
|
2020-10-11 15:33:23 +02:00
|
|
|
const QList<QStringList> imageShowModeMethodsMap = {
|
|
|
|
|
{"center", "Place the object in the center of the screen in both the vertical and horizontal axis,\n"
|
|
|
|
|
"not changing its size."},
|
|
|
|
|
{"fill", "Grow the horizontal and vertical size of the image if needed so it completely fills its screen."}};
|
|
|
|
|
for (int i = 0; i < imageShowModeMethodsMap.size(); ++i) {
|
|
|
|
|
m_imageShowMode->addItem(imageShowModeMethodsMap.at(i).first());
|
|
|
|
|
m_imageShowMode->setItemData(i, imageShowModeMethodsMap.at(i).at(1), Qt::ToolTipRole);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
m_backgroundColor = new QToolButton(this);
|
2022-10-06 17:53:35 +02:00
|
|
|
m_backgroundColor->setToolTip(Tr::tr("Background color of the splash screen."));
|
|
|
|
|
formLayout->addRow(Tr::tr("Background color:"), m_backgroundColor);
|
2020-10-11 15:33:23 +02:00
|
|
|
|
|
|
|
|
m_masterImage = new QToolButton(this);
|
2022-10-06 17:53:35 +02:00
|
|
|
m_masterImage->setToolTip(Tr::tr("Select master image to use."));
|
2020-10-11 15:33:23 +02:00
|
|
|
m_masterImage->setIcon(QIcon::fromTheme(QLatin1String("document-open"), Utils::Icons::OPENFILE.icon()));
|
2022-10-06 17:53:35 +02:00
|
|
|
formLayout->addRow(Tr::tr("Master image:"), m_masterImage);
|
2020-10-11 15:33:23 +02:00
|
|
|
|
|
|
|
|
m_portraitMasterImage = new QToolButton(this);
|
2022-10-06 17:53:35 +02:00
|
|
|
m_portraitMasterImage->setToolTip(Tr::tr("Select portrait master image to use."));
|
2020-10-11 15:33:23 +02:00
|
|
|
m_portraitMasterImage->setIcon(QIcon::fromTheme(QLatin1String("document-open"), Utils::Icons::OPENFILE.icon()));
|
2022-10-06 17:53:35 +02:00
|
|
|
formLayout->addRow(Tr::tr("Portrait master image:"), m_portraitMasterImage);
|
2020-10-11 15:33:23 +02:00
|
|
|
|
|
|
|
|
m_landscapeMasterImage = new QToolButton(this);
|
2022-10-06 17:53:35 +02:00
|
|
|
m_landscapeMasterImage->setToolTip(Tr::tr("Select landscape master image to use."));
|
2020-10-11 15:33:23 +02:00
|
|
|
m_landscapeMasterImage->setIcon(QIcon::fromTheme(QLatin1String("document-open"), Utils::Icons::OPENFILE.icon()));
|
2022-10-06 17:53:35 +02:00
|
|
|
formLayout->addRow(Tr::tr("Landscape master image:"), m_landscapeMasterImage);
|
2020-10-11 15:33:23 +02:00
|
|
|
|
|
|
|
|
auto clearAllButton = new QToolButton(this);
|
2022-10-06 17:53:35 +02:00
|
|
|
clearAllButton->setText(Tr::tr("Clear All"));
|
2020-10-11 15:33:23 +02:00
|
|
|
|
|
|
|
|
auto ldpiPage = createPage(textEditorWidget,
|
|
|
|
|
m_imageWidgets, m_portraitImageWidgets, m_landscapeImageWidgets,
|
|
|
|
|
lowDpiScalingRatio,
|
|
|
|
|
lowDpiImageSize,
|
|
|
|
|
lowDpiImageSize,
|
|
|
|
|
lowDpiImageSize.transposed(),
|
|
|
|
|
lowDpiImagePath);
|
2022-10-06 17:53:35 +02:00
|
|
|
tab->addTab(ldpiPage, Tr::tr("LDPI"));
|
2020-10-11 15:33:23 +02:00
|
|
|
auto mdpiPage = createPage(textEditorWidget,
|
|
|
|
|
m_imageWidgets, m_portraitImageWidgets, m_landscapeImageWidgets,
|
|
|
|
|
mediumDpiScalingRatio,
|
|
|
|
|
mediumDpiImageSize,
|
|
|
|
|
mediumDpiImageSize,
|
|
|
|
|
mediumDpiImageSize.transposed(),
|
|
|
|
|
mediumDpiImagePath);
|
2022-10-06 17:53:35 +02:00
|
|
|
tab->addTab(mdpiPage, Tr::tr("MDPI"));
|
2020-10-11 15:33:23 +02:00
|
|
|
auto hdpiPage = createPage(textEditorWidget,
|
|
|
|
|
m_imageWidgets, m_portraitImageWidgets, m_landscapeImageWidgets,
|
|
|
|
|
highDpiScalingRatio,
|
|
|
|
|
highDpiImageSize,
|
|
|
|
|
highDpiImageSize,
|
|
|
|
|
highDpiImageSize.transposed(),
|
|
|
|
|
highDpiImagePath);
|
2022-10-06 17:53:35 +02:00
|
|
|
tab->addTab(hdpiPage, Tr::tr("HDPI"));
|
2020-10-11 15:33:23 +02:00
|
|
|
auto xHdpiPage = createPage(textEditorWidget,
|
|
|
|
|
m_imageWidgets, m_portraitImageWidgets, m_landscapeImageWidgets,
|
|
|
|
|
extraHighDpiScalingRatio,
|
|
|
|
|
extraHighDpiImageSize,
|
|
|
|
|
extraHighDpiImageSize,
|
|
|
|
|
extraHighDpiImageSize.transposed(),
|
|
|
|
|
extraHighDpiImagePath);
|
2022-10-06 17:53:35 +02:00
|
|
|
tab->addTab(xHdpiPage, Tr::tr("XHDPI"));
|
2020-10-11 15:33:23 +02:00
|
|
|
auto xxHdpiPage = createPage(textEditorWidget,
|
|
|
|
|
m_imageWidgets, m_portraitImageWidgets, m_landscapeImageWidgets,
|
|
|
|
|
extraExtraHighDpiScalingRatio,
|
|
|
|
|
extraExtraHighDpiImageSize,
|
|
|
|
|
extraExtraHighDpiImageSize,
|
|
|
|
|
extraExtraHighDpiImageSize.transposed(),
|
|
|
|
|
extraExtraHighDpiImagePath);
|
2022-10-06 17:53:35 +02:00
|
|
|
tab->addTab(xxHdpiPage, Tr::tr("XXHDPI"));
|
2020-10-11 15:33:23 +02:00
|
|
|
auto xxxHdpiPage = createPage(textEditorWidget,
|
|
|
|
|
m_imageWidgets, m_portraitImageWidgets, m_landscapeImageWidgets,
|
|
|
|
|
extraExtraExtraHighDpiScalingRatio,
|
|
|
|
|
extraExtraExtraHighDpiImageSize,
|
|
|
|
|
extraExtraExtraHighDpiImageSize,
|
|
|
|
|
extraExtraExtraHighDpiImageSize.transposed(),
|
|
|
|
|
extraExtraExtraHighDpiImagePath);
|
2022-10-06 17:53:35 +02:00
|
|
|
tab->addTab(xxxHdpiPage, Tr::tr("XXXHDPI"));
|
2020-10-11 15:33:23 +02:00
|
|
|
formLayout->setContentsMargins(10, 10, 10, 10);
|
|
|
|
|
formLayout->setSpacing(10);
|
|
|
|
|
settingsLayout->addLayout(formLayout);
|
|
|
|
|
settingsLayout->addWidget(clearAllButton);
|
|
|
|
|
settingsLayout->setAlignment(clearAllButton, Qt::AlignHCenter);
|
|
|
|
|
layout->addLayout(settingsLayout);
|
|
|
|
|
layout->addWidget(tab);
|
|
|
|
|
splashscreenWidget->setLayout(layout);
|
|
|
|
|
addWidget(splashscreenWidget);
|
|
|
|
|
setBackgroundColor(Qt::white);
|
|
|
|
|
|
|
|
|
|
auto warningLabel = new QLabel(this);
|
|
|
|
|
warningLabel->setAlignment(Qt::AlignHCenter);
|
2022-10-06 17:53:35 +02:00
|
|
|
warningLabel->setText(Tr::tr("An image is used for the splashscreen. Qt Creator manages\n"
|
|
|
|
|
"splashscreen by using a different method which requires changing\n"
|
|
|
|
|
"the manifest file by overriding your settings. Allow override?"));
|
2020-10-11 15:33:23 +02:00
|
|
|
m_convertSplashscreen = new QToolButton(this);
|
2022-10-06 17:53:35 +02:00
|
|
|
m_convertSplashscreen->setText(Tr::tr("Convert"));
|
2020-10-11 15:33:23 +02:00
|
|
|
noSplashscreenLayout->addStretch();
|
|
|
|
|
noSplashscreenLayout->addWidget(warningLabel);
|
|
|
|
|
noSplashscreenLayout->addWidget(m_convertSplashscreen);
|
|
|
|
|
noSplashscreenLayout->addStretch();
|
|
|
|
|
noSplashscreenLayout->setSpacing(10);
|
|
|
|
|
noSplashscreenLayout->setAlignment(warningLabel, Qt::AlignHCenter);
|
|
|
|
|
noSplashscreenLayout->setAlignment(m_convertSplashscreen, Qt::AlignHCenter);
|
|
|
|
|
noSplashscreenWidget->setLayout(noSplashscreenLayout);
|
|
|
|
|
addWidget(noSplashscreenWidget);
|
|
|
|
|
|
2021-05-28 18:22:44 +03:00
|
|
|
const auto splashFileName = QString(splashscreenFileName).append(imageSuffix);
|
|
|
|
|
const auto portraitSplashFileName = QString(splashscreenPortraitFileName).append(imageSuffix);
|
|
|
|
|
const auto landscapeSplashFileName = QString(splashscreenLandscapeFileName).append(imageSuffix);
|
|
|
|
|
|
2020-10-11 15:33:23 +02:00
|
|
|
for (auto &&imageWidget : m_imageWidgets)
|
2021-05-28 18:22:44 +03:00
|
|
|
imageWidget->setImageFileName(splashFileName);
|
2020-10-11 15:33:23 +02:00
|
|
|
for (auto &&imageWidget : m_portraitImageWidgets)
|
2021-05-28 18:22:44 +03:00
|
|
|
imageWidget->setImageFileName(portraitSplashFileName);
|
2020-10-11 15:33:23 +02:00
|
|
|
for (auto &&imageWidget : m_landscapeImageWidgets)
|
2021-05-28 18:22:44 +03:00
|
|
|
imageWidget->setImageFileName(landscapeSplashFileName);
|
2020-10-11 15:33:23 +02:00
|
|
|
|
|
|
|
|
for (auto &&imageWidget : m_imageWidgets) {
|
2021-08-24 16:08:52 +02:00
|
|
|
connect(imageWidget, &SplashScreenWidget::imageChanged, this, [this] {
|
2020-10-11 15:33:23 +02:00
|
|
|
createSplashscreenThemes();
|
|
|
|
|
emit splashScreensModified();
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
for (auto &&imageWidget : m_portraitImageWidgets) {
|
2021-08-24 16:08:52 +02:00
|
|
|
connect(imageWidget, &SplashScreenWidget::imageChanged, this, [this] {
|
2020-10-11 15:33:23 +02:00
|
|
|
createSplashscreenThemes();
|
|
|
|
|
emit splashScreensModified();
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
for (auto &&imageWidget : m_landscapeImageWidgets) {
|
2021-08-24 16:08:52 +02:00
|
|
|
connect(imageWidget, &SplashScreenWidget::imageChanged, this, [this] {
|
2020-10-11 15:33:23 +02:00
|
|
|
createSplashscreenThemes();
|
|
|
|
|
emit splashScreensModified();
|
|
|
|
|
});
|
|
|
|
|
}
|
2021-08-24 16:08:52 +02:00
|
|
|
connect(m_stickyCheck, &QCheckBox::stateChanged, this, [this](int state) {
|
2020-10-11 15:33:23 +02:00
|
|
|
bool old = m_splashScreenSticky;
|
|
|
|
|
m_splashScreenSticky = (state == Qt::Checked);
|
|
|
|
|
if (old != m_splashScreenSticky)
|
|
|
|
|
emit splashScreensModified();
|
|
|
|
|
});
|
2021-08-24 16:08:52 +02:00
|
|
|
connect(m_backgroundColor, &QToolButton::clicked, this, [this] {
|
2020-10-11 15:33:23 +02:00
|
|
|
const QColor color = QColorDialog::getColor(m_splashScreenBackgroundColor,
|
|
|
|
|
this,
|
2022-10-06 17:53:35 +02:00
|
|
|
Tr::tr("Select background color"));
|
2020-10-11 15:33:23 +02:00
|
|
|
if (color.isValid()) {
|
|
|
|
|
setBackgroundColor(color);
|
|
|
|
|
createSplashscreenThemes();
|
|
|
|
|
emit splashScreensModified();
|
|
|
|
|
}
|
|
|
|
|
});
|
2021-08-24 16:08:52 +02:00
|
|
|
connect(m_masterImage, &QToolButton::clicked, this, [this] {
|
2022-10-06 17:53:35 +02:00
|
|
|
const FilePath file = FileUtils::getOpenFilePath(this, Tr::tr("Select master image"),
|
2021-08-17 16:19:15 +02:00
|
|
|
FileUtils::homePath(), fileDialogImageFiles);
|
2020-10-11 15:33:23 +02:00
|
|
|
if (!file.isEmpty()) {
|
|
|
|
|
for (auto &&imageWidget : m_imageWidgets)
|
|
|
|
|
imageWidget->setImageFromPath(file);
|
|
|
|
|
createSplashscreenThemes();
|
|
|
|
|
emit splashScreensModified();
|
|
|
|
|
}
|
|
|
|
|
});
|
2021-08-24 16:08:52 +02:00
|
|
|
connect(m_portraitMasterImage, &QToolButton::clicked, this, [this] {
|
2022-10-06 17:53:35 +02:00
|
|
|
const FilePath file = FileUtils::getOpenFilePath(this, Tr::tr("Select portrait master image"),
|
2021-08-17 16:19:15 +02:00
|
|
|
FileUtils::homePath(), fileDialogImageFiles);
|
2020-10-11 15:33:23 +02:00
|
|
|
if (!file.isEmpty()) {
|
|
|
|
|
for (auto &&imageWidget : m_portraitImageWidgets)
|
|
|
|
|
imageWidget->setImageFromPath(file);
|
|
|
|
|
createSplashscreenThemes();
|
|
|
|
|
emit splashScreensModified();
|
|
|
|
|
}
|
|
|
|
|
});
|
2021-08-24 16:08:52 +02:00
|
|
|
connect(m_landscapeMasterImage, &QToolButton::clicked, this, [this] {
|
2022-10-06 17:53:35 +02:00
|
|
|
const FilePath file = FileUtils::getOpenFilePath(this, Tr::tr("Select landscape master image"),
|
2021-08-17 16:19:15 +02:00
|
|
|
FileUtils::homePath(), fileDialogImageFiles);
|
2020-10-11 15:33:23 +02:00
|
|
|
if (!file.isEmpty()) {
|
|
|
|
|
for (auto &&imageWidget : m_landscapeImageWidgets)
|
|
|
|
|
imageWidget->setImageFromPath(file);
|
|
|
|
|
createSplashscreenThemes();
|
|
|
|
|
emit splashScreensModified();
|
|
|
|
|
}
|
|
|
|
|
});
|
2021-08-24 16:08:52 +02:00
|
|
|
connect(m_imageShowMode, &QComboBox::currentTextChanged, this, [this](const QString &mode) {
|
2020-10-11 15:33:23 +02:00
|
|
|
setImageShowMode(mode);
|
|
|
|
|
createSplashscreenThemes();
|
|
|
|
|
emit splashScreensModified();
|
|
|
|
|
});
|
2021-08-24 16:08:52 +02:00
|
|
|
connect(clearAllButton, &QToolButton::clicked, this, [this] {
|
2020-10-11 15:33:23 +02:00
|
|
|
clearAll();
|
|
|
|
|
emit splashScreensModified();
|
|
|
|
|
});
|
2021-08-24 16:08:52 +02:00
|
|
|
connect(m_convertSplashscreen, &QToolButton::clicked, this, [this] {
|
2020-10-11 15:33:23 +02:00
|
|
|
clearAll();
|
|
|
|
|
setCurrentIndex(0);
|
|
|
|
|
emit splashScreensModified();
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void SplashScreenContainerWidget::loadImages()
|
|
|
|
|
{
|
|
|
|
|
if (isSplashscreenEnabled()) {
|
|
|
|
|
for (auto &&imageWidget : m_imageWidgets) {
|
|
|
|
|
imageWidget->loadImage();
|
|
|
|
|
}
|
|
|
|
|
loadSplashscreenDrawParams(splashscreenName);
|
|
|
|
|
for (auto &&imageWidget : m_portraitImageWidgets) {
|
|
|
|
|
imageWidget->loadImage();
|
|
|
|
|
}
|
|
|
|
|
loadSplashscreenDrawParams(splashscreenPortraitName);
|
|
|
|
|
for (auto &&imageWidget : m_landscapeImageWidgets) {
|
|
|
|
|
imageWidget->loadImage();
|
|
|
|
|
}
|
|
|
|
|
loadSplashscreenDrawParams(splashscreenLandscapeName);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void SplashScreenContainerWidget::loadSplashscreenDrawParams(const QString &name)
|
|
|
|
|
{
|
2021-08-17 16:19:15 +02:00
|
|
|
const FilePath filePath = manifestDir(m_textEditorWidget).pathAppended("res/drawable/" + name + ".xml");
|
|
|
|
|
QFile file(filePath.toString());
|
2020-10-11 15:33:23 +02:00
|
|
|
if (file.open(QIODevice::ReadOnly | QIODevice::Text)) {
|
|
|
|
|
QXmlStreamReader reader(&file);
|
|
|
|
|
reader.setNamespaceProcessing(false);
|
|
|
|
|
while (!reader.atEnd()) {
|
|
|
|
|
reader.readNext();
|
|
|
|
|
if (reader.hasError()) {
|
|
|
|
|
// This should not happen
|
|
|
|
|
return;
|
|
|
|
|
} else {
|
|
|
|
|
if (reader.name() == QLatin1String("solid")) {
|
|
|
|
|
const QXmlStreamAttributes attributes = reader.attributes();
|
2020-11-26 15:30:16 +01:00
|
|
|
const auto color = attributes.value(QLatin1String("android:color"));
|
2020-10-11 15:33:23 +02:00
|
|
|
if (!color.isEmpty())
|
|
|
|
|
setBackgroundColor(QColor(color));
|
|
|
|
|
}
|
|
|
|
|
else if (reader.name() == QLatin1String("bitmap")) {
|
|
|
|
|
const QXmlStreamAttributes attributes = reader.attributes();
|
2020-11-26 15:30:16 +01:00
|
|
|
const auto showMode = attributes.value(QLatin1String("android:gravity"));
|
2020-10-11 15:33:23 +02:00
|
|
|
if (!showMode.isEmpty())
|
|
|
|
|
setImageShowMode(showMode.toString());
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void SplashScreenContainerWidget::clearAll()
|
|
|
|
|
{
|
|
|
|
|
for (auto &&imageWidget : m_imageWidgets) {
|
|
|
|
|
imageWidget->clearImage();
|
|
|
|
|
}
|
|
|
|
|
for (auto &&imageWidget : m_portraitImageWidgets) {
|
|
|
|
|
imageWidget->clearImage();
|
|
|
|
|
}
|
|
|
|
|
for (auto &&imageWidget : m_landscapeImageWidgets) {
|
|
|
|
|
imageWidget->clearImage();
|
|
|
|
|
}
|
|
|
|
|
setBackgroundColor(Qt::white);
|
|
|
|
|
createSplashscreenThemes();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool SplashScreenContainerWidget::hasImages() const
|
|
|
|
|
{
|
|
|
|
|
for (auto &&imageWidget : m_imageWidgets) {
|
|
|
|
|
if (imageWidget->hasImage())
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool SplashScreenContainerWidget::hasPortraitImages() const
|
|
|
|
|
{
|
|
|
|
|
for (auto &&imageWidget : m_portraitImageWidgets) {
|
|
|
|
|
if (imageWidget->hasImage())
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool SplashScreenContainerWidget::hasLandscapeImages() const
|
|
|
|
|
{
|
|
|
|
|
for (auto &&imageWidget : m_landscapeImageWidgets) {
|
|
|
|
|
if (imageWidget->hasImage())
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool SplashScreenContainerWidget::isSticky() const
|
|
|
|
|
{
|
|
|
|
|
return m_splashScreenSticky;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void SplashScreenContainerWidget::setSticky(bool sticky)
|
|
|
|
|
{
|
|
|
|
|
m_splashScreenSticky = sticky;
|
|
|
|
|
m_stickyCheck->setCheckState(m_splashScreenSticky ? Qt::Checked : Qt::Unchecked);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void SplashScreenContainerWidget::setBackgroundColor(const QColor &color)
|
|
|
|
|
{
|
|
|
|
|
if (color != m_splashScreenBackgroundColor) {
|
2021-07-15 23:09:23 +02:00
|
|
|
m_splashScreenBackgroundColor = color;
|
2020-10-11 15:33:23 +02:00
|
|
|
m_backgroundColor->setStyleSheet(QString("QToolButton {background-color: %1; border: 1px solid gray;}").arg(color.name()));
|
|
|
|
|
|
|
|
|
|
for (auto &&imageWidget : m_imageWidgets)
|
|
|
|
|
imageWidget->setBackgroundColor(color);
|
|
|
|
|
for (auto &&imageWidget : m_portraitImageWidgets)
|
|
|
|
|
imageWidget->setBackgroundColor(color);
|
|
|
|
|
for (auto &&imageWidget : m_landscapeImageWidgets)
|
|
|
|
|
imageWidget->setBackgroundColor(color);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void SplashScreenContainerWidget::setImageShowMode(const QString &mode)
|
|
|
|
|
{
|
|
|
|
|
bool imageFullScreen;
|
|
|
|
|
|
|
|
|
|
if (mode == "center")
|
|
|
|
|
imageFullScreen = false;
|
|
|
|
|
else if (mode == "fill")
|
|
|
|
|
imageFullScreen = true;
|
|
|
|
|
else
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
for (auto &&imageWidget : m_imageWidgets)
|
|
|
|
|
imageWidget->showImageFullScreen(imageFullScreen);
|
|
|
|
|
for (auto &&imageWidget : m_portraitImageWidgets)
|
|
|
|
|
imageWidget->showImageFullScreen(imageFullScreen);
|
|
|
|
|
for (auto &&imageWidget : m_landscapeImageWidgets)
|
|
|
|
|
imageWidget->showImageFullScreen(imageFullScreen);
|
|
|
|
|
|
|
|
|
|
m_imageShowMode->setCurrentText(mode);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void SplashScreenContainerWidget::createSplashscreenThemes()
|
|
|
|
|
{
|
2021-08-17 16:19:15 +02:00
|
|
|
const QString baseDir = manifestDir(m_textEditorWidget).toString();
|
2020-10-11 15:33:23 +02:00
|
|
|
const QStringList splashscreenThemeFiles = {"/res/values/splashscreentheme.xml",
|
|
|
|
|
"/res/values-port/splashscreentheme.xml",
|
|
|
|
|
"/res/values-land/splashscreentheme.xml"};
|
|
|
|
|
const QStringList splashscreenDrawableFiles = {QString("/res/drawable/%1.xml").arg(splashscreenName),
|
|
|
|
|
QString("/res/drawable/%1.xml").arg(splashscreenPortraitName),
|
|
|
|
|
QString("/res/drawable/%1.xml").arg(splashscreenLandscapeName)};
|
|
|
|
|
QStringList splashscreens[3];
|
|
|
|
|
|
|
|
|
|
if (hasImages())
|
|
|
|
|
splashscreens[0] << splashscreenName << splashscreenFileName;
|
|
|
|
|
if (hasPortraitImages())
|
|
|
|
|
splashscreens[1] << splashscreenPortraitName << splashscreenPortraitFileName;
|
|
|
|
|
if (hasLandscapeImages())
|
|
|
|
|
splashscreens[2] << splashscreenLandscapeName << splashscreenLandscapeFileName;
|
|
|
|
|
|
|
|
|
|
for (int i = 0; i < 3; i++) {
|
|
|
|
|
if (!splashscreens[i].isEmpty()) {
|
|
|
|
|
QDir dir;
|
|
|
|
|
QFile themeFile(baseDir + splashscreenThemeFiles[i]);
|
|
|
|
|
dir.mkpath(QFileInfo(themeFile).absolutePath());
|
|
|
|
|
if (themeFile.open(QFile::WriteOnly | QFile::Truncate)) {
|
|
|
|
|
QXmlStreamWriter stream(&themeFile);
|
|
|
|
|
stream.setAutoFormatting(true);
|
|
|
|
|
stream.writeStartDocument();
|
|
|
|
|
stream.writeStartElement("resources");
|
|
|
|
|
stream.writeStartElement("style");
|
|
|
|
|
stream.writeAttribute("name", "splashScreenTheme");
|
|
|
|
|
stream.writeStartElement("item");
|
|
|
|
|
stream.writeAttribute("name", "android:windowBackground");
|
|
|
|
|
stream.writeCharacters(QLatin1String("@drawable/%1").arg(splashscreens[i].at(0)));
|
|
|
|
|
stream.writeEndElement(); // item
|
|
|
|
|
stream.writeEndElement(); // style
|
|
|
|
|
stream.writeEndElement(); // resources
|
|
|
|
|
stream.writeEndDocument();
|
|
|
|
|
themeFile.close();
|
|
|
|
|
}
|
|
|
|
|
QFile drawableFile(baseDir + splashscreenDrawableFiles[i]);
|
|
|
|
|
dir.mkpath(QFileInfo(drawableFile).absolutePath());
|
|
|
|
|
if (drawableFile.open(QFile::WriteOnly | QFile::Truncate)) {
|
|
|
|
|
QXmlStreamWriter stream(&drawableFile);
|
|
|
|
|
stream.setAutoFormatting(true);
|
|
|
|
|
stream.writeStartDocument();
|
|
|
|
|
stream.writeStartElement("layer-list");
|
|
|
|
|
stream.writeAttribute("xmlns:android", "http://schemas.android.com/apk/res/android");
|
|
|
|
|
stream.writeStartElement("item");
|
|
|
|
|
stream.writeStartElement("shape");
|
|
|
|
|
stream.writeAttribute("android:shape", "rectangle");
|
|
|
|
|
stream.writeEmptyElement("solid");
|
|
|
|
|
stream.writeAttribute("android:color", m_splashScreenBackgroundColor.name());
|
|
|
|
|
stream.writeEndElement(); // shape
|
|
|
|
|
stream.writeEndElement(); // item
|
|
|
|
|
stream.writeStartElement("item");
|
|
|
|
|
stream.writeEmptyElement("bitmap");
|
|
|
|
|
stream.writeAttribute("android:src", QLatin1String("@drawable/%1").arg(splashscreens[i].at(1)));
|
|
|
|
|
stream.writeAttribute("android:gravity", m_imageShowMode->currentText());
|
|
|
|
|
stream.writeEndElement(); // item
|
|
|
|
|
stream.writeEndElement(); // layer-list
|
|
|
|
|
stream.writeEndDocument();
|
|
|
|
|
drawableFile.close();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
QFile::remove(baseDir + splashscreenThemeFiles[i]);
|
|
|
|
|
QFile::remove(baseDir + splashscreenDrawableFiles[i]);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void SplashScreenContainerWidget::checkSplashscreenImage(const QString &name)
|
|
|
|
|
{
|
|
|
|
|
if (isSplashscreenEnabled()) {
|
2021-08-17 16:19:15 +02:00
|
|
|
const FilePath baseDir = manifestDir(m_textEditorWidget);
|
|
|
|
|
const QString paths[] = {extraExtraExtraHighDpiImagePath,
|
|
|
|
|
extraExtraHighDpiImagePath,
|
|
|
|
|
extraHighDpiImagePath,
|
|
|
|
|
highDpiImagePath,
|
|
|
|
|
mediumDpiImagePath,
|
|
|
|
|
lowDpiImagePath};
|
2020-10-11 15:33:23 +02:00
|
|
|
|
|
|
|
|
for (const QString &path : paths) {
|
2021-08-17 16:19:15 +02:00
|
|
|
const FilePath filePath = baseDir.pathAppended(path + name);
|
2021-11-05 15:21:21 +02:00
|
|
|
if (filePath.stringAppended(".png").exists() || filePath.stringAppended(".jpg").exists()
|
|
|
|
|
|| filePath.stringAppended(".jpeg").exists()) {
|
2020-10-11 15:33:23 +02:00
|
|
|
setCurrentIndex(1);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool SplashScreenContainerWidget::isSplashscreenEnabled()
|
|
|
|
|
{
|
|
|
|
|
return (currentIndex() == 0);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
QString SplashScreenContainerWidget::imageName() const
|
|
|
|
|
{
|
|
|
|
|
return splashscreenName;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
QString SplashScreenContainerWidget::portraitImageName() const
|
|
|
|
|
{
|
|
|
|
|
return splashscreenPortraitName;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
QString SplashScreenContainerWidget::landscapeImageName() const
|
|
|
|
|
{
|
|
|
|
|
return splashscreenLandscapeName;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
} // namespace Internal
|
|
|
|
|
} // namespace Android
|