diff --git a/AUTHORS b/AUTHORS index 190d298..dd2061e 100644 --- a/AUTHORS +++ b/AUTHORS @@ -4,7 +4,8 @@ Upstream Authors: Copyright: Copyright (c) 2010-2012 Razor team - Copyright (c) 2012-2014 LXQt team + Copyright (c) 2012-2016 LXQt team -License: GPL-2 and LGPL-2.1+ -The full text of the licenses can be found in the 'COPYING' file. +License: LGPL-2.1+ and LGPL-2.1-or-3-with-Digia-1.1-exception +The full text of the LGPL-2.1+ license can be found in the 'COPYING' file. +The Digia-1.1 exception can be found in the 'Digia-Qt-LGPL-Exception-1.1' file. diff --git a/CMakeLists.txt b/CMakeLists.txt index d7c6686..7c4586c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -2,10 +2,29 @@ cmake_minimum_required(VERSION 3.0.2 FATAL_ERROR) project(libqtxdg) option(BUILD_TESTS "Builds tests" OFF) +option(BUILD_DEV_UTILS "Builds and install development utils" OFF) # additional cmake files set(CMAKE_MODULE_PATH "${CMAKE_MODULE_PATH}" "${CMAKE_CURRENT_SOURCE_DIR}/cmake") +if (CMAKE_VERSION VERSION_LESS "3.1") + include(CheckCXXCompilerFlag) + CHECK_CXX_COMPILER_FLAG("-std=c++11" COMPILER_SUPPORTS_CXX11) + if(COMPILER_SUPPORTS_CXX11) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") + else() + CHECK_CXX_COMPILER_FLAG("-std=c++0x" COMPILER_SUPPORTS_CXX0X) + # -std=c++0x is deprecated but some tools e.g. qmake or older gcc are still using it + if(COMPILER_SUPPORTS_CXX0X) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++0x") + else() + message(FATAL_ERROR "Compiler ${CMAKE_CXX_COMPILER} does not support c++11/c++0x") + endif() + endif() +else() + set(CMAKE_CXX_STANDARD 11) +endif() + set(QTXDG_MAJOR_VERSION 1) set(QTXDG_MINOR_VERSION 3) set(QTXDG_PATCH_VERSION 0) @@ -13,6 +32,7 @@ set(QTXDG_VERSION_STRING ${QTXDG_MAJOR_VERSION}.${QTXDG_MINOR_VERSION}.${QTXDG_P include(GNUInstallDirs) # Standard directories for installation include(CMakePackageConfigHelpers) +include(GenerateExportHeader) include(create_portable_headers) include(create_pkgconfig_file) include(compiler_settings NO_POLICY_SCOPE) @@ -20,6 +40,7 @@ include(compiler_settings NO_POLICY_SCOPE) find_package(Qt5Widgets REQUIRED QUIET) find_package(Qt5Xml REQUIRED QUIET) find_package(Qt5DBus REQUIRED QUIET) + if (BUILD_TESTS) find_package(Qt5Test REQUIRED QUIET) endif() @@ -28,15 +49,16 @@ endif() set(QTXDGX_LIBRARY_NAME "Qt5Xdg") set(QTXDGX_FILE_NAME "qt5xdg") +set(QTXDGX_ICONLOADER_LIBRARY_NAME "Qt5XdgIconLoader") +set(QTXDGX_ICONLOADER_FILE_NAME "qt5xdgiconloader") + set(QTXDGX_PKG_CONFIG_DESCRIPTION "Qt5Xdg, a Qt5 implementation of XDG standards") -set(QTXDGX_PKG_CONFIG_REQUIRES "Qt5Core, Qt5Xml, Qt5Widgets, Qt5DBus") -set(QTXDGX_INTREE_INCLUDEDIR "${CMAKE_CURRENT_BINARY_DIR}/InTreeBuild/include") +set(QTXDGX_PKG_CONFIG_REQUIRES "Qt5Core, Qt5Xml, Qt5Widgets, Qt5DBus, Qt5XdgIconLoader") -include_directories( - "${Qt5Gui_PRIVATE_INCLUDE_DIRS}" -) +set(QTXDGX_ICONLOADER_PKG_CONFIG_DESCRIPTION "Qt5XdgIconLader, a Qt5 XDG Icon Loader") +set(QTXDGX_ICONLOADER_PKG_CONFIG_REQUIRES "Qt5Gui") -set(QTX_LIBRARIES Qt5::Widgets Qt5::Xml Qt5::DBus) +set(QTXDGX_INTREE_INCLUDEDIR "${CMAKE_CURRENT_BINARY_DIR}/InTreeBuild/include") if (NOT CMAKE_BUILD_TYPE) set ( CMAKE_BUILD_TYPE Release ) @@ -44,101 +66,45 @@ endif (NOT CMAKE_BUILD_TYPE) message(STATUS "Building with Qt ${Qt5Core_VERSION_STRING}") -set(libqtxdg_PUBLIC_H_FILES - xdgaction.h - xdgdesktopfile.h - xdgdirs.h - xdgicon.h - xdgmenu.h - xdgmenuwidget.h - xmlhelper.h - xdgautostart.h - xdgmacros.h - xdgmimetype.h -) - -set(libqtxdg_PUBLIC_CLASSES - XdgAction - XdgDesktopFile - XdgDirs - XdgIcon - XdgMenu - XdgMenuWidget - XmlHelper - XdgAutoStart - XdgMimeType -) +add_subdirectory(xdgiconloader) +add_subdirectory(qtxdg) -set(libqtxdg_PRIVATE_H_FILES - xdgmenuapplinkprocessor.h - xdgmenulayoutprocessor.h - xdgmenu_p.h - xdgmenureader.h - xdgmenurules.h - xdgdesktopfile_p.h -) - -set(libqtxdg_CPP_FILES - xdgaction.cpp - xdgdesktopfile.cpp - xdgdirs.cpp - xdgicon.cpp - xdgmenuapplinkprocessor.cpp - xdgmenu.cpp - xdgmenulayoutprocessor.cpp - xdgmenureader.cpp - xdgmenurules.cpp - xdgmenuwidget.cpp - xmlhelper.cpp - xdgautostart.cpp - xdgmimetype.cpp - qiconfix/qiconloader.cpp -) - -set(libqtxdg_MOCS - xdgaction.h - xdgmenuapplinkprocessor.h - xdgmenu.h - xdgmenu_p.h - xdgmenureader.h - xdgmenurules.h - xdgmenuwidget.h -) - -set(libqtxdg_PRIVATE_INSTALLABLE_H_FILES - qiconfix/qiconloader_p.h -) - -QT5_WRAP_CPP(libqtxdg_CXX_FILES ${libqtxdg_MOCS}) - -add_library(${QTXDGX_LIBRARY_NAME} SHARED - ${libqtxdg_PUBLIC_H_FILES} - ${libqtxdg_PRIVATE_H_FILES} - ${libqtxdg_PRIVATE_INSTALLABLE_H_FILES} - ${libqtxdg_PRIVATE_H_FILES} - ${libqtxdg_CPP_FILES} - ${libqtxdg_CXX_FILES} -) +if(BUILD_TESTS) + enable_testing() + target_compile_definitions(${QTXDGX_LIBRARY_NAME} + PRIVATE "QTXDG_TESTS=\"1\"" + ) + add_subdirectory(test) +else() + message(STATUS "") + message(STATUS "For building tests use -DBUILD_TESTS=Yes option.") + message(STATUS "") +endif() +if (BUILD_DEV_UTILS) + add_subdirectory(util) +endif() -target_link_libraries(${QTXDGX_LIBRARY_NAME} - PUBLIC - ${QTX_LIBRARIES} +configure_package_config_file( + "${PROJECT_SOURCE_DIR}/cmake/${QTXDGX_FILE_NAME}-config.cmake.in" + "${CMAKE_BINARY_DIR}/${QTXDGX_FILE_NAME}-config.cmake" + INSTALL_DESTINATION "${CMAKE_INSTALL_DATADIR}/cmake/${QTXDGX_FILE_NAME}" ) -set_target_properties(${QTXDGX_LIBRARY_NAME} PROPERTIES - VERSION ${QTXDG_VERSION_STRING} - SOVERSION ${QTXDG_MAJOR_VERSION} +write_basic_package_version_file( + "${CMAKE_BINARY_DIR}/${QTXDGX_FILE_NAME}-config-version.cmake" + VERSION ${QTXDG_VERSION_STRING} + COMPATIBILITY AnyNewerVersion ) configure_package_config_file( - "${CMAKE_CURRENT_SOURCE_DIR}/cmake/${QTXDGX_FILE_NAME}-config.cmake.in" - "${CMAKE_BINARY_DIR}/${QTXDGX_FILE_NAME}-config.cmake" - INSTALL_DESTINATION "${CMAKE_INSTALL_DATADIR}/cmake/${QTXDGX_FILE_NAME}" + "${PROJECT_SOURCE_DIR}/cmake/${QTXDGX_ICONLOADER_FILE_NAME}-config.cmake.in" + "${CMAKE_BINARY_DIR}/${QTXDGX_ICONLOADER_FILE_NAME}-config.cmake" + INSTALL_DESTINATION "${CMAKE_INSTALL_DATADIR}/cmake/${QTXDGX_ICONLOADER_FILE_NAME}" ) write_basic_package_version_file( - "${CMAKE_BINARY_DIR}/${QTXDGX_FILE_NAME}-config-version.cmake" + "${CMAKE_BINARY_DIR}/${QTXDGX_ICONLOADER_FILE_NAME}-config-version.cmake" VERSION ${QTXDG_VERSION_STRING} COMPATIBILITY AnyNewerVersion ) @@ -150,97 +116,50 @@ create_pkgconfig_file( INCLUDEDIRS ${QTXDGX_FILE_NAME} LIBS ${QTXDGX_LIBRARY_NAME} REQUIRES ${QTXDGX_PKG_CONFIG_REQUIRES} + REQUIRES_PRIVATE ${QTXDGX_ICONLOADER_LIBRARY_NAME} VERSION ${QTXDG_VERSION_STRING} INSTALL ) -target_compile_definitions(${QTXDGX_LIBRARY_NAME} - PRIVATE "QTXDG_COMPILATION=\"1\"" -) - -target_include_directories(${QTXDGX_LIBRARY_NAME} - INTERFACE "$" - INTERFACE "$" - INTERFACE "$" -) - -# include directories and targets for the in tree build -target_include_directories(${QTXDGX_LIBRARY_NAME} - INTERFACE "$" - INTERFACE "$" - INTERFACE "$" -) - -export(TARGETS ${QTXDGX_LIBRARY_NAME} FILE "${CMAKE_BINARY_DIR}/${QTXDGX_FILE_NAME}-targets.cmake") -# end of in tree build stuff - -# create the portble headers -create_portable_headers(libqtxdg_PORTABLE_HEADERS - HEADER_NAMES ${libqtxdg_PUBLIC_CLASSES} - OUTPUT_DIR "${QTXDGX_INTREE_INCLUDEDIR}/${QTXDGX_FILE_NAME}" -) - -# Copy public headers (in tree building) -foreach(h ${libqtxdg_PUBLIC_H_FILES}) - get_filename_component(bh ${h} NAME) - configure_file(${h} "${QTXDGX_INTREE_INCLUDEDIR}/${QTXDGX_FILE_NAME}/${bh}" COPYONLY) -endforeach() - -# Copy private headers (in tree building) -foreach(h ${libqtxdg_PRIVATE_INSTALLABLE_H_FILES}) - get_filename_component(bh ${h} NAME) - configure_file(${h} "${QTXDGX_INTREE_INCLUDEDIR}/${QTXDGX_FILE_NAME}/${QTXDG_VERSION_STRING}/private/qtxdg/${bh}" COPYONLY) -endforeach() - -install(TARGETS - ${QTXDGX_LIBRARY_NAME} DESTINATION "${CMAKE_INSTALL_LIBDIR}" - EXPORT "${QTXDGX_FILE_NAME}-targets" - COMPONENT Runtime -) - -install(EXPORT - "${QTXDGX_FILE_NAME}-targets" - DESTINATION "${CMAKE_INSTALL_DATADIR}/cmake/${QTXDGX_FILE_NAME}" - COMPONENT Devel +create_pkgconfig_file( + PACKAGE_NAME ${QTXDGX_ICONLOADER_LIBRARY_NAME} + DESCRIPTIVE_NAME ${QTXDGX_ICONLOADER_LIBRARY_NAME} + DESCRIPTION ${QTXDGX_ICONLOADER_PKG_CONFIG_DESCRIPTION} + INCLUDEDIRS ${QTXDGX_ICONLOADER_FILE_NAME} + LIBS ${QTXDGX_ICONLOADER_LIBRARY_NAME} + REQUIRES ${QTXDGX_ICONLOADER_PKG_CONFIG_REQUIRES} + VERSION ${QTXDG_VERSION_STRING} + INSTALL ) install(FILES - ${libqtxdg_PUBLIC_H_FILES} - DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}/${QTXDGX_FILE_NAME}" + "${CMAKE_BINARY_DIR}/${QTXDGX_FILE_NAME}-config.cmake" + "${CMAKE_BINARY_DIR}/${QTXDGX_FILE_NAME}-config-version.cmake" + DESTINATION "${CMAKE_INSTALL_DATADIR}/cmake/${QTXDGX_FILE_NAME}" COMPONENT Devel ) install(FILES - ${libqtxdg_PRIVATE_INSTALLABLE_H_FILES} - DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}/${QTXDGX_FILE_NAME}/${QTXDG_VERSION_STRING}/private/qtxdg" + "${CMAKE_BINARY_DIR}/${QTXDGX_ICONLOADER_FILE_NAME}-config.cmake" + "${CMAKE_BINARY_DIR}/${QTXDGX_ICONLOADER_FILE_NAME}-config-version.cmake" + DESTINATION "${CMAKE_INSTALL_DATADIR}/cmake/${QTXDGX_ICONLOADER_FILE_NAME}" COMPONENT Devel ) -install(FILES - "${CMAKE_BINARY_DIR}/${QTXDGX_FILE_NAME}-config.cmake" - "${CMAKE_BINARY_DIR}/${QTXDGX_FILE_NAME}-config-version.cmake" +install(EXPORT + "${QTXDGX_FILE_NAME}-targets" DESTINATION "${CMAKE_INSTALL_DATADIR}/cmake/${QTXDGX_FILE_NAME}" + FILE "${QTXDGX_FILE_NAME}-targets.cmake" COMPONENT Devel ) -install(FILES - ${libqtxdg_PORTABLE_HEADERS} - DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}/${QTXDGX_FILE_NAME}" +install(EXPORT + "${QTXDGX_ICONLOADER_FILE_NAME}-targets" + DESTINATION "${CMAKE_INSTALL_DATADIR}/cmake/${QTXDGX_ICONLOADER_FILE_NAME}" + FILE "${QTXDGX_ICONLOADER_FILE_NAME}-targets.cmake" COMPONENT Devel ) -if(BUILD_TESTS) - enable_testing() - target_compile_definitions(${QTXDGX_LIBRARY_NAME} - PRIVATE "QTXDG_TESTS=\"1\"" - ) - add_subdirectory(test) -else() - message(STATUS "") - message(STATUS "For building tests use -DBUILD_TESTS=Yes option.") - message(STATUS "") -endif() - # uninstall target configure_file( "${CMAKE_CURRENT_SOURCE_DIR}/cmake/cmake_uninstall.cmake.in" diff --git a/Digia-Qt-LGPL-Exception-1.1 b/Digia-Qt-LGPL-Exception-1.1 new file mode 100644 index 0000000..7e2e30f --- /dev/null +++ b/Digia-Qt-LGPL-Exception-1.1 @@ -0,0 +1,22 @@ +Digia Qt LGPL Exception version 1.1 + +As an additional permission to the GNU Lesser General Public License version +2.1, the object code form of a "work that uses the Library" may incorporate +material from a header file that is part of the Library. You may distribute +such object code under terms of your choice, provided that: + (i) the header files of the Library have not been modified; and + (ii) the incorporated material is limited to numerical parameters, data + structure layouts, accessors, macros, inline functions and + templates; and + (iii) you comply with the terms of Section 6 of the GNU Lesser General + Public License version 2.1. + +Moreover, you may apply this exception to a modified version of the Library, +provided that such modification does not involve copying material from the +Library into the modified Library's header files unless such material is +limited to (i) numerical parameters; (ii) data structure layouts; +(iii) accessors; and (iv) small macros, templates and inline functions of +five lines or less in length. + +Furthermore, you are not required to apply this additional permission to a +modified version of the Library. diff --git a/README b/README deleted file mode 100644 index 4abf265..0000000 --- a/README +++ /dev/null @@ -1,25 +0,0 @@ -Overview -======== -libqtxdg is An Qt implementation of freedesktop.org xdg specifications. -It's built with Qt5. - - -Dependencies -============ - Qt5 - - -Configuration -============ -libqtxdg uses the CMake build system. Everything that applies to CMake also -applies here. - -Configuration options: - BUILD_TESTS Builds tests, defaults to OFF - -Configuration Examples: - Build library and build self tests: - cmake -DBUILD_TESTS=ON .. - - Build the library without building self tests - cmake .. diff --git a/README.md b/README.md new file mode 100644 index 0000000..1bc511e --- /dev/null +++ b/README.md @@ -0,0 +1,21 @@ +##Overview + +```libqtxdg``` is a Qt implementation of freedesktop.org XDG specifications which is built with Qt5. + +##Dependencies + + - Qt5 + +##Configuration + +```libqtxdg``` uses the CMake build system. Everything that applies to CMake also +applies here. + +###Configuration options: + BUILD_TESTS Builds tests, defaults to OFF + BUILD_DEV_UTILS Builds and install development utils, defaults to OFF + +###Configuration Examples: +Build library and build self tests: ```cmake -DBUILD_TESTS=ON ..``` + +Build the library without building self tests : ```cmake ..``` diff --git a/cmake/compiler_settings.cmake b/cmake/compiler_settings.cmake index da31e77..044b36a 100644 --- a/cmake/compiler_settings.cmake +++ b/cmake/compiler_settings.cmake @@ -92,3 +92,14 @@ set(QTXDG_COMMON_WARNING_FLAGS "-Wall") #----------------------------------------------------------------------------- list(APPEND QTXDG_WARNING_FLAGS ${QTXDG_COMMON_WARNING_FLAGS}) add_definitions(${QTXDG_WARNING_FLAGS}) + +#----------------------------------------------------------------------------- +# String conversion flags +#----------------------------------------------------------------------------- +add_definitions( + -DQT_USE_QSTRINGBUILDER + -DQT_NO_CAST_FROM_ASCII + -DQT_NO_CAST_TO_ASCII + -DQT_NO_URL_CAST_FROM_STRING + -DQT_NO_CAST_FROM_BYTEARRAY +) diff --git a/cmake/qt5xdg-config.cmake.in b/cmake/qt5xdg-config.cmake.in index dc312d7..045c920 100644 --- a/cmake/qt5xdg-config.cmake.in +++ b/cmake/qt5xdg-config.cmake.in @@ -5,6 +5,7 @@ include(CMakeFindDependencyMacro) find_dependency(Qt5Widgets) find_dependency(Qt5Xml) find_dependency(Qt5DBus) +find_dependency(Qt5XdgIconLoader) if (CMAKE_VERSION VERSION_GREATER 2.8.12) cmake_policy(SET CMP0024 OLD) diff --git a/cmake/qt5xdgiconloader-config.cmake.in b/cmake/qt5xdgiconloader-config.cmake.in new file mode 100644 index 0000000..0582b60 --- /dev/null +++ b/cmake/qt5xdgiconloader-config.cmake.in @@ -0,0 +1,10 @@ +@PACKAGE_INIT@ + +include(CMakeFindDependencyMacro) + +find_dependency(Qt5Gui) + +if (CMAKE_VERSION VERSION_GREATER 2.8.12) + cmake_policy(SET CMP0024 OLD) +endif() +include("${CMAKE_CURRENT_LIST_DIR}/qt5xdgiconloader-targets.cmake") diff --git a/debian/changelog b/debian/changelog index c2eb939..2786bc8 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,6 +1,6 @@ libqtxdg (1.3.1~50-g4fde773-1) experimental; urgency=medium - * New pre-release 1.3.1 + * New pre-release 1.3.1~50-g4fde773 * Fixed libqt5xdgiconloader-dev.install * Reworked descriptions in debian/control to prevent lintian whining * Fixed symbols version @@ -13,8 +13,9 @@ libqtxdg (1.3.1~50-g4fde773-1) experimental; urgency=medium * Bump years in copyright * Added hardening=+all * Added README.md to debian/docs + * set CMAKE_BUILD_TYPE=RelWithDebInfo - -- Alf Gaida Sat, 09 Jul 2016 19:39:42 +0200 + -- Alf Gaida Sat, 09 Jul 2016 20:16:32 +0200 libqtxdg (1.3.0-3) unstable; urgency=medium diff --git a/debian/libqt5xdgiconloader-dev.install b/debian/libqt5xdgiconloader-dev.install index bed378c..b24b62b 100644 --- a/debian/libqt5xdgiconloader-dev.install +++ b/debian/libqt5xdgiconloader-dev.install @@ -6,4 +6,4 @@ usr/lib/*/pkgconfig/Qt5XdgIconLoader.pc usr/share/cmake/qt5xdgiconloader/qt5xdgiconloader-config-version.cmake usr/share/cmake/qt5xdgiconloader/qt5xdgiconloader-config.cmake usr/share/cmake/qt5xdgiconloader/qt5xdgiconloader-targets.cmake -usr/share/cmake/qt5xdgiconloader/qt5xdgiconloader-targets-none.cmake +usr/share/cmake/qt5xdgiconloader/qt5xdgiconloader-targets-relwithdebinfo.cmake diff --git a/debian/rules b/debian/rules index 367cf7b..32812f6 100755 --- a/debian/rules +++ b/debian/rules @@ -8,3 +8,8 @@ export DEB_BUILD_MAINT_OPTIONS = hardening=+all dh ${@} --buildsystem cmake \ --parallel \ --fail-missing + +override_dh_auto_configure: + dh_auto_configure -- \ + -DCMAKE_BUILD_TYPE=RelWithDebInfo + diff --git a/qtxdg/CMakeLists.txt b/qtxdg/CMakeLists.txt new file mode 100644 index 0000000..6eaea07 --- /dev/null +++ b/qtxdg/CMakeLists.txt @@ -0,0 +1,146 @@ +set(QTX_LIBRARIES Qt5::Widgets Qt5::Xml Qt5::DBus) + +include_directories( + "${Qt5Gui_PRIVATE_INCLUDE_DIRS}" +) +set(libqtxdg_PUBLIC_H_FILES + xdgaction.h + xdgdesktopfile.h + xdgdirs.h + xdgicon.h + xdgmenu.h + xdgmenuwidget.h + xmlhelper.h + xdgautostart.h + xdgmacros.h + xdgmimetype.h +) + +set(libqtxdg_PUBLIC_CLASSES + XdgAction + XdgDesktopFile + XdgDirs + XdgIcon + XdgMenu + XdgMenuWidget + XmlHelper + XdgAutoStart + XdgMimeType +) + +set(libqtxdg_PRIVATE_H_FILES + xdgmenuapplinkprocessor.h + xdgmenulayoutprocessor.h + xdgmenu_p.h + xdgmenureader.h + xdgmenurules.h + xdgdesktopfile_p.h +) + +set(libqtxdg_CPP_FILES + xdgaction.cpp + xdgdesktopfile.cpp + xdgdirs.cpp + xdgicon.cpp + xdgmenuapplinkprocessor.cpp + xdgmenu.cpp + xdgmenulayoutprocessor.cpp + xdgmenureader.cpp + xdgmenurules.cpp + xdgmenuwidget.cpp + xmlhelper.cpp + xdgautostart.cpp + xdgmimetype.cpp +) + +set(libqtxdg_MOCS + xdgaction.h + xdgmenuapplinkprocessor.h + xdgmenu.h + xdgmenu_p.h + xdgmenureader.h + xdgmenurules.h + xdgmenuwidget.h +) + +QT5_WRAP_CPP(libqtxdg_CXX_FILES ${libqtxdg_MOCS}) + +add_library(${QTXDGX_LIBRARY_NAME} SHARED + ${libqtxdg_PUBLIC_H_FILES} + ${libqtxdg_PRIVATE_H_FILES} + ${libqtxdg_PRIVATE_H_FILES} + ${libqtxdg_CPP_FILES} + ${libqtxdg_CXX_FILES} +) + +target_link_libraries(${QTXDGX_LIBRARY_NAME} + PUBLIC + ${QTX_LIBRARIES} + ${QTXDGX_ICONLOADER_LIBRARY_NAME} +) + +set_target_properties(${QTXDGX_LIBRARY_NAME} PROPERTIES + VERSION ${QTXDG_VERSION_STRING} + SOVERSION ${QTXDG_MAJOR_VERSION} +) + +target_compile_definitions(${QTXDGX_LIBRARY_NAME} + PRIVATE "QTXDG_COMPILATION=\"1\"" + PRIVATE "QTXDG_VERSION=\"${QTXDG_VERSION_STRING}\"" +) + +target_include_directories(${QTXDGX_LIBRARY_NAME} + INTERFACE "$" + INTERFACE "$" +) + +# include directories and targets for the in tree build +target_include_directories(${QTXDGX_LIBRARY_NAME} + INTERFACE "$" + INTERFACE "$" +) + +export(TARGETS ${QTXDGX_LIBRARY_NAME} APPEND FILE "${CMAKE_BINARY_DIR}/${QTXDGX_FILE_NAME}-targets.cmake") +# end of in tree build stuff + +# create the portble headers +create_portable_headers(libqtxdg_PORTABLE_HEADERS + HEADER_NAMES ${libqtxdg_PUBLIC_CLASSES} + OUTPUT_DIR "${QTXDGX_INTREE_INCLUDEDIR}/${QTXDGX_FILE_NAME}" +) + +# Copy public headers (in tree building) +foreach(h ${libqtxdg_PUBLIC_H_FILES}) + get_filename_component(bh ${h} NAME) + configure_file(${h} "${QTXDGX_INTREE_INCLUDEDIR}/${QTXDGX_FILE_NAME}/${bh}" COPYONLY) +endforeach() + +# Copy private headers (in tree building) +foreach(h ${libqtxdg_PRIVATE_INSTALLABLE_H_FILES}) + get_filename_component(bh ${h} NAME) + configure_file(${h} "${QTXDGX_INTREE_INCLUDEDIR}/${QTXDGX_FILE_NAME}/${QTXDG_VERSION_STRING}/private/qtxdg/${bh}" COPYONLY) +endforeach() + +install(TARGETS + ${QTXDGX_LIBRARY_NAME} DESTINATION "${CMAKE_INSTALL_LIBDIR}" + EXPORT "${QTXDGX_FILE_NAME}-targets" + COMPONENT Runtime +) + +install(FILES + ${libqtxdg_PUBLIC_H_FILES} + DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}/${QTXDGX_FILE_NAME}" + COMPONENT Devel +) + +install(FILES + ${libqtxdg_PRIVATE_INSTALLABLE_H_FILES} + DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}/${QTXDGX_FILE_NAME}/${QTXDG_VERSION_STRING}/private/qtxdg" + COMPONENT Devel +) + +install(FILES + ${libqtxdg_PORTABLE_HEADERS} + DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}/${QTXDGX_FILE_NAME}" + COMPONENT Devel +) diff --git a/desktopenvironment_p.cpp b/qtxdg/desktopenvironment_p.cpp similarity index 100% rename from desktopenvironment_p.cpp rename to qtxdg/desktopenvironment_p.cpp diff --git a/xdgaction.cpp b/qtxdg/xdgaction.cpp similarity index 94% rename from xdgaction.cpp rename to qtxdg/xdgaction.cpp index 44d70ea..b0ba66c 100644 --- a/xdgaction.cpp +++ b/qtxdg/xdgaction.cpp @@ -91,7 +91,7 @@ void XdgAction::load(const XdgDesktopFile& desktopFile) if (mDesktopFile.isValid()) { // & is reserved for mnemonics - setText(mDesktopFile.name().replace('&', QLatin1String("&&"))); + setText(mDesktopFile.name().replace(QLatin1Char('&'), QLatin1String("&&"))); setToolTip(mDesktopFile.comment()); connect(this, SIGNAL(triggered()), this, SLOT(runConmmand())); @@ -117,6 +117,6 @@ void XdgAction::updateIcon() { setIcon(mDesktopFile.icon()); if (icon().isNull()) - setIcon(XdgIcon::fromTheme("application-x-executable")); + setIcon(XdgIcon::fromTheme(QLatin1String("application-x-executable"))); QCoreApplication::processEvents(); } diff --git a/xdgaction.h b/qtxdg/xdgaction.h similarity index 100% rename from xdgaction.h rename to qtxdg/xdgaction.h diff --git a/xdgautostart.cpp b/qtxdg/xdgautostart.cpp similarity index 89% rename from xdgautostart.cpp rename to qtxdg/xdgautostart.cpp index 85344d1..402937e 100644 --- a/xdgautostart.cpp +++ b/qtxdg/xdgautostart.cpp @@ -57,14 +57,14 @@ XdgDesktopFileList XdgAutoStart::desktopFileList(QStringList dirs, bool excludeH QSet processed; XdgDesktopFileList ret; - foreach (QString dirName, dirs) + foreach (const QString &dirName, dirs) { QDir dir(dirName); if (!dir.exists()) continue; - QFileInfoList files = dir.entryInfoList(QStringList("*.desktop"), QDir::Files | QDir::Readable); - foreach (QFileInfo fi, files) + const QFileInfoList files = dir.entryInfoList(QStringList(QLatin1String("*.desktop")), QDir::Files | QDir::Readable); + foreach (const QFileInfo &fi, files) { if (processed.contains(fi.fileName())) continue; @@ -88,5 +88,5 @@ XdgDesktopFileList XdgAutoStart::desktopFileList(QStringList dirs, bool excludeH QString XdgAutoStart::localPath(const XdgDesktopFile& file) { QFileInfo fi(file.fileName()); - return QString("%1/%2").arg(XdgDirs::autostartHome(), fi.fileName()); + return QString::fromLatin1("%1/%2").arg(XdgDirs::autostartHome(), fi.fileName()); } diff --git a/xdgautostart.h b/qtxdg/xdgautostart.h similarity index 100% rename from xdgautostart.h rename to qtxdg/xdgautostart.h diff --git a/xdgdesktopfile.cpp b/qtxdg/xdgdesktopfile.cpp similarity index 66% rename from xdgdesktopfile.cpp rename to qtxdg/xdgdesktopfile.cpp index 75a80bf..4972c37 100644 --- a/xdgdesktopfile.cpp +++ b/qtxdg/xdgdesktopfile.cpp @@ -36,6 +36,7 @@ #include #include +#include #include #include #include @@ -48,7 +49,6 @@ #include #include #include -#include // for the % operator #include #include #include @@ -63,10 +63,23 @@ static const QStringList nonDetachExecs = QStringList() << QLatin1String("pkexec"); -static const char onlyShowInKey[] = "OnlyShowIn"; -static const char notShowInKey[] = "NotShowIn"; -static const char categoriesKey[] = "Categories"; -static const char extendPrefixKey[] = "X-"; +static const QLatin1String onlyShowInKey("OnlyShowIn"); +static const QLatin1String notShowInKey("NotShowIn"); +static const QLatin1String categoriesKey("Categories"); +static const QLatin1String extendPrefixKey("X-"); +static const QLatin1String mimeTypeKey("MimeType"); +static const QLatin1String applicationsStr("applications"); + +static const QLatin1String nameKey("Name"); +static const QLatin1String typeKey("Type"); +static const QLatin1String ApplicationStr("Application"); +static const QLatin1String LinkStr("Link"); +static const QLatin1String DirectoryStr("Directory"); +static const QLatin1String execKey("Exec"); +static const QLatin1String urlKey("URL"); +static const QLatin1String iconKey("Icon"); + +static const QLatin1String initialPreferenceKey("InitialPreference"); // Helper functions prototypes bool checkTryExec(const QString& progName); @@ -90,13 +103,13 @@ void loadMimeCacheDir(const QString& dirName, QHash &repl) { // First we replace slash. - str.replace('\\', "\\\\"); + str.replace(QLatin1Char('\\'), QLatin1String("\\\\")); QHashIterator i(repl); while (i.hasNext()) { i.next(); - if (i.key() != '\\') - str.replace(i.key(), QString("\\\\%1").arg(i.value())); + if (i.key() != QLatin1Char('\\')) + str.replace(i.key(), QString::fromLatin1("\\\\%1").arg(i.value())); } return str; @@ -110,9 +123,9 @@ QString &doEscape(QString& str, const QHash &repl) QString &escape(QString& str) { QHash repl; - repl.insert('\n', 'n'); - repl.insert('\t', 't'); - repl.insert('\r', 'r'); + repl.insert(QLatin1Char('\n'), QLatin1Char('n')); + repl.insert(QLatin1Char('\t'), QLatin1Char('t')); + repl.insert(QLatin1Char('\r'), QLatin1Char('r')); return doEscape(str, repl); } @@ -143,10 +156,10 @@ QString &escapeExec(QString& str) // The parseCombinedArgString() splits the string by the space symbols, // we temporarily replace them on the special characters. // Replacement will reverse after the splitting. - repl.insert('"', '"'); // double quote, - repl.insert('\'', '\''); // single quote ("'"), - repl.insert('\\', '\\'); // backslash character ("\"), - repl.insert('$', '$'); // dollar sign ("$"), + repl.insert(QLatin1Char('"'), QLatin1Char('"')); // double quote, + repl.insert(QLatin1Char('\''), QLatin1Char('\'')); // single quote ("'"), + repl.insert(QLatin1Char('\\'), QLatin1Char('\\')); // backslash character ("\"), + repl.insert(QLatin1Char('$'), QLatin1Char('$')); // dollar sign ("$"), return doEscape(str, repl); } @@ -157,7 +170,7 @@ QString &doUnEscape(QString& str, const QHash &repl) int n = 0; while (1) { - n=str.indexOf("\\", n); + n=str.indexOf(QLatin1String("\\"), n); if (n < 0 || n > str.length() - 2) break; @@ -181,11 +194,11 @@ QString &doUnEscape(QString& str, const QHash &repl) QString &unEscape(QString& str) { QHash repl; - repl.insert('\\', '\\'); - repl.insert('s', ' '); - repl.insert('n', '\n'); - repl.insert('t', '\t'); - repl.insert('r', '\r'); + repl.insert(QLatin1Char('\\'), QLatin1Char('\\')); + repl.insert(QLatin1Char('s'), QLatin1Char(' ')); + repl.insert(QLatin1Char('n'), QLatin1Char('\n')); + repl.insert(QLatin1Char('t'), QLatin1Char('\t')); + repl.insert(QLatin1Char('r'), QLatin1Char('\r')); return doUnEscape(str, repl); } @@ -237,26 +250,26 @@ QString &unEscapeExec(QString& str) // The parseCombinedArgString() splits the string by the space symbols, // we temporarily replace them on the special characters. // Replacement will reverse after the splitting. - repl.insert(' ', 01); // space - repl.insert('\t', 02); // tab - repl.insert('\n', 03); // newline, - - repl.insert('"', '"'); // double quote, - repl.insert('\'', '\''); // single quote ("'"), - repl.insert('\\', '\\'); // backslash character ("\"), - repl.insert('>', '>'); // greater-than sign (">"), - repl.insert('<', '<'); // less-than sign ("<"), - repl.insert('~', '~'); // tilde ("~"), - repl.insert('|', '|'); // vertical bar ("|"), - repl.insert('&', '&'); // ampersand ("&"), - repl.insert(';', ';'); // semicolon (";"), - repl.insert('$', '$'); // dollar sign ("$"), - repl.insert('*', '*'); // asterisk ("*"), - repl.insert('?', '?'); // question mark ("?"), - repl.insert('#', '#'); // hash mark ("#"), - repl.insert('(', '('); // parenthesis ("(") - repl.insert(')', ')'); // parenthesis (")") - repl.insert('`', '`'); // backtick character ("`"). + repl.insert(QLatin1Char(' '), 01); // space + repl.insert(QLatin1Char('\t'), 02); // tab + repl.insert(QLatin1Char('\n'), 03); // newline, + + repl.insert(QLatin1Char('"'), QLatin1Char('"')); // double quote, + repl.insert(QLatin1Char('\''), QLatin1Char('\'')); // single quote ("'"), + repl.insert(QLatin1Char('\\'), QLatin1Char('\\')); // backslash character ("\"), + repl.insert(QLatin1Char('>'), QLatin1Char('>')); // greater-than sign (">"), + repl.insert(QLatin1Char('<'), QLatin1Char('<')); // less-than sign ("<"), + repl.insert(QLatin1Char('~'), QLatin1Char('~')); // tilde ("~"), + repl.insert(QLatin1Char('|'), QLatin1Char('|')); // vertical bar ("|"), + repl.insert(QLatin1Char('&'), QLatin1Char('&')); // ampersand ("&"), + repl.insert(QLatin1Char(';'), QLatin1Char(';')); // semicolon (";"), + repl.insert(QLatin1Char('$'), QLatin1Char('$')); // dollar sign ("$"), + repl.insert(QLatin1Char('*'), QLatin1Char('*')); // asterisk ("*"), + repl.insert(QLatin1Char('?'), QLatin1Char('?')); // question mark ("?"), + repl.insert(QLatin1Char('#'), QLatin1Char('#')); // hash mark ("#"), + repl.insert(QLatin1Char('('), QLatin1Char('(')); // parenthesis ("(") + repl.insert(QLatin1Char(')'), QLatin1Char(')')); // parenthesis (")") + repl.insert(QLatin1Char('`'), QLatin1Char('`')); // backtick character ("`"). return doUnEscape(str, repl); } @@ -281,8 +294,12 @@ public: XdgDesktopFileData::XdgDesktopFileData(): + mFileName(), mIsValid(false), - mValidIsChecked(false) + mValidIsChecked(false), + mIsShow(), + mItems(), + mType(XdgDesktopFile::UnknownType) { } @@ -301,12 +318,12 @@ bool XdgDesktopFileData::read(const QString &prefix) QString line = stream.readLine().trimmed(); // Skip comments ...................... - if (line.startsWith('#')) + if (line.startsWith(QLatin1Char('#'))) continue; // Section .............................. - if (line.startsWith('[') && line.endsWith(']')) + if (line.startsWith(QLatin1Char('[')) && line.endsWith(QLatin1Char(']'))) { section = line.mid(1, line.length()-2); if (section == prefix) @@ -315,13 +332,13 @@ bool XdgDesktopFileData::read(const QString &prefix) continue; } - QString key = line.section('=', 0, 0).trimmed(); - QString value = line.section('=', 1).trimmed(); + QString key = line.section(QLatin1Char('='), 0, 0).trimmed(); + QString value = line.section(QLatin1Char('='), 1).trimmed(); if (key.isEmpty()) continue; - mItems[section + "/" + key] = QVariant(value); + mItems[section + QLatin1Char('/') + key] = QVariant(value); } @@ -332,41 +349,62 @@ bool XdgDesktopFileData::read(const QString &prefix) XdgDesktopFile::Type XdgDesktopFileData::detectType(XdgDesktopFile *q) const { - QString typeStr = q->value("Type").toString(); - if (typeStr == "Application") + QString typeStr = q->value(typeKey).toString(); + if (typeStr == ApplicationStr) return XdgDesktopFile::ApplicationType; - if (typeStr == "Link") + if (typeStr == LinkStr) return XdgDesktopFile::LinkType; - if (typeStr == "Directory") + if (typeStr == DirectoryStr) return XdgDesktopFile::DirectoryType; - if (!q->value("Exec").toString().isEmpty()) + if (!q->value(execKey).toString().isEmpty()) return XdgDesktopFile::ApplicationType; return XdgDesktopFile::UnknownType; } - bool XdgDesktopFileData::startApplicationDetached(const XdgDesktopFile *q, const QStringList& urls) const { //DBusActivatable handling - if (q->value(QLatin1String("DBusActivatable"), false).toBool()) - return startByDBus(urls); - + if (q->value(QLatin1String("DBusActivatable"), false).toBool()) { + /* WARNING: We fallback to use Exec when the DBusActivatable fails. + * + * This is a violation of the standard and we know it! + * + * From the Standard: + * DBusActivatable A boolean value specifying if D-Bus activation is + * supported for this application. If this key is missing, the default + * value is false. If the value is true then implementations should + * ignore the Exec key and send a D-Bus message to launch the + * application. See D-Bus Activation for more information on how this + * works. Applications should still include Exec= lines in their desktop + * files for compatibility with implementations that do not understand + * the DBusActivatable key. + * + * So, why are we doing it ? In the benefit of user experience. + * We first ignore the Exec line and in use the D-Bus to lauch the + * application. But if it fails, we try the Exec method. + * + * We consider that this violation is more acceptable than an failure + * in launching an application. + */ + if (startByDBus(urls)) + return true; + } QStringList args = q->expandExecString(urls); if (args.isEmpty()) return false; - if (q->value("Terminal").toBool()) + if (q->value(QLatin1String("Terminal")).toBool()) { - QString term = getenv("TERM"); + QString term = QString::fromLocal8Bit(qgetenv("TERM")); if (term.isEmpty()) - term = "xterm"; + term = QLatin1String("xterm"); - args.prepend("-e"); + args.prepend(QLatin1String("-e")); args.prepend(term); } @@ -383,12 +421,17 @@ bool XdgDesktopFileData::startApplicationDetached(const XdgDesktopFile *q, const } QString cmd = args.takeFirst(); + QString workingDir = q->value(QLatin1String("Path")).toString(); + if (!workingDir.isEmpty() && !QDir(workingDir).exists()) + workingDir = QString(); if (nonDetach) { QScopedPointer p(new QProcess); p->setStandardInputFile(QProcess::nullDevice()); p->setProcessChannelMode(QProcess::ForwardedChannels); + if (!workingDir.isEmpty()) + p->setWorkingDirectory(workingDir); p->start(cmd, args); bool started = p->waitForStarted(); if (started) @@ -400,7 +443,7 @@ bool XdgDesktopFileData::startApplicationDetached(const XdgDesktopFile *q, const } else { - return QProcess::startDetached(cmd, args); + return QProcess::startDetached(cmd, args, workingDir); } } @@ -417,7 +460,7 @@ bool XdgDesktopFileData::startLinkDetached(const XdgDesktopFile *q) const QString scheme = QUrl(url).scheme(); - if (scheme.isEmpty() || scheme.toUpper() == "FILE") + if (scheme.isEmpty() || scheme.toUpper() == QLatin1String("FILE")) { // Local file QFileInfo fi(url); @@ -443,12 +486,28 @@ bool XdgDesktopFileData::startByDBus(const QStringList& urls) const { QFileInfo f(mFileName); QString path(f.completeBaseName()); + path = path.replace(QLatin1Char('.'), QLatin1Char('/')).prepend(QLatin1Char('/')); QVariantMap platformData; - platformData.insert(QLatin1String("desktop-startup-id"), QString::fromUtf8(qgetenv("DESKTOP_STARTUP_ID"))); + platformData.insert(QLatin1String("desktop-startup-id"), QString::fromLocal8Bit(qgetenv("DESKTOP_STARTUP_ID"))); - path = path.replace(QLatin1Char('.'), QLatin1Char('/')).prepend(QLatin1Char('/')); + QDBusObjectPath d_path(path); + if (d_path.path().isEmpty()) + { + qWarning() << "XdgDesktopFileData::startByDBus: invalid name" << f.fileName() << "of DBusActivatable .desktop file" + ", assembled DBus object path" << path << "is invalid!"; + return false; + } QDBusInterface app(f.completeBaseName(), path, QLatin1String("org.freedesktop.Application")); + //Note: after the QDBusInterface construction, it can *invalid* (has reasonable lastError()) + // but this can be due to some intermediate DBus call(s) which doesn't need to be fatal and + // our next call() can succeed + // see discussion https://github.com/lxde/libqtxdg/pull/75 + if (app.lastError().isValid()) + { + qWarning().noquote() << "XdgDesktopFileData::startByDBus: invalid interface:" << app.lastError().message() + << ", but trying to continue..."; + } QDBusMessage reply; if (urls.isEmpty()) reply = app.call(QLatin1String("Activate"), platformData); @@ -474,23 +533,23 @@ XdgDesktopFile::XdgDesktopFile(const XdgDesktopFile& other): XdgDesktopFile::XdgDesktopFile(Type type, const QString& name, const QString &value): d(new XdgDesktopFileData) { - d->mFileName = name + ".desktop"; + d->mFileName = name + QLatin1String(".desktop"); d->mType = type; - setValue("Version", "1.0"); - setValue("Name", name); + setValue(QLatin1String("Version"), QLatin1String("1.0")); + setValue(nameKey, name); if (type == XdgDesktopFile::ApplicationType) { - setValue("Type", "Application"); - setValue("Exec", value); + setValue(typeKey, ApplicationStr); + setValue(execKey, value); } else if (type == XdgDesktopFile::LinkType) { - setValue("Type", "Link"); - setValue("URL", value); + setValue(typeKey, LinkStr); + setValue(urlKey, value); } else if (type == XdgDesktopFile::DirectoryType) { - setValue("Type", "Directory"); + setValue(typeKey, DirectoryStr); } d->mIsValid = check(); } @@ -541,14 +600,15 @@ bool XdgDesktopFile::save(QIODevice *device) const while (i != d->mItems.constEnd()) { QString path = i.key(); - QString sect = path.section('/',0,0); + QString sect = path.section(QLatin1Char('/'),0,0); if (sect != section) { section = sect; - stream << "[" << section << "]" << endl; + stream << QLatin1Char('[') << section << QLatin1Char(']') << endl; + } - QString key = path.section('/', 1); - stream << key << "=" << i.value().toString() << endl; + QString key = path.section(QLatin1Char('/'), 1); + stream << key << QLatin1Char('=') << i.value().toString() << endl; ++i; } return true; @@ -567,7 +627,7 @@ bool XdgDesktopFile::save(const QString &fileName) const QVariant XdgDesktopFile::value(const QString& key, const QVariant& defaultValue) const { - QString path = (!prefix().isEmpty()) ? prefix() + "/" + key : key; + QString path = (!prefix().isEmpty()) ? prefix() + QLatin1Char('/') + key : key; QVariant res = d->mItems.value(path, defaultValue); if (res.type() == QVariant::String) { @@ -581,19 +641,19 @@ QVariant XdgDesktopFile::value(const QString& key, const QVariant& defaultValue) void XdgDesktopFile::setValue(const QString &key, const QVariant &value) { - QString path = (!prefix().isEmpty()) ? prefix() + "/" + key : key; + QString path = (!prefix().isEmpty()) ? prefix() + QLatin1Char('/') + key : key; if (value.type() == QVariant::String) { QString s=value.toString(); - if (key.toUpper() == "EXEC") + if (key.toUpper() == QLatin1String("EXEC")) escapeExec(s); else escape(s); d->mItems[path] = QVariant(s); - if (key.toUpper() == "TYPE") + if (key.toUpper() == QLatin1String("TYPE")) d->mType = d->detectType(this); } else @@ -619,28 +679,28 @@ void XdgDesktopFile::setLocalizedValue(const QString &key, const QVariant &value ************************************************/ QString XdgDesktopFile::localizedKey(const QString& key) const { - QString lang = getenv("LC_MESSAGES"); + QString lang = QString::fromLocal8Bit(qgetenv("LC_MESSAGES")); if (lang.isEmpty()) - lang = getenv("LC_ALL"); + lang = QString::fromLocal8Bit(qgetenv("LC_ALL")); if (lang.isEmpty()) - lang = getenv("LANG"); + lang = QString::fromLocal8Bit(qgetenv("LANG")); - QString modifier = lang.section('@', 1); + QString modifier = lang.section(QLatin1Char('@'), 1); if (!modifier.isEmpty()) lang.truncate(lang.length() - modifier.length() - 1); - QString encoding = lang.section('.', 1); + QString encoding = lang.section(QLatin1Char('.'), 1); if (!encoding.isEmpty()) lang.truncate(lang.length() - encoding.length() - 1); - QString country = lang.section('_', 1); + QString country = lang.section(QLatin1Char('_'), 1); if (!country.isEmpty()) lang.truncate(lang.length() - country.length() - 1); - //qDebug() << "LC_MESSAGES: " << getenv("LC_MESSAGES"); + //qDebug() << "LC_MESSAGES: " << qgetenv("LC_MESSAGES"); //qDebug() << "Lang:" << lang; //qDebug() << "Country:" << country; //qDebug() << "Encoding:" << encoding; @@ -649,7 +709,7 @@ QString XdgDesktopFile::localizedKey(const QString& key) const if (!modifier.isEmpty() && !country.isEmpty()) { - QString k = QString("%1[%2_%3@%4]").arg(key, lang, country, modifier); + QString k = QString::fromLatin1("%1[%2_%3@%4]").arg(key, lang, country, modifier); //qDebug() << "\t try " << k << contains(k); if (contains(k)) return k; @@ -657,7 +717,7 @@ QString XdgDesktopFile::localizedKey(const QString& key) const if (!country.isEmpty()) { - QString k = QString("%1[%2_%3]").arg(key, lang, country); + QString k = QString::fromLatin1("%1[%2_%3]").arg(key, lang, country); //qDebug() << "\t try " << k << contains(k); if (contains(k)) return k; @@ -665,13 +725,13 @@ QString XdgDesktopFile::localizedKey(const QString& key) const if (!modifier.isEmpty()) { - QString k = QString("%1[%2@%3]").arg(key, lang, modifier); + QString k = QString::fromLatin1("%1[%2@%3]").arg(key, lang, modifier); //qDebug() << "\t try " << k << contains(k); if (contains(k)) return k; } - QString k = QString("%1[%2]").arg(key, lang); + QString k = QString::fromLatin1("%1[%2]").arg(key, lang); //qDebug() << "\t try " << k << contains(k); if (contains(k)) return k; @@ -691,13 +751,13 @@ QVariant XdgDesktopFile::localizedValue(const QString& key, const QVariant& defa QStringList XdgDesktopFile::categories() const { QString key; - if (contains(QLatin1String(categoriesKey))) + if (contains(categoriesKey)) { - key = QLatin1String(categoriesKey); + key = categoriesKey; } else { - key = QLatin1String(extendPrefixKey) % QLatin1String(categoriesKey); + key = extendPrefixKey + categoriesKey; if (!contains(key)) return QStringList(); } @@ -709,14 +769,14 @@ QStringList XdgDesktopFile::categories() const void XdgDesktopFile::removeEntry(const QString& key) { - QString path = (!prefix().isEmpty()) ? prefix() + "/" + key : key; + QString path = (!prefix().isEmpty()) ? prefix() + QLatin1Char('/') + key : key; d->mItems.remove(path); } bool XdgDesktopFile::contains(const QString& key) const { - QString path = (!prefix().isEmpty()) ? prefix() + "/" + key : key; + QString path = (!prefix().isEmpty()) ? prefix() + QLatin1Char('/') + key : key; return d->mItems.contains(path); } @@ -735,10 +795,10 @@ QString XdgDesktopFile::fileName() const QIcon const XdgDesktopFile::icon(const QIcon& fallback) const { - QIcon result = XdgIcon::fromTheme(value("Icon").toString(), fallback); + QIcon result = XdgIcon::fromTheme(value(iconKey).toString(), fallback); if (result.isNull() && type() == ApplicationType) { - result = XdgIcon::fromTheme("application-x-executable.png"); + result = XdgIcon::fromTheme(QLatin1String("application-x-executable.png")); // TODO Maybe defaults for other desktopfile types as well.. } @@ -748,7 +808,13 @@ QIcon const XdgDesktopFile::icon(const QIcon& fallback) const QString const XdgDesktopFile::iconName() const { - return value("Icon").toString(); + return value(iconKey).toString(); +} + + +QStringList XdgDesktopFile::mimeTypes() const +{ + return value(mimeTypeKey).toString().split(QLatin1Char(';'), QString::SkipEmptyParts); } @@ -774,9 +840,11 @@ bool XdgDesktopFile::startDetached(const QStringList& urls) const { case ApplicationType: return d->startApplicationDetached(this, urls); + break; case LinkType: return d->startLinkDetached(this); + break; default: return false; @@ -839,8 +907,8 @@ static QStringList parseCombinedArgString(const QString &program) void replaceVar(QString &str, const QString &varName, const QString &after) { - str.replace(QRegExp(QString("\\$%1(?!\\w)").arg(varName)), after); - str.replace(QRegExp(QString("\\$\\{%1\\}").arg(varName)), after); + str.replace(QRegExp(QString::fromLatin1("\\$%1(?!\\w)").arg(varName)), after); + str.replace(QRegExp(QString::fromLatin1("\\$\\{%1\\}").arg(varName)), after); } @@ -848,33 +916,35 @@ QString expandEnvVariables(const QString str) { QString scheme = QUrl(str).scheme(); - if (scheme == "http" || scheme == "https" || scheme == "shttp" || - scheme == "ftp" || scheme == "ftps" || - scheme == "pop" || scheme == "pops" || - scheme == "imap" || scheme == "imaps" || - scheme == "mailto" || - scheme == "nntp" || - scheme == "irc" || - scheme == "telnet" || - scheme == "xmpp" || - scheme == "irc" || - scheme == "nfs" + if (scheme == QLatin1String("http") || scheme == QLatin1String("https") || scheme == QLatin1String("shttp") || + scheme == QLatin1String("ftp") || scheme == QLatin1String("ftps") || + scheme == QLatin1String("pop") || scheme == QLatin1String("pops") || + scheme == QLatin1String("imap") || scheme == QLatin1String("imaps") || + scheme == QLatin1String("mailto") || + scheme == QLatin1String("nntp") || + scheme == QLatin1String("irc") || + scheme == QLatin1String("telnet") || + scheme == QLatin1String("xmpp") || + scheme == QLatin1String("irc") || + scheme == QLatin1String("nfs") ) return str; + const QString homeDir = QFile::decodeName(qgetenv("HOME")); + QString res = str; - res.replace(QRegExp("~(?=$|/)"), getenv("HOME")); + res.replace(QRegExp(QString::fromLatin1("~(?=$|/)")), homeDir); - replaceVar(res, "HOME", getenv("HOME")); - replaceVar(res, "USER", getenv("USER")); + replaceVar(res, QLatin1String("HOME"), homeDir); + replaceVar(res, QLatin1String("USER"), QString::fromLocal8Bit(qgetenv("USER"))); - replaceVar(res, "XDG_DESKTOP_DIR", QStandardPaths::writableLocation(QStandardPaths::DesktopLocation)); - replaceVar(res, "XDG_TEMPLATES_DIR", QStandardPaths::writableLocation(QStandardPaths::TempLocation)); - replaceVar(res, "XDG_DOCUMENTS_DIR", QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation)); - replaceVar(res, "XDG_MUSIC_DIR", QStandardPaths::writableLocation(QStandardPaths::MusicLocation)); - replaceVar(res, "XDG_PICTURES_DIR", QStandardPaths::writableLocation(QStandardPaths::PicturesLocation)); - replaceVar(res, "XDG_VIDEOS_DIR", QStandardPaths::writableLocation(QStandardPaths::MoviesLocation)); - replaceVar(res, "XDG_PHOTOS_DIR", QStandardPaths::writableLocation(QStandardPaths::PicturesLocation)); + replaceVar(res, QLatin1String("XDG_DESKTOP_DIR"), XdgDirs::userDir(XdgDirs::Desktop)); + replaceVar(res, QLatin1String("XDG_TEMPLATES_DIR"), XdgDirs::userDir(XdgDirs::Templates)); + replaceVar(res, QLatin1String("XDG_DOCUMENTS_DIR"), XdgDirs::userDir(XdgDirs::Documents)); + replaceVar(res, QLatin1String("XDG_MUSIC_DIR"), XdgDirs::userDir(XdgDirs::Music)); + replaceVar(res, QLatin1String("XDG_PICTURES_DIR"), XdgDirs::userDir(XdgDirs::Pictures)); + replaceVar(res, QLatin1String("XDG_VIDEOS_DIR"), XdgDirs::userDir(XdgDirs::Videos)); + replaceVar(res, QLatin1String("XDG_PHOTOS_DIR"), XdgDirs::userDir(XdgDirs::Pictures)); return res; } @@ -883,7 +953,7 @@ QString expandEnvVariables(const QString str) QStringList expandEnvVariables(const QStringList strs) { QStringList res; - foreach(QString s, strs) + foreach(const QString &s, strs) res << expandEnvVariables(s); return res; @@ -897,7 +967,7 @@ QStringList XdgDesktopFile::expandExecString(const QStringList& urls) const QStringList result; - QString execStr = value("Exec").toString(); + QString execStr = value(execKey).toString(); unEscapeExec(execStr); QStringList tokens = parseCombinedArgString(execStr); @@ -906,13 +976,13 @@ QStringList XdgDesktopFile::expandExecString(const QStringList& urls) const // The parseCombinedArgString() splits the string by the space symbols, // we temporarily replaced them on the special characters. // Now we reverse it. - token.replace(01, ' '); - token.replace(02, '\t'); - token.replace(03, '\n'); + token.replace(01, QLatin1Char(' ')); + token.replace(02, QLatin1Char('\t')); + token.replace(03, QLatin1Char('\n')); // ---------------------------------------------------------- // A single file name, even if multiple files are selected. - if (token == "%f") + if (token == QLatin1String("%f")) { if (!urls.isEmpty()) result << expandEnvVariables(urls.at(0)); @@ -922,7 +992,7 @@ QStringList XdgDesktopFile::expandExecString(const QStringList& urls) const // ---------------------------------------------------------- // A list of files. Use for apps that can open several local files at once. // Each file is passed as a separate argument to the executable program. - if (token == "%F") + if (token == QLatin1String("%F")) { result << expandEnvVariables(urls); continue; @@ -930,13 +1000,13 @@ QStringList XdgDesktopFile::expandExecString(const QStringList& urls) const // ---------------------------------------------------------- // A single URL. Local files may either be passed as file: URLs or as file path. - if (token == "%u") + if (token == QLatin1String("%u")) { if (!urls.isEmpty()) { QUrl url; url.setUrl(expandEnvVariables(urls.at(0))); - result << ((!url.toLocalFile().isEmpty()) ? url.toLocalFile() : url.toEncoded()); + result << ((!url.toLocalFile().isEmpty()) ? url.toLocalFile() : QString::fromUtf8(url.toEncoded())); } continue; } @@ -944,12 +1014,12 @@ QStringList XdgDesktopFile::expandExecString(const QStringList& urls) const // ---------------------------------------------------------- // A list of URLs. Each URL is passed as a separate argument to the executable // program. Local files may either be passed as file: URLs or as file path. - if (token == "%U") + if (token == QLatin1String("%U")) { - foreach (QString s, urls) + foreach (const QString &s, urls) { QUrl url(expandEnvVariables(s)); - result << ((!url.toLocalFile().isEmpty()) ? url.toLocalFile() : url.toEncoded()); + result << ((!url.toLocalFile().isEmpty()) ? url.toLocalFile() : QString::fromUtf8(url.toEncoded())); } continue; } @@ -958,11 +1028,11 @@ QStringList XdgDesktopFile::expandExecString(const QStringList& urls) const // The Icon key of the desktop entry expanded as two arguments, first --icon // and then the value of the Icon key. Should not expand to any arguments if // the Icon key is empty or missing. - if (token == "%i") + if (token == QLatin1String("%i")) { - QString icon = value("Icon").toString(); + QString icon = value(iconKey).toString(); if (!icon.isEmpty()) - result << "-icon" << icon.replace('%', "%%"); + result << QLatin1String("-icon") << icon.replace(QLatin1Char('%'), QLatin1String("%%")); continue; } @@ -970,27 +1040,27 @@ QStringList XdgDesktopFile::expandExecString(const QStringList& urls) const // ---------------------------------------------------------- // The translated name of the application as listed in the appropriate Name key // in the desktop entry. - if (token == "%c") + if (token == QLatin1String("%c")) { - result << localizedValue("Name").toString().replace('%', "%%"); + result << localizedValue(nameKey).toString().replace(QLatin1Char('%'), QLatin1String("%%")); continue; } // ---------------------------------------------------------- // The location of the desktop file as either a URI (if for example gotten from // the vfolder system) or a local filename or empty if no location is known. - if (token == "%k") + if (token == QLatin1String("%k")) { - result << fileName().replace('%', "%%"); + result << fileName().replace(QLatin1Char('%'), QLatin1String("%%")); break; } // ---------------------------------------------------------- // Deprecated. // Deprecated field codes should be removed from the command line and ignored. - if (token == "%d" || token == "%D" || - token == "%n" || token == "%N" || - token == "%v" || token == "%m" + if (token == QLatin1String("%d") || token == QLatin1String("%D") || + token == QLatin1String("%n") || token == QLatin1String("%N") || + token == QLatin1String("%v") || token == QLatin1String("%m") ) { continue; @@ -1009,9 +1079,9 @@ bool checkTryExec(const QString& progName) if (progName.startsWith(QDir::separator())) return QFileInfo(progName).isExecutable(); - QStringList dirs = QString(getenv("PATH")).split(":"); + QStringList dirs = QFile::decodeName(qgetenv("PATH")).split(QLatin1Char(':')); - foreach (QString dir, dirs) + foreach (const QString &dir, dirs) { if (QFileInfo(QDir(dir), progName).isExecutable()) return true; @@ -1021,25 +1091,34 @@ bool checkTryExec(const QString& progName) } -bool XdgDesktopFile::isShow(const QString& environment) const +QString XdgDesktopFile::id(const QString &fileName, bool checkFileExists) { - const QString env = environment.toUpper(); + const QFileInfo f(fileName); + if (checkFileExists) { + if (!f.exists()) { + return QString(); + } + } - if (d->mIsShow.contains(env)) - return d->mIsShow.value(env); + QString id = f.absoluteFilePath(); + const QStringList dataDirs = XdgDirs::dataDirs(); - d->mIsShow.insert(env, false); - // Means "this application exists, but don't display it in the menus". - if (value("NoDisplay").toBool()) - return false; + foreach(const QString &d, dataDirs) { + if (id.startsWith(d)) { + // remove only the first occurence + id.replace(id.indexOf(d), d.size(), QString()); + } + } - // The file is inapplicable to the current environment - if (!isSuitable(true, env)) - return false; + const QLatin1Char slash('/'); + const QString s = slash + applicationsStr + slash; + if (!id.startsWith(s)) + return QString(); + id.replace(id.indexOf(s), s.size(), QString()); + id.replace(slash, QLatin1Char('-')); - d->mIsShow.insert(env, true); - return true; + return id; } @@ -1053,7 +1132,7 @@ bool XdgDesktopFile::isShown(const QString &environment) const d->mIsShow.insert(env, false); // Means "this application exists, but don't display it in the menus". - if (value("NoDisplay").toBool()) + if (value(QLatin1String("NoDisplay")).toBool()) return false; // The file is not suitable to the current environment @@ -1065,45 +1144,11 @@ bool XdgDesktopFile::isShown(const QString &environment) const } -bool XdgDesktopFile::isApplicable(bool excludeHidden, const QString& environment) const -{ - // Hidden should have been called Deleted. It means the user deleted - // (at his level) something that was present - if (excludeHidden && value("Hidden").toBool()) - return false; - - // A list of strings identifying the environments that should display/not - // display a given desktop entry. - // OnlyShowIn ........ - if (contains("OnlyShowIn")) - { - QStringList s = value("OnlyShowIn").toString().split(';'); - if (!s.contains(environment)) - return false; - } - - // NotShowIn ......... - if (contains("NotShowIn")) - { - QStringList s = value("NotShowIn").toString().split(';'); - if (s.contains(environment)) - return false; - } - - // actually installed. If not, entry may not show in menus, etc. - QString s = value("TryExec").toString(); - if (!s.isEmpty() && ! checkTryExec(s)) - return false; - - return true; -} - - bool XdgDesktopFile::isSuitable(bool excludeHidden, const QString &environment) const { // Hidden should have been called Deleted. It means the user deleted // (at his level) something that was present - if (excludeHidden && value("Hidden").toBool()) + if (excludeHidden && value(QLatin1String("Hidden")).toBool()) return false; // A list of strings identifying the environments that should display/not @@ -1111,21 +1156,21 @@ bool XdgDesktopFile::isSuitable(bool excludeHidden, const QString &environment) // OnlyShowIn ........ QString env; if (environment.isEmpty()) - env = QString(detectDesktopEnvironment()); + env = QString::fromLocal8Bit(detectDesktopEnvironment()); else { env = environment.toUpper(); } QString key; bool keyFound = false; - if (contains(QLatin1String(onlyShowInKey))) + if (contains(onlyShowInKey)) { - key = QLatin1String(onlyShowInKey); + key = onlyShowInKey; keyFound = true; } else { - key = QLatin1String(extendPrefixKey) % QLatin1String(onlyShowInKey); + key = extendPrefixKey + onlyShowInKey; keyFound = contains(key) ? true : false; } @@ -1137,15 +1182,14 @@ bool XdgDesktopFile::isSuitable(bool excludeHidden, const QString &environment) } // NotShowIn ......... - keyFound = false; - if (contains(QLatin1String(notShowInKey))) + if (contains(notShowInKey)) { - key = QLatin1String(notShowInKey); + key = notShowInKey; keyFound = true; } else { - key = QLatin1String(extendPrefixKey) % QLatin1String(notShowInKey); + key = extendPrefixKey + notShowInKey; keyFound = contains(key) ? true : false; } @@ -1157,7 +1201,7 @@ bool XdgDesktopFile::isSuitable(bool excludeHidden, const QString &environment) } // actually installed. If not, entry may not show in menus, etc. - QString s = value("TryExec").toString(); + QString s = value(QLatin1String("TryExec")).toString(); if (!s.isEmpty() && ! checkTryExec(s)) return false; @@ -1167,12 +1211,12 @@ bool XdgDesktopFile::isSuitable(bool excludeHidden, const QString &environment) QString expandDynamicUrl(QString url) { - foreach(QString line, QProcess::systemEnvironment()) + foreach(const QString &line, QProcess::systemEnvironment()) { - QString name = line.section("=", 0, 0); - QString val = line.section("=", 1); - url.replace(QString("$%1").arg(name), val); - url.replace(QString("${%1}").arg(name), val); + QString name = line.section(QLatin1Char('='), 0, 0); + QString val = line.section(QLatin1Char('='), 1); + url.replace(QString::fromLatin1("$%1").arg(name), val); + url.replace(QString::fromLatin1("${%1}").arg(name), val); } return url; @@ -1186,12 +1230,12 @@ QString XdgDesktopFile::url() const QString url; - url = value("URL").toString(); + url = value(urlKey).toString(); if (!url.isEmpty()) return url; // WTF? What standard describes it? - url = expandDynamicUrl(value("URL[$e]").toString()); + url = expandDynamicUrl(value(QLatin1String("URL[$e]")).toString()); if (!url.isEmpty()) return url; @@ -1209,7 +1253,7 @@ QString findDesktopFile(const QString& dirName, const QString& desktopName) // Working recursively ............ QFileInfoList dirs = dir.entryInfoList(QStringList(), QDir::Dirs | QDir::NoDotAndDotDot); - foreach (QFileInfo d, dirs) + foreach (const QFileInfo &d, dirs) { QString cn = d.canonicalFilePath(); if (dirName != cn) @@ -1229,9 +1273,9 @@ QString findDesktopFile(const QString& desktopName) QStringList dataDirs = XdgDirs::dataDirs(); dataDirs.prepend(XdgDirs::dataHome(false)); - foreach (QString dirName, dataDirs) + foreach (const QString &dirName, dataDirs) { - QString f = findDesktopFile(dirName + "/applications", desktopName); + QString f = findDesktopFile(dirName + QLatin1String("/applications"), desktopName); if (!f.isEmpty()) return f; } @@ -1242,45 +1286,51 @@ QString findDesktopFile(const QString& desktopName) XdgDesktopFile* XdgDesktopFileCache::getFile(const QString& fileName) { + if (fileName.isEmpty()) + return nullptr; + if (instance().m_fileCache.contains(fileName)) { return instance().m_fileCache.value(fileName); } - if (fileName.startsWith(QDir::separator())) + QString file; + if (!fileName.startsWith(QDir::separator())) { - // Absolute path ........................ - //qDebug() << "XdgDesktopFileCache: add new file" << fileName; - XdgDesktopFile* desktopFile = load(fileName); - if (desktopFile->isValid()) - instance().m_fileCache.insert(fileName, desktopFile); - return desktopFile; + // Relative path + // Search desktop file .................. + file = findDesktopFile(fileName); + if (file.isEmpty()) + return nullptr; } else { - // Search desktop file .................. - QString filePath = findDesktopFile(fileName); - XdgDesktopFile* desktopFile; - //qDebug() << "Sokoloff XdgDesktopFileCache::getFile found fileName" << fileName << filePath; - if (!filePath.isEmpty()) - { - // The file was found - if (!instance().m_fileCache.contains(filePath)) - { - desktopFile = load(filePath); - instance().m_fileCache.insert(filePath, desktopFile); - } - else - desktopFile = instance().m_fileCache.value(filePath); + file = fileName; + } - return desktopFile; + XdgDesktopFile* desktopFile; + // The file was found + if (!instance().m_fileCache.contains(file)) + { + desktopFile = load(file); + if (desktopFile) + { + instance().m_fileCache.insert(file, desktopFile); + return desktopFile; } else { - return new XdgDesktopFile; + return nullptr; } } + else + { + // already in the cache + desktopFile = instance().m_fileCache.value(file); + return desktopFile; + } + } QList XdgDesktopFileCache::getAllFiles() @@ -1318,18 +1368,18 @@ bool readDesktopFile(QIODevice & device, QSettings::SettingsMap & map) QString line = stream.readLine().trimmed(); // Skip comments and empty lines - if (line.startsWith('#') || line.isEmpty()) + if (line.startsWith(QLatin1Char('#')) || line.isEmpty()) continue; // Section .............................. - if (line.startsWith('[') && line.endsWith(']')) + if (line.startsWith(QLatin1Char('[')) && line.endsWith(QLatin1Char(']'))) { section = line.mid(1, line.length()-2); continue; } - QString key = line.section('=', 0, 0).trimmed(); - QString value = line.section('=', 1).trimmed(); + QString key = line.section(QLatin1Char('='), 0, 0).trimmed(); + QString value = line.section(QLatin1Char('='), 1).trimmed(); if (key.isEmpty()) continue; @@ -1340,12 +1390,12 @@ bool readDesktopFile(QIODevice & device, QSettings::SettingsMap & map) return false; } - key.prepend("/"); + key.prepend(QLatin1Char('/')); key.prepend(section); - if (value.contains(";")) + if (value.contains(QLatin1Char(';'))) { - map.insert(key, value.split(";")); + map.insert(key, value.split(QLatin1Char(';'))); } else { @@ -1365,14 +1415,14 @@ bool writeDesktopFile(QIODevice & device, const QSettings::SettingsMap & map) QTextStream stream(&device); QString section; - foreach (QString key, map.keys()) + foreach (const QString &key, map.keys()) { if (! map.value(key).canConvert()) { return false; } - QString thisSection = key.section("/", 0, 0); + QString thisSection = key.section(QLatin1Char('/'), 0, 0); if (thisSection.isEmpty()) { qWarning() << "No section defined"; @@ -1381,11 +1431,11 @@ bool writeDesktopFile(QIODevice & device, const QSettings::SettingsMap & map) if (thisSection != section) { - stream << "[" << thisSection << "]" << "\n"; + stream << QLatin1Char('[') << thisSection << QLatin1Char(']') << QLatin1Char('\n'); section = thisSection; } - QString remainingKey = key.section("/", 1, -1); + QString remainingKey = key.section(QLatin1Char('/'), 1, -1); if (remainingKey.isEmpty()) { @@ -1393,7 +1443,7 @@ bool writeDesktopFile(QIODevice & device, const QSettings::SettingsMap & map) return false; } - stream << remainingKey << "=" << map.value(key).toString() << "\n"; + stream << remainingKey << QLatin1Char('=') << map.value(key).toString() << QLatin1Char('\n'); } @@ -1407,12 +1457,12 @@ void XdgDesktopFileCache::initialize(const QString& dirName) // Directories have the type "application/x-directory", but in the desktop file // are shown as "inode/directory". To handle these cases, we use this hash. QHash specials; - specials.insert("inode/directory", "application/x-directory"); + specials.insert(QLatin1String("inode/directory"), QLatin1String("application/x-directory")); // Working recursively ............ QFileInfoList files = dir.entryInfoList(QStringList(), QDir::Files | QDir::Dirs | QDir::NoDotAndDotDot); - foreach (QFileInfo f, files) + foreach (const QFileInfo &f, files) { if (f.isDir()) { @@ -1430,15 +1480,15 @@ void XdgDesktopFileCache::initialize(const QString& dirName) m_fileCache.insert(f.absoluteFilePath(), df); } - QStringList mimes = df->value("MimeType").toString().split(';', QString::SkipEmptyParts); + QStringList mimes = df->value(mimeTypeKey).toString().split(QLatin1Char(';'), QString::SkipEmptyParts); - foreach (QString mime, mimes) + foreach (const QString &mime, mimes) { - int pref = df->value("InitialPreference", 0).toInt(); + int pref = df->value(initialPreferenceKey, 0).toInt(); // We move the desktopFile forward in the list for this mime, so that // no desktopfile in front of it have a lower initialPreference. int position = m_defaultAppsCache[mime].length(); - while (position > 0 && m_defaultAppsCache[mime][position - 1]->value("InitialPreference, 0").toInt() < pref) + while (position > 0 && m_defaultAppsCache[mime][position - 1]->value(initialPreferenceKey, 0).toInt() < pref) { position--; } @@ -1452,8 +1502,13 @@ void XdgDesktopFileCache::initialize(const QString& dirName) XdgDesktopFile* XdgDesktopFileCache::load(const QString& fileName) { XdgDesktopFile* desktopFile = new XdgDesktopFile(); - desktopFile->load(fileName); - return desktopFile; + + Q_CHECK_PTR(desktopFile); + if (desktopFile && desktopFile->load(fileName)) + return desktopFile; + + delete desktopFile; + return nullptr; } @@ -1463,12 +1518,12 @@ void loadMimeCacheDir(const QString& dirName, QHash specials; - specials.insert("inode/directory", "application/x-directory"); + specials.insert(QLatin1String("inode/directory"), QLatin1String("application/x-directory")); // Working recursively ............ QFileInfoList files = dir.entryInfoList(QStringList(), QDir::Files | QDir::Dirs | QDir::NoDotAndDotDot); - foreach (QFileInfo f, files) + foreach (const QFileInfo &f, files) { if (f.isDir()) { @@ -1481,15 +1536,15 @@ void loadMimeCacheDir(const QString& dirName, QHashvalue("MimeType").toString().split(';', QString::SkipEmptyParts); + QStringList mimes = df->value(mimeTypeKey).toString().split(QLatin1Char(';'), QString::SkipEmptyParts); - foreach (QString mime, mimes) + foreach (const QString &mime, mimes) { - int pref = df->value("InitialPreference", 0).toInt(); + int pref = df->value(initialPreferenceKey, 0).toInt(); // We move the desktopFile forward in the list for this mime, so that // no desktopfile in front of it have a lower initialPreference. int position = cache[mime].length(); - while (position > 0 && cache[mime][position - 1]->value("InitialPreference, 0").toInt() < pref) + while (position > 0 && cache[mime][position - 1]->value(initialPreferenceKey, 0).toInt() < pref) { position--; } @@ -1503,10 +1558,7 @@ QSettings::Format XdgDesktopFileCache::desktopFileSettingsFormat() static QSettings::Format format = QSettings::InvalidFormat; if (format == QSettings::InvalidFormat) - { - format = QSettings::registerFormat("*.list", readDesktopFile, writeDesktopFile); - qDebug() << "registerFormat returned:" << format; - } + format = QSettings::registerFormat(QLatin1String("*.list"), readDesktopFile, writeDesktopFile); return format; } @@ -1530,9 +1582,9 @@ void XdgDesktopFileCache::initialize() QStringList dataDirs = XdgDirs::dataDirs(); dataDirs.prepend(XdgDirs::dataHome(false)); - foreach (const QString dirname, dataDirs) + foreach (const QString &dirname, dataDirs) { - initialize(dirname + "/applications"); + initialize(dirname + QLatin1String("/applications")); // loadMimeCacheDir(dirname + "/applications", m_defaultAppsCache); } } @@ -1543,8 +1595,8 @@ QList XdgDesktopFileCache::getAppsOfCategory(const QString& cat const QString _category = category.toUpper(); foreach (XdgDesktopFile *desktopFile, instance().m_fileCache.values()) { - QStringList categories = desktopFile->value("Categories").toString().toUpper().split(QLatin1Char(';')); - if (!categories.isEmpty() && (categories.contains(_category) || categories.contains(QLatin1String("X-") % _category))) + QStringList categories = desktopFile->value(categoriesKey).toString().toUpper().split(QLatin1Char(';')); + if (!categories.isEmpty() && (categories.contains(_category) || categories.contains(QLatin1String("X-") + _category))) list.append(desktopFile); } return list; @@ -1562,24 +1614,24 @@ XdgDesktopFile* XdgDesktopFileCache::getDefaultApp(const QString& mimetype) // /usr/share/applications/mimeapps.list (in that order) for a default. QStringList dataDirs = XdgDirs::dataDirs(); dataDirs.prepend(XdgDirs::dataHome(false)); - foreach(const QString dataDir, dataDirs) + foreach(const QString &dataDir, dataDirs) { - QString defaultsListPath = dataDir + "/applications/mimeapps.list"; + QString defaultsListPath = dataDir + QLatin1String("/applications/mimeapps.list"); if (QFileInfo(defaultsListPath).exists()) { QSettings defaults(defaultsListPath, desktopFileSettingsFormat()); - defaults.beginGroup("Default Applications"); + defaults.beginGroup(QLatin1String("Default Applications")); if (defaults.contains(mimetype)) { QVariant value = defaults.value(mimetype); if (value.canConvert()) // A single string can also convert to a stringlist { - foreach (const QString desktopFileName, value.toStringList()) + foreach (const QString &desktopFileName, value.toStringList()) { XdgDesktopFile* desktopFile = XdgDesktopFileCache::getFile(desktopFileName); - if (desktopFile->isValid()) + if (desktopFile) { return desktopFile; } diff --git a/xdgdesktopfile.h b/qtxdg/xdgdesktopfile.h similarity index 89% rename from xdgdesktopfile.h rename to qtxdg/xdgdesktopfile.h index da7c90f..63c0994 100644 --- a/xdgdesktopfile.h +++ b/qtxdg/xdgdesktopfile.h @@ -79,7 +79,7 @@ public: - ApplicationType, "value" should be the Exec value; - LinkType, "value" should be the URL; - DirectoryType, "value" should be omitted */ - XdgDesktopFile(XdgDesktopFile::Type type, const QString& name, const QString& value = 0); + XdgDesktopFile(XdgDesktopFile::Type type, const QString& name, const QString& value = QString()); //! Destroys the object. virtual ~XdgDesktopFile(); @@ -146,11 +146,18 @@ public: //! Returns an icon name specified in this file. QString const iconName() const; + //! Returns an list of mimetypes specified in this file. + /*! @return Returns a list of the "MimeType=" entries. + * If the file doens't contain the MimeType entry, an empty QStringList is + * returned. Empty values are removed from the returned list. + */ + QStringList mimeTypes() const; + //! This function is provided for convenience. It's equivalent to calling localizedValue("Name").toString(). - QString name() const { return localizedValue("Name").toString(); } + QString name() const { return localizedValue(QLatin1String("Name")).toString(); } //! This function is provided for convenience. It's equivalent to calling localizedValue("Comment").toString(). - QString comment() const { return localizedValue("Comment").toString(); } + QString comment() const { return localizedValue(QLatin1String("Comment")).toString(); } /*! Returns the desktop file type. @see XdgDesktopFile::Type */ @@ -177,9 +184,16 @@ public: /*! Returns the URL for the Link desktop file; otherwise an empty string is returned. */ QString url() const; - /*! The desktop entry specification defines a number of fields to control the visibility of the application menu. This function - checks whether to display a this application or not. */ - QTXDG_DEPRECATED bool isShow(const QString& environment = "Razor") const; + /*! Computes the desktop file ID. It is the identifier of an installed + * desktop entry file. + * @par fileName - The desktop file complete name. + * @par checkFileExists If true and the file doesn't exist the computed ID + * will be an empty QString(). Defaults to true. + * @return The computed ID. Returns an empty QString() if it's impossible to + * compute the ID. Reference: + * https://specifications.freedesktop.org/desktop-entry-spec/desktop-entry-spec-latest.html#desktop-file-id + */ + static QString id(const QString &fileName, bool checkFileExists = true); /*! The desktop entry specification defines a number of fields to control the visibility of the application menu. Thisfunction checks whether @@ -192,12 +206,6 @@ public: */ bool isShown(const QString &environment = QString()) const; - /*! This fuction returns true if the desktop file is applicable to the current environment. - @par excludeHidden - if set to true (default), files with "Hidden=true" will be considered "not applicable". - Setting this to false is be useful when the user wants to enable/disable items and wants to see those - that are Hidden */ - QTXDG_DEPRECATED bool isApplicable(bool excludeHidden = true, const QString& environment = "Razor") const; - /*! This fuction returns true if the desktop file is applicable to the current environment. @par excludeHidden - if set to true (default), files with @@ -213,7 +221,7 @@ public: bool isSuitable(bool excludeHidden = true, const QString &environment = QString()) const; protected: - virtual QString prefix() const { return "Desktop Entry"; } + virtual QString prefix() const { return QLatin1String("Desktop Entry"); } virtual bool check() const { return true; } private: /*! Returns the localized version of the key if the Desktop File already contains a localized version of it. @@ -261,5 +269,3 @@ private: #endif // QTXDG_XDGDESKTOPFILE_H - - diff --git a/xdgdesktopfile_p.h b/qtxdg/xdgdesktopfile_p.h similarity index 100% rename from xdgdesktopfile_p.h rename to qtxdg/xdgdesktopfile_p.h diff --git a/xdgdirs.cpp b/qtxdg/xdgdirs.cpp similarity index 76% rename from xdgdirs.cpp rename to qtxdg/xdgdirs.cpp index 0d7debe..45d5367 100644 --- a/xdgdirs.cpp +++ b/qtxdg/xdgdirs.cpp @@ -28,21 +28,20 @@ #include "xdgdirs.h" #include #include -#include // for the % operator #include #include static const QString userDirectoryString[8] = { - "Desktop", - "Download", - "Templates", - "Publicshare", - "Documents", - "Music", - "Pictures", - "Videos" + QLatin1String("Desktop"), + QLatin1String("Download"), + QLatin1String("Templates"), + QLatin1String("Publicshare"), + QLatin1String("Documents"), + QLatin1String("Music"), + QLatin1String("Pictures"), + QLatin1String("Videos") }; // Helper functions prototypes @@ -51,7 +50,7 @@ void removeEndingSlash(QString &s); QString createDirectory(const QString &dir); void cleanAndAddPostfix(QStringList &dirs, const QString& postfix); - +QString userDirFallback(XdgDirs::UserDirectory dir); /************************************************ Helper func. @@ -59,7 +58,7 @@ void cleanAndAddPostfix(QStringList &dirs, const QString& postfix); void fixBashShortcuts(QString &s) { if (s.startsWith(QLatin1Char('~'))) - s = QString(getenv("HOME")) + (s).mid(1); + s = QFile::decodeName(qgetenv("HOME")) + (s).mid(1); } @@ -78,9 +77,9 @@ QString createDirectory(const QString &dir) QDir d(dir); if (!d.exists()) { - if (!d.mkpath(".")) + if (!d.mkpath(QLatin1String("."))) { - qWarning() << QString("Can't create %1 directory.").arg(d.absolutePath()); + qWarning() << QString::fromLatin1("Can't create %1 directory.").arg(d.absolutePath()); } } QString r = d.absolutePath(); @@ -101,31 +100,53 @@ void cleanAndAddPostfix(QStringList &dirs, const QString& postfix) } +QString userDirFallback(XdgDirs::UserDirectory dir) +{ + QString fallback; + const QString home = QFile::decodeName(qgetenv("HOME")); + + if (home.isEmpty()) + return QString::fromLatin1("/tmp"); + else if (dir == XdgDirs::Desktop) + fallback = QString::fromLatin1("%1/%2").arg(home).arg(QLatin1String("Desktop")); + else + fallback = home; + + return fallback; +} + + +QString XdgDirs::userDirDefault(XdgDirs::UserDirectory dir) +{ + // possible values for UserDirectory + Q_ASSERT(!(dir < XdgDirs::Desktop || dir > XdgDirs::Videos)); + if (dir < XdgDirs::Desktop || dir > XdgDirs::Videos) + return QString(); + + return userDirFallback(dir); +} + + QString XdgDirs::userDir(XdgDirs::UserDirectory dir) { // possible values for UserDirectory - if (dir < 0 || dir > 7) + Q_ASSERT(!(dir < XdgDirs::Desktop || dir > XdgDirs::Videos)); + if (dir < XdgDirs::Desktop || dir > XdgDirs::Videos) return QString(); QString folderName = userDirectoryString[dir]; - QString fallback; - if (getenv("HOME") == NULL) - return QString("/tmp"); - else if (dir == XdgDirs::Desktop) - fallback = QString("%1/%2").arg(getenv("HOME")).arg("Desktop"); - else - fallback = QString(getenv("HOME")); + const QString fallback = userDirFallback(dir); QString configDir(configHome()); - QFile configFile(configDir + "/user-dirs.dirs"); + QFile configFile(configDir + QLatin1String("/user-dirs.dirs")); if (!configFile.exists()) return fallback; if (!configFile.open(QIODevice::ReadOnly | QIODevice::Text)) return fallback; - QString userDirVar("XDG_" + folderName.toUpper() + "_DIR"); + QString userDirVar(QLatin1String("XDG_") + folderName.toUpper() + QLatin1String("_DIR")); QTextStream in(&configFile); QString line; while (!in.atEnd()) @@ -137,6 +158,8 @@ QString XdgDirs::userDir(XdgDirs::UserDirectory dir) // get path between quotes line = line.section(QLatin1Char('"'), 1, 1); + if (line.isEmpty()) + return fallback; line.replace(QLatin1String("$HOME"), QLatin1String("~")); fixBashShortcuts(line); return line; @@ -151,18 +174,19 @@ QString XdgDirs::userDir(XdgDirs::UserDirectory dir) bool XdgDirs::setUserDir(XdgDirs::UserDirectory dir, const QString& value, bool createDir) { // possible values for UserDirectory - if (dir < 0 || dir > 7) + Q_ASSERT(!(dir < XdgDirs::Desktop || dir > XdgDirs::Videos)); + if (dir < XdgDirs::Desktop || dir > XdgDirs::Videos) return false; if (!(value.startsWith(QLatin1String("$HOME")) || value.startsWith(QLatin1String("~/")) - || value.startsWith(QString(getenv("HOME"))))) + || value.startsWith(QFile::decodeName(qgetenv("HOME"))))) return false; QString folderName = userDirectoryString[dir]; QString configDir(configHome()); - QFile configFile(configDir % QLatin1String("/user-dirs.dirs")); + QFile configFile(configDir + QLatin1String("/user-dirs.dirs")); // create the file if doesn't exist and opens it if (!configFile.open(QIODevice::ReadWrite | QIODevice::Text)) @@ -191,10 +215,10 @@ bool XdgDirs::setUserDir(XdgDirs::UserDirectory dir, const QString& value, bool stream.reset(); configFile.resize(0); if (!foundVar) - stream << QString("XDG_%1_DIR=\"%2\"\n").arg(folderName.toUpper()).arg(value); + stream << QString::fromLatin1("XDG_%1_DIR=\"%2\"\n").arg(folderName.toUpper()).arg(value); for (QVector::iterator i = lines.begin(); i != lines.end(); ++i) - stream << *i << "\n"; + stream << *i << QLatin1Char('\n'); configFile.close(); @@ -293,7 +317,7 @@ QString XdgDirs::runtimeDir() QString XdgDirs::autostartHome(bool createDir) { - QString s = QString("%1/autostart").arg(configHome(createDir)); + QString s = QString::fromLatin1("%1/autostart").arg(configHome(createDir)); fixBashShortcuts(s); if (createDir) @@ -309,9 +333,9 @@ QString XdgDirs::autostartHome(bool createDir) QStringList XdgDirs::autostartDirs(const QString &postfix) { QStringList dirs; - QStringList s = configDirs(); - foreach(QString dir, s) - dirs << QString("%1/autostart").arg(dir) + postfix; + const QStringList s = configDirs(); + foreach(const QString &dir, s) + dirs << QString::fromLatin1("%1/autostart").arg(dir) + postfix; return dirs; } diff --git a/xdgdirs.h b/qtxdg/xdgdirs.h similarity index 95% rename from xdgdirs.h rename to qtxdg/xdgdirs.h index fb333d2..1d2f791 100644 --- a/xdgdirs.h +++ b/qtxdg/xdgdirs.h @@ -62,6 +62,14 @@ public: */ static QString userDir(UserDirectory dir); + + /*! @brief Returns the default path to the user specified directory. + * Returns /tmp if no $HOME defined, $HOME/Desktop if dir equals + * XdgDirs::Desktop or $HOME othewise. If dir value is invalid, an empty + * QString is returned. + */ + static QString userDirDefault(UserDirectory dir); + /*! @brief Returns true if writting into configuration file $XDG_CONFIG_HOME/user-dirs.dirs * the path in value for the directory in dir is succesfull. Returns false otherwise. If * createDir is true, dir will be created if it doesn't exist. diff --git a/xdgicon.cpp b/qtxdg/xdgicon.cpp similarity index 88% rename from xdgicon.cpp rename to qtxdg/xdgicon.cpp index 231a3d5..bb1e153 100644 --- a/xdgicon.cpp +++ b/qtxdg/xdgicon.cpp @@ -33,10 +33,10 @@ #include #include #include -#include "qiconfix/qiconloader_p.h" +#include "../xdgiconloader/xdgiconloader_p.h" #include -#define DEFAULT_APP_ICON "application-x-executable" +static const QLatin1String DEFAULT_APP_ICON("application-x-executable"); static void qt_cleanup_icon_cache(); typedef QCache IconCache; @@ -83,7 +83,7 @@ QString XdgIcon::themeName() void XdgIcon::setThemeName(const QString& themeName) { QIcon::setThemeName(themeName); - QtXdg::QIconLoader::instance()->updateSystemTheme(); + XdgIconLoader::instance()->updateSystemTheme(); } @@ -96,12 +96,12 @@ QIcon XdgIcon::fromTheme(const QString& iconName, const QIcon& fallback) if (iconName.isEmpty()) return fallback; - bool isAbsolute = (iconName[0] == '/'); + bool isAbsolute = (iconName[0] == QLatin1Char('/')); QString name = QFileInfo(iconName).fileName(); - if (name.endsWith(".png", Qt::CaseInsensitive) || - name.endsWith(".svg", Qt::CaseInsensitive) || - name.endsWith(".xpm", Qt::CaseInsensitive)) + if (name.endsWith(QLatin1String(".png"), Qt::CaseInsensitive) || + name.endsWith(QLatin1String(".svg"), Qt::CaseInsensitive) || + name.endsWith(QLatin1String(".xpm"), Qt::CaseInsensitive)) { name.truncate(name.length() - 4); } @@ -113,11 +113,12 @@ QIcon XdgIcon::fromTheme(const QString& iconName, const QIcon& fallback) } else { QIcon *cachedIcon; if (!isAbsolute) - cachedIcon = new QIcon(new QtXdg::QIconLoaderEngineFixed(name)); + cachedIcon = new QIcon(new XdgIconLoaderEngine(name)); else cachedIcon = new QIcon(iconName); - qtIconCache()->insert(name, cachedIcon); icon = *cachedIcon; + + qtIconCache()->insert(name, cachedIcon); } // Note the qapp check is to allow lazy loading of static icons @@ -136,7 +137,7 @@ QIcon XdgIcon::fromTheme(const QString& iconName, const QIcon& fallback) ************************************************/ QIcon XdgIcon::fromTheme(const QStringList& iconNames, const QIcon& fallback) { - foreach (QString iconName, iconNames) + foreach (const QString &iconName, iconNames) { QIcon icon = fromTheme(iconName); if (!icon.isNull()) diff --git a/xdgicon.h b/qtxdg/xdgicon.h similarity index 100% rename from xdgicon.h rename to qtxdg/xdgicon.h diff --git a/xdgmacros.h b/qtxdg/xdgmacros.h similarity index 100% rename from xdgmacros.h rename to qtxdg/xdgmacros.h diff --git a/xdgmenu.cpp b/qtxdg/xdgmenu.cpp similarity index 68% rename from xdgmenu.cpp rename to qtxdg/xdgmenu.cpp index c17259f..b59a001 100644 --- a/xdgmenu.cpp +++ b/qtxdg/xdgmenu.cpp @@ -157,37 +157,37 @@ bool XdgMenu::read(const QString& menuFileName) d->mXml = reader.xml(); QDomElement root = d->mXml.documentElement(); - d->saveLog("00-reader.xml"); + d->saveLog(QLatin1String("00-reader.xml")); d->simplify(root); - d->saveLog("01-simplify.xml"); + d->saveLog(QLatin1String("01-simplify.xml")); d->mergeMenus(root); - d->saveLog("02-mergeMenus.xml"); + d->saveLog(QLatin1String("02-mergeMenus.xml")); d->moveMenus(root); - d->saveLog("03-moveMenus.xml"); + d->saveLog(QLatin1String("03-moveMenus.xml")); d->mergeMenus(root); - d->saveLog("04-mergeMenus.xml"); + d->saveLog(QLatin1String("04-mergeMenus.xml")); d->deleteDeletedMenus(root); - d->saveLog("05-deleteDeletedMenus.xml"); + d->saveLog(QLatin1String("05-deleteDeletedMenus.xml")); d->processDirectoryEntries(root, QStringList()); - d->saveLog("06-processDirectoryEntries.xml"); + d->saveLog(QLatin1String("06-processDirectoryEntries.xml")); d->processApps(root); - d->saveLog("07-processApps.xml"); + d->saveLog(QLatin1String("07-processApps.xml")); d->processLayouts(root); - d->saveLog("08-processLayouts.xml"); + d->saveLog(QLatin1String("08-processLayouts.xml")); d->deleteEmpty(root); - d->saveLog("09-deleteEmpty.xml"); + d->saveLog(QLatin1String("09-deleteEmpty.xml")); d->fixSeparators(root); - d->saveLog("10-fixSeparators.xml"); + d->saveLog(QLatin1String("10-fixSeparators.xml")); d->mOutDated = false; @@ -204,7 +204,7 @@ void XdgMenu::save(const QString& fileName) QFile file(fileName); if (!file.open(QFile::WriteOnly | QFile::Text)) { - qWarning() << QString("Cannot write file %1:\n%2.") + qWarning() << QString::fromLatin1("Cannot write file %1:\n%2.") .arg(fileName) .arg(file.errorString()); return; @@ -225,7 +225,7 @@ void XdgMenuPrivate::load(const QString& fileName) QFile file(fileName); if (!file.open(QFile::ReadOnly | QFile::Text)) { - qWarning() << QString("%1 not loading: %2").arg(fileName).arg(file.errorString()); + qWarning() << QString::fromLatin1("%1 not loading: %2").arg(fileName).arg(file.errorString()); return; } mXml.setContent(&file, true); @@ -236,7 +236,7 @@ void XdgMenuPrivate::saveLog(const QString& logFileName) { Q_Q(XdgMenu); if (!mLogDir.isEmpty()) - q->save(mLogDir + "/" + logFileName); + q->save(mLogDir + QLatin1Char('/') + logFileName); } @@ -244,13 +244,13 @@ void XdgMenuPrivate::mergeMenus(QDomElement& element) { QHash menus; - MutableDomElementIterator it(element, "Menu"); + MutableDomElementIterator it(element, QLatin1String("Menu")); it.toFront(); while(it.hasNext()) { it.next(); - menus[it.current().attribute("name")] = it.current(); + menus[it.current().attribute(QLatin1String("name"))] = it.current(); } @@ -258,7 +258,7 @@ void XdgMenuPrivate::mergeMenus(QDomElement& element) while (it.hasPrevious()) { QDomElement src = it.previous(); - QDomElement dest = menus[src.attribute("name")]; + QDomElement dest = menus[src.attribute(QLatin1String("name"))]; if (dest != src) { prependChilds(src, dest); @@ -267,11 +267,11 @@ void XdgMenuPrivate::mergeMenus(QDomElement& element) } - QDomElement n = element.firstChildElement("Menu"); + QDomElement n = element.firstChildElement(QLatin1String("Menu")); while (!n.isNull()) { mergeMenus(n); - n = n.nextSiblingElement("Menu"); + n = n.nextSiblingElement(QLatin1String("Menu")); } it.toFront(); @@ -288,46 +288,46 @@ void XdgMenuPrivate::simplify(QDomElement& element) { QDomElement n = it.next(); - if (n.tagName() == "Name") + if (n.tagName() == QLatin1String("Name")) { // The field must not contain the slash character ("/"); // implementations should discard any name containing a slash. - element.setAttribute("name", n.text().remove('/')); + element.setAttribute(QLatin1String("name"), n.text().remove(QLatin1Char('/'))); n.parentNode().removeChild(n); } // ...................................... - else if(n.tagName() == "Deleted") + else if(n.tagName() == QLatin1String("Deleted")) { - element.setAttribute("deleted", true); + element.setAttribute(QLatin1String("deleted"), true); n.parentNode().removeChild(n); } - else if(n.tagName() == "NotDeleted") + else if(n.tagName() == QLatin1String("NotDeleted")) { - element.setAttribute("deleted", false); + element.setAttribute(QLatin1String("deleted"), false); n.parentNode().removeChild(n); } // ...................................... - else if(n.tagName() == "OnlyUnallocated") + else if(n.tagName() == QLatin1String("OnlyUnallocated")) { - element.setAttribute("onlyUnallocated", true); + element.setAttribute(QLatin1String("onlyUnallocated"), true); n.parentNode().removeChild(n); } - else if(n.tagName() == "NotOnlyUnallocated") + else if(n.tagName() == QLatin1String(QLatin1String("NotOnlyUnallocated"))) { - element.setAttribute("onlyUnallocated", false); + element.setAttribute(QLatin1String("onlyUnallocated"), false); n.parentNode().removeChild(n); } // ...................................... - else if(n.tagName() == "FileInfo") + else if(n.tagName() == QLatin1String("FileInfo")) { n.parentNode().removeChild(n); } // ...................................... - else if(n.tagName() == "Menu") + else if(n.tagName() == QLatin1String("Menu")) { simplify(n); } @@ -348,15 +348,15 @@ void XdgMenuPrivate::prependChilds(QDomElement& srcElement, QDomElement& destEle destElement.insertBefore(n, destElement.firstChild()); } - if (srcElement.attributes().contains("deleted") && - !destElement.attributes().contains("deleted") + if (srcElement.attributes().contains(QLatin1String("deleted")) && + !destElement.attributes().contains(QLatin1String("deleted")) ) - destElement.setAttribute("deleted", srcElement.attribute("deleted")); + destElement.setAttribute(QLatin1String("deleted"), srcElement.attribute(QLatin1String("deleted"))); - if (srcElement.attributes().contains("onlyUnallocated") && - !destElement.attributes().contains("onlyUnallocated") + if (srcElement.attributes().contains(QLatin1String("onlyUnallocated")) && + !destElement.attributes().contains(QLatin1String("onlyUnallocated")) ) - destElement.setAttribute("onlyUnallocated", srcElement.attribute("onlyUnallocated")); + destElement.setAttribute(QLatin1String("onlyUnallocated"), srcElement.attribute(QLatin1String("onlyUnallocated"))); } @@ -367,11 +367,11 @@ void XdgMenuPrivate::appendChilds(QDomElement& srcElement, QDomElement& destElem while(it.hasNext()) destElement.appendChild(it.next()); - if (srcElement.attributes().contains("deleted")) - destElement.setAttribute("deleted", srcElement.attribute("deleted")); + if (srcElement.attributes().contains(QLatin1String("deleted"))) + destElement.setAttribute(QLatin1String("deleted"), srcElement.attribute(QLatin1String("deleted"))); - if (srcElement.attributes().contains("onlyUnallocated")) - destElement.setAttribute("onlyUnallocated", srcElement.attribute("onlyUnallocated")); + if (srcElement.attributes().contains(QLatin1String("onlyUnallocated"))) + destElement.setAttribute(QLatin1String("onlyUnallocated"), srcElement.attribute(QLatin1String("onlyUnallocated"))); } @@ -384,10 +384,10 @@ QDomElement XdgMenu::findMenu(QDomElement& baseElement, const QString& path, boo { Q_D(XdgMenu); // Absolute path .................. - if (path.startsWith('/')) + if (path.startsWith(QLatin1Char('/'))) { QDomElement root = d->mXml.documentElement(); - return findMenu(root, path.section('/', 2), createNonExisting); + return findMenu(root, path.section(QLatin1Char('/'), 2), createNonExisting); } // Relative path .................. @@ -395,13 +395,13 @@ QDomElement XdgMenu::findMenu(QDomElement& baseElement, const QString& path, boo return baseElement; - QString name = path.section('/', 0, 0); + QString name = path.section(QLatin1Char('/'), 0, 0); MutableDomElementIterator it(baseElement); while(it.hasNext()) { QDomElement n = it.next(); - if (n.attribute("name") == name) - return findMenu(n, path.section('/', 1), createNonExisting); + if (n.attribute(QLatin1String("name")) == name) + return findMenu(n, path.section(QLatin1Char('/'), 1), createNonExisting); } @@ -411,14 +411,14 @@ QDomElement XdgMenu::findMenu(QDomElement& baseElement, const QString& path, boo return QDomElement(); - QStringList names = path.split('/', QString::SkipEmptyParts); + const QStringList names = path.split(QLatin1Char('/'), QString::SkipEmptyParts); QDomElement el = baseElement; - foreach (QString name, names) + foreach (const QString &name, names) { QDomElement p = el; - el = d->mXml.createElement("Menu"); + el = d->mXml.createElement(QLatin1String("Menu")); p.appendChild(el); - el.setAttribute("name", name); + el.setAttribute(QLatin1String("name"), name); } return el; @@ -454,17 +454,17 @@ void XdgMenuPrivate::moveMenus(QDomElement& element) Q_Q(XdgMenu); { - MutableDomElementIterator i(element, "Menu"); + MutableDomElementIterator i(element, QLatin1String("Menu")); while(i.hasNext()) moveMenus(i.next()); } - MutableDomElementIterator i(element, "Move"); + MutableDomElementIterator i(element, QLatin1String("Move")); while(i.hasNext()) { i.next(); - QString oldPath = i.current().lastChildElement("Old").text(); - QString newPath = i.current().lastChildElement("New").text(); + QString oldPath = i.current().lastChildElement(QLatin1String("Old")).text(); + QString newPath = i.current().lastChildElement(QLatin1String("New")).text(); element.removeChild(i.current()); @@ -494,12 +494,12 @@ void XdgMenuPrivate::moveMenus(QDomElement& element) ************************************************/ void XdgMenuPrivate::deleteDeletedMenus(QDomElement& element) { - MutableDomElementIterator i(element, "Menu"); + MutableDomElementIterator i(element, QLatin1String("Menu")); while(i.hasNext()) { QDomElement e = i.next(); - if (e.attribute("deleted") == "1" || - e.attribute("name") == ".hidden" + if (e.attribute(QLatin1String("deleted")) == QLatin1String("1") || + e.attribute(QLatin1String("name")) == QLatin1String(".hidden") ) element.removeChild(e); else @@ -514,7 +514,7 @@ void XdgMenuPrivate::processDirectoryEntries(QDomElement& element, const QString QStringList dirs; QStringList files; - element.setAttribute("title", element.attribute("name")); + element.setAttribute(QLatin1String("title"), element.attribute(QLatin1String("name"))); MutableDomElementIterator i(element, QString()); i.toBack(); @@ -522,13 +522,13 @@ void XdgMenuPrivate::processDirectoryEntries(QDomElement& element, const QString { QDomElement e = i.previous(); - if (e.tagName() == "Directory") + if (e.tagName() == QLatin1String("Directory")) { files << e.text(); element.removeChild(e); } - else if (e.tagName() == "DirectoryDir") + else if (e.tagName() == QLatin1String("DirectoryDir")) { dirs << e.text(); element.removeChild(e); @@ -538,14 +538,14 @@ void XdgMenuPrivate::processDirectoryEntries(QDomElement& element, const QString dirs << parentDirs; bool found = false; - foreach(QString file, files){ - if (file.startsWith('/')) + foreach(const QString &file, files){ + if (file.startsWith(QLatin1Char('/'))) found = loadDirectoryFile(file, element); else { - foreach (QString dir, dirs) + foreach (const QString &dir, dirs) { - found = loadDirectoryFile(dir + "/" + file, element); + found = loadDirectoryFile(dir + QLatin1Char('/') + file, element); if (found) break; } } @@ -553,7 +553,7 @@ void XdgMenuPrivate::processDirectoryEntries(QDomElement& element, const QString } - MutableDomElementIterator it(element, "Menu"); + MutableDomElementIterator it(element, QLatin1String("Menu")); while(it.hasNext()) { QDomElement e = it.next(); @@ -572,9 +572,9 @@ bool XdgMenuPrivate::loadDirectoryFile(const QString& fileName, QDomElement& ele return false; - element.setAttribute("title", file.localizedValue("Name").toString()); - element.setAttribute("comment", file.localizedValue("Comment").toString()); - element.setAttribute("icon", file.value("Icon").toString()); + element.setAttribute(QLatin1String("title"), file.localizedValue(QLatin1String("Name")).toString()); + element.setAttribute(QLatin1String("comment"), file.localizedValue(QLatin1String("Comment")).toString()); + element.setAttribute(QLatin1String("icon"), file.value(QLatin1String("Icon")).toString()); Q_Q(XdgMenu); q->addWatchPath(QFileInfo(file.fileName()).absolutePath()); @@ -592,15 +592,15 @@ void XdgMenuPrivate::processApps(QDomElement& element) void XdgMenuPrivate::deleteEmpty(QDomElement& element) { - MutableDomElementIterator it(element, "Menu"); + MutableDomElementIterator it(element, QLatin1String("Menu")); while(it.hasNext()) deleteEmpty(it.next()); - if (element.attribute("keep") == "true") + if (element.attribute(QLatin1String("keep")) == QLatin1String("true")) return; - QDomElement childMenu = element.firstChildElement("Menu"); - QDomElement childApps = element.firstChildElement("AppLink"); + QDomElement childMenu = element.firstChildElement(QLatin1String("Menu")); + QDomElement childApps = element.firstChildElement(QLatin1String("AppLink")); if (childMenu.isNull() && childApps.isNull()) { @@ -619,25 +619,25 @@ void XdgMenuPrivate::processLayouts(QDomElement& element) void XdgMenuPrivate::fixSeparators(QDomElement& element) { - MutableDomElementIterator it(element, "Separator"); + MutableDomElementIterator it(element, QLatin1String("Separator")); while(it.hasNext()) { QDomElement s = it.next(); - if (s.previousSiblingElement().tagName() == "Separator") + if (s.previousSiblingElement().tagName() == QLatin1String("Separator")) element.removeChild(s); } QDomElement first = element.firstChild().toElement(); - if (first.tagName() == "Separator") + if (first.tagName() == QLatin1String("Separator")) element.removeChild(first); QDomElement last = element.lastChild().toElement(); - if (last.tagName() == "Separator") + if (last.tagName() == QLatin1String("Separator")) element.removeChild(last); - MutableDomElementIterator mi(element, "Menu"); + MutableDomElementIterator mi(element, QLatin1String("Menu")); while(mi.hasNext()) fixSeparators(mi.next()); } @@ -649,32 +649,32 @@ void XdgMenuPrivate::fixSeparators(QDomElement& element) ************************************************/ QString XdgMenu::getMenuFileName(const QString& baseName) { - QStringList configDirs = XdgDirs::configDirs(); - QString menuPrefix = getenv("XDG_MENU_PREFIX"); + const QStringList configDirs = XdgDirs::configDirs(); + QString menuPrefix = QString::fromLocal8Bit(qgetenv("XDG_MENU_PREFIX")); - foreach(QString configDir, configDirs) + foreach(const QString &configDir, configDirs) { - QFileInfo file(QString("%1/menus/%2%3").arg(configDir, menuPrefix, baseName)); + QFileInfo file(QString::fromLatin1("%1/menus/%2%3").arg(configDir, menuPrefix, baseName)); if (file.exists()) return file.filePath(); } QStringList wellKnownFiles; // razor- is a priority for us - wellKnownFiles << "razor-applications.menu"; + wellKnownFiles << QLatin1String("razor-applications.menu"); // the "global" menu file name on suse and fedora - wellKnownFiles << "applications.menu"; + wellKnownFiles << QLatin1String("applications.menu"); // rest files ordered by priority (descending) - wellKnownFiles << "kde4-applications.menu"; - wellKnownFiles << "kde-applications.menu"; - wellKnownFiles << "gnome-applications.menu"; - wellKnownFiles << "lxde-applications.menu"; + wellKnownFiles << QLatin1String("kde4-applications.menu"); + wellKnownFiles << QLatin1String("kde-applications.menu"); + wellKnownFiles << QLatin1String("gnome-applications.menu"); + wellKnownFiles << QLatin1String("lxde-applications.menu"); - foreach(QString configDir, configDirs) + foreach(const QString &configDir, configDirs) { - foreach (QString f, wellKnownFiles) + foreach (const QString &f, wellKnownFiles) { - QFileInfo file(QString("%1/menus/%2").arg(configDir, f)); + QFileInfo file(QString::fromLatin1("%1/menus/%2").arg(configDir, f)); if (file.exists()) return file.filePath(); } diff --git a/xdgmenu.h b/qtxdg/xdgmenu.h similarity index 97% rename from xdgmenu.h rename to qtxdg/xdgmenu.h index a88aa64..e18e0c3 100644 --- a/xdgmenu.h +++ b/qtxdg/xdgmenu.h @@ -108,7 +108,7 @@ public: */ void setLogDir(const QString& directory); - static QString getMenuFileName(const QString& baseName = "applications.menu"); + static QString getMenuFileName(const QString& baseName = QLatin1String("applications.menu")); bool isOutDated() const; diff --git a/xdgmenu_p.h b/qtxdg/xdgmenu_p.h similarity index 100% rename from xdgmenu_p.h rename to qtxdg/xdgmenu_p.h diff --git a/xdgmenuapplinkprocessor.cpp b/qtxdg/xdgmenuapplinkprocessor.cpp similarity index 74% rename from xdgmenuapplinkprocessor.cpp rename to qtxdg/xdgmenuapplinkprocessor.cpp index 02265d6..f031940 100644 --- a/xdgmenuapplinkprocessor.cpp +++ b/qtxdg/xdgmenuapplinkprocessor.cpp @@ -40,9 +40,9 @@ XdgMenuApplinkProcessor::XdgMenuApplinkProcessor(QDomElement& element, XdgMenu* mParent = parent; mMenu = menu; - mOnlyUnallocated = element.attribute("onlyUnallocated") == "1"; + mOnlyUnallocated = element.attribute(QLatin1String("onlyUnallocated")) == QLatin1String("1"); - MutableDomElementIterator i(element, "Menu"); + MutableDomElementIterator i(element, QLatin1String("Menu")); while(i.hasNext()) { QDomElement e = i.next(); @@ -122,18 +122,18 @@ void XdgMenuApplinkProcessor::step2() if (!show) continue; - QDomElement appLink = doc.createElement("AppLink"); + QDomElement appLink = doc.createElement(QLatin1String("AppLink")); - appLink.setAttribute("id", fileInfo->id()); - appLink.setAttribute("title", file->localizedValue("Name").toString()); - appLink.setAttribute("comment", file->localizedValue("Comment").toString()); - appLink.setAttribute("genericName", file->localizedValue("GenericName").toString()); - appLink.setAttribute("exec", file->value("Exec").toString()); - appLink.setAttribute("terminal", file->value("Terminal").toBool()); - appLink.setAttribute("startupNotify", file->value("StartupNotify").toBool()); - appLink.setAttribute("path", file->value("Path").toString()); - appLink.setAttribute("icon", file->value("Icon").toString()); - appLink.setAttribute("desktopFile", file->fileName()); + appLink.setAttribute(QLatin1String("id"), fileInfo->id()); + appLink.setAttribute(QLatin1String("title"), file->localizedValue(QLatin1String("Name")).toString()); + appLink.setAttribute(QLatin1String("comment"), file->localizedValue(QLatin1String("Comment")).toString()); + appLink.setAttribute(QLatin1String("genericName"), file->localizedValue(QLatin1String("GenericName")).toString()); + appLink.setAttribute(QLatin1String("exec"), file->value(QLatin1String("Exec")).toString()); + appLink.setAttribute(QLatin1String("terminal"), file->value(QLatin1String("Terminal")).toBool()); + appLink.setAttribute(QLatin1String("startupNoify"), file->value(QLatin1String("StartupNotify")).toBool()); + appLink.setAttribute(QLatin1String("path"), file->value(QLatin1String("Path")).toString()); + appLink.setAttribute(QLatin1String("icon"), file->value(QLatin1String("Icon")).toString()); + appLink.setAttribute(QLatin1String("desktopFile"), file->fileName()); mElement.appendChild(appLink); @@ -159,7 +159,7 @@ void XdgMenuApplinkProcessor::fillAppFileInfoList() { // Build a pool by collecting entries found in { - MutableDomElementIterator i(mElement, "AppDir"); + MutableDomElementIterator i(mElement, QLatin1String("AppDir")); i.toBack(); while(i.hasPrevious()) { @@ -187,9 +187,9 @@ void XdgMenuApplinkProcessor::findDesktopFiles(const QString& dirName, const QSt { QDir dir(dirName); mMenu->addWatchPath(dir.absolutePath()); - QFileInfoList files = dir.entryInfoList(QStringList("*.desktop"), QDir::Files); + const QFileInfoList files = dir.entryInfoList(QStringList(QLatin1String("*.desktop")), QDir::Files); - foreach (QFileInfo file, files) + foreach (const QFileInfo &file, files) { XdgDesktopFile* f = XdgDesktopFileCache::getFile(file.canonicalFilePath()); if (f) @@ -198,13 +198,13 @@ void XdgMenuApplinkProcessor::findDesktopFiles(const QString& dirName, const QSt // Working recursively ............ - QFileInfoList dirs = dir.entryInfoList(QStringList(), QDir::Dirs | QDir::NoDotAndDotDot); - foreach (QFileInfo d, dirs) + const QFileInfoList dirs = dir.entryInfoList(QStringList(), QDir::Dirs | QDir::NoDotAndDotDot); + foreach (const QFileInfo &d, dirs) { QString dn = d.canonicalFilePath(); if (dn != dirName) { - findDesktopFiles(dn, QString("%1%2-").arg(prefix, d.fileName())); + findDesktopFiles(dn, QString::fromLatin1("%1%2-").arg(prefix, d.fileName())); } } } @@ -216,13 +216,13 @@ void XdgMenuApplinkProcessor::createRules() while(i.hasNext()) { QDomElement e = i.next(); - if (e.tagName()=="Include") + if (e.tagName()== QLatin1String("Include")) { mRules.addInclude(e); mElement.removeChild(e); } - else if (e.tagName()=="Exclude") + else if (e.tagName()== QLatin1String("Exclude")) { mRules.addExclude(e); mElement.removeChild(e); @@ -240,9 +240,9 @@ bool XdgMenuApplinkProcessor::checkTryExec(const QString& progName) if (progName.startsWith(QDir::separator())) return QFileInfo(progName).isExecutable(); - QStringList dirs = QString(getenv("PATH")).split(":"); + const QStringList dirs = QFile::decodeName(qgetenv("PATH")).split(QLatin1Char(':')); - foreach (QString dir, dirs) + foreach (const QString &dir, dirs) { if (QFileInfo(QDir(dir), progName).isExecutable()) return true; @@ -250,4 +250,3 @@ bool XdgMenuApplinkProcessor::checkTryExec(const QString& progName) return false; } - diff --git a/xdgmenuapplinkprocessor.h b/qtxdg/xdgmenuapplinkprocessor.h similarity index 100% rename from xdgmenuapplinkprocessor.h rename to qtxdg/xdgmenuapplinkprocessor.h diff --git a/xdgmenulayoutprocessor.cpp b/qtxdg/xdgmenulayoutprocessor.cpp similarity index 78% rename from xdgmenulayoutprocessor.cpp rename to qtxdg/xdgmenulayoutprocessor.cpp index 75089c2..76afb54 100644 --- a/xdgmenulayoutprocessor.cpp +++ b/qtxdg/xdgmenulayoutprocessor.cpp @@ -68,20 +68,20 @@ XdgMenuLayoutProcessor::XdgMenuLayoutProcessor(QDomElement& element): mDefaultParams.mInlineHeader = true; mDefaultParams.mInlineAlias = false; - mDefaultLayout = findLastElementByTag(element, "DefaultLayout"); + mDefaultLayout = findLastElementByTag(element, QLatin1String("DefaultLayout")); if (mDefaultLayout.isNull()) { // Create DefaultLayout node QDomDocument doc = element.ownerDocument(); - mDefaultLayout = doc.createElement("DefaultLayout"); + mDefaultLayout = doc.createElement(QLatin1String("DefaultLayout")); - QDomElement menus = doc.createElement("Merge"); - menus.setAttribute("type", "menus"); + QDomElement menus = doc.createElement(QLatin1String("Merge")); + menus.setAttribute(QLatin1String("type"), QLatin1String("menus")); mDefaultLayout.appendChild(menus); - QDomElement files = doc.createElement("Merge"); - files.setAttribute("type", "files"); + QDomElement files = doc.createElement(QLatin1String("Merge")); + files.setAttribute(QLatin1String("type"), QLatin1String("files")); mDefaultLayout.appendChild(files); mElement.appendChild(mDefaultLayout); @@ -91,7 +91,7 @@ XdgMenuLayoutProcessor::XdgMenuLayoutProcessor(QDomElement& element): // If a menu does not contain a element or if it contains an empty element // then the default layout should be used. - mLayout = findLastElementByTag(element, "Layout"); + mLayout = findLastElementByTag(element, QLatin1String("Layout")); if (mLayout.isNull() || !mLayout.hasChildNodes()) mLayout = mDefaultLayout; } @@ -103,7 +103,7 @@ XdgMenuLayoutProcessor::XdgMenuLayoutProcessor(QDomElement& element, XdgMenuLayo mDefaultParams = parent->mDefaultParams; // DefaultLayout ............................ - QDomElement defaultLayout = findLastElementByTag(element, "DefaultLayout"); + QDomElement defaultLayout = findLastElementByTag(element, QLatin1String("DefaultLayout")); if (defaultLayout.isNull()) mDefaultLayout = parent->mDefaultLayout; @@ -114,7 +114,7 @@ XdgMenuLayoutProcessor::XdgMenuLayoutProcessor(QDomElement& element, XdgMenuLayo // If a menu does not contain a element or if it contains an empty element // then the default layout should be used. - mLayout = findLastElementByTag(element, "Layout"); + mLayout = findLastElementByTag(element, QLatin1String("Layout")); if (mLayout.isNull() || !mLayout.hasChildNodes()) mLayout = mDefaultLayout; @@ -123,20 +123,20 @@ XdgMenuLayoutProcessor::XdgMenuLayoutProcessor(QDomElement& element, XdgMenuLayo void XdgMenuLayoutProcessor::setParams(QDomElement defaultLayout, LayoutParams *result) { - if (defaultLayout.hasAttribute("show_empty")) - result->mShowEmpty = defaultLayout.attribute("show_empty") == "true"; + if (defaultLayout.hasAttribute(QLatin1String("show_empty"))) + result->mShowEmpty = defaultLayout.attribute(QLatin1String("show_empty")) == QLatin1String("true"); - if (defaultLayout.hasAttribute("inline")) - result->mInline = defaultLayout.attribute("inline") == "true"; + if (defaultLayout.hasAttribute(QLatin1String("inline"))) + result->mInline = defaultLayout.attribute(QLatin1String("inline")) == QLatin1String("true"); - if (defaultLayout.hasAttribute("inline_limit")) - result->mInlineLimit = defaultLayout.attribute("inline_limit").toInt(); + if (defaultLayout.hasAttribute(QLatin1String("inline_limit"))) + result->mInlineLimit = defaultLayout.attribute(QLatin1String("inline_limit")).toInt(); - if (defaultLayout.hasAttribute("inline_header")) - result->mInlineHeader = defaultLayout.attribute("inline_header") == "true"; + if (defaultLayout.hasAttribute(QLatin1String("inline_header"))) + result->mInlineHeader = defaultLayout.attribute(QLatin1String("inline_header")) == QLatin1String("true"); - if (defaultLayout.hasAttribute("inline_alias")) - result->mInlineAlias = defaultLayout.attribute("inline_alias") == "true"; + if (defaultLayout.hasAttribute(QLatin1String("inline_alias"))) + result->mInlineAlias = defaultLayout.attribute(QLatin1String("inline_alias")) == QLatin1String("true"); } @@ -163,7 +163,7 @@ int childsCount(const QDomElement& element) while (it.hasNext()) { QString tag = it.next().tagName(); - if (tag == "AppLink" || tag == "Menu" || tag == "Separator") + if (tag == QLatin1String("AppLink") || tag == QLatin1String("Menu") || tag == QLatin1String("Separator")) count ++; } @@ -174,12 +174,12 @@ int childsCount(const QDomElement& element) void XdgMenuLayoutProcessor::run() { QDomDocument doc = mLayout.ownerDocument(); - mResult = doc.createElement("Result"); + mResult = doc.createElement(QLatin1String("Result")); mElement.appendChild(mResult); // Process childs menus ............................... { - DomElementIterator it(mElement, "Menu"); + DomElementIterator it(mElement, QLatin1String("Menu")); while (it.hasNext()) { QDomElement e = it.next(); @@ -196,26 +196,26 @@ void XdgMenuLayoutProcessor::run() { QDomElement e = it.next(); - if (e.tagName() == "Filename") + if (e.tagName() == QLatin1String("Filename")) processFilenameTag(e); - else if (e.tagName() == "Menuname") + else if (e.tagName() == QLatin1String("Menuname")) processMenunameTag(e); - else if (e.tagName() == "Separator") + else if (e.tagName() == QLatin1String("Separator")) processSeparatorTag(e); - else if (e.tagName() == "Merge") + else if (e.tagName() == QLatin1String("Merge")) { - QDomElement merge = mResult.ownerDocument().createElement("Merge"); - merge.setAttribute("type", e.attribute("type")); + QDomElement merge = mResult.ownerDocument().createElement(QLatin1String("Merge")); + merge.setAttribute(QLatin1String("type"), e.attribute(QLatin1String("type"))); mResult.appendChild(merge); } } // Step 2 ................................... { - MutableDomElementIterator ri(mResult, "Merge"); + MutableDomElementIterator ri(mResult, QLatin1String("Merge")); while (ri.hasNext()) { processMergeTag(ri.next()); @@ -249,7 +249,7 @@ void XdgMenuLayoutProcessor::processFilenameTag(const QDomElement &element) { QString id = element.text(); - QDomElement appLink = searchElement("AppLink", "id", id); + QDomElement appLink = searchElement(QLatin1String("AppLink"), QLatin1String("id"), id); if (!appLink.isNull()) mResult.appendChild(appLink); } @@ -290,7 +290,7 @@ void XdgMenuLayoutProcessor::processFilenameTag(const QDomElement &element) void XdgMenuLayoutProcessor::processMenunameTag(const QDomElement &element) { QString id = element.text(); - QDomElement menu = searchElement("Menu", "name", id); + QDomElement menu = searchElement(QLatin1String("Menu"), QLatin1String("name"), id); if (menu.isNull()) return; @@ -303,7 +303,7 @@ void XdgMenuLayoutProcessor::processMenunameTag(const QDomElement &element) { if (params.mShowEmpty) { - menu.setAttribute("keep", "true"); + menu.setAttribute(QLatin1String("keep"), QLatin1String("true")); mResult.appendChild(menu); } return; @@ -330,7 +330,7 @@ void XdgMenuLayoutProcessor::processMenunameTag(const QDomElement &element) // Header .................................... if (doHeader) { - QDomElement header = mLayout.ownerDocument().createElement("Header"); + QDomElement header = mLayout.ownerDocument().createElement(QLatin1String("Header")); QDomNamedNodeMap attrs = menu.attributes(); for (int i=0; i < attrs.count(); ++i) @@ -344,7 +344,7 @@ void XdgMenuLayoutProcessor::processMenunameTag(const QDomElement &element) // Alias ..................................... if (doAlias) { - menu.firstChild().toElement().setAttribute("title", menu.attribute("title")); + menu.firstChild().toElement().setAttribute(QLatin1String("title"), menu.attribute(QLatin1String("title"))); } // Inline .................................... @@ -364,7 +364,7 @@ void XdgMenuLayoutProcessor::processMenunameTag(const QDomElement &element) ************************************************/ void XdgMenuLayoutProcessor::processSeparatorTag(const QDomElement &element) { - QDomElement separator = element.ownerDocument().createElement("Separator"); + QDomElement separator = element.ownerDocument().createElement(QLatin1String("Separator")); mResult.appendChild(separator); } @@ -387,7 +387,7 @@ void XdgMenuLayoutProcessor::processSeparatorTag(const QDomElement &element) ************************************************/ void XdgMenuLayoutProcessor::processMergeTag(const QDomElement &element) { - QString type = element.attribute("type"); + QString type = element.attribute(QLatin1String("type")); QMap map; MutableDomElementIterator it(mElement); @@ -395,10 +395,10 @@ void XdgMenuLayoutProcessor::processMergeTag(const QDomElement &element) { QDomElement e = it.next(); if ( - ((type == "menus" || type == "all") && e.tagName() == "Menu" ) || - ((type == "files" || type == "all") && e.tagName() == "AppLink") + ((type == QLatin1String("menus") || type == QLatin1String("all")) && e.tagName() == QLatin1String("Menu" )) || + ((type == QLatin1String("files") || type == QLatin1String("all")) && e.tagName() == QLatin1String("AppLink")) ) - map.insert(e.attribute("title"), e); + map.insert(e.attribute(QLatin1String("title")), e); } QMapIterator mi(map); diff --git a/xdgmenulayoutprocessor.h b/qtxdg/xdgmenulayoutprocessor.h similarity index 100% rename from xdgmenulayoutprocessor.h rename to qtxdg/xdgmenulayoutprocessor.h diff --git a/xdgmenureader.cpp b/qtxdg/xdgmenureader.cpp similarity index 86% rename from xdgmenureader.cpp rename to qtxdg/xdgmenureader.cpp index 8333c9a..f4e4393 100644 --- a/xdgmenureader.cpp +++ b/qtxdg/xdgmenureader.cpp @@ -76,7 +76,7 @@ bool XdgMenuReader::load(const QString& fileName, const QString& baseDir) QFile file(mFileName); if (!file.open(QFile::ReadOnly | QFile::Text)) { - mErrorStr = QString("%1 not loading: %2").arg(fileName).arg(file.errorString()); + mErrorStr = QString::fromLatin1("%1 not loading: %2").arg(fileName).arg(file.errorString()); return false; } //qDebug() << "Load file:" << mFileName; @@ -88,7 +88,7 @@ bool XdgMenuReader::load(const QString& fileName, const QString& baseDir) if (!mXml.setContent(&file, true, &errorStr, &errorLine, &errorColumn)) { - mErrorStr = QString("Parse error at line %1, column %2:\n%3") + mErrorStr = QString::fromLatin1("Parse error at line %1, column %2:\n%3") .arg(errorLine) .arg(errorColumn) .arg(errorStr); @@ -97,10 +97,10 @@ bool XdgMenuReader::load(const QString& fileName, const QString& baseDir) QDomElement root = mXml.documentElement(); - QDomElement debugElement = mXml.createElement("FileInfo"); - debugElement.setAttribute("file", mFileName); + QDomElement debugElement = mXml.createElement(QLatin1String("FileInfo")); + debugElement.setAttribute(QLatin1String("file"), mFileName); if (mParentReader) - debugElement.setAttribute("parent", mParentReader->fileName()); + debugElement.setAttribute(QLatin1String("parent"), mParentReader->fileName()); QDomNode null; root.insertBefore(debugElement, null); @@ -124,49 +124,49 @@ void XdgMenuReader::processMergeTags(QDomElement& element) { QDomElement next = n.previousSiblingElement(); // MergeFile .................. - if (n.tagName() == "MergeFile") + if (n.tagName() == QLatin1String("MergeFile")) { processMergeFileTag(n, &mergedFiles); n.parentNode().removeChild(n); } // MergeDir ................... - else if(n.tagName() == "MergeDir") + else if(n.tagName() == QLatin1String("MergeDir")) { processMergeDirTag(n, &mergedFiles); n.parentNode().removeChild(n); } // DefaultMergeDirs ........... - else if (n.tagName() == "DefaultMergeDirs") + else if (n.tagName() == QLatin1String("DefaultMergeDirs")) { processDefaultMergeDirsTag(n, &mergedFiles); n.parentNode().removeChild(n); } // AppDir ................... - else if(n.tagName() == "AppDir") + else if(n.tagName() == QLatin1String("AppDir")) { processAppDirTag(n); n.parentNode().removeChild(n); } // DefaultAppDirs ............. - else if(n.tagName() == "DefaultAppDirs") + else if(n.tagName() == QLatin1String("DefaultAppDirs")) { processDefaultAppDirsTag(n); n.parentNode().removeChild(n); } // DirectoryDir ................... - else if(n.tagName() == "DirectoryDir") + else if(n.tagName() == QLatin1String("DirectoryDir")) { processDirectoryDirTag(n); n.parentNode().removeChild(n); } // DefaultDirectoryDirs ........... - else if(n.tagName() == "DefaultDirectoryDirs") + else if(n.tagName() == QLatin1String("DefaultDirectoryDirs")) { processDefaultDirectoryDirsTag(n); n.parentNode().removeChild(n); @@ -174,7 +174,7 @@ void XdgMenuReader::processMergeTags(QDomElement& element) // Menu ....................... - else if(n.tagName() == "Menu") + else if(n.tagName() == QLatin1String("Menu")) { processMergeTags(n); } @@ -205,7 +205,7 @@ void XdgMenuReader::processMergeFileTag(QDomElement& element, QStringList* merge { //qDebug() << "Process " << element;// << "in" << mFileName; - if (element.attribute("type") != "parent") + if (element.attribute(QLatin1String("type")) != QLatin1String("parent")) { mergeFile(element.text(), element, mergedFiles); } @@ -215,7 +215,7 @@ void XdgMenuReader::processMergeFileTag(QDomElement& element, QStringList* merge QString relativeName; QStringList configDirs = XdgDirs::configDirs(); - foreach (QString configDir, configDirs) + foreach (const QString &configDir, configDirs) { if (mFileName.startsWith(configDir)) { @@ -236,7 +236,7 @@ void XdgMenuReader::processMergeFileTag(QDomElement& element, QStringList* merge if (relativeName.isEmpty()) return; - foreach (QString configDir, configDirs) + foreach (const QString &configDir, configDirs) { if (QFileInfo(configDir + relativeName).exists()) { @@ -288,20 +288,20 @@ void XdgMenuReader::processDefaultMergeDirsTag(QDomElement& element, QStringList //qDebug() << "Process " << element;// << "in" << mFileName; QString menuBaseName = QFileInfo(mMenu->menuFileName()).baseName(); - int n = menuBaseName.lastIndexOf('-'); + int n = menuBaseName.lastIndexOf(QLatin1Char('-')); if (n>-1) menuBaseName = menuBaseName.mid(n+1); QStringList dirs = XdgDirs::configDirs(); dirs << XdgDirs::configHome(); - foreach (QString dir, dirs) + foreach (const QString &dir, dirs) { - mergeDir(QString("%1/menus/%2-merged").arg(dir).arg(menuBaseName), element, mergedFiles); + mergeDir(QString::fromLatin1("%1/menus/%2-merged").arg(dir).arg(menuBaseName), element, mergedFiles); } - if (menuBaseName == "applications") - mergeFile(QString("%1/menus/applications-kmenuedit.menu").arg(XdgDirs::configHome()), element, mergedFiles); + if (menuBaseName == QLatin1String("applications")) + mergeFile(QString::fromLatin1("%1/menus/applications-kmenuedit.menu").arg(XdgDirs::configHome()), element, mergedFiles); } @@ -312,7 +312,7 @@ void XdgMenuReader::processDefaultMergeDirsTag(QDomElement& element, QStringList void XdgMenuReader::processAppDirTag(QDomElement& element) { //qDebug() << "Process " << element; - addDirTag(element, "AppDir", element.text()); + addDirTag(element, QLatin1String("AppDir"), element.text()); } @@ -329,10 +329,10 @@ void XdgMenuReader::processDefaultAppDirsTag(QDomElement& element) QStringList dirs = XdgDirs::dataDirs(); dirs.prepend(XdgDirs::dataHome(false)); - foreach (QString dir, dirs) + foreach (const QString &dir, dirs) { //qDebug() << "Add AppDir: " << dir + "/applications/"; - addDirTag(element, "AppDir", dir + "/applications/"); + addDirTag(element, QLatin1String("AppDir"), dir + QLatin1String("/applications/")); } } @@ -343,7 +343,7 @@ void XdgMenuReader::processDefaultAppDirsTag(QDomElement& element) void XdgMenuReader::processDirectoryDirTag(QDomElement& element) { //qDebug() << "Process " << element; - addDirTag(element, "DirectoryDir", element.text()); + addDirTag(element, QLatin1String("DirectoryDir"), element.text()); } @@ -360,8 +360,8 @@ void XdgMenuReader::processDefaultDirectoryDirsTag(QDomElement& element) QStringList dirs = XdgDirs::dataDirs(); dirs.prepend(XdgDirs::dataHome(false)); - foreach (QString dir, dirs) - addDirTag(element, "DirectoryDir", dir + "/desktop-directories/"); + foreach (const QString &dir, dirs) + addDirTag(element, QLatin1String("DirectoryDir"), dir + QLatin1String("/desktop-directories/")); } /************************************************ @@ -409,7 +409,7 @@ void XdgMenuReader::mergeFile(const QString& fileName, QDomElement& element, QSt { // As a special exception, remove the element from the root // element of each file being merged. - if (n.tagName() != "Name") + if (n.tagName() != QLatin1String("Name")) { QDomNode imp = mXml.importNode(n, true); element.parentNode().insertBefore(imp, element); @@ -429,9 +429,9 @@ void XdgMenuReader::mergeDir(const QString& dirName, QDomElement& element, QStri { //qDebug() << "Merge dir: " << dirInfo.canonicalFilePath(); QDir dir = QDir(dirInfo.canonicalFilePath()); - const QFileInfoList files = dir.entryInfoList(QStringList() << "*.menu", QDir::Files | QDir::Readable); + const QFileInfoList files = dir.entryInfoList(QStringList() << QLatin1String("*.menu"), QDir::Files | QDir::Readable); - foreach (QFileInfo file, files) + foreach (const QFileInfo &file, files) mergeFile(file.canonicalFilePath(), element, mergedFiles); } } diff --git a/xdgmenureader.h b/qtxdg/xdgmenureader.h similarity index 100% rename from xdgmenureader.h rename to qtxdg/xdgmenureader.h diff --git a/xdgmenurules.cpp b/qtxdg/xdgmenurules.cpp similarity index 94% rename from xdgmenurules.cpp rename to qtxdg/xdgmenurules.cpp index 514c4a0..b8ee197 100644 --- a/xdgmenurules.cpp +++ b/qtxdg/xdgmenurules.cpp @@ -63,26 +63,26 @@ XdgMenuRuleOr::XdgMenuRuleOr(const QDomElement& element, QObject* parent) : { QDomElement e = iter.next(); - if (e.tagName() == "Or") + if (e.tagName() == QLatin1String("Or")) mChilds.append(new XdgMenuRuleOr(e, this)); - else if (e.tagName() == "And") + else if (e.tagName() == QLatin1String("And")) mChilds.append(new XdgMenuRuleAnd(e, this)); - else if (e.tagName() == "Not") + else if (e.tagName() == QLatin1String("Not")) mChilds.append(new XdgMenuRuleNot(e, this)); - else if (e.tagName() == "Filename") + else if (e.tagName() == QLatin1String("Filename")) mChilds.append(new XdgMenuRuleFileName(e, this)); - else if (e.tagName() == "Category") + else if (e.tagName() == QLatin1String("Category")) mChilds.append(new XdgMenuRuleCategory(e, this)); - else if (e.tagName() == "All") + else if (e.tagName() == QLatin1String("All")) mChilds.append(new XdgMenuRuleAll(e, this)); else - qWarning() << "Unknown rule" << e.tagName(); + qWarning() << QString::fromLatin1("Unknown rule") << e.tagName(); } } diff --git a/xdgmenurules.h b/qtxdg/xdgmenurules.h similarity index 100% rename from xdgmenurules.h rename to qtxdg/xdgmenurules.h diff --git a/xdgmenuwidget.cpp b/qtxdg/xdgmenuwidget.cpp similarity index 83% rename from xdgmenuwidget.cpp rename to qtxdg/xdgmenuwidget.cpp index d2e6c79..acabb8f 100644 --- a/xdgmenuwidget.cpp +++ b/qtxdg/xdgmenuwidget.cpp @@ -99,13 +99,13 @@ void XdgMenuWidgetPrivate::init(const QDomElement& xml) q->clear(); QString title; - if (! xml.attribute("title").isEmpty()) - title = xml.attribute("title"); + if (! xml.attribute(QLatin1String("title")).isEmpty()) + title = xml.attribute(QLatin1String("title")); else - title = xml.attribute("name"); + title = xml.attribute(QLatin1String("name")); q->setTitle(escape(title)); - q->setToolTip(xml.attribute("comment")); + q->setToolTip(xml.attribute(QLatin1String("comment"))); QIcon parentIcon; @@ -113,7 +113,7 @@ void XdgMenuWidgetPrivate::init(const QDomElement& xml) if (parentMenu) parentIcon = parentMenu->icon(); - q->setIcon(XdgIcon::fromTheme(mXml.attribute("icon"), parentIcon)); + q->setIcon(XdgIcon::fromTheme(mXml.attribute(QLatin1String("icon")), parentIcon)); buildMenu(); } @@ -195,15 +195,15 @@ void XdgMenuWidgetPrivate::buildMenu() QDomElement xml = it.next(); // Build submenu ........................ - if (xml.tagName() == "Menu") + if (xml.tagName() == QLatin1String("Menu")) q->insertMenu(first, new XdgMenuWidget(xml, q)); //Build application link ................ - else if (xml.tagName() == "AppLink") + else if (xml.tagName() == QLatin1String("AppLink")) q->insertAction(first, createAction(xml)); //Build separator ....................... - else if (xml.tagName() == "Separator") + else if (xml.tagName() == QLatin1String("Separator")) q->insertSeparator(first); } @@ -213,18 +213,18 @@ void XdgMenuWidgetPrivate::buildMenu() XdgAction* XdgMenuWidgetPrivate::createAction(const QDomElement& xml) { Q_Q(XdgMenuWidget); - XdgAction* action = new XdgAction(xml.attribute("desktopFile"), q); + XdgAction* action = new XdgAction(xml.attribute(QLatin1String("desktopFile")), q); QString title; - if (!xml.attribute("title").isEmpty()) - title = xml.attribute("title"); + if (!xml.attribute(QLatin1String("title")).isEmpty()) + title = xml.attribute(QLatin1String("title")); else - title = xml.attribute("name"); + title = xml.attribute(QLatin1String("name")); - if (!xml.attribute("genericName").isEmpty() && - xml.attribute("genericName") != title) - title += QString(" (%1)").arg(xml.attribute("genericName")); + if (!xml.attribute(QLatin1String("genericName")).isEmpty() && + xml.attribute(QLatin1String("genericName")) != title) + title += QString::fromLatin1(" (%1)").arg(xml.attribute(QLatin1String("genericName"))); action->setText(escape(title)); return action; @@ -237,5 +237,5 @@ XdgAction* XdgMenuWidgetPrivate::createAction(const QDomElement& xml) ************************************************/ QString XdgMenuWidgetPrivate::escape(QString string) { - return string.replace("&", "&&"); + return string.replace(QLatin1Char('&'), QLatin1String("&&")); } diff --git a/xdgmenuwidget.h b/qtxdg/xdgmenuwidget.h similarity index 100% rename from xdgmenuwidget.h rename to qtxdg/xdgmenuwidget.h diff --git a/xdgmimetype.cpp b/qtxdg/xdgmimetype.cpp similarity index 98% rename from xdgmimetype.cpp rename to qtxdg/xdgmimetype.cpp index 7bb8987..ed9ab91 100644 --- a/xdgmimetype.cpp +++ b/qtxdg/xdgmimetype.cpp @@ -96,7 +96,7 @@ QString XdgMimeType::iconName() const names.append(QMimeType::iconName()); names.append(QMimeType::genericIconName()); - foreach (QString s, names) { + foreach (const QString &s, names) { if (!XdgIcon::fromTheme(s).isNull()) { dx->iconName = s; break; diff --git a/xdgmimetype.h b/qtxdg/xdgmimetype.h similarity index 100% rename from xdgmimetype.h rename to qtxdg/xdgmimetype.h diff --git a/xmlhelper.cpp b/qtxdg/xmlhelper.cpp similarity index 85% rename from xmlhelper.cpp rename to qtxdg/xmlhelper.cpp index 648500c..6239ad4 100644 --- a/xmlhelper.cpp +++ b/qtxdg/xmlhelper.cpp @@ -39,10 +39,8 @@ QDebug operator<<(QDebug dbg, const QDomElement &el) QString args; for (int i=0; i%3").arg(el.tagName()).arg(args).arg(el.text()); + dbg.nospace() << QString::fromLatin1("<%1%2>%3").arg(el.tagName()).arg(args).arg(el.text()); return dbg.space(); } - - diff --git a/xmlhelper.h b/qtxdg/xmlhelper.h similarity index 100% rename from xmlhelper.h rename to qtxdg/xmlhelper.h diff --git a/release.sh b/release.sh index f60eb6a..29ca2c8 100755 --- a/release.sh +++ b/release.sh @@ -25,4 +25,4 @@ sha256sum --tag *.tar.gz *.tar.xz >> CHECKSUMS cd .. echo "Uploading to lxqt.org..." -scp -r "$version" "lxde.org:/var/www/lxqt/downloads/$PROJECT/" +scp -r "$version" "downloads.lxqt.org:/srv/downloads.lxqt.org/$PROJECT/" diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 19b0df6..8d7b580 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -1,5 +1,10 @@ set(PROJECT_NAME "qtxdg_test") +remove_definitions( + -DQT_USE_QSTRINGBUILDER + -DQT_NO_CAST_FROM_ASCII +) + set(CMAKE_AUTOMOC TRUE) macro(qtxdg_add_test) @@ -11,7 +16,7 @@ macro(qtxdg_add_test) endmacro() include_directories ( - ${CMAKE_SOURCE_DIR} + "${CMAKE_SOURCE_DIR}/qtxdg" ${CMAKE_CURRENT_BINARY_DIR} ) @@ -22,4 +27,5 @@ set_property(DIRECTORY APPEND qtxdg_add_test( qtxdg_test tst_xdgdirs + tst_xdgdesktopfile ) diff --git a/test/tst_xdgdesktopfile.cpp b/test/tst_xdgdesktopfile.cpp new file mode 100644 index 0000000..63dd6a3 --- /dev/null +++ b/test/tst_xdgdesktopfile.cpp @@ -0,0 +1,118 @@ +/* + * libqtxdg - An Qt implementation of freedesktop.org xdg specs. + * Copyright (C) 2016 Luís Pereira + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#include "tst_xdgdesktopfile.h" +#include "XdgDesktopFile" +#include + + +class Language +{ +public: + Language (const QString& lang) + : mPreviousLang(QString::fromLocal8Bit(qgetenv("LANG"))) + { + qputenv("LANG", lang.toLocal8Bit()); + } + ~Language() + { + qputenv("LANG", mPreviousLang.toLocal8Bit()); + } +private: + QString mPreviousLang; +}; + + +QTEST_MAIN(tst_xdgdesktopfile); + +void tst_xdgdesktopfile::testRead() +{ + QTemporaryFile file("testReadXXXXXX.desktop"); + QVERIFY(file.open()); + const QString fileName = file.fileName(); + QTextStream ts(&file); + ts << + "[Desktop Entry]\n" + "Type=Application\n" + "Name=MyApp\n" + "Icon=foobar\n" + "MimeType=text/plain;image/png;;\n" + "\n"; + file.close(); + QVERIFY(QFile::exists(fileName)); + + XdgDesktopFile df; + df.load(fileName); + + QVERIFY(df.isValid()); + QCOMPARE(df.type(), XdgDesktopFile::ApplicationType); + QCOMPARE(df.name(), QString::fromLatin1("MyApp")); + QCOMPARE(df.iconName(), QString::fromLatin1("foobar")); + QCOMPARE(df.mimeTypes(), QStringList() << QString::fromLatin1("text/plain") + << QString::fromLatin1("image/png")); + QCOMPARE(df.fileName(), QFileInfo(fileName).canonicalFilePath()); +} + +void tst_xdgdesktopfile::testReadLocalized_data() +{ + QTest::addColumn("locale"); + QTest::addColumn("translation"); + + const QString pt = QString::fromUtf8("A Minha Aplicação"); + const QString pt_BR = QString::fromUtf8("O Meu Aplicativo"); + + QTest::newRow("pt") << QStringLiteral("pt") << pt; + QTest::newRow("pt_PT") << QStringLiteral("pt_PT") << pt; + QTest::newRow("pt_BR") << QStringLiteral("pt_BR") << pt_BR; + + QTest::newRow("de") << QStringLiteral("de") << QStringLiteral("My Application"); +} + +void tst_xdgdesktopfile::testReadLocalized() +{ + QTemporaryFile file("testReadLocalizedXXXXXX.desktop"); + QVERIFY(file.open()); + const QString fileName = file.fileName(); + QTextStream ts(&file); + ts << QString::fromUtf8( + "[Desktop Entry]\n" + "Type=Application\n" + "Name=My Application\n" + "Name[pt]=A Minha Aplicação\n" + "Name[pt_BR]=O Meu Aplicativo\n" + "Icon=foo\n" + "\n"); + file.close(); + + QVERIFY(QFile::exists(fileName)); + + XdgDesktopFile df; + df.load(fileName); + QVERIFY(df.isValid()); + + QFETCH(QString, locale); + QFETCH(QString, translation); + + Language lang(locale); + + QCOMPARE(df.localizedValue("Name").toString(), translation); +} + +#include "test/tst_xdgdesktopfile.moc" diff --git a/test/tst_xdgdesktopfile.h b/test/tst_xdgdesktopfile.h new file mode 100644 index 0000000..337530c --- /dev/null +++ b/test/tst_xdgdesktopfile.h @@ -0,0 +1,35 @@ +/* + * libqtxdg - An Qt implementation of freedesktop.org xdg specs. + * Copyright (C) 2016 Luís Pereira + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#ifndef TST_XDGDESKTOPFILE_H +#define TST_XDGDESKTOPFILE_H + +#include + +class tst_xdgdesktopfile : public QObject { + Q_OBJECT +private slots: + + void testRead(); + void testReadLocalized(); + void testReadLocalized_data(); +}; + +#endif // TST_XDGDESKTOPFILE_H diff --git a/util/CMakeLists.txt b/util/CMakeLists.txt new file mode 100644 index 0000000..7d871ae --- /dev/null +++ b/util/CMakeLists.txt @@ -0,0 +1,26 @@ +include_directories ( + "${CMAKE_PROJECT_DIR}/qtxdg" + ${CMAKE_CURRENT_BINARY_DIR} +) + +set(QTXDG_DESKTOP_FILE_START_SRCS + qtxdg-desktop-file-start.cpp +) + +add_executable(qtxdg-desktop-file-start + ${QTXDG_DESKTOP_FILE_START_SRCS} +) + +target_compile_definitions(qtxdg-desktop-file-start + PRIVATE "-DQTXDG_VERSION=\"${QTXDG_VERSION_STRING}\"" +) + +target_link_libraries(qtxdg-desktop-file-start + ${QTXDGX_LIBRARY_NAME} +) + +install(TARGETS + qtxdg-desktop-file-start + RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}" + COMPONENT Runtime +) diff --git a/util/qtxdg-desktop-file-start.cpp b/util/qtxdg-desktop-file-start.cpp new file mode 100644 index 0000000..21f057e --- /dev/null +++ b/util/qtxdg-desktop-file-start.cpp @@ -0,0 +1,71 @@ +/* + * libqtxdg - An Qt implementation of freedesktop.org xdg specs + * Copyright (C) 2016 Luís Pereira + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA + */ + +#include +#include +#include + +#include + +#include + +static void printErr(const QString & out) +{ + std::cerr << qPrintable(out); +} + +int main(int argc, char *argv[]) +{ + QCoreApplication app(argc, argv); + QCoreApplication::setApplicationName(QLatin1String("qtxdg-desktop-file-start")); + QCoreApplication::setApplicationVersion(QLatin1String(QTXDG_VERSION)); + + QCommandLineParser parser; + parser.setApplicationDescription(QLatin1String("QtXdg XdgDesktopFile start Tester")); + parser.addHelpOption(); + parser.addVersionOption(); + parser.addPositionalArgument(QLatin1String("file [urls...]"), QLatin1String("desktop file to start and it's urls"),QLatin1String("file [urls...]")); + parser.process(app); + + if (parser.positionalArguments().isEmpty()) { + parser.showHelp(EXIT_FAILURE); + } + + QStringList userArgs = parser.positionalArguments(); + const QString userFileName = userArgs.takeFirst(); + const QFileInfo fileInfo(userFileName); + const QString canonicalFileName = fileInfo.canonicalFilePath(); + + if (!fileInfo.exists()) { + printErr(QString::fromLatin1("File %1 does not exist\n").arg(userFileName)); + return EXIT_FAILURE; + } + + XdgDesktopFile f; + const bool valid = f.load(canonicalFileName); + if (valid) { + f.startDetached(userArgs); + } else { + printErr(QString::fromLatin1("%1 is not a valid .desktop file\n").arg(canonicalFileName)); + return EXIT_FAILURE; + } + + return EXIT_SUCCESS; +} diff --git a/xdgiconloader/CMakeLists.txt b/xdgiconloader/CMakeLists.txt new file mode 100644 index 0000000..81a3fc0 --- /dev/null +++ b/xdgiconloader/CMakeLists.txt @@ -0,0 +1,82 @@ +include_directories( + "${Qt5Gui_PRIVATE_INCLUDE_DIRS}" +) + +set(xdgiconloader_PUBLIC_H_FILES +) + +set(xdgiconloader_PUBLIC_CLASSES +) + +set(xdgiconloader_PRIVATE_H_FILES +) + +set(xdgiconloader_CPP_FILES + xdgiconloader.cpp +) + +set(xdgiconloader_MOCS +) + +set(xdgiconloader_PRIVATE_INSTALLABLE_H_FILES + xdgiconloader_p.h +) + + +add_library(${QTXDGX_ICONLOADER_LIBRARY_NAME} SHARED + ${xdgiconloader_CPP_FILES} + ${xdgiconloader_PRIVATE_INSTALLABLE_H_FILES} +) + +generate_export_header(${QTXDGX_ICONLOADER_LIBRARY_NAME} BASE_NAME XdgIconLoader) + +# Copy public headers (in tree building) +set(XDGICONLOADER_EXPORT_FILE "xdgiconloader_export.h") +configure_file( + "${CMAKE_CURRENT_BINARY_DIR}/${XDGICONLOADER_EXPORT_FILE}" + "${QTXDGX_INTREE_INCLUDEDIR}/${QTXDGX_ICONLOADER_FILE_NAME}/${XDGICONLOADER_EXPORT_FILE}" + COPYONLY +) + +target_include_directories(${QTXDGX_ICONLOADER_LIBRARY_NAME} + INTERFACE "$" + INTERFACE "$" + INTERFACE "$" +) + +# include directories and targets for the in tree build +target_include_directories(${QTXDGX_ICONLOADER_LIBRARY_NAME} + PUBLIC "$" + PUBLIC "$" + PUBLIC "$" +) + +target_link_libraries(${QTXDGX_ICONLOADER_LIBRARY_NAME} + PUBLIC + Qt5::Gui +) + +set_target_properties(${QTXDGX_ICONLOADER_LIBRARY_NAME} + PROPERTIES + VERSION ${QTXDG_VERSION_STRING} + SOVERSION ${QTXDG_MAJOR_VERSION} +) + +export(TARGETS ${QTXDGX_ICONLOADER_LIBRARY_NAME} FILE "${CMAKE_BINARY_DIR}/${QTXDGX_ICONLOADER_FILE_NAME}-targets.cmake") + +install(TARGETS + ${QTXDGX_ICONLOADER_LIBRARY_NAME} DESTINATION "${CMAKE_INSTALL_LIBDIR}" + EXPORT "${QTXDGX_ICONLOADER_FILE_NAME}-targets" + COMPONENT Runtime +) + +install(FILES + ${xdgiconloader_PRIVATE_INSTALLABLE_H_FILES} + DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}/${QTXDGX_ICONLOADER_FILE_NAME}/${QTXDG_VERSION_STRING}/private/xdgiconloader" + COMPONENT Devel +) + +install(FILES + "${QTXDGX_INTREE_INCLUDEDIR}/${QTXDGX_ICONLOADER_FILE_NAME}/${XDGICONLOADER_EXPORT_FILE}" + DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}/${QTXDGX_ICONLOADER_FILE_NAME}" +) diff --git a/qiconfix/qiconloader.cpp b/xdgiconloader/xdgiconloader.cpp similarity index 84% rename from qiconfix/qiconloader.cpp rename to xdgiconloader/xdgiconloader.cpp index 8d8fe7e..adc4ed7 100644 --- a/qiconfix/qiconloader.cpp +++ b/xdgiconloader/xdgiconloader.cpp @@ -31,7 +31,7 @@ ** ****************************************************************************/ #ifndef QT_NO_ICON -#include "qiconloader_p.h" +#include "xdgiconloader_p.h" #include #include @@ -55,9 +55,8 @@ //QT_BEGIN_NAMESPACE -namespace QtXdg { -Q_GLOBAL_STATIC(QIconLoader, iconLoaderInstance) +Q_GLOBAL_STATIC(XdgIconLoader, iconLoaderInstance) /* Theme to use in last resort, if the theme does not have the icon, neither the parents */ static QString fallbackTheme() @@ -67,10 +66,10 @@ static QString fallbackTheme() if (themeHint.isValid()) return themeHint.toString(); } - return QString("hicolor"); + return QLatin1String("hicolor"); } -QIconLoader::QIconLoader() : +XdgIconLoader::XdgIconLoader() : m_themeKey(1), m_supportsSvg(false), m_initialized(false) { } @@ -102,7 +101,7 @@ static inline QStringList systemIconSearchPaths() //extern QFactoryLoader *qt_iconEngineFactoryLoader(); // qicon.cpp #endif -void QIconLoader::ensureInitialized() +void XdgIconLoader::ensureInitialized() { if (!m_initialized) { m_initialized = true; @@ -120,7 +119,7 @@ void QIconLoader::ensureInitialized() } } -QIconLoader *QIconLoader::instance() +XdgIconLoader *XdgIconLoader::instance() { iconLoaderInstance()->ensureInitialized(); return iconLoaderInstance(); @@ -128,7 +127,7 @@ QIconLoader *QIconLoader::instance() // Queries the system theme and invalidates existing // icons if the theme has changed. -void QIconLoader::updateSystemTheme() +void XdgIconLoader::updateSystemTheme() { // Only change if this is not explicitly set by the user if (m_userTheme.isEmpty()) { @@ -142,20 +141,20 @@ void QIconLoader::updateSystemTheme() } } -void QIconLoader::setThemeName(const QString &themeName) +void XdgIconLoader::setThemeName(const QString &themeName) { m_userTheme = themeName; invalidateKey(); } -void QIconLoader::setThemeSearchPath(const QStringList &searchPaths) +void XdgIconLoader::setThemeSearchPath(const QStringList &searchPaths) { m_iconDirs = searchPaths; themeList.clear(); invalidateKey(); } -QStringList QIconLoader::themeSearchPaths() const +QStringList XdgIconLoader::themeSearchPaths() const { if (m_iconDirs.isEmpty()) { m_iconDirs = systemIconSearchPaths(); @@ -182,7 +181,7 @@ QIconTheme::QIconTheme(const QString &themeName) QStringList themeSearchPaths = QIcon::themeSearchPaths(); foreach (QString path, themeSearchPaths) { - if (!path.startsWith(':') && QFileInfo(path).isDir()) + if (!path.startsWith(QLatin1Char(':')) && QFileInfo(path).isDir()) m_contentDirs.append(path + QLatin1Char('/') + themeName); } @@ -201,18 +200,18 @@ QIconTheme::QIconTheme(const QString &themeName) // slashes in key names, hence we have to cheat if (int size = indexReader.value(key).toInt()) { QString directoryKey = key.left(key.size() - 5); - QIconDirInfo dirInfo(directoryKey); + XdgIconDirInfo dirInfo(directoryKey); dirInfo.size = size; QString type = indexReader.value(directoryKey + QLatin1String("/Type") ).toString(); if (type == QLatin1String("Fixed")) - dirInfo.type = QIconDirInfo::Fixed; + dirInfo.type = XdgIconDirInfo::Fixed; else if (type == QLatin1String("Scalable")) - dirInfo.type = QIconDirInfo::Scalable; + dirInfo.type = XdgIconDirInfo::Scalable; else - dirInfo.type = QIconDirInfo::Threshold; + dirInfo.type = XdgIconDirInfo::Threshold; dirInfo.threshold = indexReader.value(directoryKey + QLatin1String("/Threshold"), @@ -249,7 +248,7 @@ QIconTheme::QIconTheme(const QString &themeName) #endif //QT_NO_SETTINGS } -QThemeIconInfo QIconLoader::findIconHelper(const QString &themeName, +QThemeIconInfo XdgIconLoader::findIconHelper(const QString &themeName, const QString &iconName, QStringList &visited) const { @@ -271,7 +270,7 @@ QThemeIconInfo QIconLoader::findIconHelper(const QString &themeName, } const QStringList contentDirs = theme.contentDirs(); - const QVector subDirs = theme.keyList(); + const QVector subDirs = theme.keyList(); const QString svgext(QLatin1String(".svg")); const QString pngext(QLatin1String(".png")); @@ -290,7 +289,7 @@ QThemeIconInfo QIconLoader::findIconHelper(const QString &themeName, for (int i = 0; i < contentDirs.size(); ++i) { QString contentDir = contentDirs.at(i) + QLatin1Char('/'); for (int j = 0; j < subDirs.size() ; ++j) { - const QIconDirInfo &dirInfo = subDirs.at(j); + const XdgIconDirInfo &dirInfo = subDirs.at(j); QString subdir = dirInfo.path; QDir currentDir(contentDir + subdir); if (currentDir.exists(pngIconName)) { @@ -390,7 +389,7 @@ QThemeIconInfo QIconLoader::findIconHelper(const QString &themeName, const QString pixmaps(QLatin1String("/usr/share/pixmaps")); const QDir currentDir(pixmaps); - const QIconDirInfo dirInfo(pixmaps); + const XdgIconDirInfo dirInfo(pixmaps); if (currentDir.exists(iconName + pngext)) { PixmapEntry *iconEntry = new PixmapEntry; iconEntry->dir = dirInfo; @@ -418,7 +417,7 @@ QThemeIconInfo QIconLoader::findIconHelper(const QString &themeName, return info; } -QThemeIconInfo QIconLoader::loadIcon(const QString &name) const +QThemeIconInfo XdgIconLoader::loadIcon(const QString &name) const { if (!themeName().isEmpty()) { QStringList visited; @@ -432,59 +431,59 @@ QThemeIconInfo QIconLoader::loadIcon(const QString &name) const // -------- Icon Loader Engine -------- // -QIconLoaderEngineFixed::QIconLoaderEngineFixed(const QString& iconName) +XdgIconLoaderEngine::XdgIconLoaderEngine(const QString& iconName) : m_iconName(iconName), m_key(0) { } -QIconLoaderEngineFixed::~QIconLoaderEngineFixed() +XdgIconLoaderEngine::~XdgIconLoaderEngine() { qDeleteAll(m_info.entries); } -QIconLoaderEngineFixed::QIconLoaderEngineFixed(const QIconLoaderEngineFixed &other) +XdgIconLoaderEngine::XdgIconLoaderEngine(const XdgIconLoaderEngine &other) : QIconEngine(other), m_iconName(other.m_iconName), m_key(0) { } -QIconEngine *QIconLoaderEngineFixed::clone() const +QIconEngine *XdgIconLoaderEngine::clone() const { - return new QIconLoaderEngineFixed(*this); + return new XdgIconLoaderEngine(*this); } -bool QIconLoaderEngineFixed::read(QDataStream &in) { +bool XdgIconLoaderEngine::read(QDataStream &in) { in >> m_iconName; return true; } -bool QIconLoaderEngineFixed::write(QDataStream &out) const +bool XdgIconLoaderEngine::write(QDataStream &out) const { out << m_iconName; return true; } -bool QIconLoaderEngineFixed::hasIcon() const +bool XdgIconLoaderEngine::hasIcon() const { return !(m_info.entries.isEmpty()); } // Lazily load the icon -void QIconLoaderEngineFixed::ensureLoaded() +void XdgIconLoaderEngine::ensureLoaded() { - if (!(QIconLoader::instance()->themeKey() == m_key)) { + if (!(XdgIconLoader::instance()->themeKey() == m_key)) { qDeleteAll(m_info.entries); m_info.entries.clear(); m_info.iconName.clear(); Q_ASSERT(m_info.entries.size() == 0); - m_info = QIconLoader::instance()->loadIcon(m_iconName); - m_key = QIconLoader::instance()->themeKey(); + m_info = XdgIconLoader::instance()->loadIcon(m_iconName); + m_key = XdgIconLoader::instance()->themeKey(); } } -void QIconLoaderEngineFixed::paint(QPainter *painter, const QRect &rect, +void XdgIconLoaderEngine::paint(QPainter *painter, const QRect &rect, QIcon::Mode mode, QIcon::State state) { QSize pixmapSize = rect.size(); @@ -498,16 +497,16 @@ void QIconLoaderEngineFixed::paint(QPainter *painter, const QRect &rect, * This algorithm is defined by the freedesktop spec: * http://standards.freedesktop.org/icon-theme-spec/icon-theme-spec-latest.html */ -static bool directoryMatchesSize(const QIconDirInfo &dir, int iconsize) +static bool directoryMatchesSize(const XdgIconDirInfo &dir, int iconsize) { - if (dir.type == QIconDirInfo::Fixed) { + if (dir.type == XdgIconDirInfo::Fixed) { return dir.size == iconsize; - } else if (dir.type == QIconDirInfo::Scalable) { - return dir.size <= dir.maxSize && + } else if (dir.type == XdgIconDirInfo::Scalable) { + return iconsize <= dir.maxSize && iconsize >= dir.minSize; - } else if (dir.type == QIconDirInfo::Threshold) { + } else if (dir.type == XdgIconDirInfo::Threshold) { return iconsize >= dir.size - dir.threshold && iconsize <= dir.size + dir.threshold; } @@ -520,12 +519,12 @@ static bool directoryMatchesSize(const QIconDirInfo &dir, int iconsize) * This algorithm is defined by the freedesktop spec: * http://standards.freedesktop.org/icon-theme-spec/icon-theme-spec-latest.html */ -static int directorySizeDistance(const QIconDirInfo &dir, int iconsize) +static int directorySizeDistance(const XdgIconDirInfo &dir, int iconsize) { - if (dir.type == QIconDirInfo::Fixed) { + if (dir.type == XdgIconDirInfo::Fixed) { return qAbs(dir.size - iconsize); - } else if (dir.type == QIconDirInfo::Scalable) { + } else if (dir.type == XdgIconDirInfo::Scalable) { if (iconsize < dir.minSize) return dir.minSize - iconsize; else if (iconsize > dir.maxSize) @@ -533,7 +532,7 @@ static int directorySizeDistance(const QIconDirInfo &dir, int iconsize) else return 0; - } else if (dir.type == QIconDirInfo::Threshold) { + } else if (dir.type == XdgIconDirInfo::Threshold) { if (iconsize < dir.size - dir.threshold) return dir.minSize - iconsize; else if (iconsize > dir.size + dir.threshold) @@ -545,7 +544,7 @@ static int directorySizeDistance(const QIconDirInfo &dir, int iconsize) return INT_MAX; } -QIconLoaderEngineEntry *QIconLoaderEngineFixed::entryForSize(const QSize &size) +XdgIconLoaderEngineEntry *XdgIconLoaderEngine::entryForSize(const QSize &size) { int iconsize = qMin(size.width(), size.height()); @@ -556,7 +555,7 @@ QIconLoaderEngineEntry *QIconLoaderEngineFixed::entryForSize(const QSize &size) // Search for exact matches first for (int i = 0; i < numEntries; ++i) { - QIconLoaderEngineEntry *entry = m_info.entries.at(i); + XdgIconLoaderEngineEntry *entry = m_info.entries.at(i); if (directoryMatchesSize(entry->dir, iconsize)) { return entry; } @@ -564,9 +563,9 @@ QIconLoaderEngineEntry *QIconLoaderEngineFixed::entryForSize(const QSize &size) // Find the minimum distance icon int minimalSize = INT_MAX; - QIconLoaderEngineEntry *closestMatch = 0; + XdgIconLoaderEngineEntry *closestMatch = 0; for (int i = 0; i < numEntries; ++i) { - QIconLoaderEngineEntry *entry = m_info.entries.at(i); + XdgIconLoaderEngineEntry *entry = m_info.entries.at(i); int distance = directorySizeDistance(entry->dir, iconsize); if (distance < minimalSize) { minimalSize = distance; @@ -582,18 +581,27 @@ QIconLoaderEngineEntry *QIconLoaderEngineFixed::entryForSize(const QSize &size) * we can never return a bigger size than the requested size. * */ -QSize QIconLoaderEngineFixed::actualSize(const QSize &size, QIcon::Mode mode, +QSize XdgIconLoaderEngine::actualSize(const QSize &size, QIcon::Mode mode, QIcon::State state) { ensureLoaded(); - QIconLoaderEngineEntry *entry = entryForSize(size); + XdgIconLoaderEngineEntry *entry = entryForSize(size); if (entry) { - const QIconDirInfo &dir = entry->dir; - if (dir.type == QIconDirInfo::Scalable) + const XdgIconDirInfo &dir = entry->dir; + if (dir.type == XdgIconDirInfo::Scalable || dynamic_cast(entry)) return size; else { - int result = qMin(dir.size, qMin(size.width(), size.height())); + int dir_size = dir.size; + //Note: fallback for directories that don't have its content size defined + // -> get the actual size based on the image if possible + PixmapEntry * pix_e; + if (0 == dir_size && nullptr != (pix_e = dynamic_cast(entry))) + { + QSize pix_size = pix_e->basePixmap.size(); + dir_size = qMin(pix_size.width(), pix_size.height()); + } + int result = qMin(dir_size, qMin(size.width(), size.height())); return QSize(result, result); } } @@ -644,24 +652,24 @@ QPixmap ScalableEntry::pixmap(const QSize &size, QIcon::Mode mode, QIcon::State return svgIcon.pixmap(size, mode, state); } -QPixmap QIconLoaderEngineFixed::pixmap(const QSize &size, QIcon::Mode mode, +QPixmap XdgIconLoaderEngine::pixmap(const QSize &size, QIcon::Mode mode, QIcon::State state) { ensureLoaded(); - QIconLoaderEngineEntry *entry = entryForSize(size); + XdgIconLoaderEngineEntry *entry = entryForSize(size); if (entry) return entry->pixmap(size, mode, state); return QPixmap(); } -QString QIconLoaderEngineFixed::key() const +QString XdgIconLoaderEngine::key() const { - return QLatin1String("QIconLoaderEngineFixed"); + return QLatin1String("XdgIconLoaderEngine"); } -void QIconLoaderEngineFixed::virtual_hook(int id, void *data) +void XdgIconLoaderEngine::virtual_hook(int id, void *data) { ensureLoaded(); @@ -693,7 +701,6 @@ void QIconLoaderEngineFixed::virtual_hook(int id, void *data) } } -} // QtXdg //QT_END_NAMESPACE diff --git a/qiconfix/qiconloader_p.h b/xdgiconloader/xdgiconloader_p.h similarity index 83% rename from qiconfix/qiconloader_p.h rename to xdgiconloader/xdgiconloader_p.h index f3abbb9..0511ab3 100644 --- a/qiconfix/qiconloader_p.h +++ b/xdgiconloader/xdgiconloader_p.h @@ -48,6 +48,8 @@ // We mean it. // +#include + #include #include #include @@ -59,14 +61,12 @@ //QT_BEGIN_NAMESPACE -namespace QtXdg { - -class QIconLoader; +class XdgIconLoader; -struct QIconDirInfo +struct XdgIconDirInfo { enum Type { Fixed, Scalable, Threshold }; - QIconDirInfo(const QString &_path = QString()) : + XdgIconDirInfo(const QString &_path = QString()) : path(_path), size(0), maxSize(0), @@ -81,31 +81,31 @@ struct QIconDirInfo Type type : 4; }; -class QIconLoaderEngineEntry +class XdgIconLoaderEngineEntry { public: - virtual ~QIconLoaderEngineEntry() {} + virtual ~XdgIconLoaderEngineEntry() {} virtual QPixmap pixmap(const QSize &size, QIcon::Mode mode, QIcon::State state) = 0; QString filename; - QIconDirInfo dir; + XdgIconDirInfo dir; static int count; }; -struct ScalableEntry : public QIconLoaderEngineEntry +struct ScalableEntry : public XdgIconLoaderEngineEntry { QPixmap pixmap(const QSize &size, QIcon::Mode mode, QIcon::State state) Q_DECL_OVERRIDE; QIcon svgIcon; }; -struct PixmapEntry : public QIconLoaderEngineEntry +struct PixmapEntry : public XdgIconLoaderEngineEntry { QPixmap pixmap(const QSize &size, QIcon::Mode mode, QIcon::State state) Q_DECL_OVERRIDE; QPixmap basePixmap; }; -typedef QList QThemeIconEntries; +typedef QList QThemeIconEntries; struct QThemeIconInfo { @@ -114,11 +114,11 @@ struct QThemeIconInfo }; //class QIconLoaderEngine : public QIconEngine -class QIconLoaderEngineFixed : public QIconEngine +class XDGICONLOADER_EXPORT XdgIconLoaderEngine : public QIconEngine { public: - QIconLoaderEngineFixed(const QString& iconName = QString()); - ~QIconLoaderEngineFixed(); + XdgIconLoaderEngine(const QString& iconName = QString()); + ~XdgIconLoaderEngine(); void paint(QPainter *painter, const QRect &rect, QIcon::Mode mode, QIcon::State state); QPixmap pixmap(const QSize &size, QIcon::Mode mode, QIcon::State state); @@ -132,13 +132,13 @@ private: bool hasIcon() const; void ensureLoaded(); void virtual_hook(int id, void *data); - QIconLoaderEngineEntry *entryForSize(const QSize &size); - QIconLoaderEngineFixed(const QIconLoaderEngineFixed &other); + XdgIconLoaderEngineEntry *entryForSize(const QSize &size); + XdgIconLoaderEngine(const XdgIconLoaderEngine &other); QThemeIconInfo m_info; QString m_iconName; uint m_key; - friend class QIconLoader; + friend class XdgIconLoader; }; class QIconTheme @@ -147,21 +147,21 @@ public: QIconTheme(const QString &name); QIconTheme() : m_valid(false) {} QStringList parents() { return m_parents; } - QVector keyList() { return m_keyList; } + QVector keyList() { return m_keyList; } QStringList contentDirs() { return m_contentDirs; } bool isValid() { return m_valid; } private: QStringList m_contentDirs; - QVector m_keyList; + QVector m_keyList; QStringList m_parents; bool m_valid; }; -class Q_GUI_EXPORT QIconLoader +class XDGICONLOADER_EXPORT XdgIconLoader { public: - QIconLoader(); + XdgIconLoader(); QThemeIconInfo loadIcon(const QString &iconName) const; uint themeKey() const { return m_themeKey; } @@ -170,8 +170,8 @@ public: QIconTheme theme() { return themeList.value(themeName()); } void setThemeSearchPath(const QStringList &searchPaths); QStringList themeSearchPaths() const; - QIconDirInfo dirInfo(int dirindex); - static QIconLoader *instance(); + XdgIconDirInfo dirInfo(int dirindex); + static XdgIconLoader *instance(); void updateSystemTheme(); void invalidateKey() { m_themeKey++; } void ensureInitialized(); @@ -190,11 +190,10 @@ private: mutable QHash themeList; }; -} // QtXdg // Note: class template specialization of 'QTypeInfo' must occur at // global scope -Q_DECLARE_TYPEINFO(QtXdg::QIconDirInfo, Q_MOVABLE_TYPE); +Q_DECLARE_TYPEINFO(XdgIconDirInfo, Q_MOVABLE_TYPE); //QT_END_NAMESPACE