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 }