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