Skip to content

Commit

Permalink
Implement app icon tool for Android
Browse files Browse the repository at this point in the history
  • Loading branch information
vicr123 committed Mar 18, 2024
1 parent b16dd66 commit b20bac3
Show file tree
Hide file tree
Showing 33 changed files with 1,173 additions and 1,054 deletions.
5 changes: 4 additions & 1 deletion cntp-appicontool/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,14 @@ set(SOURCES
platformicongenerator.cpp
main.cpp

platformgenerators/androidplatformicongenerator.cpp

resources.qrc)

set(HEADERS
"combinedicon.h"
"platformicongenerator.h")
"platformicongenerator.h"
platformgenerators/androidplatformicongenerator.h )

IF(${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
set(SOURCES ${SOURCES} platformgenerators/macplatformicongenerator.cpp)
Expand Down
19 changes: 14 additions & 5 deletions cntp-appicontool/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,10 @@ int main(int argc, char* argv[]) {
{"b", "blueprint"},
"Create Blueprint style icon"
});
parser.addOption({
{"p", "platform"},
"Target platform to create icon for", "platform"
});
QCommandLineOption helpOption = parser.addHelpOption();
parser.parse(a.arguments());

Expand Down Expand Up @@ -109,7 +113,7 @@ int main(int argc, char* argv[]) {
}

if (parser.isSet("output-svg")) {
eoutput << "Creating SVG icon";
eoutput << "Creating SVG icon\n";

CombinedIcon crossPlatformSvgIcon;
crossPlatformSvgIcon.setBaseIcon(CombinedIcon::CrossPlatformIcon);
Expand All @@ -125,8 +129,13 @@ int main(int argc, char* argv[]) {
}

if (parser.isSet("output-native")) {
eoutput << "Creating native icon";
PlatformIconGenerator* nativeGenerator = PlatformIconGenerator::iconGeneratorForPlatform();
auto platform = parser.value("platform").toLower();
if (!parser.isSet("platform")) {
platform = "host";
}

eoutput << "Creating native icon\n";
PlatformIconGenerator* nativeGenerator = PlatformIconGenerator::iconGeneratorForPlatform(platform);
if (nativeGenerator) {
CombinedIcon nativeSvgIcon;
nativeSvgIcon.setBaseIcon(CombinedIcon::PlatformSpecificIcon);
Expand All @@ -139,12 +148,12 @@ int main(int argc, char* argv[]) {
nativeGenerator->setOutputFile(parser.value("output-native"));
nativeGenerator->generateIcon();
} else {
eoutput << "warn: No native generator available for this platform.\n";
eoutput << "warn: No native generator available for platform " << platform << ".\n";
}
}

if (parser.isSet("output-rc")) {
eoutput << "Creating resource files";
eoutput << "Creating resource files\n";

CombinedIcon crossPlatformSvgIcon;
crossPlatformSvgIcon.setBaseIcon(CombinedIcon::CrossPlatformIcon);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
#include "androidplatformicongenerator.h"

#include <QDir>
#include <QImage>
#include <QPainter>
#include <QSize>
#include <QSvgRenderer>

AndroidPlatformIconGenerator::AndroidPlatformIconGenerator(QObject* parent) :
PlatformIconGenerator{parent} {
}

void AndroidPlatformIconGenerator::renderPng(QString output, QSizeF size) {
QImage image(size.toSize(), QImage::Format_ARGB32);
image.fill(Qt::transparent);

QPainter imagePainter(&image);

QSvgRenderer renderer(inputSvg().toUtf8());
renderer.render(&imagePainter, QRect(QPoint(0, 0), size.toSize()));
imagePainter.end();

image.save(output);
}

void AndroidPlatformIconGenerator::generateIcon() {
QDir androidDir(outputFile());
QDir resDir(androidDir.absoluteFilePath("res"));

QSizeF baseline{48, 48};
renderPng(resDir.absoluteFilePath("drawable-ldpi/icon.png"), baseline * 0.75);
renderPng(resDir.absoluteFilePath("drawable-mdpi/icon.png"), baseline * 1);
renderPng(resDir.absoluteFilePath("drawable-hdpi/icon.png"), baseline * 1.5);
renderPng(resDir.absoluteFilePath("drawable-xhdpi/icon.png"), baseline * 2);
renderPng(resDir.absoluteFilePath("drawable-xxhdpi/icon.png"), baseline * 3);
renderPng(resDir.absoluteFilePath("drawable-xxxhdpi/icon.png"), baseline * 4);
}
21 changes: 21 additions & 0 deletions cntp-appicontool/platformgenerators/androidplatformicongenerator.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
#ifndef ANDROIDPLATFORMICONGENERATOR_H
#define ANDROIDPLATFORMICONGENERATOR_H

#include "platformicongenerator.h"

class AndroidPlatformIconGenerator : public PlatformIconGenerator {
Q_OBJECT
public:
explicit AndroidPlatformIconGenerator(QObject* parent = nullptr);

signals:

private:
void renderPng(QString output, QSizeF size);

// PlatformIconGenerator interface
public:
void generateIcon();
};

#endif // ANDROIDPLATFORMICONGENERATOR_H
12 changes: 9 additions & 3 deletions cntp-appicontool/platformicongenerator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
#include "platformgenerators/winplatformicongenerator.h"
#endif

#include "platformgenerators/androidplatformicongenerator.h"

struct PlatformIconGeneratorPrivate {
QString inputSvg;
QString outputFile;
Expand Down Expand Up @@ -36,11 +38,15 @@ QString PlatformIconGenerator::outputFile() {
return d->outputFile;
}

PlatformIconGenerator* PlatformIconGenerator::iconGeneratorForPlatform() {
PlatformIconGenerator* PlatformIconGenerator::iconGeneratorForPlatform(QString platform) {
if (platform == "host") {
#ifdef Q_OS_MAC
return new MacPlatformIconGenerator();
return new MacPlatformIconGenerator();
#elif defined(Q_OS_WIN)
return new WinPlatformIconGenerator();
return new WinPlatformIconGenerator();
#endif
} else if (platform == "android") {
return new AndroidPlatformIconGenerator();
}
return nullptr;
}
2 changes: 1 addition & 1 deletion cntp-appicontool/platformicongenerator.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ class PlatformIconGenerator : public QObject
void setOutputFile(QString outputFile);
QString outputFile();

static PlatformIconGenerator* iconGeneratorForPlatform();
static PlatformIconGenerator* iconGeneratorForPlatform(QString platform);

virtual void generateIcon() = 0;

Expand Down
12 changes: 8 additions & 4 deletions lib/cmake-scripts/cntp-appicon.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,6 @@ include_guard()
function(cntp_app_icon targetName)
set(singleValueArgs BASEICON BASEICON_MAC)
cmake_parse_arguments(APP_ICON "" "${singleValueArgs}" "" ${ARGN})

IF(${CMAKE_SYSTEM_NAME} MATCHES "Android")
return()
ENDIF()

get_filename_component(BASEICON_PATH "${APP_ICON_BASEICON}" REALPATH)
get_filename_component(BASEICON_PATH_MAC "${APP_ICON_BASEICON_MAC}" REALPATH)
Expand Down Expand Up @@ -51,6 +47,14 @@ function(cntp_app_icon targetName)

ENDIF()

IF(${CMAKE_SYSTEM_NAME} MATCHES "Android")
get_target_property(ANDROID_PACKAGE_SOURCE_DIR ${targetName} QT_ANDROID_PACKAGE_SOURCE_DIR)

list(APPEND ICONTOOL_ARGS
-n "${ANDROID_PACKAGE_SOURCE_DIR}"
-p android)
ENDIF()

cntp_find_tool(CNTPAPPICONTOOL_PATH cntp-appicontool)

add_custom_command(OUTPUT ${ICONTOOL_OUTPUTS}
Expand Down
28 changes: 28 additions & 0 deletions lib/cmake-scripts/cntp-init.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,10 @@ function(cntp_init target cxx-standard)
endif()

cntp_enable_coroutines(${target})

if(${CMAKE_SYSTEM_NAME} STREQUAL "Android")
cntp_init_android(${target})
endif()
endfunction()

function(cntp_init_plugin parent target cxx-standard share-subdir)
Expand All @@ -52,3 +56,27 @@ function(cntp_init_plugin parent target cxx-standard share-subdir)
CNTP_PARENT_TARGET ${parent})
add_dependencies(${parent}-plugins ${target})
endfunction()

function(cntp_init_android target)
get_target_property(TARGET_TYPE ${target} TYPE)
if (NOT ${TARGET_TYPE} STREQUAL "MODULE_LIBRARY")
return()
endif()

get_target_property(ORIGINAL_PACKAGE_SOURCE_DIR ${target} QT_ANDROID_PACKAGE_SOURCE_DIR)
if (${ORIGINAL_PACKAGE_SOURCE_DIR} STREQUAL "ORIGINAL_PACKAGE_SOURCE_DIR-NOTFOUND")
message(FATAL_ERROR "Target ${target} does not have QT_ANDROID_PACKAGE_SOURCE_DIR defined. Create skeleton Android files and point QT_ANDROID_PACKAGE_SOURCE_DIR to the directory.")
endif()

set(ANDROID_FILES_DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/android-dist)
file(GLOB_RECURSE ANDROID_SKEL_FILES ${ORIGINAL_PACKAGE_SOURCE_DIR}/*)
foreach(file ${ANDROID_SKEL_FILES})
cmake_path(RELATIVE_PATH file BASE_DIRECTORY ${ORIGINAL_PACKAGE_SOURCE_DIR} OUTPUT_VARIABLE relFile)
set(destination ${ANDROID_FILES_DESTINATION}/${relFile})
configure_file(${file} ${destination} COPYONLY)
endforeach()

set_target_propertIES(${target} PROPERTIES
QT_ANDROID_PACKAGE_SOURCE_DIR ${ANDROID_FILES_DESTINATION}
)
endfunction()
4 changes: 2 additions & 2 deletions lib/cmake-scripts/cntp-staticmodule.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,8 @@ function(cntp_add_static_module)

qt_add_library(${ADD_STATIC_MODULE_TARGET_NAME} STATIC)

if(DEFINED ADD_STATIC_MODULE_MODULE_SOURCES)
target_sources(${ADD_STATIC_MODULE_TARGET_NAME} PRIVATE ${ADD_STATIC_MODULE_MODULE_SOURCES})
if(DEFINED ADD_STATIC_MODULE_SOURCES)
target_sources(${ADD_STATIC_MODULE_TARGET_NAME} PRIVATE ${ADD_STATIC_MODULE_SOURCES})
endif()

set_property(TARGET ${ADD_STATIC_MODULE_PARENT_TARGET} APPEND
Expand Down
17 changes: 14 additions & 3 deletions lib/tapplication.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@
#include <QLocalSocket>
#include <QPainter>
#include <QProcess>
#include <QSharedMemory>
#include <QSvgRenderer>
#include <QSysInfo>
#include <QThread>
Expand All @@ -51,6 +50,10 @@
#include <appmodel.h>
#endif

#if QT_CONFIG(sharedmemory)
#include <QSharedMemory>
#endif

#ifdef HAVE_LIBUNWIND
#define UNW_LOCAL_ONLY
#include <libunwind.h>
Expand Down Expand Up @@ -79,8 +82,10 @@ struct tApplicationPrivate {
QString copyrightHolder, copyrightYear;
QMap<tApplication::UrlType, QUrl> applicationUrls;

#if QT_CONFIG(sharedmemory)
QSharedMemory* singleInstanceMemory = nullptr;
QLocalServer* singleInstanceServer = nullptr;
#endif

static bool isInitialised;

Expand Down Expand Up @@ -318,6 +323,7 @@ QStringList tApplication::exportBacktrace(void* data) {
}

tApplication::~tApplication() {
#if QT_CONFIG(sharedmemory)
if (d->singleInstanceMemory) {
d->singleInstanceMemory->detach();
delete d->singleInstanceMemory;
Expand All @@ -328,6 +334,7 @@ tApplication::~tApplication() {
// There's a race condition here...
QThread::sleep(1);
}
#endif
}

void writeCrashSysInfo(QStringList& bt) {
Expand Down Expand Up @@ -720,13 +727,14 @@ tApplication::KnownLicenses tApplication::applicationLicense() {
void tApplication::ensureSingleInstance(QJsonObject launchData) {
QString sharedMemoryName = QStringList({"the-libs-single-instance", organizationName(), applicationName()}).join("_");

#ifdef Q_OS_UNIX
#if QT_CONFIG(sharedmemory)
#ifdef Q_OS_UNIX
// Mitigate crashes by discarding the memory if it is not being used
d->singleInstanceMemory = new QSharedMemory(sharedMemoryName);
d->singleInstanceMemory->attach();
delete d->singleInstanceMemory;
d->singleInstanceMemory = nullptr;
#endif
#endif

d->singleInstanceMemory = new QSharedMemory(sharedMemoryName);
if (d->singleInstanceMemory->create(sharedMemoryName.length())) {
Expand Down Expand Up @@ -755,6 +763,9 @@ void tApplication::ensureSingleInstance(QJsonObject launchData) {

std::exit(0);
}
#else
// Can't ensure single instance on this platform
#endif
}

tApplication::Platform tApplication::currentPlatform() {
Expand Down
Loading

0 comments on commit b20bac3

Please sign in to comment.