diff --git a/CMakeLists.txt b/CMakeLists.txt index 810ea37..92b0510 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,77 +1,84 @@ cmake_minimum_required(VERSION 2.8.12) project(Purpose) find_package(ECM 1.7.0 REQUIRED NO_MODULE) set(CMAKE_MODULE_PATH ${ECM_MODULE_PATH} ${ECM_KDE_MODULE_DIR}) set(REQUIRED_QT_VERSION "5.2") find_package(Qt5 ${REQUIRED_QT_VERSION} CONFIG REQUIRED Core Qml Gui Widgets Network Test) include(KDEInstallDirs) include(KDEFrameworkCompilerSettings NO_POLICY_SCOPE) include(KDECMakeSettings) include(FeatureSummary) include(GenerateExportHeader) include(ECMSetupVersion) include(ECMAddTests) include(ECMInstallIcons) include(ECMGenerateHeaders) include(ECMMarkNonGuiExecutable) include(ECMQtDeclareLoggingCategory) set(KF5_VERSION "5.8.0") # handled by release scripts set(KF5_DEP_VERSION "5.7.0") # handled by release scripts find_package(KF5 ${KF5_DEP_VERSION} REQUIRED COMPONENTS CoreAddons I18n Config) # Debian is a special snow flake and uses nodejs as binary name # https://lists.debian.org/debian-devel-announce/2012/07/msg00002.html if(EXISTS "/etc/debian_version") # is debian system? set(NODEJS_BINARY "nodejs" CACHE PATH "The binary name for the nodejs interpreter") else() # sane system set(NODEJS_BINARY "node" CACHE PATH "The binary name for the nodejs interpreter") endif() ecm_setup_version(${KF5_VERSION} VARIABLE_PREFIX PURPOSE VERSION_HEADER "${CMAKE_CURRENT_BINARY_DIR}/purpose_version.h" - PACKAGE_VERSION_FILE "${CMAKE_CURRENT_BINARY_DIR}/KDEExperimentalPurposeConfigVersion.cmake" + PACKAGE_VERSION_FILE "${CMAKE_CURRENT_BINARY_DIR}/KF5PurposeConfigVersion.cmake" SOVERSION 5) add_subdirectory( autotests ) add_subdirectory( src ) add_subdirectory( tests ) add_definitions(-DTRANSLATION_DOMAIN=\"purpose5\") if (IS_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/po") ki18n_install(po) endif() # create a Config.cmake and a ConfigVersion.cmake file and install them -set(CMAKECONFIG_INSTALL_DIR "${KDE_INSTALL_CMAKEPACKAGEDIR}/KDEExperimentalPurpose") +set(CMAKECONFIG_INSTALL_DIR "${KDE_INSTALL_CMAKEPACKAGEDIR}/KF5Purpose") include(ECMPackageConfigHelpers) ecm_configure_package_config_file( - "${CMAKE_CURRENT_SOURCE_DIR}/KDEExperimentalPurposeConfig.cmake.in" - "${CMAKE_CURRENT_BINARY_DIR}/KDEExperimentalPurposeConfig.cmake" + "${CMAKE_CURRENT_SOURCE_DIR}/KF5PurposeConfig.cmake.in" + "${CMAKE_CURRENT_BINARY_DIR}/KF5PurposeConfig.cmake" INSTALL_DESTINATION ${CMAKECONFIG_INSTALL_DIR} ) install(FILES - "${CMAKE_CURRENT_BINARY_DIR}/KDEExperimentalPurposeConfig.cmake" - "${CMAKE_CURRENT_BINARY_DIR}/KDEExperimentalPurposeConfigVersion.cmake" + "${CMAKE_CURRENT_BINARY_DIR}/KF5PurposeConfig.cmake" + "${CMAKE_CURRENT_BINARY_DIR}/KF5PurposeConfigVersion.cmake" DESTINATION "${CMAKECONFIG_INSTALL_DIR}" COMPONENT Devel ) -install(EXPORT KDEExperimentalPurposeTargets DESTINATION "${CMAKECONFIG_INSTALL_DIR}" FILE KDEExperimentalPurposeTargets.cmake NAMESPACE KDEExperimental:: ) +install(EXPORT KF5PurposeTargets DESTINATION "${CMAKECONFIG_INSTALL_DIR}" FILE KF5PurposeTargets.cmake NAMESPACE KF5:: ) install(FILES ${CMAKE_CURRENT_BINARY_DIR}/purpose_version.h DESTINATION ${KDE_INSTALL_INCLUDEDIR_KF5}/purpose COMPONENT Devel ) feature_summary(WHAT ALL FATAL_ON_MISSING_REQUIRED_PACKAGES) + +#TODO: Remove somewhen in the future +install(FILES + "${CMAKE_CURRENT_SOURCE_DIR}/KDEExperimentalPurposeConfig.cmake" + DESTINATION "${KDE_INSTALL_CMAKEPACKAGEDIR}/KDEExperimentalPurpose" + COMPONENT Devel +) diff --git a/KDEExperimentalPurposeConfig.cmake.in b/KDEExperimentalPurposeConfig.cmake.in deleted file mode 100644 index cd9d245..0000000 --- a/KDEExperimentalPurposeConfig.cmake.in +++ /dev/null @@ -1,5 +0,0 @@ -@PACKAGE_INIT@ - -find_dependency(KF5CoreAddons "@KF5_DEP_VERSION@") - -include("${CMAKE_CURRENT_LIST_DIR}/KDEExperimentalPurposeTargets.cmake") diff --git a/README.md b/README.md index ece1e98..6e96582 100644 --- a/README.md +++ b/README.md @@ -1,141 +1,141 @@ # Purpose Offers available actions for a specific purpose ## Introduction This framework offers the possibility to create integrate services and actions on any application without having to implement them specifically. Purpose will offer them mechanisms to list the different alternatives to execute given the requested action type and will facilitate components so that all the plugins can receive all the information they need. ## Usage There's 2 main ways of using Purpose: from C++ and QML/QtQuick. To import it from QML, import import org.kde.purpose 1.0 It offers different ways of integrating the actions in an application. For full control on the procedure, we can use: * *AlternativesModel* for listing the different possibilities * *PurposeWizard* for configuring the job * *RunningJob* for a view that displays the job as it runs Furthermore, there's the *AlternativesView* component that will integrate all the process defined below for convenience. If you want to import in the C++ application, you can import it using CMake by calling: - find_package(KDEExperimentalPurpose) + find_package(KF5Purpose) Or its QMake counterpart. Then you'll have available the Purpose library if it needs to be done specifically and PurposeWidgets for convenience. To integrate on the UI, QtQuick will still be used, as the configuration files provided by the plugins are written in QML. The recommended way to integrate on a QtWidgets interface is by using the *Purpose::Menu* class that will allow us to place the integration wherever pleases us. This class will offer us a pointer to the used *Purpose::AlternativesModel* so that we can specify what kind of services we're interested in. ## Plugins ### The plugin configuration There will be 2 files specifying the behavior of a plugin: * The `*PluginType.json` files. * The plugin metadata JSON file. The plugin type will be identified by the file name. It will specify: * `X-Purpose-InboundArguments` defines the arguments the application must provide. * `X-Purpose-OutboundArguments` defines the arguments the plugin must provide by the end of the execution. In the plugin metadata we will define: * `X-Purpose-PluginTypes` defines the purposes tackled by the plugin * `X-Purpose-Constraints` defines some conditions under the plugin is useful, considering the provided inboundArguments. For example, the youtube export plugin will specify `mimeType:video/*` as a constraint, because it's not interested in uploading images. * `X-Purpose-Configuration` provides a list of extra arguments that the plugin will need. Ideally everything should be in the plugin type but sometimes we can only wish. This allows the opportunity to the application to let the user add the missing data. ### Plugin types The application says what it wants to do, Purpose finds the correct plugins. This is how we balance decoupling of implementation but keep on top of what the framework is supposed to do. An example of such files is the `ExportPluginType.json`: ```json { "KPlugin": { "Icon": "edit-paste", "Name": "Upload..." }, "X-Purpose-InboundArguments": [ "urls", "mimeType" ], "X-Purpose-OutboundArguments": [ "url" ] } ``` As previously discussed, here we can define the generic tasks that the different plugins will implement on top, having the inbound arguments as a given and the outbound as a requirement. Examples of such plugin types are (hypothetically, not all implemented yet): * Share: where you can get the different services to share * GetImage that would list your scanner, camera and also some web services. * AddContact that would let you add a contact on your address book or in whichever plugin is offered. ### Plugin creation There's two approaches to plugin implementation: native plugins and separate processes. #### Native To implement a Qt-based plugin, it will be required to implement a `Purpose::PluginBase` class, that acts as a factory for its `Purpose::Job` instances. These will be the jobs in charge of performing the action the plugin is meant to do. Furthermore, a `pluginname_config.qml` will be provided for extra Configuration, if required. These plugins can be optionally be executed in-process. #### Separate Process Sometimes executing some actions through Qt code can require some extra work. For those cases, it's possible to implement the plugin in a separate process. It will require some extra work when it comes to implementing the feedback process with the main process but it allows to run plugins in any imaginable technologies. The file structure for these plugins is the one of defined by [KPackage](http://api.kde.org/frameworks-api/frameworks5-apidocs/kpackage/html/index.html) which allows to package and distributethe plugins in an archive. To that end, we will need to provide: * A `manifest.json` file, that will define the plugin description, capabilities and requirements. * A `code/main*` file that will be executed when the plugin action needs happen. * A `config/config.qml` file that will be in charge of requesting the necessary information to the user. ### Disallowing plugins It is possible to globally disable certain plugins through configuration file called `purposerc` in /etc/xdg (applies to all users) or in ~/.config (applies to current user). The disabled plugins are specified as a comma-separated list in the `disabled` key in the `plugins` group. ``` [plugins] # Disable KDE Connect and Imgur sharing plugins disabled=kdeconnectplugin,imgurplugin ``` diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 39a745e..a6928aa 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1,60 +1,60 @@ configure_file(${CMAKE_CURRENT_SOURCE_DIR}/cmake-paths.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/cmake-paths.h) add_library(KF5Purpose pluginbase.cpp job.cpp alternativesmodel.cpp configuration.cpp helper.cpp externalprocess/processjob.cpp ) target_include_directories(KF5Purpose PUBLIC "$" "$" INTERFACE "$" ) target_link_libraries(KF5Purpose PUBLIC KF5::CoreAddons Qt5::Gui PRIVATE Qt5::Network #QLocalSocket KF5::ConfigCore ) set_target_properties(KF5Purpose PROPERTIES VERSION ${PURPOSE_VERSION_STRING} SOVERSION ${PURPOSE_SOVERSION} EXPORT_NAME Purpose ) -install(TARGETS KF5Purpose EXPORT KDEExperimentalPurposeTargets ${KF5_INSTALL_TARGETS_DEFAULT_ARGS}) +install(TARGETS KF5Purpose EXPORT KF5PurposeTargets ${KF5_INSTALL_TARGETS_DEFAULT_ARGS}) add_library(KF5::Purpose ALIAS KF5Purpose) generate_export_header(KF5Purpose EXPORT_FILE_NAME ${Purpose_BINARY_DIR}/purpose/purpose_export.h BASE_NAME Purpose) ecm_generate_headers(Purpose_CamelCase_HEADERS HEADER_NAMES PluginBase AlternativesModel Job Configuration REQUIRED_HEADERS Purpose_HEADERS PREFIX Purpose ) install(FILES ${Purpose_CamelCase_HEADERS} DESTINATION ${KDE_INSTALL_INCLUDEDIR_KF5}/purpose/Purpose/ COMPONENT Devel) install(FILES ${Purpose_BINARY_DIR}/purpose/purpose_export.h ${Purpose_HEADERS} DESTINATION ${KDE_INSTALL_INCLUDEDIR_KF5}/purpose/purpose COMPONENT Devel ) add_executable(purposeprocess externalprocess/purposeprocess_main.cpp helper.cpp) ecm_mark_nongui_executable(purposeprocess) target_link_libraries(purposeprocess KF5::Purpose Qt5::Network Qt5::Widgets) install(TARGETS purposeprocess DESTINATION ${KDE_INSTALL_LIBEXECDIR_KF5}) add_subdirectory(plugins) add_subdirectory(quick) add_subdirectory(widgets) diff --git a/src/widgets/CMakeLists.txt b/src/widgets/CMakeLists.txt index 4151f98..36d63e8 100644 --- a/src/widgets/CMakeLists.txt +++ b/src/widgets/CMakeLists.txt @@ -1,38 +1,38 @@ qt5_add_resources(qmlfiles_SRCS purposewidgets-resources.qrc) add_library(KF5PurposeWidgets menu.cpp ${qmlfiles_SRCS}) generate_export_header(KF5PurposeWidgets EXPORT_FILE_NAME purposewidgets_export.h BASE_NAME PurposeWidgets) target_link_libraries(KF5PurposeWidgets PUBLIC KF5::Purpose Qt5::Widgets PRIVATE Qt5::Qml KF5::I18n ) set_target_properties(KF5PurposeWidgets PROPERTIES VERSION ${PURPOSE_VERSION_STRING} SOVERSION ${PURPOSE_SOVERSION} EXPORT_NAME PurposeWidgets ) target_include_directories(KF5PurposeWidgets PUBLIC "$" "$" INTERFACE "$" ) -install(TARGETS KF5PurposeWidgets EXPORT KDEExperimentalPurposeTargets ${KF5_INSTALL_TARGETS_DEFAULT_ARGS}) +install(TARGETS KF5PurposeWidgets EXPORT KF5PurposeTargets ${KF5_INSTALL_TARGETS_DEFAULT_ARGS}) add_library(KF5::PurposeWidgets ALIAS KF5PurposeWidgets) ecm_generate_headers(PurposeWidgets_CamelCase_HEADERS HEADER_NAMES Menu REQUIRED_HEADERS PurposeWidgets_HEADERS PREFIX PurposeWidgets ) install(FILES ${PurposeWidgets_CamelCase_HEADERS} DESTINATION ${KDE_INSTALL_INCLUDEDIR_KF5}/purposewidgets/PurposeWidgets/ COMPONENT Devel) install(FILES ${Purpose_BINARY_DIR}/src/widgets/purposewidgets_export.h ${PurposeWidgets_HEADERS} DESTINATION ${KDE_INSTALL_INCLUDEDIR_KF5}/purposewidgets/purposewidgets COMPONENT Devel )