File indexing completed on 2024-04-28 03:59:04

0001 /*  -*- C++ -*-
0002     This file is part of the KDE libraries
0003     SPDX-FileCopyrightText: 1997 Tim D. Gilman <tdgilman@best.org>
0004     SPDX-FileCopyrightText: 1998-2001 Mirko Boehm <mirko@kde.org>
0005     SPDX-FileCopyrightText: 2007 John Layt <john@layt.net>
0006 
0007     SPDX-License-Identifier: LGPL-2.0-or-later
0008 */
0009 
0010 #include "kdatetable_p.h"
0011 
0012 #include <QAction>
0013 #include <QActionEvent>
0014 #include <QApplication>
0015 #include <QDate>
0016 #include <QFontDatabase>
0017 #include <QMenu>
0018 #include <QPainter>
0019 #include <QStyle>
0020 #include <QStyleOptionViewItem>
0021 
0022 #include <cmath>
0023 
0024 class KDateTable::KDateTablePrivate
0025 {
0026 public:
0027     KDateTablePrivate(KDateTable *qq)
0028         : q(qq)
0029     {
0030         m_popupMenuEnabled = false;
0031         m_useCustomColors = false;
0032         m_hoveredPos = -1;
0033         setDate(QDate::currentDate());
0034     }
0035 
0036     ~KDateTablePrivate()
0037     {
0038     }
0039 
0040     void setDate(const QDate &date);
0041     void nextMonth();
0042     void previousMonth();
0043     void beginningOfMonth();
0044     void endOfMonth();
0045     void beginningOfWeek();
0046     void endOfWeek();
0047 
0048     KDateTable *q;
0049 
0050     /**
0051      * The currently selected date.
0052      */
0053     QDate m_date;
0054 
0055     /**
0056      * The weekday number of the first day in the month [1..daysInWeek()].
0057      */
0058     int m_weekDayFirstOfMonth;
0059 
0060     /**
0061      * The number of days in the current month.
0062      */
0063     int m_numDaysThisMonth;
0064 
0065     /**
0066      * Save the size of the largest used cell content.
0067      */
0068     QRectF m_maxCell;
0069 
0070     /**
0071      * How many week rows we are to draw.
0072      */
0073     int m_numWeekRows;
0074 
0075     /**
0076      * How many day columns we are to draw, i.e. days in a week.
0077      */
0078     int m_numDayColumns;
0079 
0080     /**
0081      * The font size of the displayed text.
0082      */
0083     int fontsize;
0084 
0085     bool m_popupMenuEnabled;
0086     bool m_useCustomColors;
0087 
0088     struct DatePaintingMode {
0089         QColor fgColor;
0090         QColor bgColor;
0091         BackgroundMode bgMode;
0092     };
0093     QHash<int, DatePaintingMode> m_customPaintingModes;
0094 
0095     int m_hoveredPos;
0096 };
0097 
0098 KDateTable::KDateTable(const QDate &date, QWidget *parent)
0099     : QWidget(parent)
0100     , d(new KDateTablePrivate(this))
0101 {
0102     initWidget(date);
0103 }
0104 
0105 KDateTable::KDateTable(QWidget *parent)
0106     : QWidget(parent)
0107     , d(std::make_unique<KDateTablePrivate>(this))
0108 {
0109     initWidget(QDate::currentDate());
0110 }
0111 
0112 KDateTable::~KDateTable()
0113 {
0114 }
0115 
0116 void KDateTable::initWidget(const QDate &date)
0117 {
0118     d->m_numWeekRows = 7;
0119 
0120     setFontSize(10);
0121     setFocusPolicy(Qt::StrongFocus);
0122     setBackgroundRole(QPalette::Base);
0123     setAutoFillBackground(true);
0124     initAccels();
0125     setAttribute(Qt::WA_Hover, true);
0126 
0127     setDate(date);
0128 }
0129 
0130 void KDateTable::initAccels()
0131 {
0132     QAction *next = new QAction(this);
0133     next->setObjectName(QStringLiteral("next"));
0134     next->setShortcuts(QKeySequence::keyBindings(QKeySequence::Forward));
0135     next->setShortcutContext(Qt::WidgetWithChildrenShortcut);
0136     connect(next, &QAction::triggered, this, [this]() {
0137         d->nextMonth();
0138     });
0139 
0140     QAction *prior = new QAction(this);
0141     prior->setObjectName(QStringLiteral("prior"));
0142     prior->setShortcuts(QKeySequence::keyBindings(QKeySequence::Back));
0143     prior->setShortcutContext(Qt::WidgetWithChildrenShortcut);
0144     connect(prior, &QAction::triggered, this, [this]() {
0145         d->previousMonth();
0146     });
0147 
0148     QAction *beginMonth = new QAction(this);
0149     beginMonth->setObjectName(QStringLiteral("beginMonth"));
0150     beginMonth->setShortcuts(QKeySequence::keyBindings(QKeySequence::MoveToStartOfDocument));
0151     beginMonth->setShortcutContext(Qt::WidgetWithChildrenShortcut);
0152     connect(beginMonth, &QAction::triggered, this, [this]() {
0153         d->beginningOfMonth();
0154     });
0155 
0156     QAction *endMonth = new QAction(this);
0157     endMonth->setObjectName(QStringLiteral("endMonth"));
0158     endMonth->setShortcuts(QKeySequence::keyBindings(QKeySequence::MoveToEndOfDocument));
0159     endMonth->setShortcutContext(Qt::WidgetWithChildrenShortcut);
0160     connect(endMonth, &QAction::triggered, this, [this]() {
0161         d->endOfMonth();
0162     });
0163 
0164     QAction *beginWeek = new QAction(this);
0165     beginWeek->setObjectName(QStringLiteral("beginWeek"));
0166     beginWeek->setShortcuts(QKeySequence::keyBindings(QKeySequence::MoveToStartOfLine));
0167     beginWeek->setShortcutContext(Qt::WidgetWithChildrenShortcut);
0168     connect(beginWeek, &QAction::triggered, this, [this]() {
0169         d->beginningOfWeek();
0170     });
0171 
0172     QAction *endWeek = new QAction(this);
0173     endWeek->setObjectName(QStringLiteral("endWeek"));
0174     endWeek->setShortcuts(QKeySequence::keyBindings(QKeySequence::MoveToEndOfLine));
0175     endWeek->setShortcutContext(Qt::WidgetWithChildrenShortcut);
0176     connect(endWeek, &QAction::triggered, this, [this]() {
0177         d->endOfWeek();
0178     });
0179 }
0180 
0181 int KDateTable::posFromDate(const QDate &date)
0182 {
0183     int initialPosition = date.day();
0184     int offset = (d->m_weekDayFirstOfMonth - locale().firstDayOfWeek() + d->m_numDayColumns) % d->m_numDayColumns;
0185 
0186     // make sure at least one day of the previous month is visible.
0187     // adjust this < 1 if more days should be forced visible:
0188     if (offset < 1) {
0189         offset += d->m_numDayColumns;
0190     }
0191 
0192     return initialPosition + offset;
0193 }
0194 
0195 QDate KDateTable::dateFromPos(int position)
0196 {
0197     int offset = (d->m_weekDayFirstOfMonth - locale().firstDayOfWeek() + d->m_numDayColumns) % d->m_numDayColumns;
0198 
0199     // make sure at least one day of the previous month is visible.
0200     // adjust this < 1 if more days should be forced visible:
0201     if (offset < 1) {
0202         offset += d->m_numDayColumns;
0203     }
0204 
0205     return QDate(d->m_date.year(), d->m_date.month(), 1).addDays(position - offset);
0206 }
0207 
0208 void KDateTable::paintEvent(QPaintEvent *e)
0209 {
0210     QPainter p(this);
0211     const QRect &rectToUpdate = e->rect();
0212     double cellWidth = width() / (double)d->m_numDayColumns;
0213     double cellHeight = height() / (double)d->m_numWeekRows;
0214     int leftCol = (int)std::floor(rectToUpdate.left() / cellWidth);
0215     int topRow = (int)std::floor(rectToUpdate.top() / cellHeight);
0216     int rightCol = (int)std::ceil(rectToUpdate.right() / cellWidth);
0217     int bottomRow = (int)std::ceil(rectToUpdate.bottom() / cellHeight);
0218     bottomRow = qMin(bottomRow, d->m_numWeekRows - 1);
0219     rightCol = qMin(rightCol, d->m_numDayColumns - 1);
0220     if (layoutDirection() == Qt::RightToLeft) {
0221         p.translate((d->m_numDayColumns - leftCol - 1) * cellWidth, topRow * cellHeight);
0222     } else {
0223         p.translate(leftCol * cellWidth, topRow * cellHeight);
0224     }
0225     for (int i = leftCol; i <= rightCol; ++i) {
0226         for (int j = topRow; j <= bottomRow; ++j) {
0227             paintCell(&p, j, i);
0228             p.translate(0, cellHeight);
0229         }
0230         if (layoutDirection() == Qt::RightToLeft) {
0231             p.translate(-cellWidth, 0);
0232         } else {
0233             p.translate(cellWidth, 0);
0234         }
0235         p.translate(0, -cellHeight * (bottomRow - topRow + 1));
0236     }
0237 }
0238 
0239 void KDateTable::paintCell(QPainter *painter, int row, int col)
0240 {
0241     double w = (width() / (double)d->m_numDayColumns) - 1;
0242     double h = (height() / (double)d->m_numWeekRows) - 1;
0243     QRectF cell = QRectF(0, 0, w, h);
0244     QString cellText;
0245     QColor cellBackgroundColor;
0246     QColor cellTextColor;
0247     QFont cellFont = QFontDatabase::systemFont(QFontDatabase::GeneralFont);
0248     bool workingDay = false;
0249     int cellWeekDay;
0250     int pos;
0251 
0252     // Calculate the position of the cell in the grid
0253     pos = d->m_numDayColumns * (row - 1) + col;
0254 
0255     // Calculate what day of the week the cell is
0256     if (col + locale().firstDayOfWeek() <= d->m_numDayColumns) {
0257         cellWeekDay = col + locale().firstDayOfWeek();
0258     } else {
0259         cellWeekDay = col + locale().firstDayOfWeek() - d->m_numDayColumns;
0260     }
0261 
0262     // FIXME This is wrong if the widget is not using the global!
0263     // See if cell day is normally a working day
0264     if (locale().weekdays().first() <= locale().weekdays().last()) {
0265         if (cellWeekDay >= locale().weekdays().first() && cellWeekDay <= locale().weekdays().last()) {
0266             workingDay = true;
0267         }
0268     } else {
0269         if (cellWeekDay >= locale().weekdays().first() //
0270             || cellWeekDay <= locale().weekdays().last()) {
0271             workingDay = true;
0272         }
0273     }
0274 
0275     if (row == 0) {
0276         // We are drawing a header cell
0277 
0278         // If not a normal working day, then use "do not work today" color
0279         if (workingDay) {
0280             cellTextColor = palette().color(QPalette::WindowText);
0281         } else {
0282             cellTextColor = Qt::darkRed;
0283         }
0284         cellBackgroundColor = palette().color(QPalette::Window);
0285 
0286         // Set the text to the short day name and bold it
0287         cellFont.setBold(true);
0288         cellText = locale().dayName(cellWeekDay, QLocale::ShortFormat);
0289 
0290     } else {
0291         // We are drawing a day cell
0292 
0293         // Calculate the date the cell represents
0294         QDate cellDate = dateFromPos(pos);
0295 
0296         bool validDay = cellDate.isValid();
0297 
0298         // Draw the day number in the cell, if the date is not valid then we don't want to show it
0299         if (validDay) {
0300             cellText = locale().toString(cellDate.day());
0301         } else {
0302             cellText = QString();
0303         }
0304 
0305         if (!validDay || cellDate.month() != d->m_date.month()) {
0306             // we are either
0307             // ° painting an invalid day
0308             // ° painting a day of the previous month or
0309             // ° painting a day of the following month or
0310             cellBackgroundColor = palette().color(backgroundRole());
0311             cellTextColor = palette().color(QPalette::Disabled, QPalette::Text);
0312         } else {
0313             // Paint a day of the current month
0314 
0315             // Background Colour priorities will be (high-to-low):
0316             // * Selected Day Background Colour
0317             // * Customized Day Background Colour
0318             // * Normal Day Background Colour
0319 
0320             // Background Shape priorities will be (high-to-low):
0321             // * Customized Day Shape
0322             // * Normal Day Shape
0323 
0324             // Text Colour priorities will be (high-to-low):
0325             // * Customized Day Colour
0326             // * Day of Pray Colour (Red letter)
0327             // * Selected Day Colour
0328             // * Normal Day Colour
0329 
0330             // Determine various characteristics of the cell date
0331             bool selectedDay = (cellDate == date());
0332             bool currentDay = (cellDate == QDate::currentDate());
0333             bool dayOfPray = (cellDate.dayOfWeek() == Qt::Sunday);
0334             // TODO: Uncomment if QLocale ever gets the feature...
0335             // bool dayOfPray = ( cellDate.dayOfWeek() == locale().dayOfPray() );
0336             bool customDay = (d->m_useCustomColors && d->m_customPaintingModes.contains(cellDate.toJulianDay()));
0337 
0338             // Default values for a normal cell
0339             cellBackgroundColor = palette().color(backgroundRole());
0340             cellTextColor = palette().color(foregroundRole());
0341 
0342             // If we are drawing the current date, then draw it bold and active
0343             if (currentDay) {
0344                 cellFont.setBold(true);
0345                 cellTextColor = palette().color(QPalette::LinkVisited);
0346             }
0347 
0348             // if we are drawing the day cell currently selected in the table
0349             if (selectedDay) {
0350                 // set the background to highlighted
0351                 cellBackgroundColor = palette().color(QPalette::Highlight);
0352                 cellTextColor = palette().color(QPalette::HighlightedText);
0353             }
0354 
0355             // If custom colors or shape are required for this date
0356             if (customDay) {
0357                 KDateTablePrivate::DatePaintingMode mode = d->m_customPaintingModes[cellDate.toJulianDay()];
0358                 if (mode.bgMode != NoBgMode) {
0359                     if (!selectedDay) {
0360                         cellBackgroundColor = mode.bgColor;
0361                     }
0362                 }
0363                 cellTextColor = mode.fgColor;
0364             }
0365 
0366             // If the cell day is the day of religious observance, then always color text red unless Custom overrides
0367             if (!customDay && dayOfPray) {
0368                 cellTextColor = Qt::darkRed;
0369             }
0370         }
0371     }
0372 
0373     // Draw the background
0374     if (row == 0) {
0375         painter->setPen(cellBackgroundColor);
0376         painter->setBrush(cellBackgroundColor);
0377         painter->drawRect(cell);
0378     } else if (cellBackgroundColor != palette().color(backgroundRole()) || pos == d->m_hoveredPos) {
0379         QStyleOptionViewItem opt;
0380         opt.initFrom(this);
0381         opt.rect = cell.toRect();
0382         if (cellBackgroundColor != palette().color(backgroundRole())) {
0383             opt.palette.setBrush(QPalette::Highlight, cellBackgroundColor);
0384             opt.state |= QStyle::State_Selected;
0385         }
0386         if (pos == d->m_hoveredPos && opt.state & QStyle::State_Enabled) {
0387             opt.state |= QStyle::State_MouseOver;
0388         } else {
0389             opt.state &= ~QStyle::State_MouseOver;
0390         }
0391         opt.showDecorationSelected = true;
0392         opt.viewItemPosition = QStyleOptionViewItem::OnlyOne;
0393         style()->drawPrimitive(QStyle::PE_PanelItemViewItem, &opt, painter, this);
0394     }
0395 
0396     // Draw the text
0397     painter->setPen(cellTextColor);
0398     painter->setFont(cellFont);
0399     painter->drawText(cell, Qt::AlignCenter, cellText, &cell);
0400 
0401     // Draw the base line
0402     if (row == 0) {
0403         painter->setPen(palette().color(foregroundRole()));
0404         painter->drawLine(QPointF(0, h), QPointF(w, h));
0405     }
0406 
0407     // If the day cell we just drew is bigger than the current max cell sizes,
0408     // then adjust the max to the current cell
0409     if (cell.width() > d->m_maxCell.width()) {
0410         d->m_maxCell.setWidth(cell.width());
0411     }
0412     if (cell.height() > d->m_maxCell.height()) {
0413         d->m_maxCell.setHeight(cell.height());
0414     }
0415 }
0416 
0417 void KDateTable::KDateTablePrivate::nextMonth()
0418 {
0419     // setDate does validity checking for us
0420     q->setDate(m_date.addMonths(1));
0421 }
0422 
0423 void KDateTable::KDateTablePrivate::previousMonth()
0424 {
0425     // setDate does validity checking for us
0426     q->setDate(m_date.addMonths(-1));
0427 }
0428 
0429 void KDateTable::KDateTablePrivate::beginningOfMonth()
0430 {
0431     // setDate does validity checking for us
0432     q->setDate(QDate(m_date.year(), m_date.month(), 1));
0433 }
0434 
0435 void KDateTable::KDateTablePrivate::endOfMonth()
0436 {
0437     // setDate does validity checking for us
0438     q->setDate(QDate(m_date.year(), m_date.month() + 1, 0));
0439 }
0440 
0441 // JPL Do these make the assumption that first day of week is weekday 1? As it may not be.
0442 void KDateTable::KDateTablePrivate::beginningOfWeek()
0443 {
0444     // setDate does validity checking for us
0445     q->setDate(m_date.addDays(1 - m_date.dayOfWeek()));
0446 }
0447 
0448 // JPL Do these make the assumption that first day of week is weekday 1? As it may not be.
0449 void KDateTable::KDateTablePrivate::endOfWeek()
0450 {
0451     // setDate does validity checking for us
0452     q->setDate(m_date.addDays(7 - m_date.dayOfWeek()));
0453 }
0454 
0455 void KDateTable::keyPressEvent(QKeyEvent *e)
0456 {
0457     switch (e->key()) {
0458     case Qt::Key_Up:
0459         // setDate does validity checking for us
0460         setDate(d->m_date.addDays(-d->m_numDayColumns));
0461         break;
0462     case Qt::Key_Down:
0463         // setDate does validity checking for us
0464         setDate(d->m_date.addDays(d->m_numDayColumns));
0465         break;
0466     case Qt::Key_Left:
0467         // setDate does validity checking for us
0468         setDate(d->m_date.addDays(-1));
0469         break;
0470     case Qt::Key_Right:
0471         // setDate does validity checking for us
0472         setDate(d->m_date.addDays(1));
0473         break;
0474     case Qt::Key_Minus:
0475         // setDate does validity checking for us
0476         setDate(d->m_date.addDays(-1));
0477         break;
0478     case Qt::Key_Plus:
0479         // setDate does validity checking for us
0480         setDate(d->m_date.addDays(1));
0481         break;
0482     case Qt::Key_N:
0483         // setDate does validity checking for us
0484         setDate(QDate::currentDate());
0485         break;
0486     case Qt::Key_Return:
0487     case Qt::Key_Enter:
0488         Q_EMIT tableClicked();
0489         break;
0490     case Qt::Key_Control:
0491     case Qt::Key_Alt:
0492     case Qt::Key_Meta:
0493     case Qt::Key_Shift:
0494         // Don't beep for modifiers
0495         break;
0496     default:
0497         if (!e->modifiers()) { // hm
0498             QApplication::beep();
0499         }
0500     }
0501 }
0502 
0503 void KDateTable::setFontSize(int size)
0504 {
0505     QFontMetricsF metrics(fontMetrics());
0506     QRectF rect;
0507     // ----- store rectangles:
0508     d->fontsize = size;
0509     // ----- find largest day name:
0510     d->m_maxCell.setWidth(0);
0511     d->m_maxCell.setHeight(0);
0512     for (int weekday = 1; weekday <= 7; ++weekday) {
0513         rect = metrics.boundingRect(locale().dayName(weekday, QLocale::ShortFormat));
0514         d->m_maxCell.setWidth(qMax(d->m_maxCell.width(), rect.width()));
0515         d->m_maxCell.setHeight(qMax(d->m_maxCell.height(), rect.height()));
0516     }
0517     // ----- compare with a real wide number and add some space:
0518     rect = metrics.boundingRect(QStringLiteral("88"));
0519     d->m_maxCell.setWidth(qMax(d->m_maxCell.width() + 2, rect.width()));
0520     d->m_maxCell.setHeight(qMax(d->m_maxCell.height() + 4, rect.height()));
0521 }
0522 
0523 void KDateTable::wheelEvent(QWheelEvent *e)
0524 {
0525     setDate(d->m_date.addMonths(-(int)(e->angleDelta().y() / 120)));
0526     e->accept();
0527 }
0528 
0529 bool KDateTable::event(QEvent *ev)
0530 {
0531     switch (ev->type()) {
0532     case QEvent::HoverMove: {
0533         QHoverEvent *e = static_cast<QHoverEvent *>(ev);
0534         const int row = e->position().y() * d->m_numWeekRows / height();
0535         int col;
0536         if (layoutDirection() == Qt::RightToLeft) {
0537             col = d->m_numDayColumns - (e->position().x() * d->m_numDayColumns / width()) - 1;
0538         } else {
0539             col = e->position().x() * d->m_numDayColumns / width();
0540         }
0541 
0542         const int pos = row < 1 ? -1 : (d->m_numDayColumns * (row - 1)) + col;
0543 
0544         if (pos != d->m_hoveredPos) {
0545             d->m_hoveredPos = pos;
0546             update();
0547         }
0548         break;
0549     }
0550     case QEvent::HoverLeave:
0551         if (d->m_hoveredPos != -1) {
0552             d->m_hoveredPos = -1;
0553             update();
0554         }
0555         break;
0556     default:
0557         break;
0558     }
0559     return QWidget::event(ev);
0560 }
0561 
0562 void KDateTable::mousePressEvent(QMouseEvent *e)
0563 {
0564     if (e->type() != QEvent::MouseButtonPress) { // the KDatePicker only reacts on mouse press events:
0565         return;
0566     }
0567 
0568     if (!isEnabled()) {
0569         QApplication::beep();
0570         return;
0571     }
0572 
0573     int row;
0574     int col;
0575     int pos;
0576 
0577     QPoint mouseCoord = e->pos();
0578     row = mouseCoord.y() * d->m_numWeekRows / height();
0579     if (layoutDirection() == Qt::RightToLeft) {
0580         col = d->m_numDayColumns - (mouseCoord.x() * d->m_numDayColumns / width()) - 1;
0581     } else {
0582         col = mouseCoord.x() * d->m_numDayColumns / width();
0583     }
0584 
0585     if (row < 1 || col < 0) { // the user clicked on the frame of the table
0586         return;
0587     }
0588 
0589     // Rows and columns are zero indexed.  The (row - 1) below is to avoid counting
0590     // the row with the days of the week in the calculation.
0591 
0592     // new position and date
0593     pos = (d->m_numDayColumns * (row - 1)) + col;
0594     QDate clickedDate = dateFromPos(pos);
0595 
0596     // set the new date. If it is in the previous or next month, the month will
0597     // automatically be changed, no need to do that manually...
0598     // validity checking done inside setDate
0599     setDate(clickedDate);
0600 
0601     // This could be optimized to only call update over the regions
0602     // of old and new cell, but 99% of times there is also a call to
0603     // setDate that already calls update() so no need to optimize that
0604     // much here
0605     update();
0606 
0607     Q_EMIT tableClicked();
0608 
0609     if (e->button() == Qt::RightButton && d->m_popupMenuEnabled) {
0610         QMenu *menu = new QMenu();
0611         menu->addSection(locale().toString(d->m_date));
0612         Q_EMIT aboutToShowContextMenu(menu, clickedDate);
0613         menu->popup(e->globalPosition().toPoint());
0614     }
0615 }
0616 
0617 void KDateTable::KDateTablePrivate::setDate(const QDate &date)
0618 {
0619     m_date = date;
0620     m_weekDayFirstOfMonth = QDate(date.year(), date.month(), 1).dayOfWeek();
0621     m_numDaysThisMonth = m_date.daysInMonth();
0622     m_numDayColumns = 7;
0623 }
0624 
0625 bool KDateTable::setDate(const QDate &toDate)
0626 {
0627     if (!toDate.isValid()) {
0628         return false;
0629     }
0630 
0631     if (toDate == date()) {
0632         return true;
0633     }
0634 
0635     d->setDate(toDate);
0636     Q_EMIT dateChanged(date());
0637     update();
0638 
0639     return true;
0640 }
0641 
0642 const QDate &KDateTable::date() const
0643 {
0644     return d->m_date;
0645 }
0646 
0647 void KDateTable::focusInEvent(QFocusEvent *e)
0648 {
0649     QWidget::focusInEvent(e);
0650 }
0651 
0652 void KDateTable::focusOutEvent(QFocusEvent *e)
0653 {
0654     QWidget::focusOutEvent(e);
0655 }
0656 
0657 QSize KDateTable::sizeHint() const
0658 {
0659     if (d->m_maxCell.height() > 0 && d->m_maxCell.width() > 0) {
0660         return QSize(qRound(d->m_maxCell.width() * d->m_numDayColumns), (qRound(d->m_maxCell.height() + 2) * d->m_numWeekRows));
0661     } else {
0662         // qCDebug(KWidgetsAddonsLog) << "KDateTable::sizeHint: obscure failure - " << endl;
0663         return QSize(-1, -1);
0664     }
0665 }
0666 
0667 void KDateTable::setPopupMenuEnabled(bool enable)
0668 {
0669     d->m_popupMenuEnabled = enable;
0670 }
0671 
0672 bool KDateTable::popupMenuEnabled() const
0673 {
0674     return d->m_popupMenuEnabled;
0675 }
0676 
0677 void KDateTable::setCustomDatePainting(const QDate &date, const QColor &fgColor, BackgroundMode bgMode, const QColor &bgColor)
0678 {
0679     if (!fgColor.isValid()) {
0680         unsetCustomDatePainting(date);
0681         return;
0682     }
0683 
0684     KDateTablePrivate::DatePaintingMode mode;
0685     mode.bgMode = bgMode;
0686     mode.fgColor = fgColor;
0687     mode.bgColor = bgColor;
0688 
0689     d->m_customPaintingModes.insert(date.toJulianDay(), mode);
0690     d->m_useCustomColors = true;
0691     update();
0692 }
0693 
0694 void KDateTable::unsetCustomDatePainting(const QDate &date)
0695 {
0696     d->m_customPaintingModes.remove(date.toJulianDay());
0697     if (d->m_customPaintingModes.isEmpty()) {
0698         d->m_useCustomColors = false;
0699     }
0700     update();
0701 }
0702 
0703 #include "moc_kdatetable_p.cpp"