kalarm

alarmlistview.cpp
1 /*
2  * alarmlistview.cpp - widget showing list of outstanding alarms
3  * Program: kalarm
4  * Copyright © 2001-2007 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 <tqtooltip.h>
24 #include <tqpainter.h>
25 #include <tqstyle.h>
26 #include <tqheader.h>
27 #include <tqregexp.h>
28 
29 #include <tdeglobal.h>
30 #include <tdelocale.h>
31 #include <kdebug.h>
32 
33 #include <libkcal/icaldrag.h>
34 #include <libkcal/calendarlocal.h>
35 
36 #include "alarmcalendar.h"
37 #include "alarmtext.h"
38 #include "functions.h"
39 #include "kalarmapp.h"
40 #include "preferences.h"
41 #include "alarmlistview.moc"
42 
43 
44 class AlarmListTooltip : public TQToolTip
45 {
46  public:
47  AlarmListTooltip(TQWidget* parent) : TQToolTip(parent) { }
48  virtual ~AlarmListTooltip() {}
49  protected:
50  virtual void maybeTip(const TQPoint&);
51 };
52 
53 
54 /*=============================================================================
55 = Class: AlarmListView
56 = Displays the list of outstanding alarms.
57 =============================================================================*/
58 TQValueList<EventListViewBase*> AlarmListView::mInstanceList;
59 bool AlarmListView::mDragging = false;
60 
61 
62 AlarmListView::AlarmListView(const TQValueList<int>& order, TQWidget* parent, const char* name)
63  : EventListViewBase(parent, name),
64  mMousePressed(false),
65  mDrawMessageInColour(false),
66  mShowExpired(false)
67 {
68  static TQString titles[COLUMN_COUNT] = {
69  i18n("Time"),
70  i18n("Time To"),
71  i18n("Repeat"),
72  TQString(),
73  TQString(),
74  i18n("Message, File or Command")
75  };
76 
77  setSelectionMode(TQListView::Extended);
78 
79  // Set the column order
80  int i;
81  bool ok = false;
82  if (order.count() >= COLUMN_COUNT)
83  {
84  // The column order is specified
85  bool posns[COLUMN_COUNT];
86  for (i = 0; i < COLUMN_COUNT; ++i)
87  posns[i] = false;
88  for (i = 0; i < COLUMN_COUNT; ++i)
89  {
90  int ord = order[i];
91  if (ord < COLUMN_COUNT && ord >= 0)
92  {
93  mColumn[i] = ord;
94  posns[ord] = true;
95  }
96  }
97  ok = true;
98  for (i = 0; i < COLUMN_COUNT; ++i)
99  if (!posns[i])
100  ok = false;
101  if (ok && mColumn[MESSAGE_COLUMN] != MESSAGE_COLUMN)
102  {
103  // Shift the message column to be last, since otherwise
104  // column widths get screwed up.
105  int messageCol = mColumn[MESSAGE_COLUMN];
106  for (i = 0; i < COLUMN_COUNT; ++i)
107  if (mColumn[i] > messageCol)
108  --mColumn[i];
109  mColumn[MESSAGE_COLUMN] = MESSAGE_COLUMN;
110  }
111  }
112  if (!ok)
113  {
114  // Either no column order was specified, or it was invalid,
115  // so use the default order
116  for (i = 0; i < COLUMN_COUNT; ++i)
117  mColumn[i] = i;
118  }
119 
120  // Initialise the columns
121  for (i = 0; i < COLUMN_COUNT; ++i)
122  {
123  for (int j = 0; j < COLUMN_COUNT; ++j)
124  if (mColumn[j] == i)
125  {
126  if (j != MESSAGE_COLUMN)
127  addColumn(titles[j]);
128  break;
129  }
130  }
131  addLastColumn(titles[MESSAGE_COLUMN]);
132 
133  setSorting(mColumn[TIME_COLUMN]); // sort initially by date/time
134  mTimeColumnHeaderWidth = columnWidth(mColumn[TIME_COLUMN]);
135  mTimeToColumnHeaderWidth = columnWidth(mColumn[TIME_TO_COLUMN]);
136  setColumnAlignment(mColumn[REPEAT_COLUMN], TQt::AlignHCenter);
137  setColumnWidthMode(mColumn[REPEAT_COLUMN], TQListView::Maximum);
138 
139  // Set the width of the colour column in proportion to height
140  setColumnWidth(mColumn[COLOUR_COLUMN], itemHeight() * 3/4);
141  setColumnWidthMode(mColumn[COLOUR_COLUMN], TQListView::Manual);
142 
143  // Set the width of the alarm type column to exactly accommodate the icons.
144  // Don't allow the user to resize it (to avoid refresh problems, and bearing
145  // in mind that resizing doesn't seem very useful anyway).
146  setColumnWidth(mColumn[TYPE_COLUMN], AlarmListViewItem::typeIconWidth(this));
147  setColumnWidthMode(mColumn[TYPE_COLUMN], TQListView::Manual);
148  header()->setResizeEnabled(false, mColumn[TYPE_COLUMN]);
149 
150  mInstanceList.append(this);
151 
152  mTooltip = new AlarmListTooltip(viewport());
153 }
154 
155 AlarmListView::~AlarmListView()
156 {
157  delete mTooltip;
158  mTooltip = 0;
159  mInstanceList.remove(this);
160 }
161 
162 /******************************************************************************
163 * Add all the current alarms to the list.
164 */
165 void AlarmListView::populate()
166 {
167  KAEvent event;
168  KCal::Event::List events;
169  KCal::Event::List::ConstIterator it;
170  TQDateTime now = TQDateTime::currentDateTime();
171  if (mShowExpired)
172  {
173  AlarmCalendar* cal = AlarmCalendar::expiredCalendarOpen();
174  if (cal)
175  {
176  events = cal->events();
177  for (it = events.begin(); it != events.end(); ++it)
178  {
179  KCal::Event* kcalEvent = *it;
180  if (kcalEvent->alarms().count() > 0)
181  {
182  event.set(*kcalEvent);
183  addEntry(event, now);
184  }
185  }
186  }
187  }
188  events = AlarmCalendar::activeCalendar()->events();
189  for (it = events.begin(); it != events.end(); ++it)
190  {
191  KCal::Event* kcalEvent = *it;
192  event.set(*kcalEvent);
193  if (mShowExpired || !event.expired())
194  addEntry(event, now);
195  }
196 }
197 
198 /******************************************************************************
199 * Set which time columns are to be displayed.
200 */
201 void AlarmListView::selectTimeColumns(bool time, bool timeTo)
202 {
203  if (!time && !timeTo)
204  return; // always show at least one time column
205  bool changed = false;
206  int w = columnWidth(mColumn[TIME_COLUMN]);
207  if (time && !w)
208  {
209  // Unhide the time column
210  int colWidth = mTimeColumnHeaderWidth;
211  TQFontMetrics fm = fontMetrics();
212  for (AlarmListViewItem* item = firstChild(); item; item = item->nextSibling())
213  {
214  int w = item->width(fm, this, mColumn[TIME_COLUMN]);
215  if (w > colWidth)
216  colWidth = w;
217  }
218  setColumnWidth(mColumn[TIME_COLUMN], colWidth);
219  setColumnWidthMode(mColumn[TIME_COLUMN], TQListView::Maximum);
220  changed = true;
221  }
222  else if (!time && w)
223  {
224  // Hide the time column
225  setColumnWidthMode(mColumn[TIME_COLUMN], TQListView::Manual);
226  setColumnWidth(mColumn[TIME_COLUMN], 0);
227  changed = true;
228  }
229  w = columnWidth(mColumn[TIME_TO_COLUMN]);
230  if (timeTo && !w)
231  {
232  // Unhide the time-to-alarm column
233  setColumnWidthMode(mColumn[TIME_TO_COLUMN], TQListView::Maximum);
234  updateTimeToAlarms(true);
235  if (columnWidth(mColumn[TIME_TO_COLUMN]) < mTimeToColumnHeaderWidth)
236  setColumnWidth(mColumn[TIME_TO_COLUMN], mTimeToColumnHeaderWidth);
237  changed = true;
238  }
239  else if (!timeTo && w)
240  {
241  // Hide the time-to-alarm column
242  setColumnWidthMode(mColumn[TIME_TO_COLUMN], TQListView::Manual);
243  setColumnWidth(mColumn[TIME_TO_COLUMN], 0);
244  changed = true;
245  }
246  if (changed)
247  {
248  resizeLastColumn();
249  triggerUpdate(); // ensure scroll bar appears if needed
250  }
251 }
252 
253 /******************************************************************************
254 * Update all the values in the time-to-alarm column.
255 */
256 void AlarmListView::updateTimeToAlarms(bool forceDisplay)
257 {
258  if (forceDisplay || columnWidth(mColumn[TIME_TO_COLUMN]))
259  {
260  TQDateTime now = TQDateTime::currentDateTime();
261  for (AlarmListViewItem* item = firstChild(); item; item = item->nextSibling())
262  item->updateTimeToAlarm(now, forceDisplay);
263  }
264 }
265 
266 /******************************************************************************
267 * Add an event to every list instance.
268 * The selection highlight is moved to the new event in the specified instance only.
269 */
270 void AlarmListView::addEvent(const KAEvent& event, EventListViewBase* view)
271 {
272  TQDateTime now = TQDateTime::currentDateTime();
273  for (InstanceListConstIterator it = mInstanceList.begin(); it != mInstanceList.end(); ++it)
274  static_cast<AlarmListView*>(*it)->addEntry(event, now, true, (*it == view));
275 }
276 
277 /******************************************************************************
278 * Add a new item to the list.
279 */
280 AlarmListViewItem* AlarmListView::addEntry(const KAEvent& event, const TQDateTime& now, bool setSize, bool reselect)
281 {
282  if (!mShowExpired && event.expired())
283  return 0;
284  AlarmListViewItem* item = new AlarmListViewItem(this, event, now);
285  return static_cast<AlarmListViewItem*>(EventListViewBase::addEntry(item, setSize, reselect));
286 }
287 
288 /******************************************************************************
289 * Create a new list item for addEntry().
290 */
291 EventListViewItemBase* AlarmListView::createItem(const KAEvent& event)
292 {
293  return new AlarmListViewItem(this, event, TQDateTime::currentDateTime());
294 }
295 
296 /******************************************************************************
297 * Check whether an item's alarm has expired.
298 */
299 bool AlarmListView::expired(AlarmListViewItem* item) const
300 {
301  return item->event().expired();
302 }
303 
304 /******************************************************************************
305 * Return the column order.
306 */
307 TQValueList<int> AlarmListView::columnOrder() const
308 {
309  TQHeader* hdr = header();
310  int order[COLUMN_COUNT];
311  order[TIME_COLUMN] = hdr->mapToIndex(mColumn[TIME_COLUMN]);
312  order[TIME_TO_COLUMN] = hdr->mapToIndex(mColumn[TIME_TO_COLUMN]);
313  order[REPEAT_COLUMN] = hdr->mapToIndex(mColumn[REPEAT_COLUMN]);
314  order[COLOUR_COLUMN] = hdr->mapToIndex(mColumn[COLOUR_COLUMN]);
315  order[TYPE_COLUMN] = hdr->mapToIndex(mColumn[TYPE_COLUMN]);
316  order[MESSAGE_COLUMN] = hdr->mapToIndex(mColumn[MESSAGE_COLUMN]);
317  TQValueList<int> orderList;
318  for (int i = 0; i < COLUMN_COUNT; ++i)
319  orderList += order[i];
320  return orderList;
321 }
322 
323 /******************************************************************************
324 * Returns the TQWhatsThis text for a specified column.
325 */
326 TQString AlarmListView::whatsThisText(int column) const
327 {
328  if (column == mColumn[TIME_COLUMN])
329  return i18n("Next scheduled date and time of the alarm");
330  if (column == mColumn[TIME_TO_COLUMN])
331  return i18n("How long until the next scheduled trigger of the alarm");
332  if (column == mColumn[REPEAT_COLUMN])
333  return i18n("How often the alarm recurs");
334  if (column == mColumn[COLOUR_COLUMN])
335  return i18n("Background color of alarm message");
336  if (column == mColumn[TYPE_COLUMN])
337  return i18n("Alarm type (message, file, command or email)");
338  if (column == mColumn[MESSAGE_COLUMN])
339  return i18n("Alarm message text, URL of text file to display, command to execute, or email subject line");
340  return i18n("List of scheduled alarms");
341 }
342 
343 /******************************************************************************
344 * Called when the mouse button is pressed.
345 * Records the position of the mouse when the left button is pressed, for use
346 * in drag operations.
347 */
348 void AlarmListView::contentsMousePressEvent(TQMouseEvent* e)
349 {
350  TQListView::contentsMousePressEvent(e);
351  if (e->button() == TQt::LeftButton)
352  {
353  TQPoint p(contentsToViewport(e->pos()));
354  if (itemAt(p))
355  {
356  mMousePressPos = e->pos();
357  mMousePressed = true;
358  }
359  mDragging = false;
360  }
361 }
362 
363 /******************************************************************************
364 * Called when the mouse is moved.
365 * Creates a drag object when the mouse drags one or more selected items.
366 */
367 void AlarmListView::contentsMouseMoveEvent(TQMouseEvent* e)
368 {
369  TQListView::contentsMouseMoveEvent(e);
370  if (mMousePressed
371  && (mMousePressPos - e->pos()).manhattanLength() > TQApplication::startDragDistance())
372  {
373  // Create a calendar object containing all the currently selected alarms
374  kdDebug(5950) << "AlarmListView::contentsMouseMoveEvent(): drag started" << endl;
375  mMousePressed = false;
376  KCal::CalendarLocal cal(TQString::fromLatin1("UTC"));
377  cal.setLocalTime(); // write out using local time (i.e. no time zone)
378  TQValueList<EventListViewItemBase*> items = selectedItems();
379  if (!items.count())
380  return;
381  for (TQValueList<EventListViewItemBase*>::Iterator it = items.begin(); it != items.end(); ++it)
382  {
383  const KAEvent& event = (*it)->event();
384  KCal::Event* kcalEvent = new KCal::Event;
385  event.updateKCalEvent(*kcalEvent, false, true);
386  kcalEvent->setUid(event.id());
387  cal.addEvent(kcalEvent);
388  }
389 
390  // Create the drag object for the destination program to receive
391  mDragging = true;
392  KCal::ICalDrag* dobj = new KCal::ICalDrag(&cal, this);
393  dobj->dragCopy(); // the drag operation will copy the alarms
394  }
395 }
396 
397 /******************************************************************************
398 * Called when the mouse button is released.
399 * Notes that the mouse left button is no longer pressed, for use in drag
400 * operations.
401 */
402 void AlarmListView::contentsMouseReleaseEvent(TQMouseEvent *e)
403 {
404  TQListView::contentsMouseReleaseEvent(e);
405  mMousePressed = false;
406  mDragging = false;
407 }
408 
409 
410 /*=============================================================================
411 = Class: AlarmListViewItem
412 = Contains the details of one alarm for display in the AlarmListView.
413 =============================================================================*/
414 int AlarmListViewItem::mTimeHourPos = -2;
415 int AlarmListViewItem::mDigitWidth = -1;
416 
417 AlarmListViewItem::AlarmListViewItem(AlarmListView* parent, const KAEvent& event, const TQDateTime& now)
418  : EventListViewItemBase(parent, event),
419  mMessageTruncated(false),
420  mTimeToAlarmShown(false)
421 {
422  setLastColumnText(); // set the message column text
423 
424  DateTime dateTime = event.expired() ? event.startDateTime() : event.displayDateTime();
425  if (parent->column(AlarmListView::TIME_COLUMN) >= 0)
426  setText(parent->column(AlarmListView::TIME_COLUMN), alarmTimeText(dateTime));
427  if (parent->column(AlarmListView::TIME_TO_COLUMN) >= 0)
428  {
429  TQString tta = timeToAlarmText(now);
430  setText(parent->column(AlarmListView::TIME_TO_COLUMN), tta);
431  mTimeToAlarmShown = !tta.isNull();
432  }
433  TQTime t = dateTime.time();
434  mDateTimeOrder.sprintf("%04d%03d%02d%02d", dateTime.date().year(), dateTime.date().dayOfYear(),
435  t.hour(), t.minute());
436 
437  int repeatOrder = 0;
438  int repeatInterval = 0;
439  TQString repeatText = event.recurrenceText(true); // text displayed in Repeat column
440  if (repeatText.isEmpty())
441  repeatText = event.repetitionText(true);
442  if (event.repeatAtLogin())
443  repeatOrder = 1;
444  else
445  {
446  repeatInterval = event.recurInterval();
447  switch (event.recurType())
448  {
449  case KARecurrence::MINUTELY:
450  repeatOrder = 2;
451  break;
452  case KARecurrence::DAILY:
453  repeatOrder = 3;
454  break;
455  case KARecurrence::WEEKLY:
456  repeatOrder = 4;
457  break;
458  case KARecurrence::MONTHLY_DAY:
459  case KARecurrence::MONTHLY_POS:
460  repeatOrder = 5;
461  break;
462  case KARecurrence::ANNUAL_DATE:
463  case KARecurrence::ANNUAL_POS:
464  repeatOrder = 6;
465  break;
466  case KARecurrence::NO_RECUR:
467  default:
468  break;
469  }
470  }
471  setText(parent->column(AlarmListView::REPEAT_COLUMN), repeatText);
472  mRepeatOrder.sprintf("%c%08d", '0' + repeatOrder, repeatInterval);
473 
474  bool showColour = (event.action() == KAEvent::MESSAGE || event.action() == KAEvent::FILE);
475  mColourOrder.sprintf("%06u", (showColour ? event.bgColour().rgb() : 0));
476 
477  mTypeOrder.sprintf("%02d", event.action());
478 }
479 
480 /******************************************************************************
481 * Return the single line alarm summary text.
482 */
483 TQString AlarmListViewItem::alarmText(const KAEvent& event) const
484 {
485  bool truncated;
486  TQString text = AlarmText::summary(event, 1, &truncated);
487  mMessageTruncated = truncated;
488  return text;
489 }
490 
491 /******************************************************************************
492 * Return the alarm time text in the form "date time".
493 */
494 TQString AlarmListViewItem::alarmTimeText(const DateTime& dateTime) const
495 {
496  TDELocale* locale = TDEGlobal::locale();
497  TQString dateTimeText = locale->formatDate(dateTime.date(), true);
498  if (!dateTime.isDateOnly())
499  {
500  dateTimeText += ' ';
501  TQString time = locale->formatTime(dateTime.time());
502  if (mTimeHourPos == -2)
503  {
504  // Initialise the position of the hour within the time string, if leading
505  // zeroes are omitted, so that displayed times can be aligned with each other.
506  mTimeHourPos = -1; // default = alignment isn't possible/sensible
507  if (!TQApplication::reverseLayout()) // don't try to align right-to-left languages
508  {
509  TQString fmt = locale->timeFormat();
510  int i = fmt.find(TQRegExp("%[kl]")); // check if leading zeroes are omitted
511  if (i >= 0 && i == fmt.find('%')) // and whether the hour is first
512  mTimeHourPos = i; // yes, so need to align
513  }
514  }
515  if (mTimeHourPos >= 0 && (int)time.length() > mTimeHourPos + 1
516  && time[mTimeHourPos].isDigit() && !time[mTimeHourPos + 1].isDigit())
517  dateTimeText += '~'; // improve alignment of times with no leading zeroes
518  dateTimeText += time;
519  }
520  return dateTimeText + ' ';
521 }
522 
523 /******************************************************************************
524 * Return the time-to-alarm text.
525 */
526 TQString AlarmListViewItem::timeToAlarmText(const TQDateTime& now) const
527 {
528  if (event().expired())
529  return TQString();
530  DateTime dateTime = event().displayDateTime();
531  if (dateTime.isDateOnly())
532  {
533  int days = now.date().daysTo(dateTime.date());
534  return i18n("n days", " %1d ").arg(days);
535  }
536  int mins = (now.secsTo(dateTime.dateTime()) + 59) / 60;
537  if (mins < 0)
538  return TQString();
539  char minutes[3] = "00";
540  minutes[0] = (mins%60) / 10 + '0';
541  minutes[1] = (mins%60) % 10 + '0';
542  if (mins < 24*60)
543  return i18n("hours:minutes", " %1:%2 ").arg(mins/60).arg(minutes);
544  int days = mins / (24*60);
545  mins = mins % (24*60);
546  return i18n("days hours:minutes", " %1d %2:%3 ").arg(days).arg(mins/60).arg(minutes);
547 }
548 
549 /******************************************************************************
550 * Update the displayed time-to-alarm value.
551 * The updated value is only displayed if it is different from the existing value,
552 * or if 'forceDisplay' is true.
553 */
554 void AlarmListViewItem::updateTimeToAlarm(const TQDateTime& now, bool forceDisplay)
555 {
556  if (event().expired())
557  {
558  if (forceDisplay || mTimeToAlarmShown)
559  {
560  setText(alarmListView()->column(AlarmListView::TIME_TO_COLUMN), TQString());
561  mTimeToAlarmShown = false;
562  }
563  }
564  else
565  {
566  TQString tta = timeToAlarmText(now);
567  if (forceDisplay || tta != text(alarmListView()->column(AlarmListView::TIME_TO_COLUMN)))
568  setText(alarmListView()->column(AlarmListView::TIME_TO_COLUMN), tta);
569  mTimeToAlarmShown = !tta.isNull();
570  }
571 }
572 
573 /******************************************************************************
574 * Paint one value in one of the columns in the list view.
575 */
576 void AlarmListViewItem::paintCell(TQPainter* painter, const TQColorGroup& cg, int column, int width, int /*align*/)
577 {
578  const AlarmListView* listView = alarmListView();
579  int margin = listView->itemMargin();
580  TQRect box(margin, margin, width - margin*2, height() - margin*2); // area within which to draw
581  bool selected = isSelected();
582  TQColor bgColour = selected ? cg.highlight() : cg.base();
583  TQColor fgColour = selected ? cg.highlightedText()
584  : !event().enabled() ? Preferences::disabledColour()
585  : event().expired() ? Preferences::expiredColour() : cg.text();
586  painter->setPen(fgColour);
587  painter->fillRect(0, 0, width, height(), bgColour);
588 
589  if (column == listView->column(AlarmListView::TIME_COLUMN))
590  {
591  int i = -1;
592  TQString str = text(column);
593  if (mTimeHourPos >= 0)
594  {
595  // Need to pad out spacing to align times without leading zeroes
596  i = str.find(" ~");
597  if (i >= 0)
598  {
599  if (mDigitWidth < 0)
600  mDigitWidth = painter->fontMetrics().width("0");
601  TQString date = str.left(i + 1);
602  int w = painter->fontMetrics().width(date) + mDigitWidth;
603  painter->drawText(box, AlignVCenter, date);
604  box.setLeft(box.left() + w);
605  painter->drawText(box, AlignVCenter, str.mid(i + 2));
606  }
607  }
608  if (i < 0)
609  painter->drawText(box, AlignVCenter, str);
610  }
611  else if (column == listView->column(AlarmListView::TIME_TO_COLUMN))
612  painter->drawText(box, AlignVCenter | AlignRight, text(column));
613  else if (column == listView->column(AlarmListView::REPEAT_COLUMN))
614  painter->drawText(box, AlignVCenter | AlignHCenter, text(column));
615  else if (column == listView->column(AlarmListView::COLOUR_COLUMN))
616  {
617  // Paint the cell the colour of the alarm message
618  if (event().action() == KAEvent::MESSAGE || event().action() == KAEvent::FILE)
619  painter->fillRect(box, event().bgColour());
620  }
621  else if (column == listView->column(AlarmListView::TYPE_COLUMN))
622  {
623  // Display the alarm type icon, horizontally and vertically centred in the cell
624  TQPixmap* pixmap = eventIcon();
625  TQRect pixmapRect = pixmap->rect();
626  int diff = box.height() - pixmap->height();
627  if (diff < 0)
628  {
629  pixmapRect.setTop(-diff / 2);
630  pixmapRect.setHeight(box.height());
631  }
632  TQPoint iconTopLeft(box.left() + (box.width() - pixmapRect.width()) / 2,
633  box.top() + (diff > 0 ? diff / 2 : 0));
634  painter->drawPixmap(iconTopLeft, *pixmap, pixmapRect);
635  }
636  else if (column == listView->column(AlarmListView::MESSAGE_COLUMN))
637  {
638  if (!selected && listView->drawMessageInColour())
639  {
640  painter->fillRect(box, event().bgColour());
641  painter->setBackgroundColor(event().bgColour());
642 // painter->setPen(event().fgColour());
643  }
644  TQString txt = text(column);
645  painter->drawText(box, AlignVCenter, txt);
646  mMessageColWidth = listView->fontMetrics().boundingRect(txt).width();
647  }
648 }
649 
650 /******************************************************************************
651 * Return the width needed for the icons in the alarm type column.
652 */
653 int AlarmListViewItem::typeIconWidth(AlarmListView* v)
654 {
655  return iconWidth() + 2 * v->style().pixelMetric(TQStyle::PM_DefaultFrameWidth);
656 }
657 
658 /******************************************************************************
659 * Return the column sort order for one item in the list.
660 */
661 TQString AlarmListViewItem::key(int column, bool) const
662 {
663  AlarmListView* listView = alarmListView();
664  if (column == listView->column(AlarmListView::TIME_COLUMN)
665  || column == listView->column(AlarmListView::TIME_TO_COLUMN))
666  return mDateTimeOrder;
667  if (column == listView->column(AlarmListView::REPEAT_COLUMN))
668  return mRepeatOrder;
669  if (column == listView->column(AlarmListView::COLOUR_COLUMN))
670  return mColourOrder;
671  if (column == listView->column(AlarmListView::TYPE_COLUMN))
672  return mTypeOrder;
673  return text(column).lower();
674 }
675 
676 
677 /*=============================================================================
678 = Class: AlarmListTooltip
679 = Displays the full alarm text in a tooltip when necessary.
680 =============================================================================*/
681 
682 /******************************************************************************
683 * Displays the full alarm text in a tooltip, if not all the text is displayed.
684 */
685 void AlarmListTooltip::maybeTip(const TQPoint& pt)
686 {
687  AlarmListView* listView = (AlarmListView*)parentWidget()->parentWidget();
688  int column = listView->column(AlarmListView::MESSAGE_COLUMN);
689  int xOffset = listView->contentsX();
690  if (listView->header()->sectionAt(pt.x() + xOffset) == column)
691  {
692  AlarmListViewItem* item = (AlarmListViewItem*)listView->itemAt(pt);
693  if (item)
694  {
695  int columnX = listView->header()->sectionPos(column) - xOffset;
696  int columnWidth = listView->columnWidth(column);
697  int widthNeeded = item->messageColWidthNeeded();
698  if (!item->messageTruncated() && columnWidth >= widthNeeded)
699  {
700  if (columnX + widthNeeded <= listView->viewport()->width())
701  return;
702  }
703  TQRect rect = listView->itemRect(item);
704  rect.setLeft(columnX);
705  rect.setWidth(columnWidth);
706  kdDebug(5950) << "AlarmListTooltip::maybeTip(): display\n";
707  tip(rect, AlarmText::summary(item->event(), 10)); // display up to 10 lines of text
708  }
709  }
710 }
711 
Provides read and write access to calendar files.
Definition: alarmcalendar.h:37
KAEvent corresponds to a KCal::Event instance.
Definition: alarmevent.h:232
void setUid(const TQString &)
const Alarm::List & alarms() const
miscellaneous functions
the KAlarm application object