eventlistviewbase.cpp
00001 /* 00002 * eventlistviewbase.cpp - base classes for widget showing list of events 00003 * Program: kalarm 00004 * Copyright (c) 2004-2006 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 <tqwhatsthis.h> 00024 #include <tqheader.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 TQWhatsThis 00034 { 00035 public: 00036 EventListWhatsThisBase(EventListViewBase* lv) : TQWhatsThis(lv), mListView(lv) { } 00037 virtual TQString text(const TQPoint&); 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(TQWidget* parent, const char* name) 00049 : TDEListView(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 TQString& title) 00061 { 00062 addColumn(title); 00063 mLastColumn = columns() - 1; 00064 mLastColumnHeaderWidth = columnWidth(mLastColumn); 00065 setColumnWidthMode(mLastColumn, TQListView::Maximum); 00066 } 00067 00068 /****************************************************************************** 00069 * Refresh the list by clearing it and redisplaying all the current alarms. 00070 */ 00071 void EventListViewBase::refresh() 00072 { 00073 TQString 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 TQString& 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 TQString& 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 TQString& 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, TQT_SIGNAL(active(bool)), TQT_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 * Called when the Select All action is selected. 00218 * Select all items in the list. 00219 */ 00220 void EventListViewBase::slotSelectAll() 00221 { 00222 if (selectionMode() == TQListView::Multi || selectionMode() == TQListView::Extended) 00223 selectAll(true); 00224 } 00225 00226 /****************************************************************************** 00227 * Called when the Deselect action is selected. 00228 * Deselect all items in the list. 00229 */ 00230 void EventListViewBase::slotDeselect() 00231 { 00232 selectAll(false); 00233 } 00234 00235 /****************************************************************************** 00236 * Check whether there are any selected items. 00237 */ 00238 bool EventListViewBase::anySelected() const 00239 { 00240 for (TQListViewItem* item = TDEListView::firstChild(); item; item = item->nextSibling()) 00241 if (isSelected(item)) 00242 return true; 00243 return false; 00244 } 00245 00246 /****************************************************************************** 00247 * Get the single selected event. 00248 * Reply = the event 00249 * = 0 if no event is selected or multiple events are selected. 00250 */ 00251 const KAEvent* EventListViewBase::selectedEvent() const 00252 { 00253 EventListViewItemBase* sel = selectedItem(); 00254 return sel ? &sel->event() : 0; 00255 } 00256 00257 /****************************************************************************** 00258 * Fetch the single selected item. 00259 * This method works in both Single and Multi selection mode, unlike 00260 * TQListView::selectedItem(). 00261 * Reply = null if no items are selected, or if multiple items are selected. 00262 */ 00263 EventListViewItemBase* EventListViewBase::selectedItem() const 00264 { 00265 if (selectionMode() == TQListView::Single) 00266 return (EventListViewItemBase*)TDEListView::selectedItem(); 00267 00268 TQListViewItem* item = 0; 00269 for (TQListViewItem* it = firstChild(); it; it = it->nextSibling()) 00270 { 00271 if (isSelected(it)) 00272 { 00273 if (item) 00274 return 0; 00275 item = it; 00276 } 00277 } 00278 return (EventListViewItemBase*)item; 00279 } 00280 00281 /****************************************************************************** 00282 * Fetch all selected items. 00283 */ 00284 TQValueList<EventListViewItemBase*> EventListViewBase::selectedItems() const 00285 { 00286 TQValueList<EventListViewItemBase*> items; 00287 for (TQListViewItem* item = firstChild(); item; item = item->nextSibling()) 00288 { 00289 if (isSelected(item)) 00290 items.append((EventListViewItemBase*)item); 00291 } 00292 return items; 00293 } 00294 00295 /****************************************************************************** 00296 * Return how many items are selected. 00297 */ 00298 int EventListViewBase::selectedCount() const 00299 { 00300 int count = 0; 00301 for (TQListViewItem* item = firstChild(); item; item = item->nextSibling()) 00302 { 00303 if (isSelected(item)) 00304 ++count; 00305 } 00306 return count; 00307 } 00308 00309 /****************************************************************************** 00310 * Sets the last column in the list view to extend at least to the right hand 00311 * edge of the list view. 00312 */ 00313 void EventListViewBase::resizeLastColumn() 00314 { 00315 int lastColumnWidth = mLastColumnHeaderWidth; 00316 for (EventListViewItemBase* item = firstChild(); item; item = item->nextSibling()) 00317 { 00318 int mw = item->lastColumnWidth(); 00319 if (mw > lastColumnWidth) 00320 lastColumnWidth = mw; 00321 } 00322 TQHeader* head = header(); 00323 int x = head->sectionPos(mLastColumn); 00324 int availableWidth = visibleWidth() - x; 00325 int rightColWidth = 0; 00326 int index = head->mapToIndex(mLastColumn); 00327 if (index < mLastColumn) 00328 { 00329 // The last column has been dragged by the user to a different position. 00330 // Ensure that the columns now to the right of it are still shown. 00331 for (int i = index + 1; i <= mLastColumn; ++i) 00332 rightColWidth += columnWidth(head->mapToSection(i)); 00333 availableWidth -= rightColWidth; 00334 } 00335 if (availableWidth < lastColumnWidth) 00336 availableWidth = lastColumnWidth; 00337 setColumnWidth(mLastColumn, availableWidth); 00338 if (contentsWidth() > x + availableWidth + rightColWidth) 00339 resizeContents(x + availableWidth + rightColWidth, contentsHeight()); 00340 } 00341 00342 /****************************************************************************** 00343 * Called when the widget's size has changed (before it is painted). 00344 * Sets the last column in the list view to extend at least to the right hand 00345 * edge of the list view. 00346 */ 00347 void EventListViewBase::resizeEvent(TQResizeEvent* re) 00348 { 00349 TDEListView::resizeEvent(re); 00350 resizeLastColumn(); 00351 } 00352 00353 /****************************************************************************** 00354 * Called when the widget is first displayed. 00355 * Sets the last column in the list view to extend at least to the right hand 00356 * edge of the list view. 00357 */ 00358 void EventListViewBase::showEvent(TQShowEvent* se) 00359 { 00360 TDEListView::showEvent(se); 00361 resizeLastColumn(); 00362 } 00363 00364 /****************************************************************************** 00365 * Find the height of one list item. 00366 */ 00367 int EventListViewBase::itemHeight() 00368 { 00369 EventListViewItemBase* item = firstChild(); 00370 if (!item) 00371 { 00372 // The list is empty, so create a temporary item to find its height 00373 TQListViewItem* item = new TQListViewItem(this, TQString()); 00374 int height = item->height(); 00375 delete item; 00376 return height; 00377 } 00378 else 00379 return item->height(); 00380 } 00381 00382 00383 /*============================================================================= 00384 = Class: EventListViewItemBase 00385 = Base class containing the details of one event for display in an 00386 * EventListViewBase. 00387 =============================================================================*/ 00388 TQPixmap* EventListViewItemBase::mTextIcon; 00389 TQPixmap* EventListViewItemBase::mFileIcon; 00390 TQPixmap* EventListViewItemBase::mCommandIcon; 00391 TQPixmap* EventListViewItemBase::mEmailIcon; 00392 int EventListViewItemBase::mIconWidth = 0; 00393 00394 00395 EventListViewItemBase::EventListViewItemBase(EventListViewBase* parent, const KAEvent& event) 00396 : TQListViewItem(parent), 00397 mEvent(event) 00398 { 00399 iconWidth(); // load the icons 00400 } 00401 00402 /****************************************************************************** 00403 * Set the text for the last column, and find its width. 00404 */ 00405 void EventListViewItemBase::setLastColumnText() 00406 { 00407 EventListViewBase* parent = (EventListViewBase*)listView(); 00408 setText(parent->lastColumn(), lastColumnText()); 00409 mLastColumnWidth = width(parent->fontMetrics(), parent, parent->lastColumn()); 00410 } 00411 00412 /****************************************************************************** 00413 * Return the width of the widest alarm type icon. 00414 */ 00415 int EventListViewItemBase::iconWidth() 00416 { 00417 if (!mIconWidth) 00418 { 00419 mTextIcon = new TQPixmap(SmallIcon("message")); 00420 mFileIcon = new TQPixmap(SmallIcon("file")); 00421 mCommandIcon = new TQPixmap(SmallIcon("application-x-executable")); 00422 mEmailIcon = new TQPixmap(SmallIcon("mail_generic")); 00423 if (mTextIcon) 00424 mIconWidth = mTextIcon->width(); 00425 if (mFileIcon && mFileIcon->width() > mIconWidth) 00426 mIconWidth = mFileIcon->width(); 00427 if (mCommandIcon && mCommandIcon->width() > mIconWidth) 00428 mIconWidth = mCommandIcon->width(); 00429 if (mEmailIcon && mEmailIcon->width() > mIconWidth) 00430 mIconWidth = mEmailIcon->width(); 00431 } 00432 return mIconWidth; 00433 } 00434 00435 /****************************************************************************** 00436 * Return the icon associated with the event's action. 00437 */ 00438 TQPixmap* EventListViewItemBase::eventIcon() const 00439 { 00440 switch (mEvent.action()) 00441 { 00442 case KAAlarm::FILE: return mFileIcon; 00443 case KAAlarm::COMMAND: return mCommandIcon; 00444 case KAAlarm::EMAIL: return mEmailIcon; 00445 case KAAlarm::MESSAGE: 00446 default: return mTextIcon; 00447 } 00448 } 00449 00450 00451 /*============================================================================= 00452 = Class: EventListWhatsThisBase 00453 = Sets What's This? text depending on where in the list view is clicked. 00454 =============================================================================*/ 00455 00456 TQString EventListWhatsThisBase::text(const TQPoint& pt) 00457 { 00458 int column = -1; 00459 TQPoint viewportPt = mListView->viewport()->mapFrom(mListView, pt); 00460 TQRect frame = mListView->header()->frameGeometry(); 00461 if (frame.contains(pt) 00462 || (mListView->itemAt(TQPoint(mListView->itemMargin(), viewportPt.y())) && frame.contains(TQPoint(pt.x(), frame.y())))) 00463 column = mListView->header()->sectionAt(pt.x()); 00464 return mListView->whatsThisText(column); 00465 } 00466