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

kalarm

resourcemodelview.cpp

Go to the documentation of this file.
00001 /*
00002  *  resourcemodelview.cpp  -  model/view classes for alarm resource lists
00003  *  Program:  kalarm
00004  *  Copyright © 2007,2008 by David Jarvie <djarvie@kde.org>
00005  *
00006  *  This program is free software; you can redistribute it and/or modify
00007  *  it under the terms of the GNU General Public License as published by
00008  *  the Free Software Foundation; either version 2 of the License, or
00009  *  (at your option) any later version.
00010  *
00011  *  This program is distributed in the hope that it will be useful,
00012  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
00014  *  GNU General Public License for more details.
00015  *
00016  *  You should have received a copy of the GNU General Public License along
00017  *  with this program; if not, write to the Free Software Foundation, Inc.,
00018  *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00019  */
00020 
00021 #include "kalarm.h"
00022 
00023 #include <QApplication>
00024 #include <QToolTip>
00025 #include <QMouseEvent>
00026 #include <QKeyEvent>
00027 #include <QHelpEvent>
00028 #include <QTextLayout>
00029 #include <QTextLine>
00030 
00031 #include <klocale.h>
00032 #include <kmessagebox.h>
00033 #include <kdebug.h>
00034 
00035 #include "preferences.h"
00036 #include "resourcemodelview.moc"
00037 
00038 
00039 ResourceModel* ResourceModel::mInstance = 0;
00040 
00041 
00042 ResourceModel* ResourceModel::instance(QObject* parent)
00043 {
00044     if (!mInstance)
00045         mInstance = new ResourceModel(parent);
00046     return mInstance;
00047 }
00048 
00049 ResourceModel::ResourceModel(QObject* parent)
00050     : QAbstractListModel(parent)
00051 {
00052     refresh();
00053     AlarmResources* resources = AlarmResources::instance();
00054     connect(resources, SIGNAL(signalResourceModified(AlarmResource*)), SLOT(updateResource(AlarmResource*)));
00055     connect(resources, SIGNAL(standardResourceChange(AlarmResource::Type)), SLOT(slotStandardChanged(AlarmResource::Type)));
00056     connect(resources, SIGNAL(resourceStatusChanged(AlarmResource*, AlarmResources::Change)), SLOT(slotStatusChanged(AlarmResource*, AlarmResources::Change)));
00057     connect(resources, SIGNAL(resourceLoaded(AlarmResource*, bool)), SLOT(slotLoaded(AlarmResource*, bool)));
00058 }
00059 
00060 int ResourceModel::rowCount(const QModelIndex& parent) const
00061 {
00062     if (parent.isValid())
00063         return 0;
00064     return mResources.count();
00065 }
00066 
00067 QModelIndex ResourceModel::index(int row, int column, const QModelIndex& parent) const
00068 {
00069     if (parent.isValid()  ||  row >= mResources.count())
00070         return QModelIndex();
00071     return createIndex(row, column, mResources[row]);
00072 }
00073 
00074 QVariant ResourceModel::data(const QModelIndex& index, int role) const
00075 {
00076     if (!index.isValid())
00077         return QVariant();
00078     AlarmResource* resource = static_cast<AlarmResource*>(index.internalPointer());
00079     if (!resource)
00080         return QVariant();
00081     switch (role)
00082     {
00083         case Qt::DisplayRole:
00084             return resource->resourceName();
00085         case Qt::CheckStateRole:
00086             return resource->isEnabled() ? Qt::Checked : Qt::Unchecked;
00087         case Qt::DecorationRole:
00088             if (!resource->colour().isValid())
00089                 return QApplication::palette().color(QPalette::Base);
00090             return resource->colour();
00091         case Qt::ForegroundRole:
00092             switch (resource->alarmType())
00093             {
00094                 case AlarmResource::ACTIVE:    return resource->readOnly() ? Qt::darkGray : Qt::black;
00095                 case AlarmResource::ARCHIVED:  return resource->readOnly() ? Qt::green : Qt::darkGreen;
00096                 case AlarmResource::TEMPLATE:  return resource->readOnly() ? Qt::blue : Qt::darkBlue;
00097                 default:  break;
00098             }
00099             break;
00100         case Qt::FontRole:
00101         {
00102             if (!resource->isEnabled()  ||  !resource->standardResource())
00103                 break;
00104             QFont font = mFont;
00105             font.setBold(true);
00106             return font;
00107         }
00108         case Qt::ToolTipRole:
00109         {
00110             QString name = '@' + resource->resourceName();   // insert markers for stripping out name
00111             QString type = '@' + resource->displayType();
00112             bool inactive = !resource->isActive();
00113             QString disabled = i18nc("@info/plain", "Disabled");
00114             QString readonly = i18nc("@info/plain", "Read-only");
00115             if (inactive  &&  resource->readOnly())
00116                 return i18nc("@info:tooltip",
00117                              "%1"
00118                              "<nl/>%2: <filename>%3</filename>"
00119                              "<nl/>%4, %5",
00120                              name, type, resource->displayLocation(), disabled, readonly);
00121             if (inactive  ||  resource->readOnly())
00122                 return i18nc("@info:tooltip",
00123                              "%1"
00124                              "<nl/>%2: <filename>%3</filename>"
00125                              "<nl/>%4",
00126                              name, type, resource->displayLocation(),
00127                              (inactive ? disabled : readonly));
00128             return i18nc("@info:tooltip",
00129                          "%1"
00130                          "<nl/>%2: <filename>%3</filename>",
00131                          name, type, resource->displayLocation());
00132         }
00133         default:
00134             break;
00135     }
00136     return QVariant();
00137 }
00138 
00139 /******************************************************************************
00140 * Set the font to use for all items, or the checked state of one item.
00141 * The font must always be set at initialisation.
00142 */
00143 bool ResourceModel::setData(const QModelIndex& index, const QVariant& value, int role)
00144 {
00145     mErrorPrompt.clear();
00146     if (role == Qt::FontRole)
00147     {
00148         // Set the font used in all views.
00149         // This enables data(index, Qt::FontRole) to return bold when appropriate.
00150         mFont = value.value<QFont>();
00151         return true;
00152     }
00153     if (role != Qt::CheckStateRole  ||  !index.isValid())
00154         return false;
00155     AlarmResource* resource = static_cast<AlarmResource*>(index.internalPointer());
00156     if (!resource)
00157         return false;
00158     Qt::CheckState state = static_cast<Qt::CheckState>(value.toInt());
00159     bool active = (state == Qt::Checked);
00160     bool saveChange = false;
00161     AlarmResources* resources = AlarmResources::instance();
00162     if (active)
00163     {
00164         // Enable the resource
00165         resource->setActive(true);     // enable it now so that load() will work
00166         saveChange = resources->load(resource);
00167         resource->setActive(false);    // reset so that setEnabled() will work
00168     }
00169     else
00170     {
00171         // Disable the resource
00172         saveChange = resource->saveAndClose();   // close resource after it is saved
00173     }
00174     if (saveChange)
00175         resource->setEnabled(active);
00176     emit dataChanged(index, index);
00177     return true;
00178 }
00179 
00180 Qt::ItemFlags ResourceModel::flags(const QModelIndex&) const
00181 {
00182     return Qt::ItemIsSelectable | Qt::ItemIsEnabled | Qt::ItemIsUserCheckable;
00183 }
00184 
00185 /******************************************************************************
00186 * Return the resource referred to by an index.
00187 */
00188 AlarmResource* ResourceModel::resource(const QModelIndex& index) const
00189 {
00190     if (!index.isValid())
00191         return 0;
00192     return static_cast<AlarmResource*>(index.internalPointer());
00193 }
00194 
00195 /******************************************************************************
00196 * Emit a signal that a resource has changed.
00197 */
00198 void ResourceModel::notifyChange(const QModelIndex& index)
00199 {
00200     if (index.isValid())
00201         emit dataChanged(index, index);
00202 }
00203 
00204 /******************************************************************************
00205 * Reload the resources list.
00206 */
00207 void ResourceModel::refresh()
00208 {
00209     // This would be better done by a reset(), but the signals are private to QAbstractItemModel
00210     if (!mResources.isEmpty())
00211     {
00212         beginRemoveRows(QModelIndex(), 0, mResources.count() - 1);
00213         mResources.clear();
00214         endRemoveRows();
00215     }
00216     QList<AlarmResource*> newResources;
00217     AlarmResourceManager* manager = AlarmResources::instance()->resourceManager();
00218     for (AlarmResourceManager::Iterator it = manager->begin();  it != manager->end();  ++it)
00219         newResources += *it;
00220     if (!newResources.isEmpty())
00221     {
00222         beginInsertRows(QModelIndex(), 0, newResources.count() - 1);
00223         mResources = newResources;
00224         endInsertRows();
00225     }
00226 }
00227 
00228 /******************************************************************************
00229 * Add the specified resource to the list.
00230 */
00231 void ResourceModel::addResource(AlarmResource* resource)
00232 {
00233     int row = mResources.count();
00234     beginInsertRows(QModelIndex(), row, row);
00235     mResources += resource;
00236     endInsertRows();
00237 }
00238 
00239 /******************************************************************************
00240 * Delete the specified resource from the list.
00241 */
00242 void ResourceModel::removeResource(AlarmResource* resource)
00243 {
00244     int row = mResources.indexOf(resource);
00245     if (row >= 0)
00246     {
00247         beginRemoveRows(QModelIndex(), row, row);
00248         mResources.removeAt(row);
00249         endRemoveRows();
00250     }
00251 }
00252 
00253 /******************************************************************************
00254 * Called when the resource has been updated , to update the
00255 * active status displayed for the resource item.
00256 */
00257 void ResourceModel::updateResource(AlarmResource* resource)
00258 {
00259     int row = mResources.indexOf(resource);
00260     if (row >= 0)
00261     {
00262         QModelIndex ix = index(row, 0, QModelIndex());
00263         emit dataChanged(ix, ix);
00264     }
00265 }
00266 
00267 /******************************************************************************
00268 * Called when a different resource has been set as the standard resource.
00269 */
00270 void ResourceModel::slotStandardChanged(AlarmResource::Type type)
00271 {
00272     for (int row = 0, end = mResources.count();  row < end;  ++row)
00273     {
00274         if (mResources[row]->alarmType() == type)
00275         {
00276             QModelIndex ix = index(row, 0, QModelIndex());
00277             emit dataChanged(ix, ix);
00278         }
00279     }
00280 }
00281 
00282 /******************************************************************************
00283 * Called when a resource has completed loading.
00284 * Check in case its status has changed.
00285 */
00286 void ResourceModel::slotLoaded(AlarmResource* resource, bool active)
00287 {
00288     if (active)
00289         updateResource(resource);
00290 }
00291 
00292 /******************************************************************************
00293 * Called when a resource status has changed, to update the list.
00294 */
00295 void ResourceModel::slotStatusChanged(AlarmResource* resource, AlarmResources::Change change)
00296 {
00297     switch (change)
00298     {
00299         case AlarmResources::Added:
00300             addResource(resource);
00301             break;
00302         case AlarmResources::Enabled:
00303         case AlarmResources::ReadOnly:
00304         case AlarmResources::Colour:
00305             updateResource(resource);
00306             break;
00307         default:
00308             break;
00309     }
00310 }
00311 
00312 
00313 /*=============================================================================
00314 = Class: ResourceFilterModel
00315 = Proxy model for filtering resource lists.
00316 =============================================================================*/
00317 
00318 ResourceFilterModel::ResourceFilterModel(QAbstractItemModel* baseModel, QObject* parent)
00319     : QSortFilterProxyModel(parent),
00320       mResourceType(AlarmResource::INVALID)
00321 {
00322     setSourceModel(baseModel);
00323 }
00324 
00325 void ResourceFilterModel::setFilter(AlarmResource::Type type)
00326 {
00327     if (type != mResourceType)
00328     {
00329         mResourceType = type;
00330         filterChanged();
00331     }
00332 }
00333 
00334 bool ResourceFilterModel::filterAcceptsRow(int sourceRow, const QModelIndex&) const
00335 {
00336     return static_cast<ResourceModel*>(sourceModel())->resource(sourceModel()->index(sourceRow, 0))->alarmType() == mResourceType;
00337 }
00338 
00339 /******************************************************************************
00340 * Return the resource referred to by an index.
00341 */
00342 AlarmResource* ResourceFilterModel::resource(int row) const
00343 {
00344     return static_cast<ResourceModel*>(sourceModel())->resource(mapToSource(index(row, 0)));
00345 }
00346 
00347 AlarmResource* ResourceFilterModel::resource(const QModelIndex& index) const
00348 {
00349     return static_cast<ResourceModel*>(sourceModel())->resource(mapToSource(index));
00350 }
00351 
00352 /******************************************************************************
00353 * Emit a signal that a resource has changed.
00354 */
00355 void ResourceFilterModel::notifyChange(int row)
00356 {
00357     static_cast<ResourceModel*>(sourceModel())->notifyChange(mapToSource(index(row, 0)));
00358 }
00359 
00360 void ResourceFilterModel::notifyChange(const QModelIndex& index)
00361 {
00362     static_cast<ResourceModel*>(sourceModel())->notifyChange(mapToSource(index));
00363 }
00364 
00365 
00366 /*=============================================================================
00367 = Class: ResourceDelegate
00368 = Model/view delegate for resource list.
00369 =============================================================================*/
00370 
00371 /******************************************************************************
00372 * Process a change of state of the checkbox for a resource.
00373 */
00374 bool ResourceDelegate::editorEvent(QEvent* event, QAbstractItemModel* model, const QStyleOptionViewItem& option, const QModelIndex& index)
00375 {
00376     if (!(model->flags(index) & Qt::ItemIsEnabled))
00377         return false;
00378     if (event->type() == QEvent::MouseButtonRelease
00379     ||  event->type() == QEvent::MouseButtonDblClick)
00380     {
00381         const int textMargin = QApplication::style()->pixelMetric(QStyle::PM_FocusFrameHMargin) + 1;
00382         QRect checkRect = QStyle::alignedRect(option.direction, Qt::AlignLeft | Qt::AlignVCenter,
00383                                               check(option, option.rect, Qt::Checked).size(),
00384                                               QRect(option.rect.x() + textMargin, option.rect.y(), option.rect.width(), option.rect.height()));
00385         if (!checkRect.contains(static_cast<QMouseEvent*>(event)->pos()))
00386             return false;
00387         if (event->type() == QEvent::MouseButtonDblClick)
00388             return true;    // ignore double clicks
00389     }
00390     else if (event->type() == QEvent::KeyPress)
00391     {
00392         if (static_cast<QKeyEvent*>(event)->key() != Qt::Key_Space
00393         &&  static_cast<QKeyEvent*>(event)->key() != Qt::Key_Select)
00394             return false;
00395     }
00396     else
00397         return false;
00398 
00399     QVariant value = index.data(Qt::CheckStateRole);
00400     if (!value.isValid())
00401         return false;
00402     Qt::CheckState state = (static_cast<Qt::CheckState>(value.toInt()) == Qt::Checked ? Qt::Unchecked : Qt::Checked);
00403     if (state == Qt::Unchecked)
00404     {
00405         // The resource is to be disabled.
00406         // Check for eligibility.
00407         AlarmResource* resource = static_cast<ResourceFilterModel*>(model)->resource(index);
00408         if (!resource)
00409             return false;
00410         if (resource->standardResource())
00411         {
00412             // It's the standard resource for its type.
00413             if (resource->alarmType() == AlarmResource::ACTIVE)
00414             {
00415                 KMessageBox::sorry(static_cast<QWidget*>(parent()),
00416                                    i18nc("@info", "You cannot disable your default active alarm resource."));
00417                 return false;
00418 
00419             }
00420             if (resource->alarmType() == AlarmResource::ARCHIVED  &&  Preferences::archivedKeepDays())
00421             {
00422                 // Only allow the archived alarms standard resource to be disabled if
00423                 // we're not saving archived alarms.
00424                 KMessageBox::sorry(static_cast<QWidget*>(parent()),
00425                                    i18nc("@info", "You cannot disable your default archived alarm resource "
00426                                         "while expired alarms are configured to be kept."));
00427                 return false;
00428             }
00429             if (KMessageBox::warningContinueCancel(static_cast<QWidget*>(parent()),
00430                                                    i18nc("@info", "Do you really want to disable your default resource?"))
00431                        == KMessageBox::Cancel)
00432                 return false;
00433         }
00434     }
00435     return model->setData(index, state, Qt::CheckStateRole);
00436 }
00437 
00438 
00439 /*=============================================================================
00440 = Class: ResourceView
00441 = View displaying a list of resources.
00442 =============================================================================*/
00443 
00444 void ResourceView::setModel(QAbstractItemModel* model)
00445 {
00446     model->setData(QModelIndex(), viewOptions().font, Qt::FontRole);
00447     QListView::setModel(model);
00448 }
00449 
00450 /******************************************************************************
00451 * Return the resource for a given row.
00452 */
00453 AlarmResource* ResourceView::resource(int row) const
00454 {
00455     return static_cast<ResourceFilterModel*>(model())->resource(row);
00456 }
00457 
00458 AlarmResource* ResourceView::resource(const QModelIndex& index) const
00459 {
00460     return static_cast<ResourceFilterModel*>(model())->resource(index);
00461 }
00462 
00463 /******************************************************************************
00464 * Emit a signal that a resource has changed.
00465 */
00466 void ResourceView::notifyChange(int row) const
00467 {
00468     static_cast<ResourceFilterModel*>(model())->notifyChange(row);
00469 }
00470 
00471 void ResourceView::notifyChange(const QModelIndex& index) const
00472 {
00473     static_cast<ResourceFilterModel*>(model())->notifyChange(index);
00474 }
00475 
00476 /******************************************************************************
00477 * Called when a mouse button is released.
00478 * Any currently selected resource is deselected.
00479 */
00480 void ResourceView::mouseReleaseEvent(QMouseEvent* e)
00481 {
00482     if (!indexAt(e->pos()).isValid())
00483         clearSelection();
00484     QListView::mouseReleaseEvent(e);
00485 }
00486 
00487 /******************************************************************************
00488 * Called when a ToolTip or WhatsThis event occurs.
00489 */
00490 bool ResourceView::viewportEvent(QEvent* e)
00491 {
00492     if (e->type() == QEvent::ToolTip  &&  isActiveWindow())
00493     {
00494         QHelpEvent* he = static_cast<QHelpEvent*>(e);
00495         QModelIndex index = indexAt(he->pos());
00496         QVariant value = model()->data(index, Qt::ToolTipRole);
00497         if (qVariantCanConvert<QString>(value))
00498         {
00499             QString toolTip = value.toString();
00500             int i = toolTip.indexOf('@');
00501             if (i > 0)
00502             {
00503                 int j = toolTip.indexOf(QRegExp("<(nl|br)", Qt::CaseInsensitive), i + 1);
00504                 int k = toolTip.indexOf('@', j);
00505                 QString name = toolTip.mid(i + 1, j - i - 1);
00506                 value = model()->data(index, Qt::FontRole);
00507                 QFontMetrics fm(qvariant_cast<QFont>(value).resolve(viewOptions().font));
00508                 int textWidth = fm.boundingRect(name).width() + 1;
00509                 const int margin = QApplication::style()->pixelMetric(QStyle::PM_FocusFrameHMargin) + 1;
00510                 QStyleOptionButton opt;
00511                 opt.QStyleOption::operator=(viewOptions());
00512                 opt.rect = rectForIndex(index);
00513                 int checkWidth = QApplication::style()->subElementRect(QStyle::SE_ViewItemCheckIndicator, &opt).width();
00514                 int left = spacing() + 3*margin + checkWidth + viewOptions().decorationSize.width();   // left offset of text
00515                 int right = left + textWidth;
00516                 if (left >= horizontalOffset() + spacing()
00517                 &&  right <= horizontalOffset() + width() - spacing() - 2*frameWidth())
00518                 {
00519                     // The whole of the resource name is already displayed,
00520                     // so omit it from the tooltip.
00521                     if (k > 0)
00522                         toolTip.remove(i, k + 1 - i);
00523                 }
00524                 else
00525                 {
00526                     toolTip.remove(k, 1);
00527                     toolTip.remove(i, 1);
00528                 }
00529             }
00530             QToolTip::showText(he->globalPos(), toolTip, this);
00531             return true;
00532         }
00533     }
00534     return QListView::viewportEvent(e);
00535 }

kalarm

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

kdepim

Skip menu "kdepim"
  • akonadi
  •   clients
  •   kabc
  •   kcal
  •   kcm
  • akregator
  • console
  •   kabcclient
  •   konsolekalendar
  • kaddressbook
  • kalarm
  •   lib
  • kdgantt
  • kdgantt1
  • kjots
  • kleopatra
  • kmail
  • kmobiletools
  • knode
  • knotes
  • kontact
  • kontactinterfaces
  • korganizer
  •   korgac
  • kpilot
  • ktimetracker
  •   doc
  • libkdepim
  • libkholidays
  • libkleo
  • libkpgp
  • maildir
Generated for kdepim by doxygen 1.5.4
This website is maintained by Adriaan de Groot and Allen Winter.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal