kalarm Library API Documentation

alarmlistview.cpp

00001 /*
00002  *  alarmlistview.cpp  -  widget showing list of outstanding alarms
00003  *  Program:  kalarm
00004  *  (C) 2001, 2002 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
00017  *  along with this program; if not, write to the Free Software
00018  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
00019  */
00020 
00021 #include "kalarm.h"
00022 
00023 #include <qwhatsthis.h>
00024 #include <qheader.h>
00025 #include <qpainter.h>
00026 #include <qstyle.h>
00027 
00028 #include <kglobal.h>
00029 #include <klocale.h>
00030 #include <klistview.h>
00031 #include <kiconloader.h>
00032 #include <kdebug.h>
00033 
00034 #include "kalarmapp.h"
00035 #include "alarmcalendar.h"
00036 #include "alarmlistview.moc"
00037 
00038 
00039 class AlarmListWhatsThis : public QWhatsThis
00040 {
00041         public:
00042                 AlarmListWhatsThis(AlarmListView* lv) : QWhatsThis(lv), listView(lv) { }
00043                 virtual QString text(const QPoint&);
00044         private:
00045                 AlarmListView* listView;
00046 };
00047 
00048 
00049 /*=============================================================================
00050 =  Class: AlarmListView
00051 =  Displays the list of outstanding alarms.
00052 =============================================================================*/
00053 
00054 AlarmListView::AlarmListView(QWidget* parent, const char* name)
00055         : KListView(parent, name),
00056           drawMessageInColour_(false)
00057 {
00058         addColumn(i18n("Time"));           // date/time column
00059         addColumn(i18n("Repeat"));         // repeat count column
00060         addColumn(QString::null);          // colour column
00061         addColumn(i18n("Message, File or Command"));
00062         setColumnWidthMode(MESSAGE_COLUMN, QListView::Maximum);
00063         setAllColumnsShowFocus(true);
00064         setSorting(TIME_COLUMN);           // sort initially by date/time
00065         setShowSortIndicator(true);
00066         lastColumnHeaderWidth_ = columnWidth(MESSAGE_COLUMN);
00067         setColumnAlignment(REPEAT_COLUMN, Qt::AlignHCenter);
00068         setColumnWidthMode(REPEAT_COLUMN, QListView::Manual);
00069 
00070         // Find the height of the list items, and set the width of the colour column accordingly
00071         setColumnWidth(COLOUR_COLUMN, itemHeight() * 3/4);
00072         setColumnWidthMode(COLOUR_COLUMN, QListView::Manual);
00073         new AlarmListWhatsThis(this);
00074 }
00075 
00076 void AlarmListView::clear()
00077 {
00078         entries.clear();
00079         KListView::clear();
00080 }
00081 
00082 /******************************************************************************
00083 *  Refresh the list by clearing it and redisplaying all the current messages.
00084 */
00085 void AlarmListView::refresh()
00086 {
00087         QPtrList<Event> events = theApp()->getCalendar().events();
00088         clear();
00089         KAlarmEvent event;
00090         for (Event* kcalEvent = events.first();  kcalEvent;  kcalEvent = events.next())
00091         {
00092                 event.set(*kcalEvent);
00093                 addEntry(event);
00094         }
00095         resizeLastColumn();
00096 }
00097 
00098 AlarmListViewItem* AlarmListView::getEntry(const QString& eventID)
00099 {
00100         for (EntryMap::ConstIterator it = entries.begin();  it != entries.end();  ++it)
00101                 if (it.data().event.id() == eventID)
00102                         return it.key();
00103         return 0L;
00104 }
00105 
00106 AlarmListViewItem* AlarmListView::addEntry(const KAlarmEvent& event, bool setSize)
00107 {
00108         QDateTime dateTime = event.dateTime();
00109         AlarmItemData data;
00110         data.event = event;
00111         data.messageText = event.cleanText();
00112         int newline = data.messageText.find('\n');
00113         if (newline >= 0)
00114                 data.messageText = data.messageText.left(newline) + QString::fromLatin1("...");
00115         data.dateTimeText = KGlobal::locale()->formatDate(dateTime.date(), true);
00116         if (!event.anyTime())
00117         {
00118                 data.dateTimeText += ' ';
00119                 data.dateTimeText += KGlobal::locale()->formatTime(dateTime.time()) + ' ';
00120         }
00121         QString dateTimeOrder;
00122         dateTimeOrder.sprintf("%04d%03d%02d%02d", dateTime.date().year(), dateTime.date().dayOfYear(),
00123                                                   dateTime.time().hour(), dateTime.time().minute());
00124 
00125         int repeatOrder = 0;
00126         int repeatInterval = 0;
00127         data.repeatText = QString();    // text displayed in Repeat column
00128         if (event.repeatAtLogin())
00129         {
00130                 repeatOrder = 1;
00131                 data.repeatText = i18n("Login");
00132         }
00133         else
00134         {
00135                 repeatInterval = event.recurInterval();
00136                 switch (event.recurs())
00137                 {
00138                         case KAlarmEvent::MINUTELY:
00139                                 repeatOrder = 2;
00140                                 if (repeatInterval < 60)
00141                                 {
00142                                         data.repeatText = i18n("1 Minute", "%n Minutes", repeatInterval);
00143                                 }
00144                                 else if (repeatInterval % 60 == 0)
00145                                 {
00146                                         data.repeatText = i18n("1 Hour", "%n Hours", repeatInterval/60);
00147                                 }
00148                                 else
00149                                 {
00150                                         QString mins;
00151                                         data.repeatText = i18n("Hours and Minutes", "%1H %2M").arg(QString::number(repeatInterval/60)).arg(mins.sprintf("%02d", repeatInterval%60));
00152                                 }
00153                                 break;
00154                         case KAlarmEvent::DAILY:
00155                                 repeatOrder = 3;
00156                                 data.repeatText = i18n("1 Day","%n Days",repeatInterval);
00157                                 break;
00158                         case KAlarmEvent::WEEKLY:
00159                                 repeatOrder = 4;
00160                                 data.repeatText = i18n("1 Week","%n Weeks",repeatInterval);
00161                                 break;
00162                         case KAlarmEvent::MONTHLY_DAY:
00163                         case KAlarmEvent::MONTHLY_POS:
00164                                 repeatOrder = 5;
00165                                 data.repeatText = i18n("1 Month","%n Months",repeatInterval);
00166                                 break;
00167                         case KAlarmEvent::ANNUAL_DATE:
00168                         case KAlarmEvent::ANNUAL_POS:
00169                         case KAlarmEvent::ANNUAL_DAY:
00170                                 repeatOrder = 6;
00171                                 data.repeatText = i18n("1 Year","%n Years",repeatInterval);
00172                                 break;
00173                         case KAlarmEvent::NO_RECUR:
00174                         default:
00175                                 break;
00176                 }
00177         }
00178 
00179         // Set the texts to what will be displayed, so as to make the columns the correct width
00180         AlarmListViewItem* item = new AlarmListViewItem(this, data.dateTimeText, data.messageText);
00181         data.messageWidth = item->width(fontMetrics(), this, MESSAGE_COLUMN);
00182         setColumnWidthMode(REPEAT_COLUMN, QListView::Maximum);
00183         item->setText(REPEAT_COLUMN, data.repeatText);
00184         setColumnWidthMode(REPEAT_COLUMN, QListView::Manual);
00185 
00186         // Now set the texts so that the columns can be sorted. The visible text is different,
00187         // being displayed by paintCell().
00188         item->setText(TIME_COLUMN, dateTimeOrder);
00189         item->setText(REPEAT_COLUMN, QString().sprintf("%c%08d", '0' + repeatOrder, repeatInterval));
00190         item->setText(COLOUR_COLUMN, QString().sprintf("%06u", (event.type() == KAlarmAlarm::COMMAND ? 0 : event.colour().rgb())));
00191         item->setText(MESSAGE_COLUMN, data.messageText.lower());
00192         entries[item] = data;
00193         if (setSize)
00194                 resizeLastColumn();
00195         return item;
00196 }
00197 
00198 AlarmListViewItem* AlarmListView::updateEntry(AlarmListViewItem* item, const KAlarmEvent& newEvent, bool setSize)
00199 {
00200         deleteEntry(item);
00201         return addEntry(newEvent, setSize);
00202 }
00203 
00204 void AlarmListView::deleteEntry(AlarmListViewItem* item, bool setSize)
00205 {
00206         EntryMap::Iterator it = entries.find(item);
00207         if (it != entries.end())
00208         {
00209                 entries.remove(it);
00210                 delete item;
00211                 if (setSize)
00212                         resizeLastColumn();
00213                 emit itemDeleted();
00214         }
00215 }
00216 
00217 const AlarmItemData* AlarmListView::getData(AlarmListViewItem* item) const
00218 {
00219         EntryMap::ConstIterator it = entries.find(item);
00220         if (it == entries.end())
00221                 return 0L;
00222         return &it.data();
00223 }
00224 
00225 /******************************************************************************
00226 *  Sets the last column in the list view to extend at least to the right hand
00227 *  edge of the list view.
00228 */
00229 void AlarmListView::resizeLastColumn()
00230 {
00231         int messageWidth = lastColumnHeaderWidth_;
00232         for (EntryMap::ConstIterator it = entries.begin();  it != entries.end();  ++it)
00233         {
00234                 int mw = it.data().messageWidth;
00235                 if (mw > messageWidth)
00236                         messageWidth = mw;
00237         }
00238         int x = header()->sectionPos(AlarmListView::MESSAGE_COLUMN);
00239         int width = visibleWidth();
00240         width -= x;
00241         if (width < messageWidth)
00242                 width = messageWidth;
00243         setColumnWidth(AlarmListView::MESSAGE_COLUMN, width);
00244         if (contentsWidth() > x + width)
00245                 resizeContents(x + width, contentsHeight());
00246 }
00247 
00248 int AlarmListView::itemHeight()
00249 {
00250         EntryMap::ConstIterator it = entries.begin();
00251         if (it == entries.end())
00252         {
00253                 // The list is empty, so create a temporary item to find its height
00254                 QListViewItem* item = new QListViewItem(this, QString::null);
00255                 int height = item->height();
00256                 delete item;
00257                 return height;
00258         }
00259         else
00260                 return it.key()->height();
00261 }
00262 
00263 /*=============================================================================
00264 =  Class: AlarmListViewItem
00265 =  Contains the details of one alarm for display in the AlarmListView.
00266 =============================================================================*/
00267 QPixmap* AlarmListViewItem::textIcon;
00268 QPixmap* AlarmListViewItem::fileIcon;
00269 QPixmap* AlarmListViewItem::commandIcon;
00270 
00271 AlarmListViewItem::AlarmListViewItem(QListView* parent, const QString& dateTime, const QString& message)
00272         :  QListViewItem(parent, dateTime, QString(), message)
00273 {
00274 }
00275 
00276 void AlarmListViewItem::paintCell(QPainter* painter, const QColorGroup& cg, int column, int width, int /*align*/)
00277 {
00278         const AlarmListView* listView = alarmListView();
00279         const AlarmItemData* data   = listView->getData(this);
00280         int                  margin = listView->itemMargin();
00281         QRect box (margin, margin, width - margin*2, height() - margin*2);
00282         bool   selected = isSelected();
00283         QColor bgColour = selected ? cg.highlight() : cg.base();
00284         painter->setPen(selected ? cg.highlightedText() : cg.text());
00285         painter->fillRect(0, 0, width, height(), bgColour);
00286         switch (column)
00287         {
00288         case AlarmListView::TIME_COLUMN:
00289                 painter->drawText(box, AlignVCenter, data->dateTimeText);
00290                 break;
00291         case AlarmListView::REPEAT_COLUMN:
00292                 painter->drawText(box, AlignVCenter | AlignHCenter, data->repeatText);
00293                 break;
00294         case AlarmListView::COLOUR_COLUMN:
00295                 // Paint the cell the colour of the alarm message
00296                 if (data->event.type() == KAlarmAlarm::MESSAGE || data->event.type() == KAlarmAlarm::FILE)
00297                         painter->fillRect(box, data->event.colour());
00298                 break;
00299         case AlarmListView::MESSAGE_COLUMN:
00300         {
00301                 QPixmap* pixmap;
00302                 switch (data->event.type())
00303                 {
00304                         case KAlarmAlarm::FILE:
00305                                 if (!fileIcon)
00306                                         fileIcon = new QPixmap(SmallIcon("file"));
00307                                 pixmap = fileIcon;
00308                                 break;
00309                         case KAlarmAlarm::COMMAND:
00310                                 if (!commandIcon)
00311                                         commandIcon = new QPixmap(SmallIcon("exec"));
00312                                 pixmap = commandIcon;
00313                                 break;
00314                         case KAlarmAlarm::MESSAGE:
00315                         default:
00316                                 if (!textIcon)
00317                                         textIcon = new QPixmap(SmallIcon("message"));
00318                                 pixmap = textIcon;
00319                                 break;
00320                 }
00321                 int diff = box.height() - pixmap->height();
00322                 QRect pixmapRect = pixmap->rect();
00323                 if (diff < 0)
00324                 {
00325                         pixmapRect.setTop(-diff / 2);
00326                         pixmapRect.setHeight(box.height());
00327                 }
00328                 QRect iconRect(box.left(), box.top() + (diff > 0 ? diff / 2 : 0), pixmap->width(), (diff > 0 ? pixmap->height() : box.height()));
00329                 QRect textRect = box;
00330                 textRect.setLeft(box.left() + pixmap->width() + 2*listView->style().defaultFrameWidth());
00331                 if (!selected  &&  listView->drawMessageInColour())
00332                 {
00333                         QColor colour = data->event.colour();
00334                         painter->fillRect(box, colour);
00335                         painter->setBackgroundColor(colour);
00336 //                      painter->setPen(data->event->fgColour());
00337                 }
00338                 painter->drawPixmap(iconRect.topLeft(), *pixmap, pixmapRect);
00339                 painter->drawText(textRect, AlignVCenter, data->messageText);
00340                 break;
00341         }
00342         }
00343 }
00344 
00345 
00346 /*=============================================================================
00347 =  Class: AlarmListWhatsThis
00348 =  Sets What's This? text depending on where in the list view is clicked.
00349 =============================================================================*/
00350 
00351 QString AlarmListWhatsThis::text(const QPoint& pt)
00352 {
00353         QRect frame = listView->header()->frameGeometry();
00354         if (frame.contains(pt)
00355         ||  listView->itemAt(QPoint(listView->itemMargin(), pt.y())) && frame.contains(QPoint(pt.x(), frame.y())))
00356         {
00357                 switch (listView->header()->sectionAt(pt.x()))
00358                 {
00359                         case AlarmListView::TIME_COLUMN:     return i18n("Next scheduled date and time of the alarm");
00360                         case AlarmListView::COLOUR_COLUMN:   return i18n("Background color of alarm message");
00361                         case AlarmListView::MESSAGE_COLUMN:  return i18n("Alarm message text, URL of text file to display, or command to execute. The alarm type is indicated by the icon at the left.");
00362                         case AlarmListView::REPEAT_COLUMN:   return i18n("The alarm's repetition type or recurrence interval.");
00363                 }
00364         }
00365         return i18n("List of scheduled alarms");
00366 }
00367 
KDE Logo
This file is part of the documentation for kdelibs Version 3.1.5.
Documentation copyright © 1996-2002 the KDE developers.
Generated on Sun Feb 15 11:41:02 2004 by doxygen 1.3.5 written by Dimitri van Heesch, © 1997-2001