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
33class 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
48EventListViewBase::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
60void 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*/
71void 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*/
90EventListViewItemBase* 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*/
106void 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*/
117void 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*/
133void 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*/
150EventListViewItemBase* 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
157EventListViewItemBase* 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*/
173EventListViewItemBase* 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*/
182void 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*/
197void 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*/
210void 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*/
220void 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*/
230void EventListViewBase::slotDeselect()
231{
232 selectAll(false);
233}
234
235/******************************************************************************
236* Check whether there are any selected items.
237*/
238bool 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*/
251const 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*/
263EventListViewItemBase* 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*/
284TQValueList<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*/
298int 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*/
313void 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*/
347void 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*/
358void EventListViewBase::showEvent(TQShowEvent* se)
359{
360 TDEListView::showEvent(se);
361 resizeLastColumn();
362}
363
364/******************************************************************************
365* Find the height of one list item.
366*/
367int 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=============================================================================*/
388TQPixmap* EventListViewItemBase::mTextIcon;
389TQPixmap* EventListViewItemBase::mFileIcon;
390TQPixmap* EventListViewItemBase::mCommandIcon;
391TQPixmap* EventListViewItemBase::mEmailIcon;
392int EventListViewItemBase::mIconWidth = 0;
393
394
395EventListViewItemBase::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*/
405void 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*/
415int 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*/
438TQPixmap* 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
456TQString 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