diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 8b2e6eb04..5826f416d 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -173,6 +173,13 @@ jobs: # Prefix the list here with "+" to use these queries and those in the config file. # queries: ./path/to/local/query, your-org/your-repo/queries@main + - name: Build and install ECM + run: | + cd .. + git clone https://invent.kde.org/frameworks/extra-cmake-modules.git + cmake -S extra-cmake-modules -B extra-cmake-modules/build $CMAKE_ARGS + cmake --build extra-cmake-modules/build --target install + - name: Configure libQuotient run: | cmake -S $GITHUB_WORKSPACE -B $BUILD_PATH $CMAKE_ARGS -DQuotient_INSTALL_TESTS=ON diff --git a/.gitignore b/.gitignore index f86acb26d..98f4fe484 100644 --- a/.gitignore +++ b/.gitignore @@ -32,3 +32,5 @@ compile_commands.json # Created by doxygen html/ latex/ + +.qmlls.ini diff --git a/CMakeLists.txt b/CMakeLists.txt index 205ddde04..c58a8e5b9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -11,7 +11,7 @@ string(JOIN ~ FULL_VERSION ${PROJECT_VERSION} ${PRE_STAGE}) message(STATUS) message(STATUS "Configuring ${PROJECT_NAME} ${FULL_VERSION} ==>") -find_package(ECM NO_MODULE) +find_package(ECM REQUIRED NO_MODULE) if (ECM_FOUND) set(CMAKE_MODULE_PATH ${ECM_MODULE_PATH}) include(ECMEnableSanitizers) @@ -257,6 +257,15 @@ target_sources(${QUOTIENT_LIB_NAME} PUBLIC FILE_SET HEADERS BASE_DIRS . libquotientemojis.qrc ) +include(ECMQmlModule) +include(KDEInstallDirs) + +qt_extract_metatypes(${QUOTIENT_LIB_NAME}) +ecm_add_qml_module(${QUOTIENT_LIB_NAME}plugin URI io.github.quotient_im.libquotient GENERATE_PLUGIN_SOURCE) +target_sources(${QUOTIENT_LIB_NAME}plugin PRIVATE Quotient/types.h) +target_link_libraries(${QUOTIENT_LIB_NAME}plugin PRIVATE ${Qt}::Core ${Qt}::Qml ${QUOTIENT_LIB_NAME}) +ecm_finalize_qml_module(${QUOTIENT_LIB_NAME}plugin DESTINATION ${KDE_INSTALL_QMLDIR} EXPORT ${QUOTIENT_LIB_NAME}Targets) + # Configure API files generation set(CSAPI_DIR csapi) diff --git a/Quotient/connection.h b/Quotient/connection.h index 56d7e7cf8..c668e0370 100644 --- a/Quotient/connection.h +++ b/Quotient/connection.h @@ -103,7 +103,7 @@ using IgnoredUsersList = IgnoredUsersEvent::value_type; class QUOTIENT_API Connection : public QObject { Q_OBJECT - Q_PROPERTY(User* localUser READ user NOTIFY stateChanged) + Q_PROPERTY(Quotient::User* localUser READ user NOTIFY stateChanged) Q_PROPERTY(QString localUserId READ userId NOTIFY stateChanged) Q_PROPERTY(QString domain READ domain NOTIFY stateChanged STORED false) Q_PROPERTY(QString deviceId READ deviceId NOTIFY stateChanged) diff --git a/Quotient/room.h b/Quotient/room.h index 01e38ef4d..763ecd041 100644 --- a/Quotient/room.h +++ b/Quotient/room.h @@ -118,8 +118,8 @@ struct Notification class QUOTIENT_API Room : public QObject { Q_OBJECT - Q_PROPERTY(Connection* connection READ connection CONSTANT) - Q_PROPERTY(RoomMember localMember READ localMember CONSTANT) + Q_PROPERTY(Quotient::Connection* connection READ connection CONSTANT) + Q_PROPERTY(Quotient::RoomMember localMember READ localMember CONSTANT) Q_PROPERTY(QString id READ id CONSTANT) Q_PROPERTY(QString version READ version NOTIFY baseStateLoaded) Q_PROPERTY(bool isUnstable READ isUnstable NOTIFY stabilityUpdated) @@ -143,8 +143,8 @@ class QUOTIENT_API Room : public QObject { Q_PROPERTY(int joinedCount READ joinedCount NOTIFY memberListChanged) Q_PROPERTY(int invitedCount READ invitedCount NOTIFY memberListChanged) Q_PROPERTY(int totalMemberCount READ totalMemberCount NOTIFY memberListChanged) - Q_PROPERTY(QList membersTyping READ membersTyping NOTIFY typingChanged) - Q_PROPERTY(QList otherMembersTyping READ otherMembersTyping NOTIFY typingChanged) + Q_PROPERTY(QList membersTyping READ membersTyping NOTIFY typingChanged) + Q_PROPERTY(QList otherMembersTyping READ otherMembersTyping NOTIFY typingChanged) Q_PROPERTY(int localMemberEffectivePowerLevel READ memberEffectivePowerLevel NOTIFY changed) Q_PROPERTY(bool displayed READ displayed WRITE setDisplayed NOTIFY @@ -159,14 +159,14 @@ class QUOTIENT_API Room : public QObject { NOTIFY highlightCountChanged) Q_PROPERTY(qsizetype notificationCount READ notificationCount NOTIFY notificationCountChanged) - Q_PROPERTY(EventStats partiallyReadStats READ partiallyReadStats NOTIFY partiallyReadStatsChanged) - Q_PROPERTY(EventStats unreadStats READ unreadStats NOTIFY unreadStatsChanged) + Q_PROPERTY(Quotient::EventStats partiallyReadStats READ partiallyReadStats NOTIFY partiallyReadStatsChanged) + Q_PROPERTY(Quotient::EventStats unreadStats READ unreadStats NOTIFY unreadStatsChanged) Q_PROPERTY(bool allHistoryLoaded READ allHistoryLoaded NOTIFY allHistoryLoadedChanged STORED false) Q_PROPERTY(QStringList tagNames READ tagNames NOTIFY tagsChanged) Q_PROPERTY(bool isFavourite READ isFavourite NOTIFY tagsChanged STORED false) Q_PROPERTY(bool isLowPriority READ isLowPriority NOTIFY tagsChanged STORED false) - Q_PROPERTY(JoinRule joinRule READ joinRule WRITE setJoinRule NOTIFY joinRuleChanged) + Q_PROPERTY(Quotient::JoinRule joinRule READ joinRule WRITE setJoinRule NOTIFY joinRuleChanged) Q_PROPERTY(QList allowIds READ allowIds NOTIFY joinRuleChanged) Q_PROPERTY(GetRoomEventsJob* eventsHistoryJob READ eventsHistoryJob NOTIFY eventsHistoryJobChanged) diff --git a/Quotient/types.h b/Quotient/types.h new file mode 100644 index 000000000..ec1ff35b4 --- /dev/null +++ b/Quotient/types.h @@ -0,0 +1,86 @@ +// SPDX-FileCopyrightText: 2025 Tobias Fella +// SPDX-License-Identifier: LGPL-2.0-or-later + +#pragma once + +#include "connection.h" +#include "e2ee/sssshandler.h" +#include "eventstats.h" +#include "keyimport.h" +#include "user.h" +#include "keyverificationsession.h" +#include "room.h" +#include "roommember.h" + +#include + +struct ConnectionForeign +{ + Q_GADGET + QML_NAMED_ELEMENT(Connection) + QML_FOREIGN(Quotient::Connection) + QML_UNCREATABLE("") +}; + +struct SSSSHandlerForeign +{ + Q_GADGET + QML_NAMED_ELEMENT(SSSSHandler) + QML_FOREIGN(Quotient::SSSSHandler) +}; + +struct EventStatsForeign +{ + Q_GADGET + QML_NAMED_ELEMENT(eventStats) + QML_FOREIGN(Quotient::EventStats) + QML_UNCREATABLE("") +}; + +struct KeyImportForeign +{ + Q_GADGET + QML_NAMED_ELEMENT(KeyImport) + QML_SINGLETON + QML_FOREIGN(Quotient::KeyImport) +}; + +struct UserForeign +{ + Q_GADGET + QML_NAMED_ELEMENT(User) + QML_UNCREATABLE("") + QML_FOREIGN(Quotient::User) +}; + +struct KeyVerificationSessionForeign +{ + Q_GADGET + QML_NAMED_ELEMENT(KeyVerificationSession) + QML_UNCREATABLE("") + QML_FOREIGN(Quotient::KeyVerificationSession) +}; + +struct JoinRuleForeign +{ + Q_GADGET + QML_NAMED_ELEMENT(JoinRule) + QML_UNCREATABLE("Only for enum values") + QML_FOREIGN_NAMESPACE(Quotient) +}; + +struct RoomForeign +{ + Q_GADGET + QML_NAMED_ELEMENT(Room) + QML_UNCREATABLE("") + QML_FOREIGN(Quotient::Room) +}; + +struct RoomMemberForeign +{ + Q_GADGET + QML_NAMED_ELEMENT(roomMember) + QML_UNCREATABLE("") + QML_FOREIGN(Quotient::RoomMember) +};