diff --git a/src/plugins/android/CMakeLists.txt b/src/plugins/android/CMakeLists.txt index c19da7c15a0..563732fbd4f 100644 --- a/src/plugins/android/CMakeLists.txt +++ b/src/plugins/android/CMakeLists.txt @@ -51,4 +51,5 @@ add_qtc_plugin(Android javaeditor.cpp javaeditor.h javaindenter.cpp javaindenter.h javaparser.cpp javaparser.h + splashiconcontainerwidget.cpp splashiconcontainerwidget.h ) diff --git a/src/plugins/android/android.pro b/src/plugins/android/android.pro index 529e4d090c7..bdf7efb38f6 100644 --- a/src/plugins/android/android.pro +++ b/src/plugins/android/android.pro @@ -53,7 +53,8 @@ HEADERS += \ androidpackageinstallationstep.h \ androidextralibrarylistmodel.h \ createandroidmanifestwizard.h \ - androidsdkdownloader.h + androidsdkdownloader.h \ + splashiconcontainerwidget.h SOURCES += \ androidconfigurations.cpp \ @@ -99,7 +100,8 @@ SOURCES += \ androidpackageinstallationstep.cpp \ androidextralibrarylistmodel.cpp \ createandroidmanifestwizard.cpp \ - androidsdkdownloader.cpp + androidsdkdownloader.cpp \ + splashiconcontainerwidget.cpp FORMS += \ androidsettingswidget.ui \ diff --git a/src/plugins/android/android.qbs b/src/plugins/android/android.qbs index 0edfce86a53..85cd34d83d6 100644 --- a/src/plugins/android/android.qbs +++ b/src/plugins/android/android.qbs @@ -117,6 +117,8 @@ Project { "javaindenter.h", "javaparser.cpp", "javaparser.h", + "splashiconcontainerwidget.cpp" + "splashiconcontainerwidget.h" ] } } diff --git a/src/plugins/android/androidmanifesteditoriconcontainerwidget.cpp b/src/plugins/android/androidmanifesteditoriconcontainerwidget.cpp index 9a9c01da3e0..a79caa91026 100644 --- a/src/plugins/android/androidmanifesteditoriconcontainerwidget.cpp +++ b/src/plugins/android/androidmanifesteditoriconcontainerwidget.cpp @@ -50,6 +50,7 @@ AndroidManifestEditorIconContainerWidget::AndroidManifestEditorIconContainerWidg { auto iconLayout = new QHBoxLayout(this); auto masterIconButton = new AndroidManifestEditorIconWidget(this, + lowDpiIconSize, lowDpiIconSize, tr("Master icon"), tr("Select master icon")); masterIconButton->setIcon(QIcon::fromTheme(QLatin1String("document-open"), Utils::Icons::OPENFILE.icon())); @@ -63,6 +64,7 @@ AndroidManifestEditorIconContainerWidget::AndroidManifestEditorIconContainerWidg iconLayout->addStretch(1); auto lIconButton = new AndroidManifestEditorIconWidget(this, + lowDpiIconSize, lowDpiIconSize, tr("Low DPI icon"), tr("Select low DPI icon"), textEditorWidget, lowDpiIconPath); @@ -71,6 +73,7 @@ AndroidManifestEditorIconContainerWidget::AndroidManifestEditorIconContainerWidg iconLayout->addStretch(1); auto mIconButton = new AndroidManifestEditorIconWidget(this, + mediumDpiIconSize, mediumDpiIconSize, tr("Medium DPI icon"), tr("Select medium DPI icon"), textEditorWidget, mediumDpiIconPath); @@ -79,6 +82,7 @@ AndroidManifestEditorIconContainerWidget::AndroidManifestEditorIconContainerWidg iconLayout->addStretch(1); auto hIconButton = new AndroidManifestEditorIconWidget(this, + highDpiIconSize, highDpiIconSize, tr("High DPI icon"), tr("Select high DPI icon"), textEditorWidget, highDpiIconPath); diff --git a/src/plugins/android/androidmanifesteditoriconwidget.cpp b/src/plugins/android/androidmanifesteditoriconwidget.cpp index e609b174911..5d0407ca759 100644 --- a/src/plugins/android/androidmanifesteditoriconwidget.cpp +++ b/src/plugins/android/androidmanifesteditoriconwidget.cpp @@ -56,11 +56,11 @@ AndroidManifestEditorIconWidget::AndroidManifestEditorIconWidget(QWidget *parent } AndroidManifestEditorIconWidget::AndroidManifestEditorIconWidget( - QWidget *parent, const QSize &buttonSize, const QString &title, + QWidget *parent, const QSize &iconSize, const QSize &buttonSize, const QString &title, const QString &tooltip, TextEditor::TextEditorWidget *textEditorWidget, const QString &targetIconPath) - : QWidget(parent), m_buttonSize(buttonSize), + : QWidget(parent), m_iconSize(iconSize), m_buttonSize(buttonSize), m_textEditorWidget(textEditorWidget), m_targetIconPath(targetIconPath) { auto iconLayout = new QVBoxLayout(this); @@ -108,9 +108,12 @@ AndroidManifestEditorIconWidget::AndroidManifestEditorIconWidget( this->setLayout(iconLayout); connect(m_button, &QAbstractButton::clicked, this, &AndroidManifestEditorIconWidget::selectIcon); - if (clearButton) + if (clearButton) { connect(clearButton, &QAbstractButton::clicked, this, &AndroidManifestEditorIconWidget::removeIcon); + connect(clearButton, &QAbstractButton::clicked, + this, &AndroidManifestEditorIconWidget::iconRemoved); + } m_iconSelectionText = tooltip; } @@ -128,14 +131,26 @@ void AndroidManifestEditorIconWidget::loadIcon() void AndroidManifestEditorIconWidget::setIconFromPath(const QString &iconPath) { - if (!m_textEditorWidget) { - iconSelected(iconPath); + iconSelected(iconPath); + if (!m_textEditorWidget) return; - } m_iconPath = iconPath; QString baseDir = manifestDir(m_textEditorWidget); copyIcon(); QString iconFile = baseDir + m_targetIconPath; + if (!m_scaled) { + QImage original(iconFile); + if ((original.width() > original.height() && m_buttonSize.height() > m_buttonSize.width()) + || (original.height() > original.width() && m_buttonSize.width() > m_buttonSize.height())) { + auto width = m_buttonSize.height(); + auto height = m_buttonSize.width(); + m_buttonSize = QSize(width, height); + m_button->setMinimumSize(m_buttonSize); + m_button->setMaximumSize(m_buttonSize); + m_button->setIconSize(m_buttonSize); + } + + } m_button->setIcon(QIcon(iconFile)); } @@ -156,11 +171,9 @@ void AndroidManifestEditorIconWidget::removeIcon() qCDebug(androidManifestEditorLog) << "Icon target path empty, cannot remove icon."; return; } - QFileInfo targetFile(targetPath); - if (targetFile.exists()) { - QDir rmRf(targetFile.absoluteDir()); - rmRf.removeRecursively(); - } + QFile targetFile(targetPath); + targetFile.remove(); + m_iconPath.clear(); setScaleWarningLabelVisible(false); m_button->setIcon(QIcon()); } @@ -170,6 +183,11 @@ bool AndroidManifestEditorIconWidget::hasIcon() return !m_iconPath.isEmpty(); } +void AndroidManifestEditorIconWidget::setScaled(bool scaled) +{ + m_scaled = scaled; +} + void AndroidManifestEditorIconWidget::setScaleWarningLabelVisible(bool visible) { if (m_scaleWarningLabel) @@ -187,10 +205,15 @@ void AndroidManifestEditorIconWidget::copyIcon() return; } QFileInfo targetFile(targetPath); + QImage original(m_iconPath); + if (m_iconPath != targetPath) + removeIcon(); + if (original.isNull()) { + m_iconPath.clear(); + return; + } if (m_iconPath == targetPath) return; - removeIcon(); - QImage original(m_iconPath); if (!targetPath.isEmpty() && !original.isNull()) { QDir dir; if (!dir.mkpath(QFileInfo(targetPath).absolutePath())) { @@ -198,11 +221,14 @@ void AndroidManifestEditorIconWidget::copyIcon() m_iconPath.clear(); return; } - QSize targetSize = m_buttonSize; - QImage scaled = original.scaled(targetSize.width(), targetSize.height(), - Qt::KeepAspectRatio, Qt::SmoothTransformation); - setScaleWarningLabelVisible(scaled.width() > original.width() || scaled.height() > original.height()); - scaled.save(targetPath); + QSize targetSize = m_iconSize; + if (m_scaled) { + QImage scaled = original.scaled(targetSize.width(), targetSize.height(), + Qt::KeepAspectRatio, Qt::SmoothTransformation); + setScaleWarningLabelVisible(scaled.width() > original.width() || scaled.height() > original.height()); + scaled.save(targetPath); + } else + original.save(targetPath); m_iconPath = m_targetIconPath; } else { m_iconPath.clear(); diff --git a/src/plugins/android/androidmanifesteditoriconwidget.h b/src/plugins/android/androidmanifesteditoriconwidget.h index 955ac11b8e4..c1049cff3ef 100644 --- a/src/plugins/android/androidmanifesteditoriconwidget.h +++ b/src/plugins/android/androidmanifesteditoriconwidget.h @@ -45,6 +45,7 @@ class AndroidManifestEditorIconWidget : public QWidget public: explicit AndroidManifestEditorIconWidget(QWidget *parent); AndroidManifestEditorIconWidget(QWidget *parent, + const QSize &iconSize, const QSize &buttonSize, const QString &title, const QString &tooltip, @@ -54,9 +55,10 @@ public: void loadIcon(); void setIconFromPath(const QString &iconPath); bool hasIcon(); - + void setScaled(bool scaled); signals: void iconSelected(const QString &path); + void iconRemoved(); private: void selectIcon(); @@ -65,12 +67,14 @@ private: void setScaleWarningLabelVisible(bool visible); private: QToolButton *m_button = nullptr; + QSize m_iconSize; QSize m_buttonSize; QLabel *m_scaleWarningLabel = nullptr; TextEditor::TextEditorWidget *m_textEditorWidget = nullptr; QString m_iconPath; QString m_targetIconPath; QString m_iconSelectionText; + bool m_scaled = true; }; } // namespace Internal diff --git a/src/plugins/android/androidmanifesteditorwidget.cpp b/src/plugins/android/androidmanifesteditorwidget.cpp index 51827af221e..fe8cafb6316 100644 --- a/src/plugins/android/androidmanifesteditorwidget.cpp +++ b/src/plugins/android/androidmanifesteditorwidget.cpp @@ -31,6 +31,7 @@ #include "androidmanifestdocument.h" #include "androidmanager.h" #include "androidservicewidget.h" +#include "splashiconcontainerwidget.h" #include #include @@ -250,11 +251,13 @@ void AndroidManifestEditorWidget::initializePage() } m_iconButtons = new AndroidManifestEditorIconContainerWidget(applicationGroupBox, m_textEditorWidget); - formLayout->addRow(tr("Application icon:"), new QLabel()); - formLayout->addRow(QString(), m_iconButtons); + m_splashButtons = new SplashIconContainerWidget(applicationGroupBox, m_textEditorWidget); + formLayout->addRow(tr("Splash screen:"), new QLabel()); + formLayout->addRow(QString(), m_splashButtons); + m_services = new AndroidServiceWidget(this); formLayout->addRow(tr("Android services:"), m_services); @@ -271,6 +274,8 @@ void AndroidManifestEditorWidget::initializePage() this, setDirtyFunc); connect(m_services, &AndroidServiceWidget::servicesModified, this, setDirtyFunc); + connect(m_splashButtons, &SplashIconContainerWidget::splashScreensModified, + this, setDirtyFunc); connect(m_services, &AndroidServiceWidget::servicesModified, this, &AndroidManifestEditorWidget::clearInvalidServiceInfo); connect(m_services, &AndroidServiceWidget::servicesInvalid, @@ -801,21 +806,27 @@ void AndroidManifestEditorWidget::syncToWidgets(const QDomDocument &doc) m_activityNameLineEdit->setText(activityElem.attribute(QLatin1String("android:label"))); QDomElement metadataElem = activityElem.firstChildElement(QLatin1String("meta-data")); - - const int parseItemsCount = 2; - int counter = 0; + enum ActivityParseGuard {none = 0, libName = 1, styleExtract = 2, stickySplash = 4, done = 8}; + int activityParseGuard = ActivityParseGuard::none; while (!metadataElem.isNull()) { - if (metadataElem.attribute(QLatin1String("android:name")) == QLatin1String("android.app.lib_name")) { + if (metadataElem.attribute(QLatin1String("android:name")) == QLatin1String("android.app.lib_name") + && !(activityParseGuard & ActivityParseGuard::libName)) { m_targetLineEdit->setEditText(metadataElem.attribute(QLatin1String("android:value"))); - ++counter; + activityParseGuard |= ActivityParseGuard::libName; } else if (metadataElem.attribute(QLatin1String("android:name")) - == QLatin1String("android.app.extract_android_style")) { + == QLatin1String("android.app.extract_android_style") + && !(activityParseGuard & ActivityParseGuard::styleExtract)) { m_styleExtractMethod->setCurrentText( metadataElem.attribute(QLatin1String("android:value"))); - ++counter; + activityParseGuard |= ActivityParseGuard::styleExtract; + } else if (metadataElem.attribute(QLatin1String("android:name")) + == QLatin1String("android.app.splash_screen_sticky") + && !(activityParseGuard & ActivityParseGuard::stickySplash)) { + QString sticky = metadataElem.attribute(QLatin1String("android:value")); + m_splashButtons->setSticky(sticky == QLatin1String("true")); + activityParseGuard |= ActivityParseGuard::stickySplash; } - - if (counter == parseItemsCount) + if (activityParseGuard == ActivityParseGuard::done) break; metadataElem = metadataElem.nextSiblingElement(QLatin1String("meta-data")); } @@ -887,6 +898,7 @@ void AndroidManifestEditorWidget::syncToWidgets(const QDomDocument &doc) m_services->setServices(services); m_iconButtons->loadIcons(); + m_splashButtons->loadImages(); m_stayClean = false; m_dirty = false; @@ -1085,28 +1097,7 @@ void AndroidManifestEditorWidget::parseApplication(QXmlStreamReader &reader, QXm } } -static int findService(const QString &name, const QList &data) -{ - for (int i = 0; i < data.size(); ++i) { - if (data[i].className() == name) - return i; - } - return -1; -} - -static void writeServiceMetadataElement(const char *name, - const char *attributeName, - const char *value, - QXmlStreamWriter &writer) -{ - writer.writeStartElement(QLatin1String("meta-data")); - writer.writeAttribute(QLatin1String("android:name"), QLatin1String(name)); - writer.writeAttribute(QLatin1String(attributeName), QLatin1String(value)); - writer.writeEndElement(); - -} - -static void writeServiceMetadataElement(const char *name, +static void writeMetadataElement(const char *name, const char *attributeName, const QString &value, QXmlStreamWriter &writer) @@ -1118,28 +1109,69 @@ static void writeServiceMetadataElement(const char *name, } +void AndroidManifestEditorWidget::parseSplashScreen(QXmlStreamWriter &writer) +{ + if (m_splashButtons->hasImages()) + writeMetadataElement("android.app.splash_screen_drawable", + "android:resource", "@drawable/logo", + writer); + if (m_splashButtons->hasPortraitImages()) + writeMetadataElement("android.app.splash_screen_drawable_portrait", + "android:resource", "@drawable/logo_portrait", + writer); + if (m_splashButtons->hasLandscapeImages()) + writeMetadataElement("android.app.splash_screen_drawable_landscape", + "android:resource", "@drawable/logo_landscape", + writer); + if (m_splashButtons->isSticky()) + writeMetadataElement("android.app.splash_screen_sticky", + "android:value", "true", + writer); +} + +static int findService(const QString &name, const QList &data) +{ + for (int i = 0; i < data.size(); ++i) { + if (data[i].className() == name) + return i; + } + return -1; +} + +static void writeMetadataElement(const char *name, + const char *attributeName, + const char *value, + QXmlStreamWriter &writer) +{ + writer.writeStartElement(QLatin1String("meta-data")); + writer.writeAttribute(QLatin1String("android:name"), QLatin1String(name)); + writer.writeAttribute(QLatin1String(attributeName), QLatin1String(value)); + writer.writeEndElement(); + +} + static void addServiceArgumentsAndLibName(const AndroidServiceData &service, QXmlStreamWriter &writer) { if (!service.isRunInExternalLibrary() && !service.serviceArguments().isEmpty()) - writeServiceMetadataElement("android.app.arguments", "android:value", service.serviceArguments(), writer); + writeMetadataElement("android.app.arguments", "android:value", service.serviceArguments(), writer); if (service.isRunInExternalLibrary() && !service.externalLibraryName().isEmpty()) - writeServiceMetadataElement("android.app.lib_name", "android:value", service.externalLibraryName(), writer); + writeMetadataElement("android.app.lib_name", "android:value", service.externalLibraryName(), writer); else - writeServiceMetadataElement("android.app.lib_name", "android:value", "-- %%INSERT_APP_LIB_NAME%% --", writer); + writeMetadataElement("android.app.lib_name", "android:value", "-- %%INSERT_APP_LIB_NAME%% --", writer); } static void addServiceMetadata(QXmlStreamWriter &writer) { - writeServiceMetadataElement("android.app.qt_sources_resource_id", "android:resource", "@array/qt_sources", writer); - writeServiceMetadataElement("android.app.repository", "android:value", "default", writer); - writeServiceMetadataElement("android.app.qt_libs_resource_id", "android:resource", "@array/qt_libs", writer); - writeServiceMetadataElement("android.app.bundled_libs_resource_id", "android:resource", "@array/bundled_libs", writer); - writeServiceMetadataElement("android.app.bundle_local_qt_libs", "android:value", "-- %%BUNDLE_LOCAL_QT_LIBS%% --", writer); - writeServiceMetadataElement("android.app.use_local_qt_libs", "android:value", "-- %%USE_LOCAL_QT_LIBS%% --", writer); - writeServiceMetadataElement("android.app.libs_prefix", "android:value", "/data/local/tmp/qt/", writer); - writeServiceMetadataElement("android.app.load_local_libs_resource_id", "android:resource", "@array/load_local_libs", writer); - writeServiceMetadataElement("android.app.load_local_jars", "android:value", "-- %%INSERT_LOCAL_JARS%% --", writer); - writeServiceMetadataElement("android.app.static_init_classes", "android:value", "-- %%INSERT_INIT_CLASSES%% --", writer); + writeMetadataElement("android.app.qt_sources_resource_id", "android:resource", "@array/qt_sources", writer); + writeMetadataElement("android.app.repository", "android:value", "default", writer); + writeMetadataElement("android.app.qt_libs_resource_id", "android:resource", "@array/qt_libs", writer); + writeMetadataElement("android.app.bundled_libs_resource_id", "android:resource", "@array/bundled_libs", writer); + writeMetadataElement("android.app.bundle_local_qt_libs", "android:value", "-- %%BUNDLE_LOCAL_QT_LIBS%% --", writer); + writeMetadataElement("android.app.use_local_qt_libs", "android:value", "-- %%USE_LOCAL_QT_LIBS%% --", writer); + writeMetadataElement("android.app.libs_prefix", "android:value", "/data/local/tmp/qt/", writer); + writeMetadataElement("android.app.load_local_libs_resource_id", "android:resource", "@array/load_local_libs", writer); + writeMetadataElement("android.app.load_local_jars", "android:value", "-- %%INSERT_LOCAL_JARS%% --", writer); + writeMetadataElement("android.app.static_init_classes", "android:value", "-- %%INSERT_INIT_CLASSES%% --", writer); } void AndroidManifestEditorWidget::parseService(QXmlStreamReader &reader, QXmlStreamWriter &writer) @@ -1240,6 +1272,7 @@ void AndroidManifestEditorWidget::parseActivity(QXmlStreamReader &reader, QXmlSt while (!reader.atEnd()) { if (reader.isEndElement()) { + parseSplashScreen(writer); if (!found) { writer.writeEmptyElement(QLatin1String("meta-data")); writer.writeAttribute(QLatin1String("android:name"), @@ -1250,10 +1283,16 @@ void AndroidManifestEditorWidget::parseActivity(QXmlStreamReader &reader, QXmlSt writer.writeCurrentToken(reader); return; } else if (reader.isStartElement()) { - if (reader.name() == QLatin1String("meta-data")) - found = parseMetaData(reader, writer) || found; // ORDER MATTERS - else + if (reader.name() == QLatin1String("meta-data")) { + QString metaTagName = reader.attributes().value(QLatin1String("android:name")).toString(); + if (metaTagName.startsWith(QLatin1String("android.app.splash_screen"))) + parseUnknownElement(reader, writer, true); + else + found = parseMetaData(reader, writer) || found; // ORDER MATTERS + } else parseUnknownElement(reader, writer); + } else if (reader.isWhitespace()) { + /* no copying of whitespace */ } else { writer.writeCurrentToken(reader); } diff --git a/src/plugins/android/androidmanifesteditorwidget.h b/src/plugins/android/androidmanifesteditorwidget.h index 1e8808cfc7f..7a69ac49adc 100644 --- a/src/plugins/android/androidmanifesteditorwidget.h +++ b/src/plugins/android/androidmanifesteditorwidget.h @@ -55,6 +55,7 @@ class AndroidManifestEditor; class AndroidManifestEditorIconContainerWidget; class AndroidManifestEditorWidget; class AndroidServiceWidget; +class SplashIconContainerWidget; class PermissionsModel: public QAbstractListModel { @@ -143,6 +144,7 @@ private: void parseManifest(QXmlStreamReader &reader, QXmlStreamWriter &writer); void parseApplication(QXmlStreamReader &reader, QXmlStreamWriter &writer); + void parseSplashScreen(QXmlStreamWriter &writer); void parseService(QXmlStreamReader &reader, QXmlStreamWriter &writer); void parseNewServices(QXmlStreamWriter &writer); void parseActivity(QXmlStreamReader &reader, QXmlStreamWriter &writer); @@ -173,6 +175,7 @@ private: QComboBox *m_targetLineEdit; QComboBox *m_styleExtractMethod; AndroidManifestEditorIconContainerWidget *m_iconButtons; + SplashIconContainerWidget *m_splashButtons; // Permissions QCheckBox *m_defaultPermissonsCheckBox; diff --git a/src/plugins/android/splashiconcontainerwidget.cpp b/src/plugins/android/splashiconcontainerwidget.cpp new file mode 100644 index 00000000000..89ef2d77949 --- /dev/null +++ b/src/plugins/android/splashiconcontainerwidget.cpp @@ -0,0 +1,215 @@ +/**************************************************************************** +** +** Copyright (C) 2020 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +#include "splashiconcontainerwidget.h" +#include "androidmanifesteditoriconwidget.h" + +#include + +#include +#include +#include + +namespace Android { +namespace Internal { + +namespace { +const QString highDpiImagePath = "/res/drawable-hdpi/logo.png"; +const QString mediumDpiImagePath = "/res/drawable-mdpi/logo.png"; +const QString lowDpiImagePath = "/res/drawable-ldpi/logo.png"; +const QString highDpiLandscapeImagePath = "/res/drawable-hdpi/logo_landscape.png"; +const QString mediumDpiLandscapeImagePath = "/res/drawable-mdpi/logo_landscape.png"; +const QString lowDpiLandscapeImagePath = "/res/drawable-ldpi/logo_landscape.png"; +const QString highDpiPortraitImagePath = "/res/drawable-hdpi/logo_portrait.png"; +const QString mediumDpiPortraitImagePath = "/res/drawable-mdpi/logo_portrait.png"; +const QString lowDpiPortraitImagePath = "/res/drawable-ldpi/logo_portrait.png"; +const QSize lowDpiImageSize{200, 320}; +const QSize mediumDpiImageSize{320, 480}; +const QSize highDpiImageSize{480, 720}; +const QSize lowDpiLandscapeImageSize{320, 200}; +const QSize mediumDpiLandscapeImageSize{480, 320}; +const QSize highDpiLandscapeImageSize{720, 480}; +const QSize displaySize{48, 72}; +const QSize landscapeDisplaySize{72, 48}; +} + +static QWidget *createPage(TextEditor::TextEditorWidget *textEditorWidget, + QVector &buttonContainer, + QVector &portraitButtonContainer, + QVector &landscapeButtonContainer, + const QSize &splashSize, + const QSize &portraitSplashSize, + const QSize &landscapeSplashSize, + const QString &splashPath, + const QString &portraitSplashPath, + const QString &landscapeSplashPath) +{ + QWidget *page = new QWidget(); + auto iconLayout = new QHBoxLayout(page); + auto splashButton = new AndroidManifestEditorIconWidget(page, + splashSize, + landscapeDisplaySize, + SplashIconContainerWidget::tr("Splash screen"), + SplashIconContainerWidget::tr("Select splash screen image"), + textEditorWidget, splashPath); + splashButton->setScaled(false); + iconLayout->addWidget(splashButton); + buttonContainer.push_back(splashButton); + iconLayout->addStretch(1); + + auto portraitButton = new AndroidManifestEditorIconWidget(page, + portraitSplashSize, + displaySize, + SplashIconContainerWidget::tr("Portrait splash screen"), + SplashIconContainerWidget::tr("Select portrait splash screen image"), + textEditorWidget, portraitSplashPath); + iconLayout->addWidget(portraitButton); + portraitButtonContainer.push_back(portraitButton); + iconLayout->addStretch(1); + + auto landscapeButton = new AndroidManifestEditorIconWidget(page, + landscapeSplashSize, + landscapeDisplaySize, + SplashIconContainerWidget::tr("Landscape splash screen"), + SplashIconContainerWidget::tr("Select landscape splash screen image"), + textEditorWidget, landscapeSplashPath); + iconLayout->addWidget(landscapeButton); + landscapeButtonContainer.push_back(landscapeButton); + iconLayout->addStretch(1); + + iconLayout->addStretch(6); + + return page; +} + + +SplashIconContainerWidget::SplashIconContainerWidget( + QWidget *parent, + TextEditor::TextEditorWidget *textEditorWidget) + : QWidget(parent) +{ + auto layout = new QVBoxLayout(this); + m_stickyCheck = new QCheckBox(tr("Sticky splash screen"), this); + m_stickyCheck->setToolTip(tr("A non-sticky splash screen is hidden automatically when an activity is drawn.\n" + "To hide a sticky splash screen, invoke QtAndroid::hideSplashScreen().")); + QTabWidget *tab = new QTabWidget(this); + + auto hdpiPage = createPage(textEditorWidget, + m_imageButtons, m_portraitImageButtons, m_landscapeImageButtons, + highDpiImageSize, + highDpiImageSize, + highDpiLandscapeImageSize, + highDpiImagePath, highDpiPortraitImagePath, highDpiLandscapeImagePath); + tab->addTab(hdpiPage, tr("High DPI splash screen")); + auto mdpiPage = createPage(textEditorWidget, + m_imageButtons, m_portraitImageButtons, m_landscapeImageButtons, + mediumDpiImageSize, + mediumDpiImageSize, + mediumDpiLandscapeImageSize, + mediumDpiImagePath, mediumDpiPortraitImagePath, mediumDpiLandscapeImagePath); + tab->addTab(mdpiPage, tr("Medium DPI splash screen")); + auto ldpiPage = createPage(textEditorWidget, + m_imageButtons, m_portraitImageButtons, m_landscapeImageButtons, + lowDpiImageSize, + lowDpiImageSize, + lowDpiLandscapeImageSize, + lowDpiImagePath, lowDpiPortraitImagePath, lowDpiLandscapeImagePath); + tab->addTab(ldpiPage, tr("Low DPI splash screen")); + layout->addWidget(m_stickyCheck); + layout->setAlignment(m_stickyCheck, Qt::AlignLeft); + layout->addWidget(tab); + for (auto &&imageButton : m_imageButtons) + connect(imageButton, &AndroidManifestEditorIconWidget::iconSelected, + this, &SplashIconContainerWidget::splashScreensModified); + for (auto &&imageButton : m_portraitImageButtons) { + connect(imageButton, &AndroidManifestEditorIconWidget::iconSelected, + this, &SplashIconContainerWidget::splashScreensModified); + connect(imageButton, &AndroidManifestEditorIconWidget::iconRemoved, + this, &SplashIconContainerWidget::splashScreensModified); + } + for (auto &&imageButton : m_landscapeImageButtons) { + connect(imageButton, &AndroidManifestEditorIconWidget::iconSelected, + this, &SplashIconContainerWidget::splashScreensModified); + connect(imageButton, &AndroidManifestEditorIconWidget::iconRemoved, + this, &SplashIconContainerWidget::splashScreensModified); + } + connect(m_stickyCheck, &QCheckBox::stateChanged, [this](int state) { + bool old = m_splashScreenSticky; + m_splashScreenSticky = (state == Qt::Checked); + if (old != m_splashScreenSticky) + splashScreensModified(); + }); +} + +void SplashIconContainerWidget::loadImages() +{ + for (auto &&imageButton : m_imageButtons) + imageButton->loadIcon(); + for (auto &&imageButton : m_portraitImageButtons) + imageButton->loadIcon(); + for (auto &&imageButton : m_landscapeImageButtons) + imageButton->loadIcon(); +} + +bool SplashIconContainerWidget::hasImages() +{ + for (auto &&iconButton : m_imageButtons) { + if (iconButton->hasIcon()) + return true; + } + return false; +} + +bool SplashIconContainerWidget::hasPortraitImages() +{ + for (auto &&iconButton : m_portraitImageButtons) { + if (iconButton->hasIcon()) + return true; + } + return false; +} + +bool SplashIconContainerWidget::hasLandscapeImages() +{ + for (auto &&iconButton : m_landscapeImageButtons) { + if (iconButton->hasIcon()) + return true; + } + return false; +} + +bool SplashIconContainerWidget::isSticky() +{ + return m_splashScreenSticky; +} + +void SplashIconContainerWidget::setSticky(bool sticky) +{ + m_splashScreenSticky = sticky; + m_stickyCheck->setCheckState(m_splashScreenSticky ? Qt::Checked : Qt::Unchecked); +} + +} // namespace Internal +} // namespace Android diff --git a/src/plugins/android/splashiconcontainerwidget.h b/src/plugins/android/splashiconcontainerwidget.h new file mode 100644 index 00000000000..d7d33e0920f --- /dev/null +++ b/src/plugins/android/splashiconcontainerwidget.h @@ -0,0 +1,67 @@ +/**************************************************************************** +** +** Copyright (C) 2020 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +#pragma once + +#include +#include + +QT_BEGIN_NAMESPACE +class QCheckBox; +QT_END_NAMESPACE + +namespace TextEditor { + class TextEditorWidget; +} + +namespace Android { +namespace Internal { + +class AndroidManifestEditorIconWidget; + +class SplashIconContainerWidget : public QWidget +{ + Q_OBJECT +public: + explicit SplashIconContainerWidget(QWidget *parent, + TextEditor::TextEditorWidget *textEditorWidget); + void loadImages(); + bool hasImages(); + bool hasPortraitImages(); + bool hasLandscapeImages(); + bool isSticky(); + void setSticky(bool sticky); +signals: + void splashScreensModified(); +private: + QVector m_imageButtons; + QVector m_portraitImageButtons; + QVector m_landscapeImageButtons; + bool m_splashScreenSticky = false; + QCheckBox *m_stickyCheck = nullptr; +}; + +} // namespace Internal +} // namespace Android