diff --git a/CMakeLists.txt b/CMakeLists.txt --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -106,6 +106,7 @@ ) install(FILES + qrc.cmake "${CMAKE_CURRENT_BINARY_DIR}/KF5PackageConfig.cmake" "${CMAKE_CURRENT_BINARY_DIR}/KF5PackageConfigVersion.cmake" "${CMAKE_CURRENT_SOURCE_DIR}/KF5PackageMacros.cmake" diff --git a/KF5PackageMacros.cmake b/KF5PackageMacros.cmake --- a/KF5PackageMacros.cmake +++ b/KF5PackageMacros.cmake @@ -21,28 +21,33 @@ # kpackage_install_package(declarativetoolbox org.kde.toolbox) # installs a generic package # +set(kpackagedir ${CMAKE_CURRENT_LIST_DIR}) function(kpackage_install_package dir component) + message(AUTHOR_WARNING "Deprecated: use kpackage_install_bundle_package") set(root ${ARGV2}) set(install_dir ${ARGV3}) if(NOT root) set(root packages) endif() if(NOT install_dir) set(install_dir ${KPACKAGE_RELATIVE_DATA_INSTALL_DIR}) endif() + install(DIRECTORY ${dir}/ DESTINATION ${KDE_INSTALL_DATADIR}/${install_dir}/${root}/${component} - PATTERN .svn EXCLUDE - PATTERN *.qmlc EXCLUDE - PATTERN CMakeLists.txt EXCLUDE - PATTERN Messages.sh EXCLUDE - PATTERN dummydata EXCLUDE) + PATTERN .svn EXCLUDE + PATTERN *.qmlc EXCLUDE + PATTERN CMakeLists.txt EXCLUDE + PATTERN Messages.sh EXCLUDE + PATTERN dummydata EXCLUDE) + set(metadatajson) if(NOT EXISTS ${component}-${root}-metadata.json AND EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/${dir}/metadata.desktop) set(GENERATED_METADATA "${CMAKE_CURRENT_BINARY_DIR}/${component}-${root}-metadata.json") add_custom_command(OUTPUT ${GENERATED_METADATA} COMMAND KF5::desktoptojson -i ${CMAKE_CURRENT_SOURCE_DIR}/${dir}/metadata.desktop -o ${GENERATED_METADATA}) add_custom_target(${component}-${root}-metadata-json ALL DEPENDS ${GENERATED_METADATA}) install(FILES ${GENERATED_METADATA} DESTINATION ${KDE_INSTALL_DATADIR}/${install_dir}/${root}/${component} RENAME metadata.json) + set(metadatajson ${GENERATED_METADATA}) endif() @@ -77,7 +82,73 @@ set_directory_properties(PROPERTIES kpackageindex "${regenerateindex}") file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/regenerateindex.sh ${regenerateindex}) endif() + endfunction() +#use this version instead: it compresses the contents directory +#into a binary rcc file +function(kpackage_install_bundled_package dir component) + set(root ${ARGV2}) + set(install_dir ${ARGV3}) + if(NOT root) + set(root packages) + endif() + if(NOT install_dir) + set(install_dir ${KPACKAGE_RELATIVE_DATA_INSTALL_DIR}) + endif() + + set(metadatajson) + if(NOT EXISTS ${component}-${root}-metadata.json AND EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/${dir}/metadata.desktop) + set(GENERATED_METADATA "${CMAKE_CURRENT_BINARY_DIR}/${component}-${root}-metadata.json") + add_custom_command(OUTPUT ${GENERATED_METADATA} + COMMAND KF5::desktoptojson -i ${CMAKE_CURRENT_SOURCE_DIR}/${dir}/metadata.desktop -o ${GENERATED_METADATA}) + add_custom_target(${component}-${root}-metadata-json ALL DEPENDS ${GENERATED_METADATA}) + install(FILES ${GENERATED_METADATA} DESTINATION ${KDE_INSTALL_DATADIR}/${install_dir}/${root}/${component} RENAME metadata.json) + set(metadatajson ${GENERATED_METADATA}) + endif() + get_target_property(kpackagetool_cmd KF5::kpackagetool5 LOCATION) + if (${component} MATCHES "^.+\\..+\\.") #we make sure there's at least 2 dots + set(APPDATAFILE "${CMAKE_CURRENT_BINARY_DIR}/${component}.appdata.xml") + + execute_process( + COMMAND ${kpackagetool_cmd} --appstream-metainfo ${CMAKE_CURRENT_SOURCE_DIR}/${dir} --appstream-metainfo-output ${APPDATAFILE} + ERROR_VARIABLE appstreamerror + RESULT_VARIABLE result) + if (NOT result EQUAL 0) + message(WARNING "couldn't generate metainfo for ${component}: ${appstreamerror}") + else() + if(appstreamerror) + message(WARNING "warnings during generation of metainfo for ${component}: ${appstreamerror}") + endif() + + # OPTIONAL because desktop files can be NoDisplay so they render no XML. + install(FILES ${APPDATAFILE} DESTINATION ${KDE_INSTALL_METAINFODIR} OPTIONAL) + endif() + else() + message(WARNING "KPackage components should be specified in reverse domain notation. Appstream information won't be generated for ${component}.") + endif() + + set(newentry "${kpackagetool_cmd} --generate-index -g -p ${CMAKE_INSTALL_PREFIX}/${KDE_INSTALL_DATADIR}/${install_dir}/${root}\n") + get_directory_property(currentindex kpackageindex) + string(FIND "${currentindex}" "${newentry}" alreadyin) + if (alreadyin LESS 0) + set(regenerateindex "${currentindex}${newentry}") + + set_directory_properties(PROPERTIES kpackageindex "${regenerateindex}") + file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/regenerateindex.sh ${regenerateindex}) + endif() + + set(kpkgqrc "${CMAKE_CURRENT_BINARY_DIR}/${component}.qrc") + set(kpkgrcc "${CMAKE_CURRENT_BINARY_DIR}/${component}.rcc") + add_custom_command(OUTPUT ${kpkgqrc} ${kpkgrcc} + DEPENDS ${metadatajson} + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/${dir} + COMMAND cmake "-Dmetadatajson=${metadatajson}" -Droot=${root} -Dinstall_dir=${install_dir} -DBINARYDIR=${CMAKE_CURRENT_BINARY_DIR} -DDIRECTORY="${CMAKE_CURRENT_SOURCE_DIR}/${dir}" -DOUTPUTFILE=${kpkgqrc} -DCOMPONENT=${component} -P ${kpackagedir}/qrc.cmake + COMMAND Qt5::rcc ${kpkgqrc} --binary -compress 5 -threshold 0 -o ${kpkgrcc} + ) + add_custom_target(${component}-${root}-qrc ALL DEPENDS ${kpkgqrc}) + install(FILES ${kpkgrcc} DESTINATION ${KDE_INSTALL_DATADIR}/${install_dir}/${root}/${component}/ RENAME contents.rcc) + +endfunction() diff --git a/qrc.cmake b/qrc.cmake new file mode 100644 --- /dev/null +++ b/qrc.cmake @@ -0,0 +1,17 @@ +set(OUTPUT "\n + +") + +file(GLOB_RECURSE files LIST_DIRECTORIES FALSE RELATIVE ${DIRECTORY} ${DIRECTORY}/*) +foreach(v IN LISTS files) + set(OUTPUT "${OUTPUT} ${DIRECTORY}/${v}\n") +endforeach() + +if (metadatajson) + set(OUTPUT "${OUTPUT} ${metadatajson}\n") +endif() + +set(OUTPUT "${OUTPUT} + +") +file(WRITE "${OUTPUTFILE}" "${OUTPUT}") diff --git a/src/kpackage/package.h b/src/kpackage/package.h --- a/src/kpackage/package.h +++ b/src/kpackage/package.h @@ -23,6 +23,7 @@ #include #include #include +#include #include diff --git a/src/kpackage/package.cpp b/src/kpackage/package.cpp --- a/src/kpackage/package.cpp +++ b/src/kpackage/package.cpp @@ -23,6 +23,7 @@ #include "package.h" #include +#include #include #include @@ -213,6 +214,7 @@ //qDebug() << "metadata: " << d->path << filePath("metadata"); if (!d->metadata && !d->path.isEmpty()) { const QString metadataPath = filePath("metadata"); + if (!metadataPath.isEmpty()) { d->createPackageMetadata(metadataPath); } else { @@ -401,7 +403,13 @@ QUrl Package::fileUrl(const QByteArray &fileType, const QString &filename) const { - return QUrl::fromLocalFile(filePath(fileType, filename)); + QString path = filePath(fileType, filename); + //consytruct a qrc:/ url or a file:/ url, the only two protocols supported + if (path.startsWith(QStringLiteral(":"))) { + return QUrl(QStringLiteral("qrc") + path); + } else { + return QUrl::fromLocalFile(path); + } } QStringList Package::entryList(const QByteArray &key) const @@ -504,6 +512,7 @@ } if (QDir::isRelativePath(p)) { + //FIXME: can searching of the qrc be better? paths << QStandardPaths::locateAll(QStandardPaths::GenericDataLocation, p, QStandardPaths::LocateDirectory); } else { const QDir dir(p); @@ -532,7 +541,15 @@ foreach (const QString &p, paths) { d->checkedValid = false; QDir dir(p); + Q_ASSERT(QFile::exists(dir.canonicalPath())); + + //if it has a contents.rcc, give priority to it + if (dir.exists(QStringLiteral("contents.rcc"))) { + QResource::registerResource(dir.absoluteFilePath(QStringLiteral("contents.rcc"))); + dir = QDir(QStringLiteral(":")+defaultPackageRoot()+path); + } + d->path = dir.canonicalPath(); // canonicalPath() does not include a trailing slash (unless it is the root dir) if (!d->path.endsWith(QLatin1Char('/'))) {