33#include <libkcal/icaldrag.h> 
   34#include <libkcal/calendarlocal.h> 
   36#include "alarmcalendar.h" 
   40#include "preferences.h" 
   41#include "alarmlistview.moc" 
   44class AlarmListTooltip : 
public TQToolTip
 
   47        AlarmListTooltip(TQWidget* parent) : TQToolTip(parent) { }
 
   48        virtual ~AlarmListTooltip() {}
 
   50        virtual void maybeTip(
const TQPoint&);
 
   58TQValueList<EventListViewBase*>  AlarmListView::mInstanceList;
 
   59bool                            AlarmListView::mDragging = 
false;
 
   62AlarmListView::AlarmListView(
const TQValueList<int>& order, TQWidget* parent, 
const char* name)
 
   63    : EventListViewBase(parent, name),
 
   65      mDrawMessageInColour(false),
 
   68    static TQString titles[COLUMN_COUNT] = {
 
   74        i18n(
"Message, File or Command")
 
   77    setSelectionMode(TQListView::Extended);
 
   82    if (order.count() >= COLUMN_COUNT)
 
   85        bool posns[COLUMN_COUNT];
 
   86        for (i = 0;  i < COLUMN_COUNT;  ++i)
 
   88        for (i = 0;  i < COLUMN_COUNT;  ++i)
 
   91            if (ord < COLUMN_COUNT  &&  ord >= 0)
 
   98        for (i = 0;  i < COLUMN_COUNT;  ++i)
 
  101        if (ok  &&  mColumn[MESSAGE_COLUMN] != MESSAGE_COLUMN)
 
  105            int messageCol = mColumn[MESSAGE_COLUMN];
 
  106            for (i = 0;  i < COLUMN_COUNT;  ++i)
 
  107                if (mColumn[i] > messageCol)
 
  109            mColumn[MESSAGE_COLUMN] = MESSAGE_COLUMN;
 
  116        for (i = 0;  i < COLUMN_COUNT;  ++i)
 
  121    for (i = 0;  i < COLUMN_COUNT;  ++i)
 
  123        for (
int j = 0;  j < COLUMN_COUNT;  ++j)
 
  126                if (j != MESSAGE_COLUMN)
 
  127                    addColumn(titles[j]);
 
  131    addLastColumn(titles[MESSAGE_COLUMN]);
 
  133    setSorting(mColumn[TIME_COLUMN]);           
 
  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);
 
  140    setColumnWidth(mColumn[COLOUR_COLUMN], itemHeight() * 3/4);
 
  141    setColumnWidthMode(mColumn[COLOUR_COLUMN], TQListView::Manual);
 
  146    setColumnWidth(mColumn[TYPE_COLUMN], AlarmListViewItem::typeIconWidth(
this));
 
  147    setColumnWidthMode(mColumn[TYPE_COLUMN], TQListView::Manual);
 
  148    header()->setResizeEnabled(
false, mColumn[TYPE_COLUMN]);
 
  150    mInstanceList.append(
this);
 
  152    mTooltip = 
new AlarmListTooltip(viewport());
 
  155AlarmListView::~AlarmListView()
 
  159    mInstanceList.remove(
this);
 
  165void AlarmListView::populate()
 
  168    KCal::Event::List events;
 
  169    KCal::Event::List::ConstIterator it;
 
  170    TQDateTime now = TQDateTime::currentDateTime();
 
  176            events = cal->events();
 
  177                        for (it = events.begin();  it != events.end();  ++it)
 
  180                if (kcalEvent->
alarms().count() > 0)
 
  182                    event.set(*kcalEvent);
 
  183                    addEntry(event, now);
 
  188    events = AlarmCalendar::activeCalendar()->events();
 
  189        for (it = events.begin();  it != events.end();  ++it)
 
  192        event.set(*kcalEvent);
 
  193        if (mShowExpired  ||  !event.expired())
 
  194            addEntry(event, now);
 
  201void AlarmListView::selectTimeColumns(
bool time, 
bool timeTo)
 
  203    if (!time  &&  !timeTo)
 
  205    bool changed = 
false;
 
  206    int w = columnWidth(mColumn[TIME_COLUMN]);
 
  210        int colWidth = mTimeColumnHeaderWidth;
 
  211        TQFontMetrics fm = fontMetrics();
 
  212        for (AlarmListViewItem* item = firstChild();  item;  item = item->nextSibling())
 
  214            int w = item->width(fm, 
this, mColumn[TIME_COLUMN]);
 
  218        setColumnWidth(mColumn[TIME_COLUMN], colWidth);
 
  219        setColumnWidthMode(mColumn[TIME_COLUMN], TQListView::Maximum);
 
  225        setColumnWidthMode(mColumn[TIME_COLUMN], TQListView::Manual);
 
  226        setColumnWidth(mColumn[TIME_COLUMN], 0);
 
  229    w = columnWidth(mColumn[TIME_TO_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);
 
  239    else if (!timeTo  &&  w)
 
  242        setColumnWidthMode(mColumn[TIME_TO_COLUMN], TQListView::Manual);
 
  243        setColumnWidth(mColumn[TIME_TO_COLUMN], 0);
 
  256void AlarmListView::updateTimeToAlarms(
bool forceDisplay)
 
  258    if (forceDisplay  ||  columnWidth(mColumn[TIME_TO_COLUMN]))
 
  260        TQDateTime now = TQDateTime::currentDateTime();
 
  261        for (AlarmListViewItem* item = firstChild();  item;  item = item->nextSibling())
 
  262            item->updateTimeToAlarm(now, forceDisplay);
 
  270void AlarmListView::addEvent(
const KAEvent& event, EventListViewBase* view)
 
  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));
 
  280AlarmListViewItem* AlarmListView::addEntry(
const KAEvent& event, 
const TQDateTime& now, 
bool setSize, 
bool reselect)
 
  282    if (!mShowExpired  &&  event.expired())
 
  284    AlarmListViewItem* item = 
new AlarmListViewItem(
this, event, now);
 
  285    return static_cast<AlarmListViewItem*
>(EventListViewBase::addEntry(item, setSize, reselect));
 
  291EventListViewItemBase* AlarmListView::createItem(
const KAEvent& event)
 
  293    return new AlarmListViewItem(
this, event, TQDateTime::currentDateTime());
 
  299bool AlarmListView::expired(AlarmListViewItem* item)
 const 
  301    return item->event().expired();
 
  307TQValueList<int> AlarmListView::columnOrder()
 const 
  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];
 
  326TQString AlarmListView::whatsThisText(
int column)
 const 
  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");
 
  348void AlarmListView::contentsMousePressEvent(TQMouseEvent* e)
 
  350    TQListView::contentsMousePressEvent(e);
 
  351    if (e->button() == TQt::LeftButton)
 
  353        TQPoint p(contentsToViewport(e->pos()));
 
  356            mMousePressPos = e->pos();
 
  357            mMousePressed  = 
true;
 
  367void AlarmListView::contentsMouseMoveEvent(TQMouseEvent* e)
 
  369    TQListView::contentsMouseMoveEvent(e);
 
  371    &&  (mMousePressPos - e->pos()).manhattanLength() > TQApplication::startDragDistance())
 
  374        kdDebug(5950) << 
"AlarmListView::contentsMouseMoveEvent(): drag started" << endl;
 
  375        mMousePressed = 
false;
 
  378        TQValueList<EventListViewItemBase*> items = selectedItems();
 
  381        for (TQValueList<EventListViewItemBase*>::Iterator it = items.begin();  it != items.end();  ++it)
 
  383            const KAEvent& 
event = (*it)->event();
 
  385            event.updateKCalEvent(*kcalEvent, 
false, 
true);
 
  386            kcalEvent->
setUid(event.id());
 
  387            cal.addEvent(kcalEvent);
 
  402void AlarmListView::contentsMouseReleaseEvent(TQMouseEvent *e)
 
  404    TQListView::contentsMouseReleaseEvent(e);
 
  405    mMousePressed = 
false;
 
  414int AlarmListViewItem::mTimeHourPos = -2;
 
  415int AlarmListViewItem::mDigitWidth  = -1;
 
  417AlarmListViewItem::AlarmListViewItem(AlarmListView* parent, 
const KAEvent& event, 
const TQDateTime& now)
 
  418    : EventListViewItemBase(parent, event),
 
  419      mMessageTruncated(false),
 
  420      mTimeToAlarmShown(false)
 
  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)
 
  429        TQString tta = timeToAlarmText(now);
 
  430        setText(parent->column(AlarmListView::TIME_TO_COLUMN), tta);
 
  431        mTimeToAlarmShown = !tta.isNull();
 
  433    TQTime t = dateTime.time();
 
  434    mDateTimeOrder.sprintf(
"%04d%03d%02d%02d", dateTime.date().year(), dateTime.date().dayOfYear(),
 
  435                                               t.hour(), t.minute());
 
  438    int repeatInterval = 0;
 
  439    TQString repeatText = 
event.recurrenceText(
true);     
 
  440    if (repeatText.isEmpty())
 
  441        repeatText = 
event.repetitionText(
true);
 
  442    if (event.repeatAtLogin())
 
  446        repeatInterval = 
event.recurInterval();
 
  447        switch (event.recurType())
 
  449            case KARecurrence::MINUTELY:
 
  452            case KARecurrence::DAILY:
 
  455            case KARecurrence::WEEKLY:
 
  458            case KARecurrence::MONTHLY_DAY:
 
  459            case KARecurrence::MONTHLY_POS:
 
  462            case KARecurrence::ANNUAL_DATE:
 
  463            case KARecurrence::ANNUAL_POS:
 
  466            case KARecurrence::NO_RECUR:
 
  471    setText(parent->column(AlarmListView::REPEAT_COLUMN), repeatText);
 
  472    mRepeatOrder.sprintf(
"%c%08d", 
'0' + repeatOrder, repeatInterval);
 
  474    bool showColour = (
event.action() == KAEvent::MESSAGE || 
event.action() == KAEvent::FILE);
 
  475    mColourOrder.sprintf(
"%06u", (showColour ? event.bgColour().rgb() : 0));
 
  477    mTypeOrder.sprintf(
"%02d", event.action());
 
  483TQString AlarmListViewItem::alarmText(
const KAEvent& event)
 const 
  486    TQString text = AlarmText::summary(event, 1, &truncated);
 
  487    mMessageTruncated = truncated;
 
  494TQString AlarmListViewItem::alarmTimeText(
const DateTime& dateTime)
 const 
  496    TDELocale* locale = TDEGlobal::locale();
 
  497    TQString dateTimeText = locale->formatDate(dateTime.date(), 
true);
 
  498    if (!dateTime.isDateOnly())
 
  501        TQString time = locale->formatTime(dateTime.time());
 
  502        if (mTimeHourPos == -2)
 
  507            if (!TQApplication::reverseLayout())    
 
  509                TQString fmt = locale->timeFormat();
 
  510                int i = fmt.find(TQRegExp(
"%[kl]"));   
 
  511                if (i >= 0  &&  i == fmt.find(
'%'))   
 
  515        if (mTimeHourPos >= 0  &&  (
int)time.length() > mTimeHourPos + 1
 
  516        &&  time[mTimeHourPos].isDigit()  &&  !time[mTimeHourPos + 1].isDigit())
 
  518        dateTimeText += time;
 
  520    return dateTimeText + 
' ';
 
  526TQString AlarmListViewItem::timeToAlarmText(
const TQDateTime& now)
 const 
  528    if (event().expired())
 
  530    DateTime dateTime = event().displayDateTime();
 
  531    if (dateTime.isDateOnly())
 
  533        int days = now.date().daysTo(dateTime.date());
 
  534        return i18n(
"n days", 
" %1d ").arg(days);
 
  536    int mins = (now.secsTo(dateTime.dateTime()) + 59) / 60;
 
  539    char minutes[3] = 
"00";
 
  540    minutes[0] = (mins%60) / 10 + 
'0';
 
  541    minutes[1] = (mins%60) % 10 + 
'0';
 
  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);
 
  554void AlarmListViewItem::updateTimeToAlarm(
const TQDateTime& now, 
bool forceDisplay)
 
  556    if (event().expired())
 
  558        if (forceDisplay  ||  mTimeToAlarmShown)
 
  560            setText(alarmListView()->column(AlarmListView::TIME_TO_COLUMN), TQString());
 
  561            mTimeToAlarmShown = 
false;
 
  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();
 
  576void AlarmListViewItem::paintCell(TQPainter* painter, 
const TQColorGroup& cg, 
int column, 
int width, 
int )
 
  578    const AlarmListView* listView = alarmListView();
 
  579    int    margin = listView->itemMargin();
 
  580    TQRect  box(margin, margin, width - margin*2, height() - margin*2);   
 
  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);
 
  589    if (column == listView->column(AlarmListView::TIME_COLUMN))
 
  592        TQString str = text(column);
 
  593        if (mTimeHourPos >= 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));
 
  609            painter->drawText(box, AlignVCenter, str);
 
  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))
 
  618        if (event().action() == KAEvent::MESSAGE || event().action() == KAEvent::FILE)
 
  619            painter->fillRect(box, event().bgColour());
 
  621    else if (column == listView->column(AlarmListView::TYPE_COLUMN))
 
  624        TQPixmap* pixmap = eventIcon();
 
  625        TQRect pixmapRect = pixmap->rect();
 
  626        int diff = box.height() - pixmap->height();
 
  629            pixmapRect.setTop(-diff / 2);
 
  630            pixmapRect.setHeight(box.height());
 
  632        TQPoint iconTopLeft(box.left() + (box.width() - pixmapRect.width()) / 2,
 
  633                           box.top() + (diff > 0 ? diff / 2 : 0));
 
  634        painter->drawPixmap(iconTopLeft, *pixmap, pixmapRect);
 
  636    else if (column == listView->column(AlarmListView::MESSAGE_COLUMN))
 
  638        if (!selected  &&  listView->drawMessageInColour())
 
  640            painter->fillRect(box, event().bgColour());
 
  641            painter->setBackgroundColor(event().bgColour());
 
  644        TQString txt = text(column);
 
  645        painter->drawText(box, AlignVCenter, txt);
 
  646        mMessageColWidth = listView->fontMetrics().boundingRect(txt).width();
 
  653int AlarmListViewItem::typeIconWidth(AlarmListView* v)
 
  655    return iconWidth() +  2 * v->style().pixelMetric(TQStyle::PM_DefaultFrameWidth);
 
  661TQString AlarmListViewItem::key(
int column, 
bool)
 const 
  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))
 
  669    if (column == listView->column(AlarmListView::COLOUR_COLUMN))
 
  671    if (column == listView->column(AlarmListView::TYPE_COLUMN))
 
  673    return text(column).lower();
 
  685void AlarmListTooltip::maybeTip(
const TQPoint& pt)
 
  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)
 
  692        AlarmListViewItem* item = (AlarmListViewItem*)listView->itemAt(pt);
 
  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)
 
  700                if (columnX + widthNeeded <= listView->viewport()->width())
 
  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));    
 
Provides read and write access to calendar files.
KAEvent corresponds to a KCal::Event instance.
void setUid(const TQString &)
const Alarm::List & alarms() const
the KAlarm application object