Commit 33af2809 authored by Alexander Akulich's avatar Alexander Akulich
Browse files

[debugger] TelepathyProcess extracted from DebugMessageView

The main goal of this change is to split logic and UI parts

This is the first step in direction to debugger, which:
1) works with any Telepathy process with DebugInterface support;
2) detects new processess "on fly";
3) has no hardcoded services;
4) shows every single process just once, independently of a number
   dbus services, registered by the process.

The change also opens a way to QML-based UI

REVIEW: 128847
parent 431db458
......@@ -5,8 +5,9 @@ include_directories(
)
set(ktp-debugger_SRCS
main-window.cpp
debug-message-view.cpp
telepathy-process.cpp
main-window.cpp
main.cpp
)
......
......@@ -37,9 +37,10 @@
#include <QLayout>
#include <QMenu>
#include "telepathy-process.h"
DebugMessageView::DebugMessageView(QWidget *parent)
: QWidget(parent)
, m_ready(false)
{
KService::Ptr service = KService::serviceByDesktopPath(QString::fromLatin1("katepart.desktop"));
......@@ -62,13 +63,6 @@ DebugMessageView::DebugMessageView(QWidget *parent)
DebugMessageView::~DebugMessageView()
{
if (m_debugReceiver && m_ready) {
//disable monitoring and do it synchronously before all the objects are destroyed
Tp::PendingOperation *op = m_debugReceiver->setMonitoringEnabled(false);
QEventLoop loop;
connect(op, SIGNAL(finished(Tp::PendingOperation*)), &loop, SLOT(quit()));
loop.exec();
}
}
void DebugMessageView::clear()
......@@ -78,12 +72,18 @@ void DebugMessageView::clear()
m_editor->setReadWrite(false);
}
void DebugMessageView::showEvent(QShowEvent* event)
void DebugMessageView::showEvent(QShowEvent *event)
{
QWidget::showEvent(event);
addDelayedMessages();
}
void DebugMessageView::setTelepathyProcess(TelepathyProcess *process)
{
connect(process, SIGNAL(newDebugMessage(Tp::DebugMessage)),
SLOT(appendMessage(Tp::DebugMessage)));
}
void DebugMessageView::addDelayedMessages()
{
KTextEditor::Document::EditingTransaction transaction(m_editor);
......@@ -93,108 +93,6 @@ void DebugMessageView::addDelayedMessages()
m_tmpCache.clear();
}
void DebugMessageView::setService(const QString &service)
{
m_serviceName = service;
m_serviceWatcher = new QDBusServiceWatcher(service, QDBusConnection::sessionBus(),
QDBusServiceWatcher::WatchForRegistration, this);
connect(m_serviceWatcher, SIGNAL(serviceRegistered(QString)),
SLOT(onServiceRegistered(QString)));
if (QDBusConnection::sessionBus().interface()->isServiceRegistered(service)) {
onServiceRegistered(service);
}
}
void DebugMessageView::onServiceRegistered(const QString & service)
{
qDebug() << "Service" << service << "registered. Introspecting Debug interface...";
m_debugReceiver = Tp::DebugReceiver::create(service);
Tp::PendingReady *op = m_debugReceiver->becomeReady();
connect(op, SIGNAL(finished(Tp::PendingOperation*)),
SLOT(onDebugReceiverReady(Tp::PendingOperation*)));
}
void DebugMessageView::onDebugReceiverInvalidated(Tp::DBusProxy *proxy,
const QString &errorName, const QString &errorMessage)
{
Q_UNUSED(proxy);
qDebug() << "DebugReceiver invalidated" << errorName << errorMessage;
m_ready = false;
m_debugReceiver.reset();
}
void DebugMessageView::onDebugReceiverReady(Tp::PendingOperation *op)
{
if (op->isError()) {
qDebug() << "Failed to introspect Debug interface for" << m_serviceName
<< "Error was:" << op->errorName() << "-" << op->errorMessage();
m_debugReceiver.reset();
} else {
connect(m_debugReceiver.data(), SIGNAL(newDebugMessage(Tp::DebugMessage)),
SLOT(onNewDebugMessage(Tp::DebugMessage)));
connect(m_debugReceiver->setMonitoringEnabled(true),
SIGNAL(finished(Tp::PendingOperation*)),
SLOT(onDebugReceiverMonitoringEnabled(Tp::PendingOperation*)));
}
}
void DebugMessageView::onDebugReceiverMonitoringEnabled(Tp::PendingOperation* op)
{
if (op->isError()) {
qWarning() << "Failed to enable monitoring on the Debug object of" << m_serviceName
<< "Error was:" << op->errorName() << "-" << op->errorMessage();
m_tmpCache.clear();
m_debugReceiver.reset();
} else {
connect(m_debugReceiver->fetchMessages(), SIGNAL(finished(Tp::PendingOperation*)),
SLOT(onFetchMessagesFinished(Tp::PendingOperation*)));
}
}
void DebugMessageView::onFetchMessagesFinished(Tp::PendingOperation* op)
{
if (op->isError()) {
qWarning() << "Failed to fetch messages from" << m_serviceName
<< "Error was:" << op->errorName() << "-" << op->errorMessage();
m_tmpCache.clear();
m_debugReceiver.reset();
} else {
Tp::PendingDebugMessageList *pdml = qobject_cast<Tp::PendingDebugMessageList*>(op);
Tp::DebugMessageList messages = pdml->result();
messages.append(m_tmpCache); //append any messages that were received from onNewDebugMessage()
m_tmpCache.clear();
{
KTextEditor::Document::EditingTransaction transaction(m_editor);
Q_FOREACH(const Tp::DebugMessage &msg, messages) {
appendMessage(msg);
}
}
//TODO limit m_messages size
m_ready = true;
connect(m_debugReceiver.data(),
SIGNAL(invalidated(Tp::DBusProxy*,QString,QString)),
SLOT(onDebugReceiverInvalidated(Tp::DBusProxy*,QString,QString)));
}
}
void DebugMessageView::onNewDebugMessage(const Tp::DebugMessage & msg)
{
if (m_ready) {
appendMessage(msg);
} else {
//cache until we are ready
m_tmpCache.append(msg);
}
}
//taken from empathy
static inline QString formatTimestamp(double timestamp)
{
......
......@@ -20,39 +20,28 @@
#include <QWidget>
#include <TelepathyQt/Types>
#include <TelepathyQt/PendingOperation>
#include <KTextEditor/Document>
class TelepathyProcess;
class DebugMessageView : public QWidget
{
Q_OBJECT
Q_OBJECT
public:
explicit DebugMessageView(QWidget *parent = 0);
virtual ~DebugMessageView();
~DebugMessageView();
void setService(const QString & service);
virtual void showEvent(QShowEvent *event);
void showEvent(QShowEvent *event);
void setTelepathyProcess(TelepathyProcess *process);
void saveLogFile();
private Q_SLOTS:
void onServiceRegistered(const QString & service);
void onDebugReceiverInvalidated(Tp::DBusProxy *proxy,
const QString &errorName, const QString &errorMessage);
void onDebugReceiverReady(Tp::PendingOperation *op);
void onDebugReceiverMonitoringEnabled(Tp::PendingOperation *op);
void onFetchMessagesFinished(Tp::PendingOperation *op);
void onNewDebugMessage(const Tp::DebugMessage &msg);
void appendMessage(const Tp::DebugMessage &msg);
void addDelayedMessages();
void clear();
private:
void appendMessage(const Tp::DebugMessage &msg);
QString m_serviceName;
Tp::DebugReceiverPtr m_debugReceiver;
Tp::DebugMessageList m_tmpCache;
QDBusServiceWatcher *m_serviceWatcher;
bool m_ready;
KTextEditor::Document *m_editor;
};
......
......@@ -17,6 +17,7 @@
*/
#include "main-window.h"
#include "debug-message-view.h"
#include "telepathy-process.h"
#include <TelepathyQt/AccountManager>
#include <TelepathyQt/AccountSet>
......@@ -36,7 +37,9 @@ MainWindow::MainWindow(QWidget *parent)
m_ui.setupUi(centralWidget());
setupGUI();
m_ui.mcLogsView->setService(QLatin1String("org.freedesktop.Telepathy.MissionControl5"));
TelepathyProcess *process = new TelepathyProcess(this);
process->setOwnerId(QStringLiteral("org.freedesktop.Telepathy.MissionControl5"));
m_ui.mcLogsView->setTelepathyProcess(process);
m_AccountManager = Tp::AccountManager::create();
Tp::PendingReady *pendingReady = m_AccountManager->becomeReady();
......@@ -88,7 +91,10 @@ void MainWindow::initConnectionManagerTabs(const QSet<QString>& connectionManage
QWidget *cmTab = new QWidget();
QHBoxLayout *horizontalLayout = new QHBoxLayout(cmTab);
DebugMessageView *cmDebugMessageView = new DebugMessageView(cmTab);
cmDebugMessageView->setService(QString(QLatin1String("org.freedesktop.Telepathy.ConnectionManager.%1")).arg(connectionManager));
TelepathyProcess *process = new TelepathyProcess(cmDebugMessageView);
process->setOwnerId(QString(QStringLiteral("org.freedesktop.Telepathy.ConnectionManager.%1")).arg(connectionManager));
cmDebugMessageView->setTelepathyProcess(process);
horizontalLayout->addWidget(cmDebugMessageView);
......
/*
Copyright (C) 2011 Collabora Ltd. <info@collabora.com>
@author George Kiagiadakis <george.kiagiadakis@collabora.com>
Copyright (C) 2016 Alexandr Akulich <akulichalexander@gmail.com>
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 program 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 General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "telepathy-process.h"
#include <TelepathyQt/Constants>
#include <TelepathyQt/PendingReady>
#include <TelepathyQt/PendingDebugMessageList>
TelepathyProcess::TelepathyProcess(QObject *parent) :
QObject(parent),
m_ready(false)
{
}
TelepathyProcess::~TelepathyProcess()
{
if (m_debugReceiver && m_ready) {
//disable monitoring and do it synchronously before all the objects are destroyed
Tp::PendingOperation *op = m_debugReceiver->setMonitoringEnabled(false);
QEventLoop loop;
connect(op, SIGNAL(finished(Tp::PendingOperation*)), &loop, SLOT(quit()));
loop.exec();
}
}
void TelepathyProcess::setOwnerId(const QString &owner)
{
m_owner = owner;
m_debugReceiver = Tp::DebugReceiver::create(owner);
Tp::PendingReady *op = m_debugReceiver->becomeReady();
connect(op, SIGNAL(finished(Tp::PendingOperation*)),
SLOT(onDebugReceiverReady(Tp::PendingOperation*)));
}
void TelepathyProcess::onDebugReceiverInvalidated(Tp::DBusProxy *proxy, const QString &errorName, const QString &errorMessage)
{
Q_UNUSED(proxy);
qDebug() << "DebugReceiver invalidated" << errorName << errorMessage;
m_debugReceiver.reset();
m_ready = false;
}
void TelepathyProcess::onDebugReceiverReady(Tp::PendingOperation *op)
{
if (op->isError()) {
qDebug() << "Failed to introspect Debug interface for" << m_owner
<< "Error was:" << op->errorName() << "-" << op->errorMessage();
m_debugReceiver.reset();
} else {
connect(m_debugReceiver.data(), SIGNAL(newDebugMessage(Tp::DebugMessage)),
SLOT(onNewDebugMessage(Tp::DebugMessage)));
connect(m_debugReceiver->setMonitoringEnabled(true),
SIGNAL(finished(Tp::PendingOperation*)),
SLOT(onDebugReceiverMonitoringEnabled(Tp::PendingOperation*)));
}
}
void TelepathyProcess::onDebugReceiverMonitoringEnabled(Tp::PendingOperation *op)
{
if (op->isError()) {
qWarning() << "Failed to enable monitoring on the Debug object of" << m_owner
<< "Error was:" << op->errorName() << "-" << op->errorMessage();
m_tmpCache.clear();
m_debugReceiver.reset();
} else {
connect(m_debugReceiver->fetchMessages(), SIGNAL(finished(Tp::PendingOperation*)),
SLOT(onFetchMessagesFinished(Tp::PendingOperation*)));
}
}
void TelepathyProcess::onFetchMessagesFinished(Tp::PendingOperation *op)
{
if (op->isError()) {
qWarning() << "Failed to fetch messages from" << m_owner
<< "Error was:" << op->errorName() << "-" << op->errorMessage();
m_tmpCache.clear();
m_debugReceiver.reset();
} else {
Tp::PendingDebugMessageList *pendingMessages = qobject_cast<Tp::PendingDebugMessageList*>(op);
Tp::DebugMessageList messages = pendingMessages->result();
messages.append(m_tmpCache); //append any messages that were received from onNewDebugMessage()
m_tmpCache.clear();
Q_FOREACH(const Tp::DebugMessage &msg, messages) {
appendMessage(msg);
}
m_ready = true;
connect(m_debugReceiver.data(),
SIGNAL(invalidated(Tp::DBusProxy*,QString,QString)),
SLOT(onDebugReceiverInvalidated(Tp::DBusProxy*,QString,QString)));
}
}
void TelepathyProcess::onNewDebugMessage(const Tp::DebugMessage &msg)
{
if (m_ready) {
appendMessage(msg);
} else {
//cache until we are ready
m_tmpCache.append(msg);
}
}
void TelepathyProcess::appendMessage(const Tp::DebugMessage &msg)
{
Q_EMIT newDebugMessage(msg);
}
/*
Copyright (C) 2011 Collabora Ltd. <info@collabora.com>
@author George Kiagiadakis <george.kiagiadakis@collabora.com>
Copyright (C) 2016 Alexandr Akulich <akulichalexander@gmail.com>
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 program 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 General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef TELEPATHY_PROCESS_H
#define TELEPATHY_PROCESS_H
#include <QObject>
#include <TelepathyQt/DebugReceiver>
#include <TelepathyQt/PendingOperation>
#include <TelepathyQt/Types>
class TelepathyProcess : public QObject
{
Q_OBJECT
public:
explicit TelepathyProcess(QObject *parent = nullptr);
~TelepathyProcess();
QString ownerId() const Q_REQUIRED_RESULT { return m_owner; }
void setOwnerId(const QString &owner);
Q_SIGNALS:
void newDebugMessage(const Tp::DebugMessage &message);
protected Q_SLOTS:
void onDebugReceiverInvalidated(Tp::DBusProxy *proxy,
const QString &errorName, const QString &errorMessage);
void onDebugReceiverReady(Tp::PendingOperation *op);
void onDebugReceiverMonitoringEnabled(Tp::PendingOperation *op);
void onFetchMessagesFinished(Tp::PendingOperation *op);
void onNewDebugMessage(const Tp::DebugMessage &msg);
protected:
void appendMessage(const Tp::DebugMessage &msg);
private:
QString m_owner;
Tp::DebugReceiverPtr m_debugReceiver;
Tp::DebugMessageList m_tmpCache;
bool m_ready;
};
#endif // TELEPATHY_PROCESS_H
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment