• Skip to content
  • Skip to link menu
KDE API Reference
  • KDE API Reference
  • kdepim API Reference
  • KDE Home
  • Contact Us
 

kalarm

  • sources
  • kde-4.12
  • kdepim
  • kalarm
resourceselector.cpp
Go to the documentation of this file.
1 /*
2  * resourceselector.cpp - calendar resource selection widget
3  * Program: kalarm
4  * Copyright © 2006-2013 by David Jarvie <djarvie@kde.org>
5  * Based on KOrganizer's ResourceView class and KAddressBook's ResourceSelection class,
6  * Copyright (C) 2003,2004 Cornelius Schumacher <schumacher@kde.org>
7  * Copyright (C) 2003-2004 Reinhold Kainhofer <reinhold@kainhofer.com>
8  * Copyright (c) 2004 Tobias Koenig <tokoe@kde.org>
9  *
10  * This program is free software; you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License as published by
12  * the Free Software Foundation; either version 2 of the License, or
13  * (at your option) any later version.
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18  * GNU General Public License for more details.
19  *
20  * You should have received a copy of the GNU General Public License along
21  * with this program; if not, write to the Free Software Foundation, Inc.,
22  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
23  */
24 
25 #include "resourceselector.moc"
26 
27 #include "kalarm.h"
28 #include "alarmcalendar.h"
29 #include "autoqpointer.h"
30 #ifdef USE_AKONADI
31 #include "akonadiresourcecreator.h"
32 #include "calendarmigrator.h"
33 #include "kalarmapp.h"
34 #else
35 #include "alarmresources.h"
36 #include "eventlistmodel.h"
37 #include "resourcemodelview.h"
38 #endif
39 #include "messagebox.h"
40 #include "packedlayout.h"
41 #include "preferences.h"
42 #include "resourceconfigdialog.h"
43 
44 #ifdef USE_AKONADI
45 #include <akonadi/agentmanager.h>
46 #include <akonadi/agentinstancecreatejob.h>
47 #include <akonadi/agenttype.h>
48 #include <akonadi/collectionpropertiesdialog.h>
49 #include <akonadi/entitydisplayattribute.h>
50 #else
51 #include <kcal/resourcecalendar.h>
52 #endif
53 
54 #include <kdialog.h>
55 #include <klocale.h>
56 #include <kglobal.h>
57 #include <kcombobox.h>
58 #include <kinputdialog.h>
59 #include <kmenu.h>
60 #include <kdebug.h>
61 #include <kicon.h>
62 #include <kactioncollection.h>
63 #include <kaction.h>
64 #include <ktoggleaction.h>
65 #include <kcolordialog.h>
66 
67 #include <QLayout>
68 #include <QLabel>
69 #include <QPushButton>
70 #include <QTimer>
71 #include <QPainter>
72 #include <QFont>
73 #include <QResizeEvent>
74 #include <QApplication>
75 
76 #ifdef USE_AKONADI
77 using namespace KCalCore;
78 #else
79 using namespace KCal;
80 #endif
81 #ifdef USE_AKONADI
82 using namespace Akonadi;
83 #endif
84 
85 
86 #ifdef USE_AKONADI
87 ResourceSelector::ResourceSelector(QWidget* parent)
88 #else
89 ResourceSelector::ResourceSelector(AlarmResources* calendar, QWidget* parent)
90 #endif
91  : QFrame(parent),
92 #ifndef USE_AKONADI
93  mCalendar(calendar),
94 #endif
95  mContextMenu(0),
96  mActionReload(0),
97  mActionShowDetails(0),
98  mActionSetColour(0),
99  mActionClearColour(0),
100  mActionEdit(0),
101 #ifdef USE_AKONADI
102  mActionUpdate(0),
103 #else
104  mActionSave(0),
105 #endif
106  mActionRemove(0),
107  mActionImport(0),
108  mActionExport(0),
109  mActionSetDefault(0)
110 {
111  QBoxLayout* topLayout = new QVBoxLayout(this);
112  topLayout->setMargin(KDialog::spacingHint()); // use spacingHint for the margin
113 
114  QLabel* label = new QLabel(i18nc("@title:group", "Calendars"), this);
115  topLayout->addWidget(label, 0, Qt::AlignHCenter);
116 
117  mAlarmType = new KComboBox(this);
118  mAlarmType->addItem(i18nc("@item:inlistbox", "Active Alarms"));
119  mAlarmType->addItem(i18nc("@item:inlistbox", "Archived Alarms"));
120  mAlarmType->addItem(i18nc("@item:inlistbox", "Alarm Templates"));
121  mAlarmType->setFixedHeight(mAlarmType->sizeHint().height());
122  mAlarmType->setWhatsThis(i18nc("@info:whatsthis", "Choose which type of data to show alarm calendars for"));
123  topLayout->addWidget(mAlarmType);
124  // No spacing between combo box and listview.
125 
126 #ifdef USE_AKONADI
127  CollectionFilterCheckListModel* model = new CollectionFilterCheckListModel(this);
128  mListView = new CollectionView(model, this);
129 #else
130  ResourceModel* model = ResourceModel::instance();
131  ResourceFilterModel* filterModel = new ResourceFilterModel(model, this);
132  mListView = new ResourceView(this);
133  mListView->setModel(filterModel);
134 #endif
135  connect(mListView->selectionModel(), SIGNAL(selectionChanged(QItemSelection,QItemSelection)), SLOT(selectionChanged()));
136  mListView->setContextMenuPolicy(Qt::CustomContextMenu);
137  connect(mListView, SIGNAL(customContextMenuRequested(QPoint)), SLOT(contextMenuRequested(QPoint)));
138  mListView->setWhatsThis(i18nc("@info:whatsthis",
139  "List of available calendars of the selected type. The checked state shows whether a calendar "
140  "is enabled (checked) or disabled (unchecked). The default calendar is shown in bold."));
141  topLayout->addWidget(mListView, 1);
142  topLayout->addSpacing(KDialog::spacingHint());
143 
144  PackedLayout* blayout = new PackedLayout(Qt::AlignHCenter);
145  blayout->setMargin(0);
146  blayout->setSpacing(KDialog::spacingHint());
147  topLayout->addLayout(blayout);
148 
149  mAddButton = new QPushButton(i18nc("@action:button", "Add..."), this);
150  mEditButton = new QPushButton(i18nc("@action:button", "Edit..."), this);
151  mDeleteButton = new QPushButton(i18nc("@action:button", "Remove"), this);
152  blayout->addWidget(mAddButton);
153  blayout->addWidget(mEditButton);
154  blayout->addWidget(mDeleteButton);
155  mEditButton->setWhatsThis(i18nc("@info:whatsthis", "Edit the highlighted calendar"));
156  mDeleteButton->setWhatsThis(i18nc("@info:whatsthis", "<para>Remove the highlighted calendar from the list.</para>"
157  "<para>The calendar itself is left intact, and may subsequently be reinstated in the list if desired.</para>"));
158  mEditButton->setDisabled(true);
159  mDeleteButton->setDisabled(true);
160  connect(mAddButton, SIGNAL(clicked()), SLOT(addResource()));
161  connect(mEditButton, SIGNAL(clicked()), SLOT(editResource()));
162  connect(mDeleteButton, SIGNAL(clicked()), SLOT(removeResource()));
163 
164 #ifdef USE_AKONADI
165  connect(AkonadiModel::instance(), SIGNAL(collectionAdded(Akonadi::Collection)),
166  SLOT(slotCollectionAdded(Akonadi::Collection)));
167 #else
168  connect(mCalendar, SIGNAL(resourceStatusChanged(AlarmResource*,AlarmResources::Change)), SLOT(slotStatusChanged(AlarmResource*,AlarmResources::Change)));
169 #endif
170 
171  connect(mAlarmType, SIGNAL(activated(int)), SLOT(alarmTypeSelected()));
172  QTimer::singleShot(0, this, SLOT(alarmTypeSelected()));
173 
174  Preferences::connect(SIGNAL(archivedKeepDaysChanged(int)), this, SLOT(archiveDaysChanged(int)));
175 }
176 
177 /******************************************************************************
178 * Called when an alarm type has been selected.
179 * Filter the resource list to show resources of the selected alarm type, and
180 * add appropriate whatsThis texts to the list and to the Add button.
181 */
182 void ResourceSelector::alarmTypeSelected()
183 {
184  QString addTip;
185  switch (mAlarmType->currentIndex())
186  {
187  case 0:
188  mCurrentAlarmType = CalEvent::ACTIVE;
189  addTip = i18nc("@info:tooltip", "Add a new active alarm calendar");
190  break;
191  case 1:
192  mCurrentAlarmType = CalEvent::ARCHIVED;
193  addTip = i18nc("@info:tooltip", "Add a new archived alarm calendar");
194  break;
195  case 2:
196  mCurrentAlarmType = CalEvent::TEMPLATE;
197  addTip = i18nc("@info:tooltip", "Add a new alarm template calendar");
198  break;
199  }
200  // WORKAROUND: Switch scroll bars off to avoid crash (see explanation
201  // in reinstateAlarmTypeScrollBars() description).
202  mListView->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
203  mListView->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
204 #ifdef USE_AKONADI
205  mListView->collectionModel()->setEventTypeFilter(mCurrentAlarmType);
206 #else
207  static_cast<ResourceFilterModel*>(mListView->model())->setFilter(mCurrentAlarmType);
208 #endif
209  mAddButton->setWhatsThis(addTip);
210  mAddButton->setToolTip(addTip);
211  // WORKAROUND: Switch scroll bars back on after allowing geometry to update ...
212  QTimer::singleShot(0, this, SLOT(reinstateAlarmTypeScrollBars()));
213 
214 #ifdef USE_AKONADI
215  selectionChanged(); // enable/disable buttons
216 #endif
217 }
218 
219 /******************************************************************************
220 * WORKAROUND for crash due to presumed Qt bug.
221 * Switch scroll bars off. This is to avoid a crash which can very occasionally
222 * happen when changing from a list of calendars which requires vertical scroll
223 * bars, to a list whose text is very slightly wider but which doesn't require
224 * scroll bars at all. (The suspicion is that the width is such that it would
225 * require horizontal scroll bars if the vertical scroll bars were still
226 * present.) Presumably due to a Qt bug, this can result in a recursive call to
227 * ResourceView::viewportEvent() with a Resize event.
228 *
229 * The crash only occurs if the ResourceSelector happens to have exactly (within
230 * one pixel) the "right" width to create the crash.
231 */
232 void ResourceSelector::reinstateAlarmTypeScrollBars()
233 {
234  mListView->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded);
235  mListView->setHorizontalScrollBarPolicy(Qt::ScrollBarAsNeeded);
236 }
237 
238 /******************************************************************************
239 * Prompt the user for a new resource to add to the list.
240 */
241 void ResourceSelector::addResource()
242 {
243 #ifdef USE_AKONADI
244  AkonadiResourceCreator* creator = new AkonadiResourceCreator(mCurrentAlarmType, this);
245  connect(creator, SIGNAL(finished(AkonadiResourceCreator*,bool)),
246  SLOT(resourceAdded(AkonadiResourceCreator*,bool)));
247  creator->createResource();
248 #else
249  AlarmResourceManager* manager = mCalendar->resourceManager();
250  QStringList descs = manager->resourceTypeDescriptions();
251  bool ok = false;
252  QString desc = KInputDialog::getItem(i18nc("@title:window", "Calendar Configuration"),
253  i18nc("@info", "Select storage type of new calendar:"), descs, 0, false, &ok, this);
254  if (!ok || descs.isEmpty())
255  return;
256  QString type = manager->resourceTypeNames()[descs.indexOf(desc)];
257  AlarmResource* resource = dynamic_cast<AlarmResource*>(manager->createResource(type));
258  if (!resource)
259  {
260  KAMessageBox::error(this, i18nc("@info", "Unable to create calendar of type <resource>%1</resource>.", type));
261  return;
262  }
263  resource->setResourceName(i18nc("@info/plain", "%1 calendar", type));
264  resource->setAlarmType(mCurrentAlarmType);
265  resource->setActive(false); // prevent setReadOnly() declaring it as unwritable before we've tried to load it
266 
267  // Use AutoQPointer to guard against crash on application exit while
268  // the dialogue is still open. It prevents double deletion (both on
269  // deletion of ResourceSelector, and on return from this function).
270  AutoQPointer<ResourceConfigDialog> dlg = new ResourceConfigDialog(this, resource);
271  if (dlg->exec() == QDialog::Accepted)
272  {
273  resource->setEnabled(true);
274  resource->setTimeSpec(Preferences::timeZone());
275  manager->add(resource);
276  manager->writeConfig();
277  mCalendar->resourceAdded(resource); // load the resource and connect in-process change signals
278  }
279  else
280  {
281  delete resource;
282  resource = 0;
283  }
284 #endif
285 }
286 
287 #ifdef USE_AKONADI
288 /******************************************************************************
289 * Called when the job started by AkonadiModel::addCollection() has completed.
290 */
291 void ResourceSelector::resourceAdded(AkonadiResourceCreator* creator, bool success)
292 {
293  if (success)
294  {
295  AgentInstance agent = creator->agentInstance();
296  if (agent.isValid())
297  {
298  // Note that we're expecting the agent's Collection to be added
299  mAddAgents += agent;
300  }
301  }
302  delete creator;
303 }
304 
305 /******************************************************************************
306 * Called when a collection is added to the AkonadiModel.
307 */
308 void ResourceSelector::slotCollectionAdded(const Collection& collection)
309 {
310  if (collection.isValid())
311  {
312  AgentInstance agent = AgentManager::self()->instance(collection.resource());
313  if (agent.isValid())
314  {
315  int i = mAddAgents.indexOf(agent);
316  if (i >= 0)
317  {
318  // The collection belongs to an agent created by addResource()
319  CalEvent::Types types = CalEvent::types(collection.contentMimeTypes());
320  CollectionControlModel::setEnabled(collection, types, true);
321  if (!(types & mCurrentAlarmType))
322  {
323  // The user has selected alarm types for the resource
324  // which don't include the currently displayed type.
325  // Show a collection list which includes a selected type.
326  int index = -1;
327  if (types & CalEvent::ACTIVE)
328  index = 0;
329  else if (types & CalEvent::ARCHIVED)
330  index = 1;
331  else if (types & CalEvent::TEMPLATE)
332  index = 2;
333  if (index >= 0)
334  {
335  mAlarmType->setCurrentIndex(index);
336  alarmTypeSelected();
337  }
338  }
339  mAddAgents.removeAt(i);
340  }
341  }
342  }
343 }
344 #endif
345 
346 /******************************************************************************
347 * Edit the currently selected resource.
348 */
349 void ResourceSelector::editResource()
350 {
351 #ifdef USE_AKONADI
352  Collection collection = currentResource();
353  if (collection.isValid())
354  {
355  AgentInstance instance = AgentManager::self()->instance(collection.resource());
356  if (instance.isValid())
357  instance.configure(this);
358  }
359 #else
360  AlarmResource* resource = currentResource();
361  if (!resource)
362  return;
363  bool readOnly = resource->readOnly();
364  // Use AutoQPointer to guard against crash on application exit while
365  // the dialogue is still open. It prevents double deletion (both on
366  // deletion of ResourceSelector, and on return from this function).
367  AutoQPointer<ResourceConfigDialog> dlg = new ResourceConfigDialog(this, resource);
368  if (dlg->exec() == QDialog::Accepted)
369  {
370  // Act on any changed settings.
371  // Read-only is handled automatically by AlarmResource::setReadOnly().
372  if (!readOnly && resource->readOnly() && resource->standardResource())
373  {
374  // A standard resource is being made read-only.
375  if (resource->alarmType() == CalEvent::ACTIVE)
376  {
377  KAMessageBox::sorry(this, i18nc("@info", "You cannot make your default active alarm calendar read-only."));
378  resource->setReadOnly(false);
379  }
380  else if (resource->alarmType() == CalEvent::ARCHIVED && Preferences::archivedKeepDays())
381  {
382  // Only allow the archived alarms standard resource to be made read-only
383  // if we're not saving archived alarms.
384  KAMessageBox::sorry(this, i18nc("@info", "You cannot make your default archived alarm calendar "
385  "read-only while expired alarms are configured to be kept."));
386  resource->setReadOnly(false);
387  }
388  else if (KAMessageBox::warningContinueCancel(this, i18nc("@info", "Do you really want to make your default calendar read-only?"))
389  == KMessageBox::Cancel)
390  {
391  resource->setReadOnly(false);
392  }
393  }
394  }
395 #endif
396 }
397 
398 #ifdef USE_AKONADI
399 /******************************************************************************
400 * Update the backend storage format for the currently selected resource in the
401 * displayed list.
402 */
403 void ResourceSelector::updateResource()
404 {
405  Collection collection = currentResource();
406  if (!collection.isValid())
407  return;
408  AkonadiModel::instance()->refresh(collection); // update with latest data
409  CalendarMigrator::updateToCurrentFormat(collection, true, this);
410 }
411 #endif
412 
413 /******************************************************************************
414 * Remove the currently selected resource from the displayed list.
415 */
416 void ResourceSelector::removeResource()
417 {
418 #ifdef USE_AKONADI
419  Collection collection = currentResource();
420  if (!collection.isValid())
421  return;
422  QString name = collection.name();
423  // Check if it's the standard or only resource for at least one type.
424  CalEvent::Types allTypes = AkonadiModel::types(collection);
425  CalEvent::Types standardTypes = CollectionControlModel::standardTypes(collection, true);
426  CalEvent::Type currentType = currentResourceType();
427  CalEvent::Type stdType = (standardTypes & CalEvent::ACTIVE) ? CalEvent::ACTIVE
428  : (standardTypes & CalEvent::ARCHIVED) ? CalEvent::ARCHIVED
429  : CalEvent::EMPTY;
430 #else
431  AlarmResource* resource = currentResource();
432  if (!resource)
433  return;
434  QString name = resource->resourceName();
435  bool std = resource->standardResource();
436  // Check if it's the standard resource for its type.
437  CalEvent::Type stdType = std ? resource->alarmType() : CalEvent::EMPTY;
438 #endif
439  if (stdType == CalEvent::ACTIVE)
440  {
441  KAMessageBox::sorry(this, i18nc("@info", "You cannot remove your default active alarm calendar."));
442  return;
443  }
444  if (stdType == CalEvent::ARCHIVED && Preferences::archivedKeepDays())
445  {
446  // Only allow the archived alarms standard resource to be removed if
447  // we're not saving archived alarms.
448  KAMessageBox::sorry(this, i18nc("@info", "You cannot remove your default archived alarm calendar "
449  "while expired alarms are configured to be kept."));
450  return;
451  }
452 #ifdef USE_AKONADI
453  QString text;
454  if (standardTypes)
455  {
456  // It's a standard resource for at least one alarm type
457  if (allTypes != currentType)
458  {
459  // It also contains alarm types other than the currently displayed type
460  QString stdTypes = CollectionControlModel::typeListForDisplay(standardTypes);
461  QString otherTypes;
462  CalEvent::Types nonStandardTypes(allTypes & ~standardTypes);
463  if (nonStandardTypes != currentType)
464  otherTypes = i18nc("@info", "<para>It also contains:%1</para>", CollectionControlModel::typeListForDisplay(nonStandardTypes));
465  text = i18nc("@info", "<para><resource>%1</resource> is the default calendar for:%2</para>%3"
466  "<para>Do you really want to remove it from all calendar lists?</para>", name, stdTypes, otherTypes);
467  }
468  else
469  text = i18nc("@info", "Do you really want to remove your default calendar (<resource>%1</resource>) from the list?", name);
470  }
471  else if (allTypes != currentType)
472  text = i18nc("@info", "<para><resource>%1</resource> contains:%2</para><para>Do you really want to remove it from all calendar lists?</para>",
473  name, CollectionControlModel::typeListForDisplay(allTypes));
474  else
475  text = i18nc("@info", "Do you really want to remove the calendar <resource>%1</resource> from the list?", name);
476 #else
477  QString text = std ? i18nc("@info", "Do you really want to remove your default calendar (<resource>%1</resource>) from the list?", name)
478  : i18nc("@info", "Do you really want to remove the calendar <resource>%1</resource> from the list?", name);
479 #endif
480  if (KAMessageBox::warningContinueCancel(this, text, QString(), KStandardGuiItem::remove()) == KMessageBox::Cancel)
481  return;
482 
483 #ifdef USE_AKONADI
484  AkonadiModel::instance()->removeCollection(collection);
485 #else
486  // Remove resource from alarm and resource lists before deleting it, to avoid
487  // crashes when display updates occur immediately after it is deleted.
488  if (resource->alarmType() == CalEvent::TEMPLATE)
489  EventListModel::templates()->removeResource(resource);
490  else
491  EventListModel::alarms()->removeResource(resource);
492  ResourceModel::instance()->removeResource(resource);
493  AlarmResourceManager* manager = mCalendar->resourceManager();
494  manager->remove(resource);
495  manager->writeConfig();
496 #endif
497 }
498 
499 /******************************************************************************
500 * Called when the current selection changes, to enable/disable the
501 * Delete and Edit buttons accordingly.
502 */
503 void ResourceSelector::selectionChanged()
504 {
505  bool state = mListView->selectionModel()->selectedRows().count();
506  mDeleteButton->setEnabled(state);
507  mEditButton->setEnabled(state);
508 }
509 
510 /******************************************************************************
511 * Initialise the button and context menu actions.
512 */
513 void ResourceSelector::initActions(KActionCollection* actions)
514 {
515  mActionReload = new KAction(KIcon(QLatin1String("view-refresh")), i18nc("@action Reload calendar", "Re&load"), this);
516  actions->addAction(QLatin1String("resReload"), mActionReload);
517  connect(mActionReload, SIGNAL(triggered(bool)), SLOT(reloadResource()));
518 #ifndef USE_AKONADI
519  mActionSave = new KAction(KIcon(QLatin1String("document-save")), i18nc("@action", "&Save"), this);
520  actions->addAction(QLatin1String("resSave"), mActionSave);
521  connect(mActionSave, SIGNAL(triggered(bool)), SLOT(saveResource()));
522 #endif
523  mActionShowDetails = new KAction(KIcon(QLatin1String("help-about")), i18nc("@action", "Show &Details"), this);
524  actions->addAction(QLatin1String("resDetails"), mActionShowDetails);
525  connect(mActionShowDetails, SIGNAL(triggered(bool)), SLOT(showInfo()));
526  mActionSetColour = new KAction(KIcon(QLatin1String("color-picker")), i18nc("@action", "Set &Color..."), this);
527  actions->addAction(QLatin1String("resSetColour"), mActionSetColour);
528  connect(mActionSetColour, SIGNAL(triggered(bool)), SLOT(setColour()));
529  mActionClearColour = new KAction(i18nc("@action", "Clear C&olor"), this);
530  actions->addAction(QLatin1String("resClearColour"), mActionClearColour);
531  connect(mActionClearColour, SIGNAL(triggered(bool)), SLOT(clearColour()));
532  mActionEdit = new KAction(KIcon(QLatin1String("document-properties")), i18nc("@action", "&Edit..."), this);
533  actions->addAction(QLatin1String("resEdit"), mActionEdit);
534  connect(mActionEdit, SIGNAL(triggered(bool)), SLOT(editResource()));
535 #ifdef USE_AKONADI
536  mActionUpdate = new KAction(i18nc("@action", "&Update Calendar Format"), this);
537  actions->addAction(QLatin1String("resUpdate"), mActionUpdate);
538  connect(mActionUpdate, SIGNAL(triggered(bool)), SLOT(updateResource()));
539 #endif
540  mActionRemove = new KAction(KIcon(QLatin1String("edit-delete")), i18nc("@action", "&Remove"), this);
541  actions->addAction(QLatin1String("resRemove"), mActionRemove);
542  connect(mActionRemove, SIGNAL(triggered(bool)), SLOT(removeResource()));
543  mActionSetDefault = new KToggleAction(this);
544  actions->addAction(QLatin1String("resDefault"), mActionSetDefault);
545  connect(mActionSetDefault, SIGNAL(triggered(bool)), SLOT(setStandard()));
546  QAction* action = new KAction(KIcon(QLatin1String("document-new")), i18nc("@action", "&Add..."), this);
547  actions->addAction(QLatin1String("resAdd"), action);
548  connect(action, SIGNAL(triggered(bool)), SLOT(addResource()));
549  mActionImport = new KAction(i18nc("@action", "Im&port..."), this);
550  actions->addAction(QLatin1String("resImport"), mActionImport);
551  connect(mActionImport, SIGNAL(triggered(bool)), SLOT(importCalendar()));
552  mActionExport = new KAction(i18nc("@action", "E&xport..."), this);
553  actions->addAction(QLatin1String("resExport"), mActionExport);
554  connect(mActionExport, SIGNAL(triggered(bool)), SLOT(exportCalendar()));
555 }
556 
557 void ResourceSelector::setContextMenu(KMenu* menu)
558 {
559  mContextMenu = menu;
560 }
561 
562 /******************************************************************************
563 * Display the context menu for the selected calendar.
564 */
565 void ResourceSelector::contextMenuRequested(const QPoint& viewportPos)
566 {
567  if (!mContextMenu)
568  return;
569  bool active = false;
570  bool writable = false;
571 #ifdef USE_AKONADI
572  bool updatable = false;
573  Collection collection;
574 #else
575  AlarmResource* resource = 0;
576 #endif
577  if (mListView->selectionModel()->hasSelection())
578  {
579  QModelIndex index = mListView->indexAt(viewportPos);
580  if (index.isValid())
581 #ifdef USE_AKONADI
582  collection = mListView->collectionModel()->collection(index);
583 #else
584  resource = static_cast<ResourceFilterModel*>(mListView->model())->resource(index);
585 #endif
586  else
587  mListView->clearSelection();
588  }
589  CalEvent::Type type = currentResourceType();
590 #ifdef USE_AKONADI
591  bool haveCalendar = collection.isValid();
592 #else
593  bool haveCalendar = resource;
594 #endif
595  if (haveCalendar)
596  {
597 #ifdef USE_AKONADI
598  // Note: the CollectionControlModel functions call AkonadiModel::refresh(collection)
599  active = CollectionControlModel::isEnabled(collection, type);
600  KACalendar::Compat compatibility;
601  int rw = CollectionControlModel::isWritableEnabled(collection, type, compatibility);
602  writable = (rw > 0);
603  if (!rw
604  && (compatibility & ~KACalendar::Converted)
605  && !(compatibility & ~(KACalendar::Convertible | KACalendar::Converted)))
606  updatable = true; // the calendar format is convertible to the current KAlarm format
607  if (!(AkonadiModel::instance()->types(collection) & type))
608  type = CalEvent::EMPTY;
609 #else
610  active = resource->isEnabled();
611  type = resource->alarmType();
612  writable = resource->writable();
613 #endif
614  }
615  mActionReload->setEnabled(active);
616  mActionShowDetails->setEnabled(haveCalendar);
617  mActionSetColour->setEnabled(haveCalendar);
618  mActionClearColour->setEnabled(haveCalendar);
619 #ifdef USE_AKONADI
620  mActionClearColour->setVisible(AkonadiModel::instance()->backgroundColor(collection).isValid());
621 #else
622  mActionClearColour->setVisible(resource && resource->colour().isValid());
623  mActionSave->setEnabled(active && writable);
624 #endif
625  mActionEdit->setEnabled(haveCalendar);
626 #ifdef USE_AKONADI
627  mActionUpdate->setEnabled(updatable);
628 #endif
629  mActionRemove->setEnabled(haveCalendar);
630  mActionImport->setEnabled(active && writable);
631  mActionExport->setEnabled(active);
632  QString text;
633  switch (type)
634  {
635  case CalEvent::ACTIVE: text = i18nc("@action", "Use as &Default for Active Alarms"); break;
636  case CalEvent::ARCHIVED: text = i18nc("@action", "Use as &Default for Archived Alarms"); break;
637  case CalEvent::TEMPLATE: text = i18nc("@action", "Use as &Default for Alarm Templates"); break;
638  default: break;
639  }
640  mActionSetDefault->setText(text);
641 #ifdef USE_AKONADI
642  bool standard = CollectionControlModel::isStandard(collection, type);
643 #else
644  bool standard = (resource && resource == mCalendar->getStandardResource(static_cast<CalEvent::Type>(type)) && resource->standardResource());
645 #endif
646  mActionSetDefault->setChecked(active && writable && standard);
647  mActionSetDefault->setEnabled(active && writable);
648  mContextMenu->popup(mListView->viewport()->mapToGlobal(viewportPos));
649 }
650 
651 /******************************************************************************
652 * Called from the context menu to reload the selected resource.
653 */
654 void ResourceSelector::reloadResource()
655 {
656 #ifdef USE_AKONADI
657  Collection collection = currentResource();
658  if (collection.isValid())
659  AkonadiModel::instance()->reloadCollection(collection);
660 #else
661  AlarmResource* resource = currentResource();
662  if (resource)
663  AlarmCalendar::resources()->loadResource(resource, this);
664 #endif
665 }
666 
667 /******************************************************************************
668 * Called from the context menu to save the selected resource.
669 */
670 void ResourceSelector::saveResource()
671 {
672 #ifdef USE_AKONADI
673  // Save resource is not applicable to Akonadi
674 #else
675  AlarmResource* resource = currentResource();
676  if (resource)
677  resource->save();
678 #endif
679 }
680 
681 /******************************************************************************
682 * Called when the length of time archived alarms are to be stored changes.
683 * If expired alarms are now to be stored, set any single archived alarm
684 * resource to be the default.
685 */
686 void ResourceSelector::archiveDaysChanged(int days)
687 {
688  if (days)
689  {
690 #ifdef USE_AKONADI
691  if (!CollectionControlModel::getStandard(CalEvent::ARCHIVED).isValid())
692  {
693  Collection::List cols = CollectionControlModel::enabledCollections(CalEvent::ARCHIVED, true);
694  if (cols.count() == 1)
695  {
696  CollectionControlModel::setStandard(cols[0], CalEvent::ARCHIVED);
697  theApp()->purgeNewArchivedDefault(cols[0]);
698  }
699  }
700 #else
701  AlarmResources* resources = AlarmResources::instance();
702  AlarmResource* std = resources->getStandardResource(CalEvent::ARCHIVED);
703  if (std && !std->standardResource())
704  resources->setStandardResource(std);
705 #endif
706  }
707 }
708 
709 /******************************************************************************
710 * Called from the context menu to set the selected resource as the default
711 * for its alarm type. The resource is automatically made active.
712 */
713 void ResourceSelector::setStandard()
714 {
715 #ifdef USE_AKONADI
716  Collection collection = currentResource();
717  if (collection.isValid())
718  {
719  CalEvent::Type alarmType = currentResourceType();
720  bool standard = mActionSetDefault->isChecked();
721  if (standard)
722  CollectionControlModel::setEnabled(collection, alarmType, true);
723  CollectionControlModel::setStandard(collection, alarmType, standard);
724  if (alarmType == CalEvent::ARCHIVED)
725  theApp()->purgeNewArchivedDefault(collection);
726  }
727 #else
728  AlarmResource* resource = currentResource();
729  if (resource)
730  {
731  if (mActionSetDefault->isChecked())
732  {
733  resource->setEnabled(true);
734  mCalendar->setStandardResource(resource);
735  }
736  else
737  resource->setStandardResource(false);
738  }
739 #endif
740 }
741 
742 #ifndef USE_AKONADI
743 /******************************************************************************
744 * Called when a calendar status has changed.
745 */
746 void ResourceSelector::slotStatusChanged(AlarmResource* resource, AlarmResources::Change change)
747 {
748  if (change == AlarmResources::WrongType && resource->isWrongAlarmType())
749  {
750  QString text;
751  switch (resource->alarmType())
752  {
753  case CalEvent::ACTIVE:
754  text = i18nc("@info/plain", "It is not an active alarm calendar.");
755  break;
756  case CalEvent::ARCHIVED:
757  text = i18nc("@info/plain", "It is not an archived alarm calendar.");
758  break;
759  case CalEvent::TEMPLATE:
760  text = i18nc("@info/plain", "It is not an alarm template calendar.");
761  break;
762  default:
763  return;
764  }
765  KAMessageBox::sorry(this, i18nc("@info", "<para>Calendar <resource>%1</resource> has been disabled:</para><para>%2</para>", resource->resourceName(), text));
766  }
767 }
768 #endif
769 
770 /******************************************************************************
771 * Called from the context menu to merge alarms from an external calendar into
772 * the selected resource (if any).
773 */
774 void ResourceSelector::importCalendar()
775 {
776 #ifdef USE_AKONADI
777  Collection collection = currentResource();
778  AlarmCalendar::importAlarms(this, (collection.isValid() ? &collection : 0));
779 #else
780  AlarmCalendar::importAlarms(this, currentResource());
781 #endif
782 }
783 
784 /******************************************************************************
785 * Called from the context menu to copy the selected resource's alarms to an
786 * external calendar.
787 */
788 void ResourceSelector::exportCalendar()
789 {
790 #ifdef USE_AKONADI
791  Collection calendar = currentResource();
792  if (calendar.isValid())
793 #else
794  AlarmResource* calendar = currentResource();
795  if (calendar)
796 #endif
797  AlarmCalendar::exportAlarms(AlarmCalendar::resources()->events(calendar), this);
798 }
799 
800 /******************************************************************************
801 * Called from the context menu to set a colour for the selected resource.
802 */
803 void ResourceSelector::setColour()
804 {
805 #ifdef USE_AKONADI
806  Collection collection = currentResource();
807  if (collection.isValid())
808  {
809  QColor colour = AkonadiModel::instance()->backgroundColor(collection);
810  if (!colour.isValid())
811  colour = QApplication::palette().color(QPalette::Base);
812  if (KColorDialog::getColor(colour, QColor(), this) == KColorDialog::Accepted)
813  AkonadiModel::instance()->setBackgroundColor(collection, colour);
814  }
815 #else
816  AlarmResource* resource = currentResource();
817  if (resource)
818  {
819  QColor colour = resource->colour();
820  if (!colour.isValid())
821  colour = QApplication::palette().color(QPalette::Base);
822  if (KColorDialog::getColor(colour, QColor(), this) == KColorDialog::Accepted)
823  resource->setColour(colour);
824  }
825 #endif
826 }
827 
828 /******************************************************************************
829 * Called from the context menu to clear the display colour for the selected
830 * resource.
831 */
832 void ResourceSelector::clearColour()
833 {
834 #ifdef USE_AKONADI
835  Collection collection = currentResource();
836  if (collection.isValid())
837  AkonadiModel::instance()->setBackgroundColor(collection, QColor());
838 #else
839  AlarmResource* resource = currentResource();
840  if (resource)
841  resource->setColour(QColor());
842 #endif
843 }
844 
845 /******************************************************************************
846 * Called from the context menu to display information for the selected resource.
847 */
848 void ResourceSelector::showInfo()
849 {
850 #ifdef USE_AKONADI
851  Collection collection = currentResource();
852  if (collection.isValid())
853  {
854  const QString name = collection.displayName();
855  QString id = collection.resource(); // resource name
856  CalEvent::Type alarmType = currentResourceType();
857  QString calType = AgentManager::self()->instance(id).type().name();
858  QString storage = AkonadiModel::instance()->storageType(collection);
859  QString location = collection.remoteId();
860  KUrl url(location);
861  if (url.isLocalFile())
862  location = url.path();
863  CalEvent::Types altypes = AkonadiModel::instance()->types(collection);
864  QStringList alarmTypes;
865  if (altypes & CalEvent::ACTIVE)
866  alarmTypes << i18nc("@info/plain", "Active alarms");
867  if (altypes & CalEvent::ARCHIVED)
868  alarmTypes << i18nc("@info/plain", "Archived alarms");
869  if (altypes & CalEvent::TEMPLATE)
870  alarmTypes << i18nc("@info/plain", "Alarm templates");
871  QString alarmTypeString = alarmTypes.join(i18nc("@info/plain List separator", ", "));
872  KACalendar::Compat compat;
873  QString perms = AkonadiModel::readOnlyTooltip(collection);
874  if (perms.isEmpty())
875  perms = i18nc("@info/plain", "Read-write");
876  QString enabled = CollectionControlModel::isEnabled(collection, alarmType)
877  ? i18nc("@info/plain", "Enabled")
878  : i18nc("@info/plain", "Disabled");
879  QString std = CollectionControlModel::isStandard(collection, alarmType)
880  ? i18nc("@info/plain Parameter in 'Default calendar: Yes/No'", "Yes")
881  : i18nc("@info/plain Parameter in 'Default calendar: Yes/No'", "No");
882  QString text = i18nc("@info",
883  "<title>%1</title>"
884  "<para>ID: %2<nl/>"
885  "Calendar type: %3<nl/>"
886  "Contents: %4<nl/>"
887  "%5: <filename>%6</filename><nl/>"
888  "Permissions: %7<nl/>"
889  "Status: %8<nl/>"
890  "Default calendar: %9</para>",
891  name, id, calType, alarmTypeString, storage, location, perms, enabled, std);
892  // Display the collection information. Because the user requested
893  // the information, don't raise a KNotify event.
894  KAMessageBox::information(this, text, QString(), QString(), 0);
895  }
896 #else
897  AlarmResource* resource = currentResource();
898  if (resource)
899  {
900  // Display the collection information. Because the user requested
901  // the information, don't raise a KNotify event.
902  KAMessageBox::information(this, resource->infoText(), QString(), QString(), 0);
903  }
904 #endif
905 }
906 
907 /******************************************************************************
908 * Return the currently selected resource in the list.
909 */
910 #ifdef USE_AKONADI
911 Collection ResourceSelector::currentResource() const
912 {
913  return mListView->collection(mListView->selectionModel()->currentIndex());
914 }
915 #else
916 AlarmResource* ResourceSelector::currentResource() const
917 {
918  return mListView->resource(mListView->selectionModel()->currentIndex());
919 }
920 #endif
921 
922 /******************************************************************************
923 * Return the currently selected resource type.
924 */
925 CalEvent::Type ResourceSelector::currentResourceType() const
926 {
927  switch (mAlarmType->currentIndex())
928  {
929  case 0: return CalEvent::ACTIVE;
930  case 1: return CalEvent::ARCHIVED;
931  case 2: return CalEvent::TEMPLATE;
932  default: return CalEvent::EMPTY;
933  }
934 }
935 
936 void ResourceSelector::resizeEvent(QResizeEvent* re)
937 {
938  emit resized(re->oldSize(), re->size());
939 }
940 
941 // vim: et sw=4:
AkonadiResourceCreator::agentInstance
Akonadi::AgentInstance agentInstance() const
Definition: akonadiresourcecreator.h:43
calendarmigrator.h
CollectionControlModel::getStandard
static Akonadi::Collection getStandard(CalEvent::Type, bool useDefault=false)
Return the standard collection for a specified mime type.
Definition: collectionmodel.cpp:991
AkonadiModel::readOnlyTooltip
static QString readOnlyTooltip(const Akonadi::Collection &)
Return the read-only status tooltip for a collection.
Definition: akonadimodel.cpp:927
EventListModel::alarms
static EventListModel * alarms()
Definition: eventlistmodel.cpp:56
AlarmCalendar::importAlarms
static bool importAlarms(QWidget *, AlarmResource *=0)
Definition: alarmcalendar.cpp:875
ResourceSelector::resizeEvent
virtual void resizeEvent(QResizeEvent *)
Definition: resourceselector.cpp:936
CollectionControlModel::setStandard
static void setStandard(Akonadi::Collection &, CalEvent::Type, bool standard)
Set or clear a collection as the standard collection for a specified mime type.
Definition: collectionmodel.cpp:1064
CollectionControlModel::isWritableEnabled
static int isWritableEnabled(const Akonadi::Collection &, CalEvent::Type)
Return whether a collection is both enabled and fully writable for a given alarm type, i.e.
Definition: collectionmodel.cpp:966
ResourceModel::removeResource
void removeResource(AlarmResource *)
Definition: resourcemodelview.cpp:248
text
virtual QByteArray text(quint32 serialNumber) const =0
AlarmCalendar::loadResource
void loadResource(AlarmResource *, QWidget *parent)
Definition: alarmcalendar.cpp:536
AlarmCalendar::resources
static AlarmCalendar * resources()
Definition: alarmcalendar.h:130
QWidget
CalendarMigrator::updateToCurrentFormat
static void updateToCurrentFormat(const Akonadi::Collection &, bool ignoreKeepFormat, QWidget *parent)
Definition: calendarmigrator.cpp:367
KAMessageBox::error
static void error(QWidget *parent, const QString &text, const QString &caption=QString(), Options options=Options(Notify|WindowModal))
CollectionControlModel::isStandard
static bool isStandard(Akonadi::Collection &, CalEvent::Type)
Return whether a collection is the standard collection for a specified mime type. ...
Definition: collectionmodel.cpp:1016
AkonadiModel::refresh
bool refresh(Akonadi::Collection &) const
Refresh the specified collection instance with up to date data.
Definition: akonadimodel.cpp:1744
QPushButton
alarmcalendar.h
ResourceView
Definition: resourcemodelview.h:90
PreferencesBase::archivedKeepDays
static int archivedKeepDays()
Get Days to keep expired alarms.
Definition: kalarmconfig.h:926
AkonadiModel::storageType
QString storageType(const Akonadi::Collection &) const
Return the storage type (file/directory/URL etc.) for a collection.
Definition: akonadimodel.cpp:882
CollectionControlModel::isEnabled
static bool isEnabled(const Akonadi::Collection &, CalEvent::Type)
Return whether a collection is enabled (and valid).
Definition: collectionmodel.cpp:714
CollectionControlModel::typeListForDisplay
static QString typeListForDisplay(CalEvent::Types)
Return a bulleted list of alarm types for inclusion in an i18n message.
Definition: collectionmodel.cpp:944
kalarmapp.h
the KAlarm application object
ResourceConfigDialog
Definition: resourceconfigdialog.h:37
ResourceModel::instance
static ResourceModel * instance(QObject *parent=0)
Definition: resourcemodelview.cpp:43
packedlayout.h
autoqpointer.h
Preferences::timeZone
static KTimeZone timeZone(bool reload=false)
Definition: preferences.cpp:122
AkonadiModel::instance
static AkonadiModel * instance()
Definition: akonadimodel.cpp:83
resourcemodelview.h
eventlistmodel.h
CollectionControlModel::standardTypes
static CalEvent::Types standardTypes(const Akonadi::Collection &, bool useDefault=false)
Return the alarm type(s) for which a collection is the standard collection.
Definition: collectionmodel.cpp:1030
PackedLayout
messagebox.h
theApp
KAlarmApp * theApp()
Definition: kalarmapp.h:259
AkonadiModel::removeCollection
bool removeCollection(const Akonadi::Collection &)
Remove a collection from Akonadi.
Definition: akonadimodel.cpp:1045
AkonadiModel::reloadCollection
bool reloadCollection(const Akonadi::Collection &)
Reload a collection's data from Akonadi storage (not from the backend).
Definition: akonadimodel.cpp:1103
AutoQPointer
preferences.h
Preferences::connect
static void connect(const char *signal, const QObject *receiver, const char *member)
Definition: preferences.cpp:292
CollectionControlModel::enabledCollections
static Akonadi::Collection::List enabledCollections(CalEvent::Type, bool writable)
Return the enabled collections which contain a specified mime type.
Definition: collectionmodel.cpp:1227
EventListModel::templates
static EventListModel * templates()
Definition: eventlistmodel.cpp:69
ResourceSelector::ResourceSelector
ResourceSelector(AlarmResources *, QWidget *parent=0)
Definition: resourceselector.cpp:89
AkonadiModel::types
static CalEvent::Types types(const Akonadi::Collection &)
Definition: akonadimodel.cpp:1863
KAMessageBox::warningContinueCancel
static int warningContinueCancel(QWidget *parent, ButtonCode defaultButton, const QString &text, const QString &caption=QString(), const KGuiItem &buttonContinue=KStandardGuiItem::cont(), const QString &dontAskAgainName=QString())
KAMessageBox::sorry
static void sorry(QWidget *parent, const QString &text, const QString &caption=QString(), Options options=Options(Notify|WindowModal))
kalarm.h
QLabel
ResourceSelector::initActions
void initActions(KActionCollection *)
Definition: resourceselector.cpp:513
AkonadiModel::setBackgroundColor
void setBackgroundColor(Akonadi::Collection &, const QColor &)
Set the background color for a collection and its alarms.
Definition: akonadimodel.cpp:838
CollectionFilterCheckListModel
Definition: collectionmodel.h:113
KComboBox
akonadiresourcecreator.h
ResourceModel
Definition: resourcemodelview.h:39
ResourceFilterModel
Definition: resourcemodelview.h:71
EventListModel::removeResource
void removeResource(AlarmResource *)
Definition: eventlistmodel.cpp:641
AlarmCalendar::exportAlarms
static bool exportAlarms(const KAEvent::List &, QWidget *parent)
Definition: alarmcalendar.cpp:1077
CollectionView
Definition: collectionmodel.h:141
ResourceSelector::setContextMenu
void setContextMenu(KMenu *)
Definition: resourceselector.cpp:557
AkonadiModel::backgroundColor
QColor backgroundColor(Akonadi::Collection &) const
Get the background color for a collection and its alarms.
Definition: akonadimodel.cpp:849
QFrame
resourceconfigdialog.h
AkonadiResourceCreator::createResource
void createResource()
Definition: akonadiresourcecreator.cpp:53
AkonadiResourceCreator
Definition: akonadiresourcecreator.h:37
KAMessageBox::information
static void information(QWidget *parent, const QString &text, const QString &caption=QString(), const QString &dontShowAgainName=QString(), Options options=Options(Notify|WindowModal))
CollectionControlModel::setEnabled
static CalEvent::Types setEnabled(const Akonadi::Collection &, CalEvent::Types, bool enabled)
Enable or disable a collection (if it is valid) for specified alarm types.
Definition: collectionmodel.cpp:735
This file is part of the KDE documentation.
Documentation copyright © 1996-2014 The KDE developers.
Generated on Tue Oct 14 2014 22:59:10 by doxygen 1.8.7 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.

kalarm

Skip menu "kalarm"
  • Main Page
  • Namespace List
  • Namespace Members
  • Alphabetical List
  • Class List
  • Class Hierarchy
  • Class Members
  • File List
  • File Members

kdepim API Reference

Skip menu "kdepim API Reference"
  • akonadi_next
  • akregator
  • blogilo
  • calendarsupport
  • console
  •   kabcclient
  •   konsolekalendar
  • kaddressbook
  • kalarm
  •   lib
  • kdgantt2
  • kjots
  • kleopatra
  • kmail
  • knode
  • knotes
  • kontact
  • korgac
  • korganizer
  • ktimetracker
  • libkdepim
  • libkleo
  • libkpgp
  • mailcommon
  • messagelist
  • messageviewer

Search



Report problems with this website to our bug tracking system.
Contact the specific authors with questions and comments about the page contents.

KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal