kalarm

eventlistviewbase.cpp
1 /*
2  * eventlistviewbase.cpp - base classes for widget showing list of events
3  * Program: kalarm
4  * Copyright (c) 2004-2006 by David Jarvie <software@astrojar.org.uk>
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 <tqwhatsthis.h>
24 #include <tqheader.h>
25 
26 #include <kiconloader.h>
27 #include <kdebug.h>
28 
29 #include "find.h"
30 #include "eventlistviewbase.moc"
31 
32 
33 class EventListWhatsThisBase : public TQWhatsThis
34 {
35  public:
36  EventListWhatsThisBase(EventListViewBase* lv) : TQWhatsThis(lv), mListView(lv) { }
37  virtual TQString text(const TQPoint&);
38  private:
39  EventListViewBase* mListView;
40 };
41 
42 
43 /*=============================================================================
44 = Class: EventListViewBase
45 = Base class for displaying a list of events.
46 =============================================================================*/
47 
48 EventListViewBase::EventListViewBase(TQWidget* parent, const char* name)
49  : TDEListView(parent, name),
50  mFind(0),
51  mLastColumn(-1),
52  mLastColumnHeaderWidth(0)
53 {
54  setAllColumnsShowFocus(true);
55  setShowSortIndicator(true);
56 
57  new EventListWhatsThisBase(this);
58 }
59 
60 void EventListViewBase::addLastColumn(const TQString& title)
61 {
62  addColumn(title);
63  mLastColumn = columns() - 1;
64  mLastColumnHeaderWidth = columnWidth(mLastColumn);
65  setColumnWidthMode(mLastColumn, TQListView::Maximum);
66 }
67 
68 /******************************************************************************
69 * Refresh the list by clearing it and redisplaying all the current alarms.
70 */
71 void EventListViewBase::refresh()
72 {
73  TQString currentID;
74  if (currentItem())
75  currentID = currentItem()->event().id(); // save current item for restoration afterwards
76  clear();
77  populate();
78  resizeLastColumn();
79  EventListViewItemBase* current = getEntry(currentID);
80  if (current)
81  {
82  setCurrentItem(current);
83  ensureItemVisible(current);
84  }
85 }
86 
87 /******************************************************************************
88 * Get the item for a given event ID.
89 */
90 EventListViewItemBase* EventListViewBase::getEntry(const TQString& eventID) const
91 {
92  if (!eventID.isEmpty())
93  {
94  for (EventListViewItemBase* item = firstChild(); item; item = item->nextSibling())
95  if (item->event().id() == eventID)
96  return item;
97  }
98  return 0;
99 }
100 
101 /******************************************************************************
102 * Add an event to every list instance.
103 * If 'selectionView' is non-null, the selection highlight is moved to the new
104 * event in that listView instance.
105 */
106 void EventListViewBase::addEvent(const KAEvent& event, const InstanceList& instanceList, EventListViewBase* selectionView)
107 {
108  for (InstanceListConstIterator it = instanceList.begin(); it != instanceList.end(); ++it)
109  (*it)->addEntry(event, true, (*it == selectionView));
110 }
111 
112 /******************************************************************************
113 * Modify an event in every list instance.
114 * If 'selectionView' is non-null, the selection highlight is moved to the
115 * modified event in that listView instance.
116 */
117 void EventListViewBase::modifyEvent(const TQString& oldEventID, const KAEvent& newEvent,
118  const InstanceList& instanceList, EventListViewBase* selectionView)
119 {
120  for (InstanceListConstIterator it = instanceList.begin(); it != instanceList.end(); ++it)
121  {
122  EventListViewBase* v = *it;
123  EventListViewItemBase* item = v->getEntry(oldEventID);
124  if (item)
125  v->deleteEntry(item, false);
126  v->addEntry(newEvent, true, (v == selectionView));
127  }
128 }
129 
130 /******************************************************************************
131 * Delete an event from every displayed list.
132 */
133 void EventListViewBase::deleteEvent(const TQString& eventID, const InstanceList& instanceList)
134 {
135  for (InstanceListConstIterator it = instanceList.begin(); it != instanceList.end(); ++it)
136  {
137  EventListViewBase* v = *it;
138  EventListViewItemBase* item = v->getEntry(eventID);
139  if (item)
140  v->deleteEntry(item, true);
141  else
142  v->refresh();
143  }
144 }
145 
146 /******************************************************************************
147 * Add a new item to the list.
148 * If 'reselect' is true, select/highlight the new item.
149 */
150 EventListViewItemBase* EventListViewBase::addEntry(const KAEvent& event, bool setSize, bool reselect)
151 {
152  if (!shouldShowEvent(event))
153  return 0;
154  return addEntry(createItem(event), setSize, reselect);
155 }
156 
157 EventListViewItemBase* EventListViewBase::addEntry(EventListViewItemBase* item, bool setSize, bool reselect)
158 {
159  if (setSize)
160  resizeLastColumn();
161  if (reselect)
162  {
163  clearSelection();
164  setSelected(item, true);
165  }
166  return item;
167 }
168 
169 /******************************************************************************
170 * Update a specified item in the list.
171 * If 'reselect' is true, select the updated item.
172 */
173 EventListViewItemBase* EventListViewBase::updateEntry(EventListViewItemBase* item, const KAEvent& newEvent, bool setSize, bool reselect)
174 {
175  deleteEntry(item);
176  return addEntry(newEvent, setSize, reselect);
177 }
178 
179 /******************************************************************************
180 * Delete a specified item from the list.
181 */
182 void EventListViewBase::deleteEntry(EventListViewItemBase* item, bool setSize)
183 {
184  if (item)
185  {
186  delete item;
187  if (setSize)
188  resizeLastColumn();
189  emit itemDeleted();
190  }
191 }
192 
193 /******************************************************************************
194 * Called when the Find action is selected.
195 * Display the non-modal Find dialog.
196 */
197 void EventListViewBase::slotFind()
198 {
199  if (!mFind)
200  {
201  mFind = new Find(this);
202  connect(mFind, TQ_SIGNAL(active(bool)), TQ_SIGNAL(findActive(bool)));
203  }
204  mFind->display();
205 }
206 
207 /******************************************************************************
208 * Called when the Find Next or Find Prev action is selected.
209 */
210 void EventListViewBase::findNext(bool forward)
211 {
212  if (mFind)
213  mFind->findNext(forward);
214 }
215 
216 /******************************************************************************
217 * Called when the Select All action is selected.
218 * Select all items in the list.
219 */
220 void EventListViewBase::slotSelectAll()
221 {
222  if (selectionMode() == TQListView::Multi || selectionMode() == TQListView::Extended)
223  selectAll(true);
224 }
225 
226 /******************************************************************************
227 * Called when the Deselect action is selected.
228 * Deselect all items in the list.
229 */
230 void EventListViewBase::slotDeselect()
231 {
232  selectAll(false);
233 }
234 
235 /******************************************************************************
236 * Check whether there are any selected items.
237 */
238 bool EventListViewBase::anySelected() const
239 {
240  for (TQListViewItem* item = TDEListView::firstChild(); item; item = item->nextSibling())
241  if (isSelected(item))
242  return true;
243  return false;
244 }
245 
246 /******************************************************************************
247 * Get the single selected event.
248 * Reply = the event
249 * = 0 if no event is selected or multiple events are selected.
250 */
251 const KAEvent* EventListViewBase::selectedEvent() const
252 {
253  EventListViewItemBase* sel = selectedItem();
254  return sel ? &sel->event() : 0;
255 }
256 
257 /******************************************************************************
258 * Fetch the single selected item.
259 * This method works in both Single and Multi selection mode, unlike
260 * TQListView::selectedItem().
261 * Reply = null if no items are selected, or if multiple items are selected.
262 */
263 EventListViewItemBase* EventListViewBase::selectedItem() const
264 {
265  if (selectionMode() == TQListView::Single)
266  return (EventListViewItemBase*)TDEListView::selectedItem();
267 
268  TQListViewItem* item = 0;
269  for (TQListViewItem* it = firstChild(); it; it = it->nextSibling())
270  {
271  if (isSelected(it))
272  {
273  if (item)
274  return 0;
275  item = it;
276  }
277  }
278  return (EventListViewItemBase*)item;
279 }
280 
281 /******************************************************************************
282 * Fetch all selected items.
283 */
284 TQValueList<EventListViewItemBase*> EventListViewBase::selectedItems() const
285 {
286  TQValueList<EventListViewItemBase*> items;
287  for (TQListViewItem* item = firstChild(); item; item = item->nextSibling())
288  {
289  if (isSelected(item))
290  items.append((EventListViewItemBase*)item);
291  }
292  return items;
293 }
294 
295 /******************************************************************************
296 * Return how many items are selected.
297 */
298 int EventListViewBase::selectedCount() const
299 {
300  int count = 0;
301  for (TQListViewItem* item = firstChild(); item; item = item->nextSibling())
302  {
303  if (isSelected(item))
304  ++count;
305  }
306  return count;
307 }
308 
309 /******************************************************************************
310 * Sets the last column in the list view to extend at least to the right hand
311 * edge of the list view.
312 */
313 void EventListViewBase::resizeLastColumn()
314 {
315  int lastColumnWidth = mLastColumnHeaderWidth;
316  for (EventListViewItemBase* item = firstChild(); item; item = item->nextSibling())
317  {
318  int mw = item->lastColumnWidth();
319  if (mw > lastColumnWidth)
320  lastColumnWidth = mw;
321  }
322  TQHeader* head = header();
323  int x = head->sectionPos(mLastColumn);
324  int availableWidth = visibleWidth() - x;
325  int rightColWidth = 0;
326  int index = head->mapToIndex(mLastColumn);
327  if (index < mLastColumn)
328  {
329  // The last column has been dragged by the user to a different position.
330  // Ensure that the columns now to the right of it are still shown.
331  for (int i = index + 1; i <= mLastColumn; ++i)
332  rightColWidth += columnWidth(head->mapToSection(i));
333  availableWidth -= rightColWidth;
334  }
335  if (availableWidth < lastColumnWidth)
336  availableWidth = lastColumnWidth;
337  setColumnWidth(mLastColumn, availableWidth);
338  if (contentsWidth() > x + availableWidth + rightColWidth)
339  resizeContents(x + availableWidth + rightColWidth, contentsHeight());
340 }
341 
342 /******************************************************************************
343 * Called when the widget's size has changed (before it is painted).
344 * Sets the last column in the list view to extend at least to the right hand
345 * edge of the list view.
346 */
347 void EventListViewBase::resizeEvent(TQResizeEvent* re)
348 {
349  TDEListView::resizeEvent(re);
350  resizeLastColumn();
351 }
352 
353 /******************************************************************************
354 * Called when the widget is first displayed.
355 * Sets the last column in the list view to extend at least to the right hand
356 * edge of the list view.
357 */
358 void EventListViewBase::showEvent(TQShowEvent* se)
359 {
360  TDEListView::showEvent(se);
361  resizeLastColumn();
362 }
363 
364 /******************************************************************************
365 * Find the height of one list item.
366 */
367 int EventListViewBase::itemHeight()
368 {
369  EventListViewItemBase* item = firstChild();
370  if (!item)
371  {
372  // The list is empty, so create a temporary item to find its height
373  TQListViewItem* item = new TQListViewItem(this, TQString());
374  int height = item->height();
375  delete item;
376  return height;
377  }
378  else
379  return item->height();
380 }
381 
382 
383 /*=============================================================================
384 = Class: EventListViewItemBase
385 = Base class containing the details of one event for display in an
386 * EventListViewBase.
387 =============================================================================*/
388 TQPixmap* EventListViewItemBase::mTextIcon;
389 TQPixmap* EventListViewItemBase::mFileIcon;
390 TQPixmap* EventListViewItemBase::mCommandIcon;
391 TQPixmap* EventListViewItemBase::mEmailIcon;
392 int EventListViewItemBase::mIconWidth = 0;
393 
394 
395 EventListViewItemBase::EventListViewItemBase(EventListViewBase* parent, const KAEvent& event)
396  : TQListViewItem(parent),
397  mEvent(event)
398 {
399  iconWidth(); // load the icons
400 }
401 
402 /******************************************************************************
403 * Set the text for the last column, and find its width.
404 */
405 void EventListViewItemBase::setLastColumnText()
406 {
407  EventListViewBase* parent = (EventListViewBase*)listView();
408  setText(parent->lastColumn(), lastColumnText());
409  mLastColumnWidth = width(parent->fontMetrics(), parent, parent->lastColumn());
410 }
411 
412 /******************************************************************************
413 * Return the width of the widest alarm type icon.
414 */
415 int EventListViewItemBase::iconWidth()
416 {
417  if (!mIconWidth)
418  {
419  mTextIcon = new TQPixmap(SmallIcon("message"));
420  mFileIcon = new TQPixmap(SmallIcon("file"));
421  mCommandIcon = new TQPixmap(SmallIcon("application-x-executable"));
422  mEmailIcon = new TQPixmap(SmallIcon("mail_generic"));
423  if (mTextIcon)
424  mIconWidth = mTextIcon->width();
425  if (mFileIcon && mFileIcon->width() > mIconWidth)
426  mIconWidth = mFileIcon->width();
427  if (mCommandIcon && mCommandIcon->width() > mIconWidth)
428  mIconWidth = mCommandIcon->width();
429  if (mEmailIcon && mEmailIcon->width() > mIconWidth)
430  mIconWidth = mEmailIcon->width();
431  }
432  return mIconWidth;
433 }
434 
435 /******************************************************************************
436 * Return the icon associated with the event's action.
437 */
438 TQPixmap* EventListViewItemBase::eventIcon() const
439 {
440  switch (mEvent.action())
441  {
442  case KAAlarm::FILE: return mFileIcon;
443  case KAAlarm::COMMAND: return mCommandIcon;
444  case KAAlarm::EMAIL: return mEmailIcon;
445  case KAAlarm::MESSAGE:
446  default: return mTextIcon;
447  }
448 }
449 
450 
451 /*=============================================================================
452 = Class: EventListWhatsThisBase
453 = Sets What's This? text depending on where in the list view is clicked.
454 =============================================================================*/
455 
456 TQString EventListWhatsThisBase::text(const TQPoint& pt)
457 {
458  int column = -1;
459  TQPoint viewportPt = mListView->viewport()->mapFrom(mListView, pt);
460  TQRect frame = mListView->header()->frameGeometry();
461  if (frame.contains(pt)
462  || (mListView->itemAt(TQPoint(mListView->itemMargin(), viewportPt.y())) && frame.contains(TQPoint(pt.x(), frame.y()))))
463  column = mListView->header()->sectionAt(pt.x());
464  return mListView->whatsThisText(column);
465 }
466 
KAEvent corresponds to a KCal::Event instance.
Definition: alarmevent.h:232