Eventviews

monthscene.cpp
1/*
2 SPDX-FileCopyrightText: 2008 Bruno Virlet <bruno.virlet@gmail.com>
3
4 SPDX-License-Identifier: GPL-2.0-or-later WITH Qt-Commercial-exception-1.0
5*/
6
7#include "monthscene.h"
8#include "helper.h"
9#include "monthgraphicsitems.h"
10#include "monthitem.h"
11#include "monthview.h"
12#include "prefs.h"
13
14#include <CalendarSupport/Utils>
15
16#include <KColorScheme>
17#include <KLocalizedString>
18#include <QGraphicsSceneMouseEvent>
19#include <QIcon>
20#include <QResizeEvent>
21#include <QToolTip>
22
23static const int AUTO_REPEAT_DELAY = 600;
24
25using namespace EventViews;
26
27MonthScene::MonthScene(MonthView *parent)
28 : QGraphicsScene(parent)
29 , mMonthView(parent)
30 , mInitialized(false)
31 , mClickedItem(nullptr)
32 , mActionItem(nullptr)
33 , mActionInitiated(false)
34 , mSelectedItem(nullptr)
35 , mStartCell(nullptr)
36 , mPreviousCell(nullptr)
37 , mActionType(None)
38 , mStartHeight(0)
39 , mCurrentIndicator(nullptr)
40{
41 mBirthdayPixmap = QIcon::fromTheme(QStringLiteral("view-calendar-birthday")).pixmap(16, 16);
42 mAnniversaryPixmap = QIcon::fromTheme(QStringLiteral("view-calendar-wedding-anniversary")).pixmap(16, 16);
43 mAlarmPixmap = QIcon::fromTheme(QStringLiteral("appointment-reminder")).pixmap(16, 16);
44 mRecurPixmap = QIcon::fromTheme(QStringLiteral("appointment-recurring")).pixmap(16, 16);
45 mReadonlyPixmap = QIcon::fromTheme(QStringLiteral("object-locked")).pixmap(16, 16);
46 mReplyPixmap = QIcon::fromTheme(QStringLiteral("mail-reply-sender")).pixmap(16, 16);
47 mHolidayPixmap = QIcon::fromTheme(QStringLiteral("view-calendar-holiday")).pixmap(16, 16);
48
49 setSceneRect(0, 0, parent->width(), parent->height());
50}
51
52MonthScene::~MonthScene()
53{
54 qDeleteAll(mMonthCellMap);
55 qDeleteAll(mManagerList);
56}
57
58MonthCell *MonthScene::selectedCell() const
59{
60 return mMonthCellMap.value(mSelectedCellDate);
61}
62
63MonthCell *MonthScene::previousCell() const
64{
65 return mPreviousCell;
66}
67
68int MonthScene::getRightSpan(QDate date) const
69{
70 MonthCell *cell = mMonthCellMap.value(date);
71 if (!cell) {
72 return 0;
73 }
74
75 return 7 - cell->x() - 1;
76}
77
78int MonthScene::getLeftSpan(QDate date) const
79{
80 MonthCell *cell = mMonthCellMap.value(date);
81 if (!cell) {
82 return 0;
83 }
84
85 return cell->x();
86}
87
88int MonthScene::maxRowCount()
89{
90 return (rowHeight() - MonthCell::topMargin()) / itemHeightIncludingSpacing();
91}
92
93int MonthScene::itemHeightIncludingSpacing()
94{
95 return MonthCell::topMargin() + 2;
96}
97
98int MonthScene::itemHeight()
99{
100 return MonthCell::topMargin();
101}
102
103MonthCell *MonthScene::firstCellForMonthItem(MonthItem *manager)
104{
105 for (QDate d = manager->startDate(); d <= manager->endDate(); d = d.addDays(1)) {
106 MonthCell *monthCell = mMonthCellMap.value(d);
107 if (monthCell) {
108 return monthCell;
109 }
110 }
111
112 return nullptr;
113}
114
115void MonthScene::updateGeometry()
116{
117 for (MonthItem *manager : std::as_const(mManagerList)) {
118 manager->updateGeometry();
119 }
120}
121
122int MonthScene::availableWidth() const
123{
124 return static_cast<int>(sceneRect().width());
125}
126
127int MonthScene::availableHeight() const
128{
129 return static_cast<int>(sceneRect().height() - headerHeight());
130}
131
132int MonthScene::columnWidth() const
133{
134 return static_cast<int>((availableWidth() - 1) / 7.);
135}
136
137int MonthScene::rowHeight() const
138{
139 return static_cast<int>((availableHeight() - 1) / 6.);
140}
141
142int MonthScene::headerHeight() const
143{
144 return 50;
145}
146
147int MonthScene::cellVerticalPos(const MonthCell *cell) const
148{
149 return headerHeight() + cell->y() * rowHeight();
150}
151
152int MonthScene::cellHorizontalPos(const MonthCell *cell) const
153{
154 return cell->x() * columnWidth();
155}
156
157int MonthScene::sceneYToMonthGridY(int yScene)
158{
159 return yScene - headerHeight();
160}
161
162int MonthScene::sceneXToMonthGridX(int xScene)
163{
164 return xScene;
165}
166
168{
169 Q_ASSERT(mScene);
170
171 PrefsPtr prefs = mScene->monthView()->preferences();
172 p->setFont(prefs->monthViewFont());
174
175 /*
176 Headers
177 */
178 QFont font = prefs->monthViewFont();
179 font.setBold(true);
180 font.setPointSize(15);
181 p->setFont(font);
182 const int dayLabelsHeight = 20;
183 const auto dayInMonth = mMonthView->averageDate();
184 p->drawText(QRect(0,
185 0, // top right
186 static_cast<int>(mScene->sceneRect().width()),
187 static_cast<int>(mScene->headerHeight() - dayLabelsHeight)),
189 i18nc("monthname year", "%1 %2", QLocale().standaloneMonthName(dayInMonth.month(), QLocale::LongFormat), QString::number(dayInMonth.year())));
190
191 font.setPointSize(dayLabelsHeight - 10);
192 p->setFont(font);
193
194 const QDate start = mMonthView->actualStartDateTime().date();
195 const QDate end = mMonthView->actualEndDateTime().date();
196
197 for (QDate d = start; d <= start.addDays(6); d = d.addDays(1)) {
198 const MonthCell *const cell = mScene->mMonthCellMap.value(d);
199
200 if (!cell) {
201 // This means drawBackground() is being called before reloadIncidences(). Can happen with some
202 // themes. Bug #190191
203 return;
204 }
205
206 p->drawText(QRect(mScene->cellHorizontalPos(cell), mScene->cellVerticalPos(cell) - 15, mScene->columnWidth(), 15),
209 }
210
211 /*
212 Month grid
213 */
214 int columnWidth = mScene->columnWidth();
215 int rowHeight = mScene->rowHeight();
216 QDate todayDate{QDate::currentDate()};
217
218 const QList<QDate> workDays = CalendarSupport::workDays(mMonthView->actualStartDateTime().date(), mMonthView->actualEndDateTime().date());
219 QRect todayRect;
220 QRect selectedRect;
221 QColor holidayBg;
222 QColor workdayBg;
223 if (mMonthView->preferences()->useSystemColor()) {
224 workdayBg = palette().color(QPalette::Base);
225 holidayBg = palette().color(QPalette::AlternateBase);
226 } else {
227 workdayBg = mMonthView->preferences()->monthGridWorkHoursBackgroundColor();
228 holidayBg = mMonthView->preferences()->monthGridBackgroundColor();
229 }
230
231 for (QDate d = start; d <= end; d = d.addDays(1)) {
232 const MonthCell *const cell = mScene->mMonthCellMap.value(d);
233
234 if (!cell) {
235 // This means drawBackground() is being called before reloadIncidences(). Can happen with some
236 // themes. Bug #190191
237 return;
238 }
239
240 const QRect cellRect(mScene->cellHorizontalPos(cell), mScene->cellVerticalPos(cell), columnWidth, rowHeight);
241 if (cell == mScene->selectedCell()) {
242 selectedRect = cellRect;
243 }
244 if (cell->date() == todayDate) {
245 todayRect = cellRect;
246 }
247
248 // Draw cell
249 p->setPen(mMonthView->preferences()->monthGridBackgroundColor().darker(150));
250 p->setBrush(workDays.contains(d) ? workdayBg : holidayBg);
251 p->drawRect(cellRect);
252 if (mMonthView->isBusyDay(d)) {
253 QColor busyColor = mMonthView->preferences()->viewBgBusyColor();
254 busyColor.setAlpha(EventViews::BUSY_BACKGROUND_ALPHA);
255 p->setBrush(busyColor);
256 p->drawRect(cellRect);
257 }
258 }
259 if (!todayRect.isNull()) {
260 KColorScheme scheme(QPalette::Normal, KColorScheme::ColorSet::View);
261 p->setPen(scheme.foreground(KColorScheme::ForegroundRole::PositiveText).color());
262 p->setBrush(scheme.background(KColorScheme::BackgroundRole::PositiveBackground));
263 p->drawRect(todayRect);
264 }
265 if (!selectedRect.isNull()) {
266 const KColorScheme scheme(QPalette::Normal, KColorScheme::ColorSet::Selection);
267 auto color = scheme.background(KColorScheme::BackgroundRole::NormalBackground).color();
268 p->setPen(color);
269 color.setAlpha(EventViews::BUSY_BACKGROUND_ALPHA);
270 p->setBrush(color);
271 p->drawRect(selectedRect);
272 }
273
274 /*
275 * Draw Dates
276 */
277
278 font = mMonthView->preferences()->monthViewFont();
279 font.setPixelSize(MonthCell::topMargin() - 4);
280 p->setFont(font);
281
282 QPen oldPen;
283 if (mMonthView->preferences()->useSystemColor()) {
284 oldPen = palette().color(QPalette::WindowText).darker(150);
285 } else {
286 oldPen = mMonthView->preferences()->monthGridBackgroundColor().darker(150);
287 }
288
289 for (QDate d = mMonthView->actualStartDateTime().date(); d <= mMonthView->actualEndDateTime().date(); d = d.addDays(1)) {
290 MonthCell *const cell = mScene->mMonthCellMap.value(d);
291
292 // Draw cell header
293 int cellHeaderX = mScene->cellHorizontalPos(cell) + 1;
294 int cellHeaderY = mScene->cellVerticalPos(cell) + 1;
295 int cellHeaderWidth = columnWidth - 2;
296 int cellHeaderHeight = cell->topMargin() - 2;
297 const auto brush = KColorScheme(QPalette::Normal, KColorScheme::ColorSet::Header).background(KColorScheme::BackgroundRole::NormalBackground);
298 p->setBrush(brush);
299 p->setPen(Qt::NoPen);
300 p->drawRect(QRect(cellHeaderX, cellHeaderY, cellHeaderWidth, cellHeaderHeight));
301
302 QFont font = p->font();
303 font.setBold(cell->date() == todayDate);
304 p->setFont(font);
305
306 if (d.month() == mMonthView->currentMonth()) {
308 } else {
309 p->setPen(oldPen);
310 }
311
312 QString dayText;
313 // Prepend month name if d is the first or last day of month
314 if (d.day() == 1 || // d is the first day of month
315 d.addDays(1).day() == 1) { // d is the last day of month
316 dayText = i18nc("'Month day' for month view cells", "%1 %2", QLocale::system().monthName(d.month(), QLocale::ShortFormat), d.day());
317 } else {
318 dayText = QString::number(d.day());
319 }
320 p->drawText(QRect(mScene->cellHorizontalPos(cell), // top right
321 mScene->cellVerticalPos(cell), // of the cell
322 mScene->columnWidth() - 2,
323 cell->topMargin()),
325 dayText);
326
327 /*
328 Draw arrows if all items won't fit
329 */
330
331 // Up arrow if first item is above cell top
332 if (mScene->startHeight() != 0 && cell->hasEventBelow(mScene->startHeight())) {
333 cell->upArrow()->setPos(mScene->cellHorizontalPos(cell) + columnWidth / 2,
334 mScene->cellVerticalPos(cell) + cell->upArrow()->boundingRect().height() / 2 + 2);
335 cell->upArrow()->show();
336 } else {
337 cell->upArrow()->hide();
338 }
339
340 // Down arrow if last item is below cell bottom
341 if (!mScene->lastItemFit(cell)) {
342 cell->downArrow()->setPos(mScene->cellHorizontalPos(cell) + columnWidth / 2,
343 mScene->cellVerticalPos(cell) + rowHeight - cell->downArrow()->boundingRect().height() / 2 - 2);
344 cell->downArrow()->show();
345 } else {
346 cell->downArrow()->hide();
347 }
348 }
349}
350
351void MonthScene::resetAll()
352{
353 qDeleteAll(mMonthCellMap);
354 mMonthCellMap.clear();
355
356 qDeleteAll(mManagerList);
357 mManagerList.clear();
358
359 mSelectedItem = nullptr;
360 mActionItem = nullptr;
361 mClickedItem = nullptr;
362}
363
364Akonadi::IncidenceChanger *MonthScene::incidenceChanger() const
365{
366 return mMonthView->changer();
367}
368
369QDate MonthScene::firstDateOnRow(int row) const
370{
371 return mMonthView->actualStartDateTime().date().addDays(7 * row);
372}
373
374bool MonthScene::lastItemFit(MonthCell *cell)
375{
376 if (cell->firstFreeSpace() > maxRowCount() + startHeight()) {
377 return false;
378 } else {
379 return true;
380 }
381}
382
383int MonthScene::totalHeight()
384{
385 int max = 0;
386 for (QDate d = mMonthView->actualStartDateTime().date(); d <= mMonthView->actualEndDateTime().date(); d = d.addDays(1)) {
387 int c = mMonthCellMap[d]->firstFreeSpace();
388 if (c > max) {
389 max = c;
390 }
391 }
392
393 return max;
394}
395
396void MonthScene::wheelEvent(QGraphicsSceneWheelEvent *event)
397{
398 Q_UNUSED(event) // until we figure out what to do in here
399
400 /* int numDegrees = -event->delta() / 8;
401 int numSteps = numDegrees / 15;
402
403 if (startHeight() + numSteps < 0) {
404 numSteps = -startHeight();
405 }
406
407 int cellHeight = 0;
408
409 MonthCell *currentCell = getCellFromPos(event->scenePos());
410 if (currentCell) {
411 cellHeight = currentCell->firstFreeSpace();
412 }
413 if (cellHeight == 0) {
414 // no items in this cell, there's no point to scroll
415 return;
416 }
417
418 int newHeight;
419 int maxStartHeight = qMax(0, cellHeight - maxRowCount());
420 if (numSteps > 0 && startHeight() + numSteps >= maxStartHeight) {
421 newHeight = maxStartHeight;
422 } else {
423 newHeight = startHeight() + numSteps;
424 }
425
426 if (newHeight == startHeight()) {
427 return;
428 }
429
430 setStartHeight(newHeight);
431
432 foreach (MonthItem *manager, mManagerList) {
433 manager->updateGeometry();
434 }
435
436 invalidate(QRectF(), BackgroundLayer);
437
438 event->accept();
439 */
440}
441
442void MonthScene::scrollCellsDown()
443{
444 int newHeight = startHeight() + 1;
445 setStartHeight(newHeight);
446
447 for (MonthItem *manager : std::as_const(mManagerList)) {
448 manager->updateGeometry();
449 }
450
452}
453
454void MonthScene::scrollCellsUp()
455{
456 int newHeight = startHeight() - 1;
457 setStartHeight(newHeight);
458
459 for (MonthItem *manager : std::as_const(mManagerList)) {
460 manager->updateGeometry();
461 }
462
464}
465
466void MonthScene::clickOnScrollIndicator(ScrollIndicator *scrollItem)
467{
468 if (scrollItem->direction() == ScrollIndicator::UpArrow) {
469 scrollCellsUp();
470 } else if (scrollItem->direction() == ScrollIndicator::DownArrow) {
471 scrollCellsDown();
472 }
473}
474
475void MonthScene::mouseDoubleClickEvent(QGraphicsSceneMouseEvent *mouseEvent)
476{
477 QPointF pos = mouseEvent->scenePos();
478 repeatTimer.stop();
479 MonthGraphicsItem *iItem = dynamic_cast<MonthGraphicsItem *>(itemAt(pos, {}));
480 if (iItem) {
481 if (iItem->monthItem()) {
482 auto tmp = qobject_cast<IncidenceMonthItem *>(iItem->monthItem());
483 if (tmp) {
484 selectItem(iItem->monthItem());
485 mMonthView->defaultAction(tmp->akonadiItem());
486
487 mouseEvent->accept();
488 }
489 }
490 } else {
491 Q_EMIT newEventSignal();
492 }
493}
494
495void MonthScene::mouseMoveEvent(QGraphicsSceneMouseEvent *mouseEvent)
496{
497 QPointF pos = mouseEvent->scenePos();
498
499 MonthGraphicsView *view = static_cast<MonthGraphicsView *>(views().at(0));
500
501 // Change cursor depending on the part of the item it hovers to inform
502 // the user that he can resize the item.
503 if (mActionType == None) {
504 MonthGraphicsItem *iItem = dynamic_cast<MonthGraphicsItem *>(itemAt(pos, {}));
505 if (iItem) {
506 if (iItem->monthItem()->isResizable() && iItem->isBeginItem() && iItem->mapFromScene(pos).x() <= 10) {
507 view->setActionCursor(Resize);
508 } else if (iItem->monthItem()->isResizable() && iItem->isEndItem() && iItem->mapFromScene(pos).x() >= iItem->boundingRect().width() - 10) {
509 view->setActionCursor(Resize);
510 } else {
511 view->setActionCursor(None);
512 }
513 } else {
514 view->setActionCursor(None);
515 }
516 mouseEvent->accept();
517 return;
518 }
519
520 // If an item was selected during the click, we maybe have an item to move !
521 if (mActionItem) {
522 // Initiate action if not already done
523 if (!mActionInitiated && mActionType != None) {
524 if (mActionType == Move) {
525 mActionItem->beginMove();
526 } else if (mActionType == Resize) {
527 mActionItem->beginResize();
528 }
529 mActionInitiated = true;
530 }
531 view->setActionCursor(mActionType);
532
533 // Move or resize action
534 MonthCell *const currentCell = getCellFromPos(pos);
535 if (currentCell && currentCell != mPreviousCell) {
536 bool ok = true;
537 if (mActionType == Move) {
538 if (currentCell) {
539 mActionItem->moveTo(currentCell->date());
540 mActionItem->updateGeometry();
541 } else {
542 mActionItem->moveTo(QDate());
543 mActionItem->updateGeometry();
544 mActionItem->endMove();
545 mActionItem = nullptr;
546 mActionType = None;
547 mStartCell = nullptr;
548 }
549 } else if (mActionType == Resize) {
550 ok = mActionItem->resizeBy(mPreviousCell->date().daysTo(currentCell->date()));
551 mActionItem->updateGeometry();
552 }
553
554 if (ok) {
555 mPreviousCell = currentCell;
556 }
557 update();
558 }
559 mouseEvent->accept();
560 }
561}
562
563void MonthScene::mousePressEvent(QGraphicsSceneMouseEvent *mouseEvent)
564{
565 QPointF pos = mouseEvent->scenePos();
566
567 mClickedItem = nullptr;
568 mCurrentIndicator = nullptr;
569
570 MonthGraphicsItem *iItem = dynamic_cast<MonthGraphicsItem *>(itemAt(pos, {}));
571 if (iItem) {
572 mClickedItem = iItem->monthItem();
573
574 selectItem(mClickedItem);
575 if (mouseEvent->button() == Qt::RightButton) {
576 auto tmp = qobject_cast<IncidenceMonthItem *>(mClickedItem);
577 if (tmp) {
578 Q_EMIT showIncidencePopupSignal(tmp->calendar(), tmp->akonadiItem(), tmp->realStartDate());
579 }
580 }
581
582 if (mouseEvent->button() == Qt::LeftButton) {
583 // Basic initialization for resize and move
584 mActionItem = mClickedItem;
585 mStartCell = getCellFromPos(pos);
586 mPreviousCell = mStartCell;
587 mActionInitiated = false;
588
589 // Move or resize ?
590 if (iItem->monthItem()->isResizable() && iItem->isBeginItem() && iItem->mapFromScene(pos).x() <= 10) {
591 mActionType = Resize;
592 mResizeType = ResizeLeft;
593 } else if (iItem->monthItem()->isResizable() && iItem->isEndItem() && iItem->mapFromScene(pos).x() >= iItem->boundingRect().width() - 10) {
594 mActionType = Resize;
595 mResizeType = ResizeRight;
596 } else if (iItem->monthItem()->isMoveable()) {
597 mActionType = Move;
598 }
599 }
600 mouseEvent->accept();
601 } else if (ScrollIndicator *scrollItem = dynamic_cast<ScrollIndicator *>(itemAt(pos, {}))) {
602 clickOnScrollIndicator(scrollItem);
603 mCurrentIndicator = scrollItem;
604 repeatTimer.start(AUTO_REPEAT_DELAY, this);
605 } else {
606 // unselect items when clicking somewhere else
607 selectItem(nullptr);
608
609 MonthCell *cell = getCellFromPos(pos);
610 if (cell) {
611 mSelectedCellDate = cell->date();
612 update();
613 if (mouseEvent->button() == Qt::RightButton) {
614 Q_EMIT showNewEventPopupSignal();
615 }
616 mouseEvent->accept();
617 }
618 }
619}
620
621void MonthScene::timerEvent(QTimerEvent *e)
622{
623 if (e->timerId() == repeatTimer.timerId()) {
624 if (mCurrentIndicator->isVisible()) {
625 clickOnScrollIndicator(mCurrentIndicator);
626 repeatTimer.start(AUTO_REPEAT_DELAY, this);
627 } else {
628 mCurrentIndicator = nullptr;
629 repeatTimer.stop();
630 }
631 }
632}
633
634void MonthScene::helpEvent(QGraphicsSceneHelpEvent *helpEvent)
635{
636 // Find the first item that does tooltips
637 const QPointF pos = helpEvent->scenePos();
638 MonthGraphicsItem *toolTipItem = dynamic_cast<MonthGraphicsItem *>(itemAt(pos, {}));
639
640 // Show or hide the tooltip
641 QString text;
642 QPoint point;
643 if (toolTipItem) {
644 text = toolTipItem->getToolTip();
645 point = helpEvent->screenPos();
646 }
647 QToolTip::showText(point, text, helpEvent->widget());
648 helpEvent->setAccepted(!text.isEmpty());
649}
650
651void MonthScene::mouseReleaseEvent(QGraphicsSceneMouseEvent *mouseEvent)
652{
653 QPointF pos = mouseEvent->scenePos();
654
655 static_cast<MonthGraphicsView *>(views().at(0))->setActionCursor(None);
656
657 repeatTimer.stop();
658 mCurrentIndicator = nullptr;
659
660 if (mActionItem) {
661 MonthCell *currentCell = getCellFromPos(pos);
662
663 const bool somethingChanged = currentCell && currentCell != mStartCell;
664
665 if (somethingChanged) { // We want to act if a move really happened
666 if (mActionType == Resize) {
667 mActionItem->endResize();
668 } else if (mActionType == Move) {
669 mActionItem->endMove();
670 }
671 }
672
673 mActionItem = nullptr;
674 mActionType = None;
675 mStartCell = nullptr;
676
677 mouseEvent->accept();
678 }
679}
680
681// returns true if the point is in the monthgrid (allows to avoid selecting a cell when
682// a click is outside the month grid
683bool MonthScene::isInMonthGrid(int x, int y) const
684{
685 return x >= 0 && y >= 0 && x <= availableWidth() && y <= availableHeight();
686}
687
688// The function converts the coordinates to the month grid coordinates to
689// be able to locate the cell.
690MonthCell *MonthScene::getCellFromPos(QPointF pos)
691{
692 int y = sceneYToMonthGridY(static_cast<int>(pos.y()));
693 int x = sceneXToMonthGridX(static_cast<int>(pos.x()));
694 if (!isInMonthGrid(x, y)) {
695 return nullptr;
696 }
697 int id = (int)(y / rowHeight()) * 7 + (int)(x / columnWidth());
698
699 return mMonthCellMap.value(mMonthView->actualStartDateTime().date().addDays(id));
700}
701
702void MonthScene::selectItem(MonthItem *item)
703{
704 /*
705 if (mSelectedItem == item) {
706 return;
707 }
708
709 I commented the above code so it's possible to selected a selected item.
710 korg-mobile needs that, otherwise clicking on a selected item won't bring the editor up.
711 Another solution would be to have two Q_SIGNALS: incidenceSelected() and incidenceClicked()
712 */
713
714 auto tmp = qobject_cast<IncidenceMonthItem *>(item);
715
716 if (!tmp) {
717 mSelectedItem = nullptr;
718 Q_EMIT incidenceSelected(Akonadi::Item(), QDate());
719 return;
720 }
721
722 mSelectedItem = item;
723 Q_ASSERT(CalendarSupport::hasIncidence(tmp->akonadiItem()));
724
725 if (mMonthView->selectedIncidenceDates().isEmpty()) {
726 Q_EMIT incidenceSelected(tmp->akonadiItem(), QDate());
727 } else {
728 Q_EMIT incidenceSelected(tmp->akonadiItem(), mMonthView->selectedIncidenceDates().at(0));
729 }
730 update();
731}
732
733void MonthScene::removeIncidence(const QString &uid)
734{
735 for (MonthItem *manager : std::as_const(mManagerList)) {
736 auto imi = qobject_cast<IncidenceMonthItem *>(manager);
737 if (!imi) {
738 continue;
739 }
740
741 KCalendarCore::Incidence::Ptr incidence = imi->incidence();
742 if (!incidence) {
743 continue;
744 }
745 if (incidence->uid() == uid) {
746 const auto lst = imi->monthGraphicsItems();
747 for (MonthGraphicsItem *gitem : lst) {
748 removeItem(gitem);
749 }
750 }
751 }
752}
753
754//----------------------------------------------------------
755MonthGraphicsView::MonthGraphicsView(MonthView *parent)
756 : QGraphicsView(parent)
757 , mMonthView(parent)
758{
759 setMouseTracking(true);
760}
761
762void MonthGraphicsView::setActionCursor(MonthScene::ActionType actionType)
763{
764 switch (actionType) {
765 case MonthScene::Move:
766#ifndef QT_NO_CURSOR
768#endif
769 break;
770 case MonthScene::Resize:
771#ifndef QT_NO_CURSOR
773#endif
774 break;
775#ifndef QT_NO_CURSOR
776 default:
778#endif
779 }
780}
781
782void MonthGraphicsView::setScene(MonthScene *scene)
783{
784 mScene = scene;
786}
787
788void MonthGraphicsView::resizeEvent(QResizeEvent *event)
789{
790 mScene->setSceneRect(0, 0, event->size().width(), event->size().height());
791 mScene->updateGeometry();
792}
793
794#include "moc_monthscene.cpp"
void defaultAction(const Akonadi::Item &incidence)
Perform the default action for an incidence, e.g.
Definition eventview.cpp:72
Keeps information about a month cell.
A MonthGraphicsItem representing a part of an event.
MonthItem * monthItem() const
Returns the associated MonthItem.
QRectF boundingRect() const override
Reimplemented from QGraphicsItem.
bool isBeginItem() const
Returns true if this MonthGraphicsItem is the first one of the MonthItem ones.
bool isEndItem() const
Returns true if this MonthGraphicsItem is the last one of the MonthItem ones.
Renders a MonthScene.
Definition monthscene.h:309
void setActionCursor(MonthScene::ActionType actionType)
Change the cursor according to actionType.
void drawBackground(QPainter *painter, const QRectF &rect) override
Draws the cells.
A month item manages different MonthGraphicsItems.
Definition monthitem.h:27
void moveTo(QDate date)
Called during a drag to move the item to a particular date.
void updateGeometry()
Updates geometry of all MonthGraphicsItems.
void beginMove()
Begin a move.
void endMove()
End a move.
QDate endDate() const
The end date of the incidence, generally realEndDate.
void endResize()
End a resize.
virtual bool isMoveable() const =0
Returns true if the item can be moved.
void beginResize()
Begin a resize.
bool resizeBy(int offsetFromPreviousDate)
Called during resize to resize the item a bit, relative to the previous resize step.
QDate startDate() const
The start date of the incidence, generally realStartDate.
virtual bool isResizable() const =0
Returns true if the item can be resized.
QDate averageDate() const
Returns the average date in the view.
KCalendarCore::DateList selectedIncidenceDates() const override
Returns dates of the currently selected events.
Graphics items which indicates that the view can be scrolled to display more events.
QBrush background(BackgroundRole=NormalBackground) const
QBrush foreground(ForegroundRole=NormalText) const
Q_SCRIPTABLE Q_NOREPLY void start()
QString i18nc(const char *context, const char *text, const TYPE &arg...)
AKONADI_CALENDAR_EXPORT KCalendarCore::Incidence::Ptr incidence(const Akonadi::Item &item)
Namespace EventViews provides facilities for displaying incidences, including events,...
Definition agenda.h:33
void start(int msec, QObject *object)
int timerId() const const
const QColor & color() const const
QColor darker(int factor) const const
void setAlpha(int alpha)
QDate addDays(qint64 ndays) const const
QDate currentDate()
qint64 daysTo(QDate d) const const
QDate date() const const
void accept()
virtual void setAccepted(bool accepted)
void setBold(bool enable)
bool isVisible() const const
QPainterPath mapFromScene(const QPainterPath &path) const const
void setPos(const QPointF &pos)
virtual bool event(QEvent *event) override
void invalidate(const QRectF &rect, SceneLayers layers)
QGraphicsItem * itemAt(const QPointF &position, const QTransform &deviceTransform) const const
void removeItem(QGraphicsItem *item)
void update(const QRectF &rect)
QList< QGraphicsView * > views() const const
QWidget * widget() const const
QPointF scenePos() const const
QPoint screenPos() const const
Qt::MouseButton button() const const
QPointF scenePos() const const
virtual bool event(QEvent *event) override
QGraphicsScene * scene() const const
void setScene(QGraphicsScene *scene)
QPixmap pixmap(QWindow *window, const QSize &size, Mode mode, State state) const const
QIcon fromTheme(const QString &name)
const_reference at(qsizetype i) const const
bool contains(const AT &value) const const
bool isEmpty() const const
QString dayName(int day, FormatType type) const const
QLocale system()
Q_EMITQ_EMIT
void drawRect(const QRect &rectangle)
void drawText(const QPoint &position, const QString &text)
void fillRect(const QRect &rectangle, QGradient::Preset preset)
const QFont & font() const const
void setBrush(Qt::BrushStyle style)
void setFont(const QFont &font)
void setPen(Qt::PenStyle style)
QColor color() const const
qreal x() const const
qreal y() const const
bool isNull() const const
qreal height() const const
qreal width() const const
bool isEmpty() const const
QString number(double n, char format, int precision)
AlignCenter
ArrowCursor
RightButton
int timerId() const const
void showText(const QPoint &pos, const QString &text, QWidget *w, const QRect &rect, int msecDisplayTime)
void setCursor(const QCursor &)
void setMouseTracking(bool enable)
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Tue Mar 26 2024 11:12:29 by doxygen 1.10.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.