File indexing completed on 2024-04-14 15:05:40

0001 /*
0002  * This file is part of TelepathyLoggerQt
0003  *
0004  * Copyright (C) 2011 Collabora Ltd. <http://www.collabora.co.uk/>
0005  *
0006  * This library is free software; you can redistribute it and/or
0007  * modify it under the terms of the GNU Lesser General Public
0008  * License as published by the Free Software Foundation; either
0009  * version 2.1 of the License, or (at your option) any later version.
0010  *
0011  * This library is distributed in the hope that it will be useful,
0012  * but WITHOUT ANY WARRANTY; without even the implied warranty of
0013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
0014  * Lesser General Public License for more details.
0015  *
0016  * You should have received a copy of the GNU Lesser General Public
0017  * License along with this library; if not, write to the Free Software
0018  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
0019  */
0020 
0021 #include "pending-events.h"
0022 #include "log-manager.h"
0023 #include "log-walker.h"
0024 #include "call-event.h"
0025 #include "entity.h"
0026 #include "text-event.h"
0027 #include "utils.h"
0028 
0029 #include <QtCore/QDebug>
0030 
0031 #include <TelepathyQt/Account>
0032 
0033 #include <telepathy-logger/log-manager.h>
0034 #include <telepathy-logger/event.h>
0035 #include <telepathy-logger/text-event.h>
0036 #include <telepathy-logger/call-event.h>
0037 
0038 #include <glib.h>
0039 
0040 using namespace Tpl;
0041 
0042 struct TELEPATHY_LOGGER_QT_NO_EXPORT PendingEvents::Private
0043 {
0044     LogManagerPtr manager;
0045     LogWalkerPtr logWalker;
0046     Tp::AccountPtr account;
0047     TpAccount *tpAccount;
0048     EntityPtr entity;
0049     EventTypeMask typeMask;
0050     QDate date;
0051 
0052     bool filtered;
0053     uint numEvents;
0054     LogEventFilter filterFunction;
0055     void *filterFunctionUserData;
0056 
0057     EventPtrList events;
0058 
0059     static void onAccountPrepared(void *logManager, void *result, PendingEvents *self);
0060     static void callback(void *caller, void *result, PendingEvents *self);
0061     static gboolean eventFilterMethod(TplEvent *event, gpointer *user_data);
0062     static void storeAndFreeEvent(TplEvent *event, PendingEvents *self);
0063 };
0064 
0065 PendingEvents::PendingEvents(const LogManagerPtr & manager, const Tp::AccountPtr & account,
0066     const EntityPtr & entity, EventTypeMask typeMask, const QDate &date)
0067     : PendingOperation(),
0068       mPriv(new Private())
0069 {
0070     mPriv->manager = manager;
0071     mPriv->account = account;
0072     mPriv->tpAccount = 0;
0073     mPriv->entity = entity;
0074     mPriv->typeMask = typeMask;
0075     mPriv->date = date;
0076     mPriv->filtered = false;
0077     mPriv->filterFunction = 0;
0078     mPriv->filterFunctionUserData = 0;
0079 }
0080 
0081 PendingEvents::PendingEvents(const LogManagerPtr & manager, const Tp::AccountPtr & account,
0082     const EntityPtr & entity, EventTypeMask typeMask, uint numEvents,
0083     LogEventFilter filterFunction, void *filterFunctionUserData)
0084     : PendingOperation(),
0085       mPriv(new Private())
0086 {
0087     mPriv->manager = manager;
0088     mPriv->account = account;
0089     mPriv->entity = entity;
0090     mPriv->typeMask = typeMask;
0091     mPriv->filtered = true;
0092     mPriv->numEvents = numEvents;
0093     mPriv->filterFunction = filterFunction;
0094     mPriv->filterFunctionUserData = filterFunctionUserData;
0095 }
0096 
0097 PendingEvents::PendingEvents(const LogWalkerPtr& logWalker, uint numEvents)
0098     : PendingOperation(),
0099       mPriv(new Private())
0100 {
0101     mPriv->logWalker = logWalker;
0102     mPriv->numEvents = numEvents;
0103     mPriv->typeMask = Tpl::EventTypeMaskAny;
0104     mPriv->filtered = false;
0105     mPriv->filterFunction = 0;
0106     mPriv->filterFunctionUserData = 0;
0107 }
0108 
0109 PendingEvents::~PendingEvents()
0110 {
0111     delete mPriv;
0112 }
0113 
0114 void PendingEvents::start()
0115 {
0116     if (mPriv->account) {
0117         mPriv->tpAccount = Utils::instance()->tpAccount(mPriv->account);
0118         if (!mPriv->tpAccount) {
0119             setFinishedWithError(TP_QT_ERROR_INVALID_ARGUMENT, "Invalid account");
0120             return;
0121         }
0122 
0123         GQuark features[] = { TP_ACCOUNT_FEATURE_CORE, 0 };
0124         tp_proxy_prepare_async(mPriv->tpAccount, features, (GAsyncReadyCallback) Private::onAccountPrepared, this);
0125     } else if (mPriv->logWalker) {
0126         tpl_log_walker_get_events_async(
0127             TPLoggerQtWrapper::unwrap<TplLogWalker, LogWalker>(mPriv->logWalker),
0128             mPriv->numEvents,
0129             (GAsyncReadyCallback) Private::callback,
0130             this);
0131     }
0132 }
0133 
0134 void PendingEvents::Private::onAccountPrepared(void *logManager, void *result, PendingEvents *self)
0135 {
0136     if (self->mPriv->filtered) {
0137         tpl_log_manager_get_filtered_events_async(
0138             TPLoggerQtWrapper::unwrap<TplLogManager, LogManager>(self->mPriv->manager),
0139             self->mPriv->tpAccount,
0140             TPLoggerQtWrapper::unwrap<TplEntity, Entity>(self->mPriv->entity),
0141             self->mPriv->typeMask,
0142             self->mPriv->numEvents,
0143             self->mPriv->filterFunction ? (TplLogEventFilter) Private::eventFilterMethod : 0,
0144             self,
0145             (GAsyncReadyCallback) Private::callback,
0146             self);
0147     } else {
0148         GDate *gdate = g_date_new_dmy(
0149             self->mPriv->date.day(),
0150             (GDateMonth) self->mPriv->date.month(),
0151             self->mPriv->date.year());
0152         tpl_log_manager_get_events_for_date_async(
0153             TPLoggerQtWrapper::unwrap<TplLogManager, LogManager>(self->mPriv->manager),
0154             self->mPriv->tpAccount,
0155             TPLoggerQtWrapper::unwrap<TplEntity, Entity>(self->mPriv->entity),
0156             self->mPriv->typeMask,
0157             gdate,
0158             (GAsyncReadyCallback) Private::callback,
0159             self);
0160         g_date_free(gdate);
0161     }
0162 }
0163 
0164 EventPtrList PendingEvents::events() const
0165 {
0166     if (!isFinished()) {
0167         qWarning() << "PendingEvents::events called before finished, returning empty";
0168         return EventPtrList();
0169     } else if (!isValid()) {
0170         qWarning() << "PendingEvents::events called when not valid, returning empty";
0171         return EventPtrList();
0172     }
0173 
0174     return mPriv->events;
0175 }
0176 
0177 void PendingEvents::Private::callback(void *caller, void *result, PendingEvents *self)
0178 {
0179     if (!G_IS_ASYNC_RESULT(result)) {
0180         self->setFinishedWithError(TP_QT_ERROR_INVALID_ARGUMENT, "Invalid async result in callback");
0181         return;
0182     }
0183 
0184     GList *events = NULL;
0185     GError *error = NULL;
0186     gboolean success = FALSE;
0187     if (TPL_IS_LOG_MANAGER(caller)) {
0188         if (self->mPriv->filtered) {
0189             success = tpl_log_manager_get_filtered_events_finish(TPL_LOG_MANAGER(caller), G_ASYNC_RESULT(result), &events, &error);
0190         } else {
0191             success = tpl_log_manager_get_events_for_date_finish(TPL_LOG_MANAGER(caller), G_ASYNC_RESULT(result), &events, &error);
0192         }
0193     } else if (TPL_IS_LOG_WALKER(caller)) {
0194         success = tpl_log_walker_get_events_finish(TPL_LOG_WALKER(caller), G_ASYNC_RESULT(result), &events, &error);
0195     } else {
0196         self->setFinishedWithError(TP_QT_ERROR_INVALID_ARGUMENT, "Invalid callback caller");
0197         return;
0198     }
0199 
0200     if (error) {
0201         self->setFinishedWithError(TP_QT_ERROR_INVALID_ARGUMENT, error->message);
0202         g_error_free(error);
0203         return;
0204     }
0205 
0206     if (!success) {
0207         self->setFinishedWithError(TP_QT_ERROR_INVALID_ARGUMENT, "Query failed without specific error");
0208         return;
0209     }
0210 
0211     g_list_foreach(events, (GFunc) &storeAndFreeEvent, self);
0212     g_list_free(events);
0213 
0214     self->setFinished();
0215 }
0216 
0217 void PendingEvents::Private::storeAndFreeEvent(TplEvent *tplEvent, PendingEvents *self)
0218 {
0219     if (TPL_IS_TEXT_EVENT(tplEvent)) {
0220         TextEventPtr eventPtr = TPLoggerQtWrapper::wrap<TplTextEvent, TextEvent>(TPL_TEXT_EVENT(tplEvent), true);
0221         self->mPriv->events << eventPtr;
0222     } else if (TPL_IS_CALL_EVENT(tplEvent)) {
0223         CallEventPtr eventPtr  = TPLoggerQtWrapper::wrap<TplCallEvent, CallEvent>(TPL_CALL_EVENT(tplEvent), true);
0224         self->mPriv->events << eventPtr;
0225     } else if (TPL_IS_EVENT(tplEvent)) {
0226         EventPtr eventPtr = TPLoggerQtWrapper::wrap<TplEvent, Event>(TPL_EVENT(tplEvent), true);
0227         self->mPriv->events << eventPtr;
0228     }
0229 
0230     g_object_unref(tplEvent);
0231 }
0232 
0233 gboolean PendingEvents::Private::eventFilterMethod(TplEvent *event, gpointer *user_data)
0234 {
0235     PendingEvents *self = (PendingEvents *) user_data;
0236     if (!self) {
0237         return FALSE;
0238     }
0239 
0240     return self->mPriv->filterFunction(TPLoggerQtWrapper::wrap<TplEvent, Event>(event, true), self->mPriv->filterFunctionUserData);
0241 }