• 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
resourcemodelview.cpp
Go to the documentation of this file.
1 /*
2  * resourcemodelview.cpp - model/view classes for alarm resource lists
3  * Program: kalarm
4  * Copyright © 2007-2011 by David Jarvie <djarvie@kde.org>
5  *
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.
10  *
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.
15  *
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.
19  */
20 
21 #include "kalarm.h"
22 
23 #include "messagebox.h"
24 #include "preferences.h"
25 #include "resourcemodelview.moc"
26 
27 #include <klocale.h>
28 #include <kcolorutils.h>
29 #include <kdebug.h>
30 
31 #include <QApplication>
32 #include <QToolTip>
33 #include <QMouseEvent>
34 #include <QKeyEvent>
35 #include <QHelpEvent>
36 #include <QTextLayout>
37 #include <QTextLine>
38 
39 
40 ResourceModel* ResourceModel::mInstance = 0;
41 
42 
43 ResourceModel* ResourceModel::instance(QObject* parent)
44 {
45  if (!mInstance)
46  mInstance = new ResourceModel(parent);
47  return mInstance;
48 }
49 
50 ResourceModel::ResourceModel(QObject* parent)
51  : QAbstractListModel(parent)
52 {
53  refresh();
54  AlarmResources* resources = AlarmResources::instance();
55  connect(resources, SIGNAL(signalResourceModified(AlarmResource*)), SLOT(updateResource(AlarmResource*)));
56  connect(resources, SIGNAL(standardResourceChange(CalEvent::Type)), SLOT(slotStandardChanged(CalEvent::Type)));
57  connect(resources, SIGNAL(resourceStatusChanged(AlarmResource*,AlarmResources::Change)), SLOT(slotStatusChanged(AlarmResource*,AlarmResources::Change)));
58  connect(resources, SIGNAL(resourceLoaded(AlarmResource*,bool)), SLOT(slotLoaded(AlarmResource*,bool)));
59 }
60 
61 int ResourceModel::rowCount(const QModelIndex& parent) const
62 {
63  if (parent.isValid())
64  return 0;
65  return mResources.count();
66 }
67 
68 QModelIndex ResourceModel::index(int row, int column, const QModelIndex& parent) const
69 {
70  if (parent.isValid() || row >= mResources.count())
71  return QModelIndex();
72  return createIndex(row, column, mResources[row]);
73 }
74 
75 QVariant ResourceModel::data(const QModelIndex& index, int role) const
76 {
77  if (!index.isValid())
78  return QVariant();
79  AlarmResource* resource = static_cast<AlarmResource*>(index.internalPointer());
80  if (!resource)
81  return QVariant();
82  switch (role)
83  {
84  case Qt::DisplayRole:
85  return resource->resourceName();
86  case Qt::CheckStateRole:
87  return resource->isEnabled() ? Qt::Checked : Qt::Unchecked;
88  case Qt::ForegroundRole:
89  {
90  QColor colour;
91  switch (resource->alarmType())
92  {
93  case CalEvent::ACTIVE: colour = KColorScheme(QPalette::Active).foreground(KColorScheme::NormalText).color(); break;
94  case CalEvent::ARCHIVED: colour = Preferences::archivedColour(); break;
95  case CalEvent::TEMPLATE: colour = KColorScheme(QPalette::Active).foreground(KColorScheme::LinkText).color(); break;
96  default: break;
97  }
98  if (colour.isValid())
99  return resource->readOnly() ? KColorUtils::lighten(colour, 0.25) : colour;
100  break;
101  }
102  case Qt::BackgroundRole:
103  if (resource->colour().isValid())
104  return resource->colour();
105  break;
106  case Qt::FontRole:
107  {
108  if (!resource->isEnabled() || !resource->standardResource())
109  break;
110  QFont font = mFont;
111  font.setBold(true);
112  return font;
113  }
114  case Qt::ToolTipRole:
115  {
116  QString name = '@' + resource->resourceName(); // insert markers for stripping out name
117  QString type = '@' + resource->displayType();
118  bool inactive = !resource->isActive();
119  QString disabled = resource->isWrongAlarmType() ? i18nc("@info/plain", "Disabled (wrong alarm type)") : i18nc("@info/plain", "Disabled");
120  QString readonly = i18nc("@info/plain", "Read-only");
121  if (inactive && resource->readOnly())
122  return i18nc("@info:tooltip",
123  "%1"
124  "<nl/>%2: <filename>%3</filename>"
125  "<nl/>%4, %5",
126  name, type, resource->displayLocation(), disabled, readonly);
127  if (inactive || resource->readOnly())
128  return i18nc("@info:tooltip",
129  "%1"
130  "<nl/>%2: <filename>%3</filename>"
131  "<nl/>%4",
132  name, type, resource->displayLocation(),
133  (inactive ? disabled : readonly));
134  return i18nc("@info:tooltip",
135  "%1"
136  "<nl/>%2: <filename>%3</filename>",
137  name, type, resource->displayLocation());
138  }
139  default:
140  break;
141  }
142  return QVariant();
143 }
144 
145 /******************************************************************************
146 * Set the font to use for all items, or the checked state of one item.
147 * The font must always be set at initialisation.
148 */
149 bool ResourceModel::setData(const QModelIndex& index, const QVariant& value, int role)
150 {
151  mErrorPrompt.clear();
152  if (role == Qt::FontRole)
153  {
154  // Set the font used in all views.
155  // This enables data(index, Qt::FontRole) to return bold when appropriate.
156  mFont = value.value<QFont>();
157  return true;
158  }
159  if (role != Qt::CheckStateRole || !index.isValid())
160  return false;
161  AlarmResource* resource = static_cast<AlarmResource*>(index.internalPointer());
162  if (!resource)
163  return false;
164  Qt::CheckState state = static_cast<Qt::CheckState>(value.toInt());
165  bool active = (state == Qt::Checked);
166  bool saveChange = false;
167  AlarmResources* resources = AlarmResources::instance();
168  if (active)
169  {
170  // Enable the resource
171  resource->setActive(true); // enable it now so that load() will work
172  saveChange = resources->load(resource);
173  resource->setActive(false); // reset so that setEnabled() will work
174  }
175  else
176  {
177  // Disable the resource
178  saveChange = resource->saveAndClose(); // close resource after it is saved
179  }
180  if (saveChange)
181  resource->setEnabled(active);
182  emit dataChanged(index, index);
183  return true;
184 }
185 
186 Qt::ItemFlags ResourceModel::flags(const QModelIndex&) const
187 {
188  return Qt::ItemIsSelectable | Qt::ItemIsEnabled | Qt::ItemIsUserCheckable;
189 }
190 
191 /******************************************************************************
192 * Return the resource referred to by an index.
193 */
194 AlarmResource* ResourceModel::resource(const QModelIndex& index) const
195 {
196  if (!index.isValid())
197  return 0;
198  return static_cast<AlarmResource*>(index.internalPointer());
199 }
200 
201 /******************************************************************************
202 * Emit a signal that a resource has changed.
203 */
204 void ResourceModel::notifyChange(const QModelIndex& index)
205 {
206  if (index.isValid())
207  emit dataChanged(index, index);
208 }
209 
210 /******************************************************************************
211 * Reload the resources list.
212 */
213 void ResourceModel::refresh()
214 {
215  // This would be better done by a reset(), but the signals are private to QAbstractItemModel
216  if (!mResources.isEmpty())
217  {
218  beginRemoveRows(QModelIndex(), 0, mResources.count() - 1);
219  mResources.clear();
220  endRemoveRows();
221  }
222  QList<AlarmResource*> newResources;
223  AlarmResourceManager* manager = AlarmResources::instance()->resourceManager();
224  for (AlarmResourceManager::Iterator it = manager->begin(); it != manager->end(); ++it)
225  newResources += *it;
226  if (!newResources.isEmpty())
227  {
228  beginInsertRows(QModelIndex(), 0, newResources.count() - 1);
229  mResources = newResources;
230  endInsertRows();
231  }
232 }
233 
234 /******************************************************************************
235 * Add the specified resource to the list.
236 */
237 void ResourceModel::addResource(AlarmResource* resource)
238 {
239  int row = mResources.count();
240  beginInsertRows(QModelIndex(), row, row);
241  mResources += resource;
242  endInsertRows();
243 }
244 
245 /******************************************************************************
246 * Delete the specified resource from the list.
247 */
248 void ResourceModel::removeResource(AlarmResource* resource)
249 {
250  int row = mResources.indexOf(resource);
251  if (row >= 0)
252  {
253  beginRemoveRows(QModelIndex(), row, row);
254  mResources.removeAt(row);
255  endRemoveRows();
256  }
257 }
258 
259 /******************************************************************************
260 * Called when the resource has been updated , to update the
261 * active status displayed for the resource item.
262 */
263 void ResourceModel::updateResource(AlarmResource* resource)
264 {
265  int row = mResources.indexOf(resource);
266  if (row >= 0)
267  {
268  QModelIndex ix = index(row, 0, QModelIndex());
269  emit dataChanged(ix, ix);
270  }
271 }
272 
273 /******************************************************************************
274 * Called when a different resource has been set as the standard resource.
275 */
276 void ResourceModel::slotStandardChanged(CalEvent::Type type)
277 {
278  for (int row = 0, end = mResources.count(); row < end; ++row)
279  {
280  if (mResources[row]->alarmType() == type)
281  {
282  QModelIndex ix = index(row, 0, QModelIndex());
283  emit dataChanged(ix, ix);
284  }
285  }
286 }
287 
288 /******************************************************************************
289 * Called when a resource has completed loading.
290 * Check in case its status has changed.
291 */
292 void ResourceModel::slotLoaded(AlarmResource* resource, bool active)
293 {
294  if (active)
295  updateResource(resource);
296 }
297 
298 /******************************************************************************
299 * Called when a resource status has changed, to update the list.
300 */
301 void ResourceModel::slotStatusChanged(AlarmResource* resource, AlarmResources::Change change)
302 {
303  switch (change)
304  {
305  case AlarmResources::Added:
306  addResource(resource);
307  break;
308  case AlarmResources::Enabled:
309  case AlarmResources::ReadOnly:
310  case AlarmResources::Colour:
311  updateResource(resource);
312  break;
313  default:
314  break;
315  }
316 }
317 
318 
319 /*=============================================================================
320 = Class: ResourceFilterModel
321 = Proxy model for filtering resource lists.
322 =============================================================================*/
323 
324 ResourceFilterModel::ResourceFilterModel(QAbstractItemModel* baseModel, QObject* parent)
325  : QSortFilterProxyModel(parent),
326  mResourceType(CalEvent::EMPTY)
327 {
328  setSourceModel(baseModel);
329 }
330 
331 void ResourceFilterModel::setFilter(CalEvent::Type type)
332 {
333  if (type != mResourceType)
334  {
335  mResourceType = type;
336  invalidateFilter();
337  }
338 }
339 
340 bool ResourceFilterModel::filterAcceptsRow(int sourceRow, const QModelIndex&) const
341 {
342  return static_cast<ResourceModel*>(sourceModel())->resource(sourceModel()->index(sourceRow, 0))->alarmType() == mResourceType;
343 }
344 
345 /******************************************************************************
346 * Return the resource referred to by an index.
347 */
348 AlarmResource* ResourceFilterModel::resource(int row) const
349 {
350  return static_cast<ResourceModel*>(sourceModel())->resource(mapToSource(index(row, 0)));
351 }
352 
353 AlarmResource* ResourceFilterModel::resource(const QModelIndex& index) const
354 {
355  return static_cast<ResourceModel*>(sourceModel())->resource(mapToSource(index));
356 }
357 
358 /******************************************************************************
359 * Emit a signal that a resource has changed.
360 */
361 void ResourceFilterModel::notifyChange(int row)
362 {
363  static_cast<ResourceModel*>(sourceModel())->notifyChange(mapToSource(index(row, 0)));
364 }
365 
366 void ResourceFilterModel::notifyChange(const QModelIndex& index)
367 {
368  static_cast<ResourceModel*>(sourceModel())->notifyChange(mapToSource(index));
369 }
370 
371 
372 /*=============================================================================
373 = Class: ResourceDelegate
374 = Model/view delegate for resource list.
375 =============================================================================*/
376 
377 /******************************************************************************
378 * Process a change of state of the checkbox for a resource.
379 */
380 bool ResourceDelegate::editorEvent(QEvent* event, QAbstractItemModel* model, const QStyleOptionViewItem& option, const QModelIndex& index)
381 {
382  if (!(model->flags(index) & Qt::ItemIsEnabled))
383  return false;
384  if (event->type() == QEvent::MouseButtonRelease
385  || event->type() == QEvent::MouseButtonDblClick)
386  {
387  const int textMargin = QApplication::style()->pixelMetric(QStyle::PM_FocusFrameHMargin) + 1;
388  QRect checkRect = QStyle::alignedRect(option.direction, Qt::AlignLeft | Qt::AlignVCenter,
389  check(option, option.rect, Qt::Checked).size(),
390  QRect(option.rect.x() + textMargin, option.rect.y(), option.rect.width(), option.rect.height()));
391  if (!checkRect.contains(static_cast<QMouseEvent*>(event)->pos()))
392  return false;
393  if (event->type() == QEvent::MouseButtonDblClick)
394  return true; // ignore double clicks
395  }
396  else if (event->type() == QEvent::KeyPress)
397  {
398  if (static_cast<QKeyEvent*>(event)->key() != Qt::Key_Space
399  && static_cast<QKeyEvent*>(event)->key() != Qt::Key_Select)
400  return false;
401  }
402  else
403  return false;
404 
405  QVariant value = index.data(Qt::CheckStateRole);
406  if (!value.isValid())
407  return false;
408  Qt::CheckState state = (static_cast<Qt::CheckState>(value.toInt()) == Qt::Checked ? Qt::Unchecked : Qt::Checked);
409  if (state == Qt::Unchecked)
410  {
411  // The resource is to be disabled.
412  // Check for eligibility.
413  AlarmResource* resource = static_cast<ResourceFilterModel*>(model)->resource(index);
414  if (!resource)
415  return false;
416  if (resource->standardResource())
417  {
418  // It's the standard resource for its type.
419  if (resource->alarmType() == CalEvent::ACTIVE)
420  {
421  KAMessageBox::sorry(static_cast<QWidget*>(parent()),
422  i18nc("@info", "You cannot disable your default active alarm calendar."));
423  return false;
424 
425  }
426  if (resource->alarmType() == CalEvent::ARCHIVED && Preferences::archivedKeepDays())
427  {
428  // Only allow the archived alarms standard resource to be disabled if
429  // we're not saving archived alarms.
430  KAMessageBox::sorry(static_cast<QWidget*>(parent()),
431  i18nc("@info", "You cannot disable your default archived alarm calendar "
432  "while expired alarms are configured to be kept."));
433  return false;
434  }
435  if (KAMessageBox::warningContinueCancel(static_cast<QWidget*>(parent()),
436  i18nc("@info", "Do you really want to disable your default calendar?"))
437  == KMessageBox::Cancel)
438  return false;
439  }
440  }
441  return model->setData(index, state, Qt::CheckStateRole);
442 }
443 
444 
445 /*=============================================================================
446 = Class: ResourceView
447 = View displaying a list of resources.
448 =============================================================================*/
449 
450 void ResourceView::setModel(QAbstractItemModel* model)
451 {
452  model->setData(QModelIndex(), viewOptions().font, Qt::FontRole);
453  QListView::setModel(model);
454  setItemDelegate(new ResourceDelegate(this));
455 }
456 
457 /******************************************************************************
458 * Return the resource for a given row.
459 */
460 AlarmResource* ResourceView::resource(int row) const
461 {
462  return static_cast<ResourceFilterModel*>(model())->resource(row);
463 }
464 
465 AlarmResource* ResourceView::resource(const QModelIndex& index) const
466 {
467  return static_cast<ResourceFilterModel*>(model())->resource(index);
468 }
469 
470 /******************************************************************************
471 * Emit a signal that a resource has changed.
472 */
473 void ResourceView::notifyChange(int row) const
474 {
475  static_cast<ResourceFilterModel*>(model())->notifyChange(row);
476 }
477 
478 void ResourceView::notifyChange(const QModelIndex& index) const
479 {
480  static_cast<ResourceFilterModel*>(model())->notifyChange(index);
481 }
482 
483 /******************************************************************************
484 * Called when a mouse button is released.
485 * Any currently selected resource is deselected.
486 */
487 void ResourceView::mouseReleaseEvent(QMouseEvent* e)
488 {
489  if (!indexAt(e->pos()).isValid())
490  clearSelection();
491  QListView::mouseReleaseEvent(e);
492 }
493 
494 /******************************************************************************
495 * Called when a ToolTip or WhatsThis event occurs.
496 */
497 bool ResourceView::viewportEvent(QEvent* e)
498 {
499  if (e->type() == QEvent::ToolTip && isActiveWindow())
500  {
501  QHelpEvent* he = static_cast<QHelpEvent*>(e);
502  QModelIndex index = indexAt(he->pos());
503  QVariant value = model()->data(index, Qt::ToolTipRole);
504  if (qVariantCanConvert<QString>(value))
505  {
506  QString toolTip = value.toString();
507  int i = toolTip.indexOf('@');
508  if (i > 0)
509  {
510  int j = toolTip.indexOf(QRegExp("<(nl|br)", Qt::CaseInsensitive), i + 1);
511  int k = toolTip.indexOf('@', j);
512  QString name = toolTip.mid(i + 1, j - i - 1);
513  value = model()->data(index, Qt::FontRole);
514  QFontMetrics fm(qvariant_cast<QFont>(value).resolve(viewOptions().font));
515  int textWidth = fm.boundingRect(name).width() + 1;
516  const int margin = QApplication::style()->pixelMetric(QStyle::PM_FocusFrameHMargin) + 1;
517  QStyleOptionButton opt;
518  opt.QStyleOption::operator=(viewOptions());
519  opt.rect = rectForIndex(index);
520  int checkWidth = QApplication::style()->subElementRect(QStyle::SE_ViewItemCheckIndicator, &opt).width();
521  int left = spacing() + 3*margin + checkWidth + viewOptions().decorationSize.width(); // left offset of text
522  int right = left + textWidth;
523  if (left >= horizontalOffset() + spacing()
524  && right <= horizontalOffset() + width() - spacing() - 2*frameWidth())
525  {
526  // The whole of the resource name is already displayed,
527  // so omit it from the tooltip.
528  if (k > 0)
529  toolTip.remove(i, k + 1 - i);
530  }
531  else
532  {
533  toolTip.remove(k, 1);
534  toolTip.remove(i, 1);
535  }
536  }
537  QToolTip::showText(he->globalPos(), toolTip, this);
538  return true;
539  }
540  }
541  return QListView::viewportEvent(e);
542 }
543 
544 // vim: et sw=4:
ResourceDelegate::editorEvent
virtual bool editorEvent(QEvent *, QAbstractItemModel *, const QStyleOptionViewItem &, const QModelIndex &)
Definition: resourcemodelview.cpp:380
ResourceModel::rowCount
virtual int rowCount(const QModelIndex &parent=QModelIndex()) const
Definition: resourcemodelview.cpp:61
ResourceModel::data
virtual QVariant data(const QModelIndex &, int role=Qt::DisplayRole) const
Definition: resourcemodelview.cpp:75
ResourceModel::removeResource
void removeResource(AlarmResource *)
Definition: resourcemodelview.cpp:248
ResourceView::mouseReleaseEvent
virtual void mouseReleaseEvent(QMouseEvent *)
Definition: resourcemodelview.cpp:487
ResourceFilterModel::setFilter
void setFilter(CalEvent::Type)
Definition: resourcemodelview.cpp:331
QAbstractListModel
ResourceModel::setData
virtual bool setData(const QModelIndex &, const QVariant &value, int role=Qt::EditRole)
Definition: resourcemodelview.cpp:149
QObject
PreferencesBase::archivedKeepDays
static int archivedKeepDays()
Get Days to keep expired alarms.
Definition: kalarmconfig.h:926
ResourceModel::flags
virtual Qt::ItemFlags flags(const QModelIndex &) const
Definition: resourcemodelview.cpp:186
ResourceView::viewportEvent
virtual bool viewportEvent(QEvent *)
Definition: resourcemodelview.cpp:497
ResourceFilterModel::resource
AlarmResource * resource(int row) const
Definition: resourcemodelview.cpp:348
ResourceModel::instance
static ResourceModel * instance(QObject *parent=0)
Definition: resourcemodelview.cpp:43
ResourceModel::resource
AlarmResource * resource(const QModelIndex &) const
Definition: resourcemodelview.cpp:194
ResourceFilterModel::ResourceFilterModel
ResourceFilterModel(QAbstractItemModel *baseModel, QObject *parent)
Definition: resourcemodelview.cpp:324
ResourceView::notifyChange
void notifyChange(int row) const
Definition: resourcemodelview.cpp:473
messagebox.h
preferences.h
QSortFilterProxyModel
PreferencesBase::archivedColour
static QColor archivedColour()
Get Archived alarm color.
Definition: kalarmconfig.h:892
ResourceModel::notifyChange
void notifyChange(const QModelIndex &)
Definition: resourcemodelview.cpp:204
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))
ResourceView::resource
AlarmResource * resource(int row) const
Definition: resourcemodelview.cpp:460
kalarm.h
ResourceModel::index
virtual QModelIndex index(int row, int column, const QModelIndex &parent) const
Definition: resourcemodelview.cpp:68
ResourceModel
Definition: resourcemodelview.h:39
ResourceFilterModel
Definition: resourcemodelview.h:71
ResourceFilterModel::filterAcceptsRow
virtual bool filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const
Definition: resourcemodelview.cpp:340
ResourceView::setModel
virtual void setModel(QAbstractItemModel *)
Definition: resourcemodelview.cpp:450
ResourceFilterModel::notifyChange
void notifyChange(int row)
Definition: resourcemodelview.cpp:361
QList< AlarmResource * >
ResourceDelegate
Definition: resourcemodelview.h:107
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