Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft: Import QXmppComponent #362

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion QXmppConfig.cmake.in
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
@PACKAGE_INIT@
include("${CMAKE_CURRENT_LIST_DIR}/QXmpp.cmake")
check_required_components(QXmpp)
include("${CMAKE_CURRENT_LIST_DIR}/QXmppComponent.cmake")

check_required_components(QXmpp)
1 change: 1 addition & 0 deletions src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -269,3 +269,4 @@ install(
DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}/qxmpp"
)

add_subdirectory(component)
47 changes: 47 additions & 0 deletions src/component/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
add_library(QXmppComponent SHARED
QXmppComponent.cpp
QXmppComponentExtension.cpp
QXmppComponentConfig.cpp
QXmppOutgoingComponent.cpp
)

set(COMPONENT_INSTALL_HEADER_FILES
QXmppComponent.h
QXmppComponentExtension.h
QXmppComponentConfig.h
QXmppOutgoingComponent.h
)

target_link_libraries(QXmppComponent PUBLIC qxmpp Qt5::Core)
set(COMPONENT_HEADER_DIR "${CMAKE_INSTALL_FULL_INCLUDEDIR}/qxmpp/component")
target_include_directories(QXmppComponent PUBLIC ${COMPONENT_HEADER_DIR})

set_target_properties(QXmppComponent PROPERTIES
VERSION ${PROJECT_VERSION}
SOVERSION ${SO_VERSION}
EXPORT_NAME Component
)

install(
TARGETS QXmppComponent
DESTINATION "${CMAKE_INSTALL_LIBDIR}"
EXPORT QXmppComponentTargets
)

install(
EXPORT QXmppComponentTargets
DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/qxmpp"
FILE QXmppComponent.cmake
NAMESPACE QXmpp::
COMPONENT Devel
)

export(
TARGETS QXmppComponent
FILE QXmppComponent.cmake
)

install(
FILES ${COMPONENT_INSTALL_HEADER_FILES}
DESTINATION ${COMPONENT_HEADER_DIR}
)
166 changes: 166 additions & 0 deletions src/component/QXmppComponent.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,166 @@
// SPDX-FileCopyrightText: 2021 Linus Jahn <[email protected]>
//
// SPDX-License-Identifier: LGPL-2.0-or-later

#include "QXmppComponent.h"
#include "QXmppOutgoingComponent.h"
#include "QXmppComponentConfig.h"
#include "QXmppComponentExtension.h"

class QXmppComponentPrivate
{
public:
QXmppComponentPrivate(QXmppComponent *parent);

QXmppOutgoingComponent *component;
QVector<QXmppComponentExtension *> extensions;
QXmppLogger *logger = nullptr;
};

QXmppComponentPrivate::QXmppComponentPrivate(QXmppComponent *parent)
: component(new QXmppOutgoingComponent(parent))
{
}

QXmppComponent::QXmppComponent(QObject *parent)
: QXmppLoggable(parent),
d(new QXmppComponentPrivate(this))
{
connect(d->component, &QXmppOutgoingComponent::connected, this, &QXmppComponent::connected);
connect(d->component, &QXmppOutgoingComponent::disconnected, this, &QXmppComponent::disconnected);

connect(d->component, &QXmppOutgoingComponent::iqReceived, this, &QXmppComponent::iqReceived);
connect(d->component, &QXmppOutgoingComponent::messageReceived, this, &QXmppComponent::messageReceived);
connect(d->component, &QXmppOutgoingComponent::presenceReceived, this, &QXmppComponent::presenceReceived);
connect(d->component, &QXmppOutgoingComponent::elementReceived, this, &QXmppComponent::onElementReceived);

// logging
setLogger(QXmppLogger::getLogger());
}

QXmppComponent::~QXmppComponent()
{
}

///
/// Registers a new \a extension with the component.
///
/// \param extension
///
bool QXmppComponent::addExtension(QXmppComponentExtension* extension)
{
return insertExtension(d->extensions.size(), extension);
}

///
/// Registers a new \a extension with the component at the given \a index.
///
/// \param index
/// \param extension
///
bool QXmppComponent::insertExtension(int index, QXmppComponentExtension *extension)
{
if (d->extensions.contains(extension)) {
qWarning("Cannot add extension, it has already been added");
return false;
}

extension->setParent(this);
extension->setComponent(this);
d->extensions.insert(index, extension);
return true;
}

///
/// Unregisters the given extension from the component. If the extension
/// is found, it will be destroyed.
///
/// \param extension
///
bool QXmppComponent::removeExtension(QXmppComponentExtension *extension)
{
if (d->extensions.contains(extension)) {
d->extensions.removeAll(extension);
extension->deleteLater();
return true;
} else {
warning("Cannot remove extension, it was never added");
return false;
}
}

///
/// Returns a list containing all the component's extensions.
///
auto QXmppComponent::extensions() -> QVector<QXmppComponentExtension*>
{
return d->extensions;
}

///
/// Returns the QXmppLogger associated with the current QXmppComponent.
///
auto QXmppComponent::logger() const -> QXmppLogger*
{
return d->logger;
}

///
/// Sets the QXmppLogger associated with the current QXmppComponent.
///
void QXmppComponent::setLogger(QXmppLogger *logger)
{
if (logger != d->logger) {
if (d->logger) {
disconnect(this, &QXmppLoggable::logMessage,
d->logger, &QXmppLogger::log);
disconnect(this, &QXmppLoggable::setGauge,
d->logger, &QXmppLogger::setGauge);
disconnect(this, &QXmppLoggable::updateCounter,
d->logger, &QXmppLogger::updateCounter);
}

d->logger = logger;
if (d->logger) {
connect(this, &QXmppLoggable::logMessage,
d->logger, &QXmppLogger::log);
connect(this, &QXmppLoggable::setGauge,
d->logger, &QXmppLogger::setGauge);
connect(this, &QXmppLoggable::updateCounter,
d->logger, &QXmppLogger::updateCounter);
}

emit loggerChanged();
}
}

QXmppComponentConfig &QXmppComponent::configuration()
{
return d->component->config();
}

void QXmppComponent::connectToServer(const QXmppComponentConfig &config)
{
d->component->config() = config;
d->component->connectToHost();
}

bool QXmppComponent::sendPacket(const QXmppStanza &packet)
{
return d->component->sendPacket(packet);
}

bool QXmppComponent::isConnected()
{
return d->component->isConnected() && d->component->isAuthenticated();
}

void QXmppComponent::onElementReceived(const QDomElement &element, bool &handled)
{
for (auto *extension : std::as_const(d->extensions)) {
if (extension->handleStanza(element)) {
handled = true;
return;
}
}
}
90 changes: 90 additions & 0 deletions src/component/QXmppComponent.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
// SPDX-FileCopyrightText: 2021 Linus Jahn <[email protected]>
//
// SPDX-License-Identifier: LGPL-2.0-or-later

#ifndef QXMPPCOMPONENT_H
#define QXMPPCOMPONENT_H

#include <memory>
#include <QVector>
#include <QXmppLogger.h>

class QXmppComponentPrivate;
class QXmppComponentConfig;
class QXmppComponentExtension;
class QDomElement;
class QXmppStanza;
class QXmppPresence;
class QXmppMessage;
class QXmppIq;

class QXmppComponent : public QXmppLoggable
{
Q_OBJECT

public:
QXmppComponent(QObject *parent = nullptr);
~QXmppComponent();

bool addExtension(QXmppComponentExtension *extension);
bool insertExtension(int index, QXmppComponentExtension *extension);
bool removeExtension(QXmppComponentExtension *extension);
auto extensions() -> QVector<QXmppComponentExtension*>;
template<typename T>
auto findExtension() -> T *;

auto logger() const -> QXmppLogger*;
void setLogger(QXmppLogger* logger);
Q_SIGNAL void loggerChanged();

QXmppComponentConfig &configuration();

Q_SLOT void connectToServer(const QXmppComponentConfig &config);
Q_SLOT bool sendPacket(const QXmppStanza &);

bool isConnected();
Q_SIGNAL void connected();
Q_SIGNAL void disconnected();

/// This signal is emitted when a presence is received.
Q_SIGNAL void presenceReceived(const QXmppPresence &);

/// This signal is emitted when a message is received.
Q_SIGNAL void messageReceived(const QXmppMessage &);

/// This signal is emitted when an IQ response (type result or error) has
/// been received that was not handled by elementReceived().
Q_SIGNAL void iqReceived(const QXmppIq &);

private:
void onElementReceived(const QDomElement &element, bool &handled);

std::unique_ptr<QXmppComponentPrivate> d;
};

///
/// \brief Returns the extension which can be cast into type T*, or 0
/// if there is no such extension.
///
/// Usage example:
/// \code
/// QXmppDiscoveryManager* ext = client->findExtension<QXmppDiscoveryManager>();
/// if(ext)
/// {
/// //extension found, do stuff...
/// }
/// \endcode
///
template<typename T>
T *QXmppComponent::findExtension()
{
const auto list = extensions();
for (auto ext : list) {
if (auto *extension = qobject_cast<T *>(ext)) {
return extension;
}
}
return nullptr;
}

#endif // QXMPPCOMPONENT_H
Loading