kalarm

eventlistviewbase.cpp

00001 /*
00002  *  eventlistviewbase.cpp  -  base classes for widget showing list of events
00003  *  Program:  kalarm
00004  *  Copyright (C) 2004, 2005 by David Jarvie <software@astrojar.org.uk>
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 <qwhatsthis.h>
00024 #include <qheader.h>
00025 
00026 #include <kiconloader.h>
00027 #include <kdebug.h>
00028 
00029 #include "find.h"
00030 #include "eventlistviewbase.moc"
00031 
00032 
00033 class EventListWhatsThisBase : public QWhatsThis
00034 {
00035     public:
00036         EventListWhatsThisBase(EventListViewBase* lv) : QWhatsThis(lv), mListView(lv) { }
00037         virtual QString text(const QPoint&);
00038     private:
00039         EventListViewBase* mListView;
00040 };
00041 
00042 
00043 /*=============================================================================
00044 =  Class: EventListViewBase
00045 =  Base class for displaying a list of events.
00046 =============================================================================*/
00047 
00048 EventListViewBase::EventListViewBase(QWidget* parent, const char* name)
00049     : KListView(parent, name),
00050       mFind(0),
00051       mLastColumn(-1),
00052       mLastColumnHeaderWidth(0)
00053 {
00054     setAllColumnsShowFocus(true);
00055     setShowSortIndicator(true);
00056 
00057     new EventListWhatsThisBase(this);
00058 }
00059 
00060 void EventListViewBase::addLastColumn(const QString& title)
00061 {
00062     addColumn(title);
00063     mLastColumn = columns() - 1;
00064     mLastColumnHeaderWidth = columnWidth(mLastColumn);
00065     setColumnWidthMode(mLastColumn, QListView::Maximum);
00066 }
00067 
00068 /******************************************************************************
00069 *  Refresh the list by clearing it and redisplaying all the current alarms.
00070 */
00071 void EventListViewBase::refresh()
00072 {
00073     QString currentID;
00074     if (currentItem())
00075         currentID = currentItem()->event().id();    // save current item for restoration afterwards
00076     clear();
00077     populate();
00078     resizeLastColumn();
00079     EventListViewItemBase* current = getEntry(currentID);
00080     if (current)
00081     {
00082         setCurrentItem(current);
00083         ensureItemVisible(current);
00084     }
00085 }
00086 
00087 /******************************************************************************
00088 *  Get the item for a given event ID.
00089 */
00090 EventListViewItemBase* EventListViewBase::getEntry(const QString& eventID) const
00091 {
00092     if (!eventID.isEmpty())
00093     {
00094         for (EventListViewItemBase* item = firstChild();  item;  item = item->nextSibling())
00095             if (item->event().id() == eventID)
00096                 return item;
00097     }
00098     return 0;
00099 }
00100 
00101 /******************************************************************************
00102 *  Add an event to every list instance.
00103 *  If 'selectionView' is non-null, the selection highlight is moved to the new
00104 *  event in that listView instance.
00105 */
00106 void EventListViewBase::addEvent(const KAEvent& event, const InstanceList& instanceList, EventListViewBase* selectionView)
00107 {
00108     for (InstanceListConstIterator it = instanceList.begin();  it != instanceList.end();  ++it)
00109         (*it)->addEntry(event, true, (*it == selectionView));
00110 }
00111 
00112 /******************************************************************************
00113 *  Modify an event in every list instance.
00114 *  If 'selectionView' is non-null, the selection highlight is moved to the
00115 *  modified event in that listView instance.
00116 */
00117 void EventListViewBase::modifyEvent(const QString& oldEventID, const KAEvent& newEvent,
00118                                     const InstanceList& instanceList, EventListViewBase* selectionView)
00119 {
00120     for (InstanceListConstIterator it = instanceList.begin();  it != instanceList.end();  ++it)
00121     {
00122         EventListViewBase* v = *it;
00123         EventListViewItemBase* item = v->getEntry(oldEventID);
00124         if (item)
00125             v->deleteEntry(item, false);
00126         v->addEntry(newEvent, true, (v == selectionView));
00127     }
00128 }
00129 
00130 /******************************************************************************
00131 *  Delete an event from every displayed list.
00132 */
00133 void EventListViewBase::deleteEvent(const QString& eventID, const InstanceList& instanceList)
00134 {
00135     for (InstanceListConstIterator it = instanceList.begin();  it != instanceList.end();  ++it)
00136     {
00137         EventListViewBase* v = *it;
00138         EventListViewItemBase* item = v->getEntry(eventID);
00139         if (item)
00140             v->deleteEntry(item, true);
00141         else
00142             v->refresh();
00143     }
00144 }
00145 
00146 /******************************************************************************
00147 *  Add a new item to the list.
00148 *  If 'reselect' is true, select/highlight the new item.
00149 */
00150 EventListViewItemBase* EventListViewBase::addEntry(const KAEvent& event, bool setSize, bool reselect)
00151 {
00152     if (!shouldShowEvent(event))
00153         return 0;
00154     return addEntry(createItem(event), setSize, reselect);
00155 }
00156 
00157 EventListViewItemBase* EventListViewBase::addEntry(EventListViewItemBase* item, bool setSize, bool reselect)
00158 {
00159     if (setSize)
00160         resizeLastColumn();
00161     if (reselect)
00162     {
00163         clearSelection();
00164         setSelected(item, true);
00165     }
00166     return item;
00167 }
00168 
00169 /******************************************************************************
00170 *  Update a specified item in the list.
00171 *  If 'reselect' is true, select the updated item.
00172 */
00173 EventListViewItemBase* EventListViewBase::updateEntry(EventListViewItemBase* item, const KAEvent& newEvent, bool setSize, bool reselect)
00174 {
00175     deleteEntry(item);
00176     return addEntry(newEvent, setSize, reselect);
00177 }
00178 
00179 /******************************************************************************
00180 *  Delete a specified item from the list.
00181 */
00182 void EventListViewBase::deleteEntry(EventListViewItemBase* item, bool setSize)
00183 {
00184     if (item)
00185     {
00186         delete item;
00187         if (setSize)
00188             resizeLastColumn();
00189         emit itemDeleted();
00190     }
00191 }
00192 
00193 /******************************************************************************
00194 *  Called when the Find action is selected.
00195 *  Display the non-modal Find dialog.
00196 */
00197 void EventListViewBase::slotFind()
00198 {
00199     if (!mFind)
00200     {
00201         mFind = new Find(this);
00202         connect(mFind, SIGNAL(active(bool)), SIGNAL(findActive(bool)));
00203     }
00204     mFind->display();
00205 }
00206 
00207 /******************************************************************************
00208 *  Called when the Find Next or Find Prev action is selected.
00209 */
00210 void EventListViewBase::findNext(bool forward)
00211 {
00212     if (mFind)
00213         mFind->findNext(forward);
00214 }
00215 
00216 /******************************************************************************
00217 *  Check whether there are any selected items.
00218 */
00219 bool EventListViewBase::anySelected() const
00220 {
00221     for (QListViewItem* item = KListView::firstChild();  item;  item = item->nextSibling())
00222         if (isSelected(item))
00223             return true;
00224     return false;
00225 }
00226 
00227 /******************************************************************************
00228 *  Get the single selected event.
00229 *  Reply = the event
00230 *        = 0 if no event is selected or multiple events are selected.
00231 */
00232 const KAEvent* EventListViewBase::selectedEvent() const
00233 {
00234     EventListViewItemBase* sel = selectedItem();
00235     return sel ? &sel->event() : 0;
00236 }
00237 
00238 /******************************************************************************
00239 *  Fetch the single selected item.
00240 *  This method works in both Single and Multi selection mode, unlike
00241 *  QListView::selectedItem().
00242 *  Reply = null if no items are selected, or if multiple items are selected.
00243 */
00244 EventListViewItemBase* EventListViewBase::selectedItem() const
00245 {
00246     if (selectionMode() == QListView::Single)
00247         return (EventListViewItemBase*)KListView::selectedItem();
00248 
00249     QListViewItem* item = 0;
00250     for (QListViewItem* it = firstChild();  it;  it = it->nextSibling())
00251     {
00252         if (isSelected(it))
00253         {
00254             if (item)
00255                 return 0;
00256             item = it;
00257         }
00258     }
00259     return (EventListViewItemBase*)item;
00260 }
00261 
00262 /******************************************************************************
00263 *  Fetch all selected items.
00264 */
00265 QValueList<EventListViewItemBase*> EventListViewBase::selectedItems() const
00266 {
00267     QValueList<EventListViewItemBase*> items;
00268     for (QListViewItem* item = firstChild();  item;  item = item->nextSibling())
00269     {
00270         if (isSelected(item))
00271             items.append((EventListViewItemBase*)item);
00272     }
00273     return items;
00274 }
00275 
00276 /******************************************************************************
00277 *  Return how many items are selected.
00278 */
00279 int EventListViewBase::selectedCount() const
00280 {
00281     int count = 0;
00282     for (QListViewItem* item = firstChild();  item;  item = item->nextSibling())
00283     {
00284         if (isSelected(item))
00285             ++count;
00286     }
00287     return count;
00288 }
00289 
00290 /******************************************************************************
00291 *  Sets the last column in the list view to extend at least to the right hand
00292 *  edge of the list view.
00293 */
00294 void EventListViewBase::resizeLastColumn()
00295 {
00296     int lastColumnWidth = mLastColumnHeaderWidth;
00297     for (EventListViewItemBase* item = firstChild();  item;  item = item->nextSibling())
00298     {
00299         int mw = item->lastColumnWidth();
00300         if (mw > lastColumnWidth)
00301             lastColumnWidth = mw;
00302     }
00303     int x = header()->sectionPos(mLastColumn);
00304     int width = visibleWidth() - x;
00305     if (width < lastColumnWidth)
00306         width = lastColumnWidth;
00307     setColumnWidth(mLastColumn, width);
00308     if (contentsWidth() > x + width)
00309         resizeContents(x + width, contentsHeight());
00310 }
00311 
00312 /******************************************************************************
00313 *  Called when the widget's size has changed (before it is painted).
00314 *  Sets the last column in the list view to extend at least to the right hand
00315 *  edge of the list view.
00316 */
00317 void EventListViewBase::resizeEvent(QResizeEvent* re)
00318 {
00319     KListView::resizeEvent(re);
00320     resizeLastColumn();
00321 }
00322 
00323 /******************************************************************************
00324 *  Called when the widget is first displayed.
00325 *  Sets the last column in the list view to extend at least to the right hand
00326 *  edge of the list view.
00327 */
00328 void EventListViewBase::showEvent(QShowEvent* se)
00329 {
00330     KListView::showEvent(se);
00331     resizeLastColumn();
00332 }
00333 
00334 /******************************************************************************
00335 *  Find the height of one list item.
00336 */
00337 int EventListViewBase::itemHeight()
00338 {
00339     EventListViewItemBase* item = firstChild();
00340     if (!item)
00341     {
00342         // The list is empty, so create a temporary item to find its height
00343         QListViewItem* item = new QListViewItem(this, QString::null);
00344         int height = item->height();
00345         delete item;
00346         return height;
00347     }
00348     else
00349         return item->height();
00350 }
00351 
00352 
00353 /*=============================================================================
00354 =  Class: EventListViewItemBase
00355 =  Base class containing the details of one event for display in an
00356 *  EventListViewBase.
00357 =============================================================================*/
00358 QPixmap* EventListViewItemBase::mTextIcon;
00359 QPixmap* EventListViewItemBase::mFileIcon;
00360 QPixmap* EventListViewItemBase::mCommandIcon;
00361 QPixmap* EventListViewItemBase::mEmailIcon;
00362 int      EventListViewItemBase::mIconWidth = 0;
00363 
00364 
00365 EventListViewItemBase::EventListViewItemBase(EventListViewBase* parent, const KAEvent& event)
00366     : QListViewItem(parent),
00367       mEvent(event)
00368 {
00369     iconWidth();    // load the icons
00370 }
00371 
00372 /******************************************************************************
00373 *  Set the text for the last column, and find its width.
00374 */
00375 void EventListViewItemBase::setLastColumnText()
00376 {
00377     EventListViewBase* parent = (EventListViewBase*)listView();
00378     setText(parent->lastColumn(), lastColumnText());
00379     mLastColumnWidth = width(parent->fontMetrics(), parent, parent->lastColumn());
00380 }
00381 
00382 /******************************************************************************
00383 *  Return the width of the widest alarm type icon.
00384 */
00385 int EventListViewItemBase::iconWidth()
00386 {
00387     if (!mIconWidth)
00388     {
00389         mTextIcon    = new QPixmap(SmallIcon("message"));
00390         mFileIcon    = new QPixmap(SmallIcon("file"));
00391         mCommandIcon = new QPixmap(SmallIcon("exec"));
00392         mEmailIcon   = new QPixmap(SmallIcon("mail_generic"));
00393         if (mTextIcon)
00394             mIconWidth = mTextIcon->width();
00395         if (mFileIcon  &&  mFileIcon->width() > mIconWidth)
00396             mIconWidth = mFileIcon->width();
00397         if (mCommandIcon  &&  mCommandIcon->width() > mIconWidth)
00398             mIconWidth = mCommandIcon->width();
00399         if (mEmailIcon  &&  mEmailIcon->width() > mIconWidth)
00400             mIconWidth = mEmailIcon->width();
00401     }
00402     return mIconWidth;
00403 }
00404 
00405 /******************************************************************************
00406 *  Return the icon associated with the event's action.
00407 */
00408 QPixmap* EventListViewItemBase::eventIcon() const
00409 {
00410     switch (mEvent.action())
00411     {
00412         case KAAlarm::FILE:     return mFileIcon;
00413         case KAAlarm::COMMAND:  return mCommandIcon;
00414         case KAAlarm::EMAIL:    return mEmailIcon;
00415         case KAAlarm::MESSAGE:
00416         default:                return mTextIcon;
00417     }
00418 }
00419 
00420 
00421 /*=============================================================================
00422 =  Class: EventListWhatsThisBase
00423 =  Sets What's This? text depending on where in the list view is clicked.
00424 =============================================================================*/
00425 
00426 QString EventListWhatsThisBase::text(const QPoint& pt)
00427 {
00428     int column = -1;
00429     QPoint viewportPt = mListView->viewport()->mapFrom(mListView, pt);
00430     QRect frame = mListView->header()->frameGeometry();
00431     if (frame.contains(pt)
00432     ||  mListView->itemAt(QPoint(mListView->itemMargin(), viewportPt.y())) && frame.contains(QPoint(pt.x(), frame.y())))
00433         column = mListView->header()->sectionAt(pt.x());
00434     return mListView->whatsThisText(column);
00435 }
00436 
KDE Home | KDE Accessibility Home | Description of Access Keys