feat: add test for desktopentry and jobmanager
Log:
This commit is contained in:
@ -1,31 +1,26 @@
|
||||
include(GNUInstallDirs)
|
||||
|
||||
set(BIN_NAME dde-application-manager)
|
||||
set(LIB_NAME ddeam)
|
||||
|
||||
set(DBUS_INTERFACE_DIR ${CMAKE_CURRENT_LIST_DIR}/dbus)
|
||||
file(GLOB_RECURSE SRCS ${CMAKE_CURRENT_LIST_DIR}/*.cpp)
|
||||
|
||||
set(DBUSADAPTORS "")
|
||||
file(GLOB_RECURSE SRCS ${CMAKE_CURRENT_LIST_DIR}/*.cpp ${CMAKE_CURRENT_LIST_DIR}/*.h)
|
||||
list(REMOVE_ITEM SRCS "${PROJECT_SOURCE_DIR}/src/utils.cpp")
|
||||
|
||||
qt_add_dbus_adaptor(DBUSADAPTORS ${PROJECT_SOURCE_DIR}/api/dbus/org.desktopspec.ApplicationManager1.xml applicationmanager1service.h ApplicationManager1Service)
|
||||
qt_add_dbus_adaptor(DBUSADAPTORS ${PROJECT_SOURCE_DIR}/api/dbus/org.desktopspec.ApplicationManager1.Application.xml applicationservice.h ApplicationService)
|
||||
qt_add_dbus_adaptor(DBUSADAPTORS ${PROJECT_SOURCE_DIR}/api/dbus/org.desktopspec.ApplicationManager1.Instance.xml instanceservice.h InstanceService)
|
||||
qt_add_dbus_adaptor(DBUSADAPTORS ${PROJECT_SOURCE_DIR}/api/dbus/org.desktopspec.JobManager1.xml jobmanager1service.h JobManager1Service)
|
||||
qt_add_dbus_adaptor(DBUSADAPTORS ${PROJECT_SOURCE_DIR}/api/dbus/org.desktopspec.JobManager1.Job.xml jobservice.h JobService)
|
||||
add_library(${LIB_NAME} ${SRCS})
|
||||
|
||||
add_executable(${BIN_NAME} ${DBUSADAPTORS} ${SRCS})
|
||||
|
||||
target_include_directories(${BIN_NAME} PRIVATE
|
||||
${CMAKE_CURRENT_LIST_DIR}/include
|
||||
${CMAKE_CURRENT_LIST_DIR}/dbus
|
||||
${CMAKE_CURRENT_BINARY_DIR}/src
|
||||
target_include_directories(${LIB_NAME} PRIVATE
|
||||
${PROJECT_BINARY_DIR}
|
||||
)
|
||||
|
||||
target_link_libraries(${BIN_NAME} PRIVATE
|
||||
Qt${QT_VERSION_MAJOR}::Core
|
||||
Qt${QT_VERSION_MAJOR}::DBus
|
||||
Qt${QT_VERSION_MAJOR}::Concurrent
|
||||
target_link_libraries(${LIB_NAME} PUBLIC
|
||||
Threads::Threads
|
||||
${AdaptorLib}
|
||||
)
|
||||
|
||||
add_executable(${BIN_NAME} main.cpp utils.cpp)
|
||||
target_link_libraries(${BIN_NAME} PRIVATE
|
||||
${LIB_NAME}
|
||||
)
|
||||
|
||||
install(TARGETS ${BIN_NAME} DESTINATION ${CMAKE_INSTALL_BINDIR})
|
||||
|
@ -2,7 +2,6 @@
|
||||
//
|
||||
// SPDX-License-Identifier: LGPL-3.0-or-later
|
||||
#include "applicationmanager1service.h"
|
||||
#include "applicationmanager1adaptor.h"
|
||||
#include "applicationadaptor.h"
|
||||
#include "global.h"
|
||||
|
||||
@ -46,7 +45,7 @@ QDBusObjectPath ApplicationManager1Service::Launch(const QString &id,
|
||||
objectPath.prepend(DDEApplicationManager1ApplicationObjectPath);
|
||||
QSharedPointer<ApplicationService> app{new ApplicationService{id}};
|
||||
auto *ptr = app.data();
|
||||
if (registerObjectToDbus<decltype(ptr), ApplicationAdaptor>(ptr, objectPath, getDBusInterface<ApplicationAdaptor>())) {
|
||||
if (registerObjectToDbus(new ApplicationAdaptor(ptr), objectPath, getDBusInterface<ApplicationAdaptor>())) {
|
||||
QDBusObjectPath path{objectPath};
|
||||
m_applicationList.insert(path, app);
|
||||
return path;
|
||||
|
@ -3,6 +3,7 @@
|
||||
// SPDX-License-Identifier: LGPL-3.0-or-later
|
||||
|
||||
#include "applicationservice.h"
|
||||
#include "applicationadaptor.h"
|
||||
#include "instanceadaptor.h"
|
||||
#include <QUuid>
|
||||
|
||||
@ -27,7 +28,7 @@ QDBusObjectPath ApplicationService::Launch(const QString &action, const QStringL
|
||||
QString objectPath{m_applicationPath.path() + "/" + QUuid::createUuid().toString()};
|
||||
QSharedPointer<InstanceService> ins{new InstanceService{objectPath, ""}};
|
||||
auto *ptr = ins.data();
|
||||
if (registerObjectToDbus<decltype(ptr), InstanceAdaptor>(ptr, objectPath, getDBusInterface<InstanceAdaptor>())) {
|
||||
if (registerObjectToDbus(new InstanceAdaptor(ptr), objectPath, getDBusInterface<InstanceAdaptor>())) {
|
||||
m_Instances.insert(QDBusObjectPath{objectPath}, ins);
|
||||
return QDBusObjectPath{objectPath};
|
||||
}
|
||||
|
@ -33,9 +33,9 @@ public:
|
||||
{
|
||||
static_assert(std::is_invocable_v<F, QVariant>, "param type must be QVariant.");
|
||||
|
||||
QString objectPath{DDEApplicationManager1JobObjectPath + QUuid::createUuid().toString()};
|
||||
QFuture<QVariantList> future = QtConcurrent::mappedReduced(
|
||||
args.begin(), args.end(), func, &QVariantList::insert, QVariantList{}, QtConcurrent::ReduceOption::OrderedReduce);
|
||||
QString objectPath{DDEApplicationManager1JobObjectPath + QUuid::createUuid().toString(QUuid::Id128)};
|
||||
auto future = QtConcurrent::mappedReduced(
|
||||
args.begin(), args.end(), func,qOverload<QVariantList::parameter_type>(&QVariantList::append), QVariantList{}, QtConcurrent::ReduceOption::OrderedReduce);
|
||||
QSharedPointer<JobService> job{new JobService{future}};
|
||||
auto path = QDBusObjectPath{objectPath};
|
||||
{
|
||||
@ -43,8 +43,8 @@ public:
|
||||
m_jobs.insert(path, job); // Insertion is always successful
|
||||
}
|
||||
emit JobNew(path, source);
|
||||
registerObjectToDbus<decltype(job.data()), JobAdaptor>(job.data(), objectPath, getDBusInterface<JobAdaptor>());
|
||||
auto emitRemove = [this, job, path, future] {
|
||||
registerObjectToDbus(new JobAdaptor(job.data()), objectPath, getDBusInterface<JobAdaptor>());
|
||||
auto emitRemove = [this, job, path, future] (QVariantList value) {
|
||||
decltype(m_jobs)::size_type removeCount{0};
|
||||
{
|
||||
QMutexLocker locker{&m_mutex};
|
||||
@ -52,20 +52,21 @@ public:
|
||||
}
|
||||
// removeCount means m_jobs can't find value which corresponding with path
|
||||
// and we shouldn't emit jobRemoved signal because this signal may already has been emit
|
||||
if (removeCount == 0) {
|
||||
if (removeCount == 0) {
|
||||
qCritical() << "Job already has been removed: " << path.path();
|
||||
return;
|
||||
return value;
|
||||
}
|
||||
QString result{job->status()};
|
||||
for (const auto &val : future.result()) {
|
||||
if (val.canConvert<QDBusError>()) {
|
||||
if (val.template canConvert<QDBusError>()) {
|
||||
result = "failed";
|
||||
}
|
||||
break;
|
||||
}
|
||||
emit this->JobRemoved(path, result, future.result());
|
||||
return value;
|
||||
};
|
||||
future.then(QtFuture::Launch::Sync, emitRemove);
|
||||
future.then(emitRemove);
|
||||
}
|
||||
|
||||
Q_SIGNALS:
|
||||
|
18
src/demo.cpp
18
src/demo.cpp
@ -1,18 +0,0 @@
|
||||
// SPDX-FileCopyrightText: 2023 UnionTech Software Technology Co., Ltd.
|
||||
//
|
||||
// SPDX-License-Identifier: LGPL-3.0-or-later
|
||||
|
||||
#include "demo.h"
|
||||
#include <iostream>
|
||||
#include <QString>
|
||||
|
||||
void greet()
|
||||
{
|
||||
std::cout << QString{"Hello"}.toStdString() <<std::endl;
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
greet();
|
||||
return 0;
|
||||
}
|
@ -110,18 +110,16 @@ std::optional<DesktopFile> DesktopFile::searchDesktopFile(const QString &desktop
|
||||
auto components = path.split(QDir::separator()).toList();
|
||||
auto it = std::find(components.cbegin(), components.cend(), "applications");
|
||||
if (it == components.cend()) {
|
||||
qWarning() << "fatal error: file location invalid";
|
||||
err = ParseError::InvalidLocation;
|
||||
return std::nullopt;
|
||||
qWarning() << "custom location detected, Id wouldn't be generated.";
|
||||
} else {
|
||||
QString FileId;
|
||||
++it;
|
||||
while (it != components.cend())
|
||||
FileId += (*(it++) + "-");
|
||||
id = FileId.chopped(1);
|
||||
}
|
||||
QString FileId;
|
||||
++it;
|
||||
while (it != components.cend())
|
||||
FileId += (*(it++) + "-");
|
||||
id = FileId.chopped(1);
|
||||
|
||||
err = ParseError::NoError;
|
||||
return DesktopFile{path,id};
|
||||
return DesktopFile{std::move(path),std::move(id)};
|
||||
}
|
||||
|
||||
ParseError DesktopEntry::parse(QTextStream& stream) noexcept
|
||||
@ -239,13 +237,16 @@ QString DesktopEntry::Value::toIconString(bool &ok) const noexcept
|
||||
|
||||
bool DesktopEntry::Value::toBoolean(bool &ok) const noexcept
|
||||
{
|
||||
ok = true;
|
||||
const auto& str = (*this)[defaultKeyStr];
|
||||
if (str.compare("true"))
|
||||
return true;
|
||||
if (str.compare("false"))
|
||||
return false;
|
||||
ok = false;
|
||||
const auto& str = (*this)[defaultKeyStr];
|
||||
if (str == "true") {
|
||||
ok = true;
|
||||
return true;
|
||||
}
|
||||
if (str == "false") {
|
||||
ok = true;
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -262,3 +263,41 @@ QDebug operator<<(QDebug debug, const DesktopEntry::Value &v)
|
||||
debug << static_cast<const QMap<QString,QString>&>(v);
|
||||
return debug;
|
||||
}
|
||||
|
||||
QDebug operator<<(QDebug debug, const ParseError &v)
|
||||
{
|
||||
QDebugStateSaver saver{debug};
|
||||
QString errMsg;
|
||||
switch (v) {
|
||||
case ParseError::NoError:{
|
||||
errMsg = "no error.";
|
||||
break;
|
||||
}
|
||||
case ParseError::NotFound:{
|
||||
errMsg = "file not found.";
|
||||
break;
|
||||
}
|
||||
case ParseError::MismatchedFile:{
|
||||
errMsg = "file type is mismatched.";
|
||||
break;
|
||||
}
|
||||
case ParseError::InvalidLocation:{
|
||||
errMsg = "file location is invalid, please check $XDG_DATA_DIRS.";
|
||||
break;
|
||||
}
|
||||
case ParseError::OpenFailed:{
|
||||
errMsg = "couldn't open the file.";
|
||||
break;
|
||||
}
|
||||
case ParseError::GroupHeaderInvalid:{
|
||||
errMsg = "groupHead syntax is invalid.";
|
||||
break;
|
||||
}
|
||||
case ParseError::EntryKeyInvalid:{
|
||||
errMsg = "key syntax is invalid.";
|
||||
break;
|
||||
}
|
||||
}
|
||||
debug << errMsg;
|
||||
return debug;
|
||||
}
|
||||
|
@ -1,5 +0,0 @@
|
||||
// SPDX-FileCopyrightText: 2023 UnionTech Software Technology Co., Ltd.
|
||||
//
|
||||
// SPDX-License-Identifier: LGPL-3.0-or-later
|
||||
|
||||
void greet();
|
@ -14,7 +14,6 @@ constexpr static auto defaultKeyStr = "default";
|
||||
enum class ParseError {
|
||||
NoError,
|
||||
NotFound,
|
||||
FilePathEmpty,
|
||||
MismatchedFile,
|
||||
InvalidLocation,
|
||||
OpenFailed,
|
||||
@ -37,13 +36,13 @@ public:
|
||||
friend QDebug operator<<(QDebug debug, const DesktopEntry::Value &v);
|
||||
|
||||
private:
|
||||
QString unescape(const QString& str) const noexcept;
|
||||
[[nodiscard]] QString unescape(const QString &str) const noexcept;
|
||||
};
|
||||
|
||||
DesktopEntry() = default;
|
||||
~DesktopEntry() = default;
|
||||
ParseError parse(QTextStream& stream) noexcept;
|
||||
QMap<QString, Value> group(const QString &key) const noexcept;
|
||||
[[nodiscard]] ParseError parse(QTextStream& stream) noexcept;
|
||||
[[nodiscard]] QMap<QString, Value> group(const QString &key) const noexcept;
|
||||
|
||||
private:
|
||||
QMap<QString, QMap<QString, Value>> m_entryMap;
|
||||
@ -54,13 +53,23 @@ private:
|
||||
|
||||
struct DesktopFile
|
||||
{
|
||||
const QString filePath;
|
||||
const QString desktopId;
|
||||
DesktopFile(const DesktopFile &) = default;
|
||||
DesktopFile(DesktopFile &&) = default;
|
||||
DesktopFile &operator=(const DesktopFile &) = default;
|
||||
DesktopFile &operator=(DesktopFile &&) = default;
|
||||
~DesktopFile() = default;
|
||||
|
||||
const QString &filePath() const { return m_filePath; }
|
||||
const QString &desktopId() const { return m_desktopId; }
|
||||
|
||||
static std::optional<DesktopFile> searchDesktopFile(const QString &desktopFilePath, ParseError& err) noexcept;
|
||||
|
||||
private:
|
||||
DesktopFile() = default;
|
||||
DesktopFile(QString &&path,QString &&fileId):m_filePath(std::move(path)),m_desktopId(std::move(fileId)){}
|
||||
QString m_filePath;
|
||||
QString m_desktopId;
|
||||
};
|
||||
|
||||
QDebug operator<<(QDebug debug, const DesktopEntry::Value& v);
|
||||
|
||||
QDebug operator<<(QDebug debug, const ParseError &v);
|
||||
|
@ -52,21 +52,7 @@ private:
|
||||
QString m_busAddress;
|
||||
};
|
||||
|
||||
template <typename T, typename U>
|
||||
bool registerObjectToDbus(T parent, const QString &path, const QString &interface)
|
||||
{
|
||||
using service_type = std::remove_const_t<T>;
|
||||
static_assert(std::is_pointer_v<service_type>, "param type must be a pointer");
|
||||
static_assert(std::is_base_of_v<QObject, std::remove_pointer_t<T>> and
|
||||
std::is_base_of_v<QObject, U>,
|
||||
"param type must derive QObject");
|
||||
auto &con = ApplicationManager1DBus::instance().CustomBus();
|
||||
if (!con.registerObject(path, interface, new U{parent})) {
|
||||
qCritical() << "register object failed:" << path << interface << con.lastError();
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
bool registerObjectToDbus(QObject* o, const QString &path, const QString &interface);
|
||||
|
||||
template <typename T>
|
||||
QString getDBusInterface()
|
||||
|
4
src/main.cpp
Normal file
4
src/main.cpp
Normal file
@ -0,0 +1,4 @@
|
||||
int main()
|
||||
{
|
||||
return 0;
|
||||
}
|
11
src/utils.cpp
Normal file
11
src/utils.cpp
Normal file
@ -0,0 +1,11 @@
|
||||
#include "global.h"
|
||||
|
||||
bool registerObjectToDbus(QObject *o, const QString &path, const QString &interface)
|
||||
{
|
||||
auto &con = ApplicationManager1DBus::instance().CustomBus();
|
||||
if (!con.registerObject(path, interface, o)) {
|
||||
qCritical() << "register object failed:" << path << interface << con.lastError();
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
Reference in New Issue
Block a user