SVN_SILENT made messages (.desktop file)
[kdepim.git] / korgac / koalarmclient.cpp
blob22f27467d07c51ccc1097d917adad0d2bb3ea1f7
1 /*
2 This file is part of the KDE reminder agent.
4 Copyright (c) 2002,2003 Cornelius Schumacher <schumacher@kde.org>
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License along
17 with this program; if not, write to the Free Software Foundation, Inc.,
18 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20 As a special exception, permission is given to link this program
21 with any edition of Qt, and distribute the resulting executable,
22 without including the source code for Qt in the source distribution.
24 //krazy:excludeall=kdebug because we use the korgac(check) debug area in here
26 #include "koalarmclient.h"
27 #if !defined(KORGAC_AKONADI_AGENT)
28 #include "alarmdialog.h"
29 #include "alarmdockwindow.h"
30 #else
31 #include <KNotification>
32 #endif
33 #include "korgacadaptor.h"
35 #include <calendarsupport/utils.h>
37 #include <Akonadi/ChangeRecorder>
38 #include <Akonadi/Collection>
39 #include <Akonadi/DBusConnectionPool>
40 #include <Akonadi/EntityTreeModel>
41 #include <Akonadi/Item>
42 #include <Akonadi/ItemFetchScope>
43 #include <Akonadi/Session>
45 #include <KCalCore/Calendar>
47 #include <KApplication>
48 #include <KCheckableProxyModel>
49 #include <KConfig>
50 #include <KConfigGroup>
51 #include <KDebug>
52 #include <KStandardDirs>
54 #ifdef Q_WS_MAEMO_5
55 #include <QtMaemo5/QMaemo5InformationBox>
56 #endif
58 using namespace KCalCore;
60 KOAlarmClient::KOAlarmClient( QObject *parent )
61 : QObject( parent ), mDocker( 0 ), mDialog( 0 )
63 new KOrgacAdaptor( this );
64 Akonadi::DBusConnectionPool::threadConnection().registerObject( QLatin1String("/ac"), this );
65 kDebug();
67 #if !defined(KORGAC_AKONADI_AGENT)
68 if ( dockerEnabled() ) {
69 mDocker = new AlarmDockWindow;
70 connect( this, SIGNAL(reminderCount(int)), mDocker, SLOT(slotUpdate(int)) );
71 connect( mDocker, SIGNAL(quitSignal()), SLOT(slotQuit()) );
73 #endif
74 QStringList mimeTypes;
75 mimeTypes << Event::eventMimeType() << Todo::todoMimeType();
76 mCalendar = Akonadi::ETMCalendar::Ptr( new Akonadi::ETMCalendar( mimeTypes ) );
77 mCalendar->setObjectName( QLatin1String("KOrgac's calendar") );
78 mETM = mCalendar->entityTreeModel();
80 connect( &mCheckTimer, SIGNAL(timeout()), SLOT(checkAlarms()) );
81 connect( mETM, SIGNAL(collectionPopulated(Akonadi::Collection::Id)),
82 SLOT(deferredInit()) );
83 connect( mETM, SIGNAL(collectionTreeFetched(Akonadi::Collection::List)),
84 SLOT(deferredInit()) );
86 KConfigGroup alarmGroup( KGlobal::config(), "Alarms" );
87 const int interval = alarmGroup.readEntry( "Interval", 60 );
88 kDebug() << "KOAlarmClient check interval:" << interval << "seconds.";
89 mLastChecked = alarmGroup.readEntry( "CalendarsLastChecked", QDateTime() );
91 checkAlarms();
92 mCheckTimer.start( 1000 * interval ); // interval in seconds
95 KOAlarmClient::~KOAlarmClient()
97 #if !defined(KORGAC_AKONADI_AGENT)
98 delete mDocker;
99 delete mDialog;
100 #endif
103 void checkAllItems( KCheckableProxyModel *model, const QModelIndex &parent = QModelIndex() )
105 const int rowCount = model->rowCount( parent );
106 for ( int row = 0; row < rowCount; row++ ) {
107 QModelIndex index = model->index( row, 0, parent );
108 model->setData( index, Qt::Checked, Qt::CheckStateRole );
110 if ( model->rowCount( index ) > 0 ) {
111 checkAllItems( model, index );
116 void KOAlarmClient::deferredInit()
118 if ( !collectionsAvailable() ) {
119 return;
122 kDebug(5891) << "Performing delayed initialization.";
124 // load reminders that were active when quitting
125 KConfigGroup genGroup( KGlobal::config(), "General" );
126 const int numReminders = genGroup.readEntry( "Reminders", 0 );
128 for ( int i=1; i<=numReminders; ++i ) {
129 const QString group( QString::fromLatin1( "Incidence-%1" ).arg( i ) );
130 const KConfigGroup incGroup( KGlobal::config(), group );
132 const KUrl url = incGroup.readEntry( "AkonadiUrl" );
133 Akonadi::Item::Id akonadiItemId = -1;
134 if ( !url.isValid() ) {
135 // logic to migrate old KOrganizer incidence uid's to a Akonadi item.
136 const QString uid = incGroup.readEntry( "UID" );
137 if ( !uid.isEmpty() ) {
138 akonadiItemId = mCalendar->item( uid ).id();
140 } else {
141 akonadiItemId = Akonadi::Item::fromUrl( url ).id();
144 if ( akonadiItemId >= 0 ) {
145 const QDateTime dt = incGroup.readEntry( "RemindAt", QDateTime() );
146 Akonadi::Item i = mCalendar->item( Akonadi::Item::fromUrl( url ).id() );
147 if ( CalendarSupport::hasIncidence( i ) && !CalendarSupport::incidence( i )->alarms().isEmpty() ) {
148 createReminder( mCalendar, i, dt, QString() );
153 KCheckableProxyModel *checkableModel = mCalendar->checkableProxyModel();
154 checkAllItems( checkableModel );
156 // Now that everything is set up, a first check for reminders can be performed.
157 checkAlarms();
160 bool KOAlarmClient::dockerEnabled()
162 KConfig korgConfig( KStandardDirs::locate( "config", QLatin1String("korganizerrc") ) );
163 KConfigGroup generalGroup( &korgConfig, "System Tray" );
164 return generalGroup.readEntry( "ShowReminderDaemon", true );
167 bool KOAlarmClient::collectionsAvailable() const
169 // The list of collections must be available.
170 if ( !mETM->isCollectionTreeFetched() ) {
171 return false;
174 // All collections must be populated.
175 const int rowCount = mETM->rowCount();
176 for ( int row = 0; row < rowCount; ++row ) {
177 static const int column = 0;
178 const QModelIndex index = mETM->index( row, column );
179 bool haveData =
180 mETM->data( index, Akonadi::EntityTreeModel::IsPopulatedRole ).toBool();
181 if ( !haveData ) {
182 return false;
186 return true;
189 void KOAlarmClient::checkAlarms()
191 KConfigGroup cfg( KGlobal::config(), "General" );
193 if ( !cfg.readEntry( "Enabled", true ) ) {
194 return;
197 // We do not want to miss any reminders, so don't perform check unless
198 // the collections are available and populated.
199 if ( !collectionsAvailable() ) {
200 kDebug(5891) << "Collections are not available; aborting check.";
201 return;
204 QDateTime from = mLastChecked.addSecs( 1 );
205 mLastChecked = QDateTime::currentDateTime();
207 kDebug(5891) << "Check:" << from.toString() << " -" << mLastChecked.toString();
209 const Alarm::List alarms = mCalendar->alarms( KDateTime( from, KDateTime::LocalZone ),
210 KDateTime( mLastChecked, KDateTime::LocalZone ),
211 true /* exclude blocked alarms */);
213 foreach ( const Alarm::Ptr &alarm, alarms ) {
214 const QString uid = alarm->customProperty( "ETMCalendar", "parentUid" );
215 const Akonadi::Item::Id id = mCalendar->item( uid ).id();
216 const Akonadi::Item item = mCalendar->item( id );
218 createReminder( mCalendar, item, from, alarm->text() );
222 void KOAlarmClient::createReminder( const Akonadi::ETMCalendar::Ptr &calendar,
223 const Akonadi::Item &aitem,
224 const QDateTime &remindAtDate,
225 const QString &displayText )
227 if ( !CalendarSupport::hasIncidence( aitem ) ) {
228 return;
231 #if !defined(Q_WS_MAEMO_5) && !defined(KORGAC_AKONADI_AGENT)
232 if ( !mDialog ) {
233 mDialog = new AlarmDialog( calendar );
234 connect( this, SIGNAL(saveAllSignal()), mDialog, SLOT(slotSave()) );
235 if ( mDocker ) {
236 connect( mDialog, SIGNAL(reminderCount(int)),
237 mDocker, SLOT(slotUpdate(int)) );
238 connect( mDocker, SIGNAL(suspendAllSignal()),
239 mDialog, SLOT(suspendAll()) );
240 connect( mDocker, SIGNAL(dismissAllSignal()),
241 mDialog, SLOT(dismissAll()) );
245 mDialog->addIncidence( aitem, remindAtDate, displayText );
246 mDialog->wakeUp();
247 #else
248 const Incidence::Ptr incidence = CalendarSupport::incidence( aitem );
249 Q_UNUSED( calendar );
250 Q_UNUSED( remindAtDate );
251 Q_UNUSED( displayText );
253 #if defined(Q_WS_MAEMO_5)
254 QMaemo5InformationBox::information( 0, incidence->summary(), QMaemo5InformationBox::NoTimeout );
255 #else
256 KNotification *notify = new KNotification( "reminder", 0, KNotification::Persistent );
257 notify->setText( incidence->summary() );
258 notify->sendEvent();
259 #endif
261 #endif
262 saveLastCheckTime();
265 void KOAlarmClient::slotQuit()
267 emit saveAllSignal();
268 saveLastCheckTime();
269 quit();
272 void KOAlarmClient::saveLastCheckTime()
274 KConfigGroup cg( KGlobal::config(), "Alarms" );
275 cg.writeEntry( "CalendarsLastChecked", mLastChecked );
276 KGlobal::config()->sync();
279 void KOAlarmClient::quit()
281 kDebug();
282 #if !defined(KORGAC_AKONADI_AGENT)
283 kapp->quit();
284 #endif
287 bool KOAlarmClient::commitData( QSessionManager & )
289 emit saveAllSignal();
290 saveLastCheckTime();
291 return true;
294 void KOAlarmClient::forceAlarmCheck()
296 checkAlarms();
297 saveLastCheckTime();
300 void KOAlarmClient::dumpDebug()
302 KConfigGroup cfg( KGlobal::config(), "Alarms" );
303 const QDateTime lastChecked = cfg.readEntry( "CalendarsLastChecked", QDateTime() );
304 kDebug() << "Last Check:" << lastChecked;
307 QStringList KOAlarmClient::dumpAlarms()
309 const KDateTime start = KDateTime( QDateTime::currentDateTime().date(),
310 QTime( 0, 0 ), KDateTime::LocalZone );
311 const KDateTime end = start.addDays( 1 ).addSecs( -1 );
313 QStringList lst;
314 // Don't translate, this is for debugging purposes.
315 lst << QLatin1String( "AlarmDeamon::dumpAlarms() from " ) + start.toString() + QLatin1String(" to ") +
316 end.toString();
318 Alarm::List alarms = mCalendar->alarms( start, end );
319 foreach( Alarm::Ptr a, alarms ) {
320 const Incidence::Ptr parentIncidence = mCalendar->incidence( a->parentUid() );
321 lst << QLatin1String( " " ) + parentIncidence->summary() + QLatin1String(" (") + a->time().toString() + QLatin1Char(')');
324 return lst;
327 void KOAlarmClient::debugShowDialog()
329 // showAlarmDialog();
332 void KOAlarmClient::hide()
334 #if !defined(KORGAC_AKONADI_AGENT)
335 delete mDocker;
336 mDocker = 0;
337 #endif
340 void KOAlarmClient::show()
342 #if !defined(KORGAC_AKONADI_AGENT)
343 if ( !mDocker ) {
344 if ( dockerEnabled() ) {
345 mDocker = new AlarmDockWindow;
346 connect( this, SIGNAL(reminderCount(int)), mDocker, SLOT(slotUpdate(int)) );
347 connect( mDocker, SIGNAL(quitSignal()), SLOT(slotQuit()) );
350 if ( mDialog ) {
351 connect( mDialog, SIGNAL(reminderCount(int)),
352 mDocker, SLOT(slotUpdate(int)) );
353 connect( mDocker, SIGNAL(suspendAllSignal()),
354 mDialog, SLOT(suspendAll()) );
355 connect( mDocker, SIGNAL(dismissAllSignal()),
356 mDialog, SLOT(dismissAll()) );
359 #endif