10#include "kdatetable_p.h"
13#include <QActionEvent>
14#include <QApplication>
16#include <QFontDatabase>
20#include <QStyleOptionViewItem>
24#include "kdaterangecontrol_p.h"
26class KDateTable::KDateTablePrivate :
public KDateRangeControlPrivate
29 KDateTablePrivate(KDateTable *qq)
32 m_popupMenuEnabled =
false;
33 m_useCustomColors =
false;
42 void setDate(
const QDate &date);
45 void beginningOfMonth();
47 void beginningOfWeek();
60 int m_weekDayFirstOfMonth;
65 int m_numDaysThisMonth;
87 bool m_popupMenuEnabled;
88 bool m_useCustomColors;
90 struct DatePaintingMode {
93 BackgroundMode bgMode;
95 QHash<int, DatePaintingMode> m_customPaintingModes;
100KDateTable::KDateTable(
const QDate &date,
QWidget *parent)
102 , d(new KDateTablePrivate(this))
107KDateTable::KDateTable(
QWidget *parent)
109 , d(std::make_unique<KDateTablePrivate>(this))
114KDateTable::~KDateTable()
118void KDateTable::initWidget(
const QDate &date)
120 d->m_numWeekRows = 7;
125 setAutoFillBackground(
true);
132void KDateTable::initAccels()
135 next->setObjectName(QStringLiteral(
"next"));
143 prior->setObjectName(QStringLiteral(
"prior"));
151 beginMonth->setObjectName(QStringLiteral(
"beginMonth"));
155 d->beginningOfMonth();
159 endMonth->setObjectName(QStringLiteral(
"endMonth"));
167 beginWeek->setObjectName(QStringLiteral(
"beginWeek"));
171 d->beginningOfWeek();
175 endWeek->setObjectName(QStringLiteral(
"endWeek"));
183int KDateTable::posFromDate(
const QDate &date)
185 int initialPosition = date.
day();
186 int offset = (d->m_weekDayFirstOfMonth - locale().firstDayOfWeek() + d->m_numDayColumns) % d->m_numDayColumns;
191 offset += d->m_numDayColumns;
194 return initialPosition + offset;
197QDate KDateTable::dateFromPos(
int position)
199 int offset = (d->m_weekDayFirstOfMonth - locale().firstDayOfWeek() + d->m_numDayColumns) % d->m_numDayColumns;
204 offset += d->m_numDayColumns;
207 return QDate(d->m_date.year(), d->m_date.month(), 1).
addDays(position - offset);
214 double cellWidth = width() / (double)d->m_numDayColumns;
215 double cellHeight = height() / (double)d->m_numWeekRows;
216 int leftCol = (int)std::floor(rectToUpdate.left() / cellWidth);
217 int topRow = (int)std::floor(rectToUpdate.top() / cellHeight);
218 int rightCol = (int)std::ceil(rectToUpdate.right() / cellWidth);
219 int bottomRow = (int)std::ceil(rectToUpdate.bottom() / cellHeight);
220 bottomRow = qMin(bottomRow, d->m_numWeekRows - 1);
221 rightCol = qMin(rightCol, d->m_numDayColumns - 1);
223 p.translate((d->m_numDayColumns - leftCol - 1) * cellWidth, topRow * cellHeight);
225 p.translate(leftCol * cellWidth, topRow * cellHeight);
227 for (
int i = leftCol; i <= rightCol; ++i) {
228 for (
int j = topRow; j <= bottomRow; ++j) {
230 p.translate(0, cellHeight);
233 p.translate(-cellWidth, 0);
235 p.translate(cellWidth, 0);
237 p.translate(0, -cellHeight * (bottomRow - topRow + 1));
241void KDateTable::paintCell(
QPainter *painter,
int row,
int col)
243 double w = (width() / (double)d->m_numDayColumns) - 1;
244 double h = (height() / (double)d->m_numWeekRows) - 1;
247 QColor cellBackgroundColor;
250 bool workingDay =
false;
255 pos = d->m_numDayColumns * (row - 1) + col;
258 if (col + locale().firstDayOfWeek() <= d->m_numDayColumns) {
259 cellWeekDay = col + locale().firstDayOfWeek();
261 cellWeekDay = col + locale().firstDayOfWeek() - d->m_numDayColumns;
266 if (locale().weekdays().first() <= locale().weekdays().last()) {
267 if (cellWeekDay >= locale().weekdays().first() && cellWeekDay <= locale().weekdays().last()) {
271 if (cellWeekDay >= locale().weekdays().first()
272 || cellWeekDay <= locale().weekdays().last()) {
296 QDate cellDate = dateFromPos(pos);
298 bool validDay = cellDate.
isValid();
302 cellText = locale().toString(cellDate.
day());
307 if (!validDay || cellDate.
month() != d->m_date.month()) {
312 cellBackgroundColor = palette().color(backgroundRole());
333 bool selectedDay = (cellDate == date());
338 bool customDay = (d->m_useCustomColors && d->m_customPaintingModes.contains(cellDate.
toJulianDay()));
341 cellBackgroundColor = palette().color(backgroundRole());
342 cellTextColor = palette().color(foregroundRole());
359 KDateTablePrivate::DatePaintingMode mode = d->m_customPaintingModes[cellDate.
toJulianDay()];
360 if (mode.bgMode != NoBgMode) {
362 cellBackgroundColor = mode.bgColor;
365 cellTextColor = mode.fgColor;
369 if (!customDay && dayOfPray) {
375 if (!d->isInDateRange(cellDate)) {
382 painter->
setPen(cellBackgroundColor);
383 painter->
setBrush(cellBackgroundColor);
385 }
else if (cellBackgroundColor != palette().color(backgroundRole()) || pos == d->m_hoveredPos) {
389 if (cellBackgroundColor != palette().color(backgroundRole())) {
396 opt.state &=
~QStyle::State_MouseOver;
398 opt.showDecorationSelected =
true;
404 painter->
setPen(cellTextColor);
410 painter->
setPen(palette().color(foregroundRole()));
416 if (cell.
width() > d->m_maxCell.width()) {
417 d->m_maxCell.setWidth(cell.
width());
419 if (cell.
height() > d->m_maxCell.height()) {
420 d->m_maxCell.setHeight(cell.
height());
424void KDateTable::KDateTablePrivate::nextMonth()
427 q->setDate(m_date.addMonths(1));
430void KDateTable::KDateTablePrivate::previousMonth()
433 q->setDate(m_date.addMonths(-1));
436void KDateTable::KDateTablePrivate::beginningOfMonth()
439 q->setDate(QDate(m_date.year(), m_date.month(), 1));
442void KDateTable::KDateTablePrivate::endOfMonth()
445 q->setDate(QDate(m_date.year(), m_date.month() + 1, 0));
449void KDateTable::KDateTablePrivate::beginningOfWeek()
452 q->setDate(m_date.addDays(1 - m_date.dayOfWeek()));
456void KDateTable::KDateTablePrivate::endOfWeek()
459 q->setDate(m_date.addDays(7 - m_date.dayOfWeek()));
462void KDateTable::keyPressEvent(QKeyEvent *e)
467 setDate(d->m_date.addDays(-d->m_numDayColumns));
471 setDate(d->m_date.addDays(d->m_numDayColumns));
475 setDate(d->m_date.addDays(-1));
479 setDate(d->m_date.addDays(1));
483 setDate(d->m_date.addDays(-1));
487 setDate(d->m_date.addDays(1));
495 Q_EMIT tableClicked();
510void KDateTable::setFontSize(
int size)
512 QFontMetricsF metrics(fontMetrics());
517 d->m_maxCell.setWidth(0);
518 d->m_maxCell.setHeight(0);
519 for (
int weekday = 1; weekday <= 7; ++weekday) {
521 d->m_maxCell.
setWidth(qMax(d->m_maxCell.width(), rect.
width()));
522 d->m_maxCell.setHeight(qMax(d->m_maxCell.height(), rect.
height()));
525 rect = metrics.boundingRect(QStringLiteral(
"88"));
526 d->m_maxCell.
setWidth(qMax(d->m_maxCell.width() + 2, rect.
width()));
527 d->m_maxCell.setHeight(qMax(d->m_maxCell.height() + 4, rect.
height()));
530void KDateTable::wheelEvent(QWheelEvent *e)
532 setDate(d->m_date.addMonths(-(
int)(e->
angleDelta().
y() / 120)));
536bool KDateTable::event(QEvent *ev)
538 switch (ev->
type()) {
540 QHoverEvent *e =
static_cast<QHoverEvent *
>(ev);
541 const int row = e->
position().
y() * d->m_numWeekRows / height();
544 col = d->m_numDayColumns - (e->
position().x() * d->m_numDayColumns / width()) - 1;
546 col = e->
position().
x() * d->m_numDayColumns / width();
549 const int pos = row < 1 ? -1 : (d->m_numDayColumns * (row - 1)) + col;
551 if (pos != d->m_hoveredPos) {
552 d->m_hoveredPos = pos;
558 if (d->m_hoveredPos != -1) {
559 d->m_hoveredPos = -1;
569void KDateTable::mousePressEvent(QMouseEvent *e)
584 QPoint mouseCoord = e->
pos();
585 row = mouseCoord.
y() * d->m_numWeekRows / height();
587 col = d->m_numDayColumns - (mouseCoord.
x() * d->m_numDayColumns / width()) - 1;
589 col = mouseCoord.
x() * d->m_numDayColumns / width();
592 if (row < 1 || col < 0) {
600 pos = (d->m_numDayColumns * (row - 1)) + col;
601 QDate clickedDate = dateFromPos(pos);
603 if (!d->isInDateRange(clickedDate)) {
610 setDate(clickedDate);
618 Q_EMIT tableClicked();
621 QMenu *menu =
new QMenu();
623 Q_EMIT aboutToShowContextMenu(menu, clickedDate);
628void KDateTable::KDateTablePrivate::setDate(
const QDate &date)
632 m_numDaysThisMonth = m_date.daysInMonth();
636bool KDateTable::setDate(
const QDate &toDate)
642 if (toDate == date()) {
646 if (!d->isInDateRange(toDate)) {
651 Q_EMIT dateChanged(date());
657const QDate &KDateTable::date()
const
662void KDateTable::focusInEvent(QFocusEvent *e)
667void KDateTable::focusOutEvent(QFocusEvent *e)
672QSize KDateTable::sizeHint()
const
674 if (d->m_maxCell.height() > 0 && d->m_maxCell.width() > 0) {
675 return QSize(qRound(d->m_maxCell.width() * d->m_numDayColumns), (qRound(d->m_maxCell.height() + 2) * d->m_numWeekRows));
678 return QSize(-1, -1);
682void KDateTable::setPopupMenuEnabled(
bool enable)
684 d->m_popupMenuEnabled = enable;
687bool KDateTable::popupMenuEnabled()
const
689 return d->m_popupMenuEnabled;
692void KDateTable::setCustomDatePainting(
const QDate &date,
const QColor &fgColor, BackgroundMode bgMode,
const QColor &bgColor)
695 unsetCustomDatePainting(date);
699 KDateTablePrivate::DatePaintingMode mode;
700 mode.bgMode = bgMode;
701 mode.fgColor = fgColor;
702 mode.bgColor = bgColor;
704 d->m_customPaintingModes.insert(date.
toJulianDay(), mode);
705 d->m_useCustomColors =
true;
709void KDateTable::unsetCustomDatePainting(
const QDate &date)
711 d->m_customPaintingModes.remove(date.
toJulianDay());
712 if (d->m_customPaintingModes.isEmpty()) {
713 d->m_useCustomColors =
false;
718void KDateTable::setDateRange(
const QDate &minDate,
const QDate &maxDate)
720 d->setDateRange(minDate, maxDate);
723#include "moc_kdatetable_p.cpp"
void update(Part *part, const QByteArray &data, qint64 dataSize)
char * toString(const EngineQuery &query)
const QList< QKeySequence > & next()
const QList< QKeySequence > & prior()
void triggered(bool checked)
bool isValid() const const
QDate addDays(qint64 ndays) const const
int dayOfWeek() const const
bool isValid(int year, int month, int day)
qint64 toJulianDay() const const
void setBold(bool enable)
QFont systemFont(SystemFont type)
Qt::KeyboardModifiers modifiers() const const
QList< QKeySequence > keyBindings(StandardKey key)
void drawLine(const QLine &line)
void drawRect(const QRect &rectangle)
void drawText(const QPoint &position, const QString &text)
void setBrush(Qt::BrushStyle style)
void setFont(const QFont &font)
void setPen(Qt::PenStyle style)
const QRect & rect() const const
QPoint toPoint() const const
qreal height() const const
void setWidth(qreal width)
QRect toRect() const const
qreal width() const const
QPointF globalPosition() const const
QPointF position() const const
void initFrom(const QWidget *widget)
WidgetWithChildrenShortcut
QFuture< ArgsType< Signal > > connect(Sender *sender, Signal signal)
QPoint angleDelta() const const