14#include "agendaview.h"
17#include <Akonadi/CalendarUtils>
18#include <Akonadi/IncidenceChanger>
19#include <CalendarSupport/Utils>
21#include <KCalendarCore/Incidence>
23#include <KCalUtils/RecurrenceActions>
25#include "calendarview_debug.h"
28#include <KLocalizedString>
29#include <QApplication>
36#include <QResizeEvent>
44using namespace std::chrono_literals;
49class EventViews::MarcusBainsPrivate
52 MarcusBainsPrivate(EventView *eventView, Agenda *agenda)
53 : mEventView(eventView)
58 [[nodiscard]]
int todayColumn()
const;
61 EventView *
const mEventView;
62 Agenda *
const mAgenda;
63 QTimer *mTimer =
nullptr;
64 QLabel *mTimeBox =
nullptr;
65 QDateTime mOldDateTime;
66 int mOldTodayCol = -1;
69int MarcusBainsPrivate::todayColumn()
const
75 for (
const QDate &date : dateList) {
76 if (date == currentDate) {
85MarcusBains::MarcusBains(
EventView *eventView, Agenda *agenda)
87 , d(new MarcusBainsPrivate(eventView, agenda))
89 d->mTimeBox =
new QLabel(d->mAgenda);
92 d->mTimer =
new QTimer(
this);
93 d->mTimer->setSingleShot(
true);
98MarcusBains::~MarcusBains() =
default;
100void MarcusBains::updateLocation()
102 updateLocationRecalc();
105void MarcusBains::updateLocationRecalc(
bool recalculate)
107 const bool showSeconds = d->mEventView->preferences()->marcusBainsShowSeconds();
108 const QColor color = d->mEventView->preferences()->agendaMarcusBainsLineLineColor();
111 const QTime time = now.
time();
113 if (now.
date() != d->mOldDateTime.date()) {
116 const int todayCol = recalculate ? d->todayColumn() : d->mOldTodayCol;
119 const int minutes = time.
hour() * 60 + time.
minute();
120 const int minutesPerCell = 24 * 60 / d->mAgenda->rows();
122 d->mOldDateTime = now;
123 d->mOldTodayCol = todayCol;
125 int y = int(minutes * d->mAgenda->gridSpacingY() / minutesPerCell);
126 int x = int(d->mAgenda->gridSpacingX() * todayCol);
128 bool hideIt = !(d->mEventView->preferences()->marcusBainsEnabled());
129 if (!
isHidden() && (hideIt || (todayCol < 0))) {
142 const int fw = d->mEventView->preferences()->agendaMarcusBainsLineFont().weight();
156 d->mTimeBox->setFont(d->mEventView->preferences()->agendaMarcusBainsLineFont());
157 QPalette pal1 = d->mTimeBox->palette();
159 if (!d->mEventView->preferences()->useSystemColor()) {
164 d->mTimeBox->setPalette(pal1);
165 d->mTimeBox->setAutoFillBackground(
true);
167 d->mTimeBox->adjustSize();
168 if (
y - d->mTimeBox->height() >= 0) {
169 y -= d->mTimeBox->height();
173 if (
x - d->mTimeBox->width() + d->mAgenda->gridSpacingX() > 0) {
174 x += int(d->mAgenda->gridSpacingX() - d->mTimeBox->width() - 1);
178 d->mTimeBox->move(
x,
y);
179 d->mTimeBox->raise();
181 if (showSeconds || recalculate) {
182 d->mTimer->start(1s);
184 d->mTimer->start(1000 * (60 - time.
second()));
190class EventViews::AgendaPrivate
193 AgendaPrivate(AgendaView *agendaView, QScrollArea *scrollArea,
int columns,
int rows,
int rowSize,
bool isInteractive)
194 : mAgendaView(agendaView)
195 , mScrollArea(scrollArea)
200 , mGridSpacingY(rowSize)
201 , mDesiredGridSpacingY(rowSize)
203 , mResizeBorderWidth(0)
204 , mScrollBorderWidth(0)
207 , mWorkingHoursEnable(false)
208 , mHolidayMask(nullptr)
209 , mWorkingHoursYTop(0)
210 , mWorkingHoursYBottom(0)
211 , mHasSelection(false)
212 , mMarcusBains(nullptr)
213 , mActionType(Agenda::NOP)
215 , mOldLowerScrollValue(0)
216 , mOldUpperScrollValue(0)
217 , mReturnPressed(false)
218 , mIsInteractive(isInteractive)
220 if (mGridSpacingY < 4 || mGridSpacingY > 30) {
228 return mAgendaView->preferences();
231 bool isQueuedForDeletion(
const QString &uid)
const
235 return mItemsQueuedForDeletion.contains(uid) && !mAgendaItemsById.contains(uid);
238 QMultiHash<QString, AgendaItem::QPtr> mAgendaItemsById;
240 QSet<QString> mItemsQueuedForDeletion;
242 AgendaView *mAgendaView =
nullptr;
243 QScrollArea *mScrollArea =
nullptr;
254 double mGridSpacingX;
255 double mGridSpacingY;
256 double mDesiredGridSpacingY;
258 Akonadi::IncidenceChanger *mChanger =
nullptr;
261 int mResizeBorderWidth;
264 int mScrollBorderWidth;
268 QTimer mScrollUpTimer;
269 QTimer mScrollDownTimer;
276 bool mWorkingHoursEnable;
277 QList<bool> *mHolidayMask =
nullptr;
278 int mWorkingHoursYTop;
279 int mWorkingHoursYBottom;
283 QPoint mSelectionStartPoint;
284 QPoint mSelectionStartCell;
285 QPoint mSelectionEndCell;
291 QPointer<AgendaItem> mClickedItem;
294 QPointer<AgendaItem> mActionItem;
297 QPointer<AgendaItem> mSelectedItem;
304 MarcusBains *mMarcusBains =
nullptr;
306 Agenda::MouseActionType mActionType;
311 QList<AgendaItem::QPtr> mItems;
312 QList<AgendaItem::QPtr> mItemsToDelete;
314 int mOldLowerScrollValue;
315 int mOldUpperScrollValue;
320 MultiViewCalendar::Ptr mCalendar;
326Agenda::Agenda(
AgendaView *agendaView, QScrollArea *scrollArea,
int columns,
int rows,
int rowSize,
bool isInteractive)
327 : QWidget(scrollArea)
328 , d(new AgendaPrivate(agendaView, scrollArea, columns, rows, rowSize, isInteractive))
330 setMouseTracking(
true);
341 , d(new AgendaPrivate(agendaView, scrollArea, columns, 1, 24, isInteractive))
343 d->mAllDayMode =
true;
350 delete d->mMarcusBains;
358QDate Agenda::selectedIncidenceDate()
const
360 return d->mSelectedItem ? d->mSelectedItem->occurrenceDate() : QDate();
363QString Agenda::lastSelectedItemUid()
const
365 return d->mSelectedId;
372 d->mGridSpacingX =
static_cast<double>(d->mScrollArea->width()) / d->mColumns;
373 d->mDesiredGridSpacingY = d->preferences()->hourSize();
374 if (d->mDesiredGridSpacingY < 4 || d->mDesiredGridSpacingY > 30) {
375 d->mDesiredGridSpacingY = 10;
379 d->mGridSpacingY =
static_cast<double>(
height()) / d->mRows;
380 if (d->mGridSpacingY < d->mDesiredGridSpacingY) {
381 d->mGridSpacingY = d->mDesiredGridSpacingY;
384 d->mResizeBorderWidth = 12;
385 d->mScrollBorderWidth = 12;
386 d->mScrollDelay = 30;
387 d->mScrollOffset = 10;
396 d->mStartCell = QPoint(0, 0);
397 d->mEndCell = QPoint(0, 0);
399 d->mHasSelection =
false;
400 d->mSelectionStartPoint = QPoint(0, 0);
401 d->mSelectionStartCell = QPoint(0, 0);
402 d->mSelectionEndCell = QPoint(0, 0);
404 d->mOldLowerScrollValue = -1;
405 d->mOldUpperScrollValue = -1;
407 d->mClickedItem =
nullptr;
409 d->mActionItem =
nullptr;
410 d->mActionType = NOP;
411 d->mItemMoved =
false;
413 d->mSelectedItem =
nullptr;
420 d->mScrollArea->viewport()->update();
424 calculateWorkingHours();
429 if (d->mAllDayMode) {
430 d->mMarcusBains =
nullptr;
432 d->mMarcusBains =
new MarcusBains(d->mAgendaView,
this);
438 qDeleteAll(d->mItems);
439 qDeleteAll(d->mItemsToDelete);
441 d->mItemsToDelete.clear();
442 d->mAgendaItemsById.clear();
443 d->mItemsQueuedForDeletion.clear();
445 d->mSelectedItem =
nullptr;
450void Agenda::clearSelection()
452 d->mHasSelection =
false;
453 d->mActionType = NOP;
457void Agenda::marcus_bains()
459 if (d->mMarcusBains) {
460 d->mMarcusBains->updateLocationRecalc(
true);
464void Agenda::changeColumns(
int columns)
467 qCDebug(CALENDARVIEW_LOG) <<
"called with argument 0";
472 d->mColumns = columns;
482int Agenda::columns()
const
487int Agenda::rows()
const
492double Agenda::gridSpacingX()
const
494 return d->mGridSpacingX;
497double Agenda::gridSpacingY()
const
499 return d->mGridSpacingY;
506bool Agenda::eventFilter(QObject *
object, QEvent *event)
508 switch (
event->type()) {
513 return eventFilter_mouse(
object,
static_cast<QMouseEvent *
>(
event));
514#ifndef QT_NO_WHEELEVENT
516 return eventFilter_wheel(
object,
static_cast<QWheelEvent *
>(
event));
520 return eventFilter_key(
object,
static_cast<QKeyEvent *
>(
event));
524 if (!d->mActionItem) {
529 if (
object ==
this) {
539#ifndef QT_NO_DRAGANDDROP
545 return eventFilter_drag(
object,
static_cast<QDropEvent *
>(
event));
553bool Agenda::eventFilter_drag(QObject *obj, QDropEvent *de)
555#ifndef QT_NO_DRAGANDDROP
556 const QMimeData *md = de->
mimeData();
558 switch (de->
type()) {
561 if (!CalendarSupport::canDecode(md)) {
565 if (CalendarSupport::mimeDataHasIncidence(md)) {
576 if (!CalendarSupport::canDecode(md)) {
580 const QList<QUrl> incidenceUrls = CalendarSupport::incidenceItemUrls(md);
589 if (dropTarget && dropTarget !=
this) {
590 dropPosition = dropTarget->
mapTo(
this, dropPosition);
593 const QPoint gridPosition = contentsToGrid(dropPosition);
594 if (!incidenceUrls.
isEmpty()) {
595 Q_EMIT droppedIncidences(incidenceUrls, gridPosition, d->mAllDayMode);
597 Q_EMIT droppedIncidences(incidences, gridPosition, d->mAllDayMode);
610#ifndef QT_NO_WHEELEVENT
611bool Agenda::eventFilter_wheel(QObject *
object, QWheelEvent *e)
614 bool accepted =
false;
617 if (
object !=
this) {
618 viewportPos = ((
QWidget *)
object)->mapToParent(
pos);
628 if (
object !=
this) {
629 viewportPos = ((
QWidget *)
object)->mapToParent(
pos);
634 Q_EMIT mousePosSignal(gridToContents(contentsToGrid(viewportPos)));
645bool Agenda::eventFilter_key(QObject *, QKeyEvent *ke)
647 return d->mAgendaView->processKeyEvent(ke);
650bool Agenda::eventFilter_mouse(QObject *
object, QMouseEvent *me)
653 if (
object !=
this) {
656 viewportPos = me->
pos();
659 switch (me->
type()) {
661 if (
object !=
this) {
664 if (d->mClickedItem) {
665 selectItem(d->mClickedItem);
666 Q_EMIT showIncidencePopupSignal(d->mClickedItem->incidence(), d->mClickedItem->occurrenceDate());
673 d->mActionItem =
nullptr;
675 d->mActionItem = item;
676 startItemAction(viewportPos);
688 QPoint gpos = contentsToGrid(viewportPos);
689 if (!ptInSelection(gpos)) {
690 d->mSelectionStartCell = gpos;
691 d->mSelectionEndCell = gpos;
692 d->mHasSelection =
true;
693 Q_EMIT newStartSelectSignal();
694 Q_EMIT newTimeSpanSignal(d->mSelectionStartCell, d->mSelectionEndCell);
697 Q_EMIT showNewEventPopupSignal();
700 d->mActionItem =
nullptr;
704 startSelectAction(viewportPos);
711 if (d->mActionItem) {
713 }
else if (d->mActionType == SELECT) {
714 endSelectAction(viewportPos);
718 Q_EMIT mousePosSignal(gridToContents(contentsToGrid(viewportPos)));
722 if (!d->mIsInteractive) {
728 QPoint indicatorPos = gridToContents(contentsToGrid(viewportPos));
729 if (
object !=
this) {
732 if (incidence && !
incidence->isReadOnly()) {
733 if (!d->mActionItem) {
734 setNoActionCursor(moveItem, viewportPos);
736 performItemAction(viewportPos);
738 if (d->mActionType == MOVE) {
740 AgendaItem::QPtr firstItem = d->mActionItem->firstMultiItem();
742 firstItem = d->mActionItem;
744 indicatorPos = gridToContents(QPoint(firstItem->cellXLeft(), firstItem->cellYTop()));
745 }
else if (d->mActionType == RESIZEBOTTOM) {
747 indicatorPos = gridToContents(QPoint(d->mActionItem->cellXLeft(), d->mActionItem->cellYBottom() + 1));
752 if (d->mActionType == SELECT) {
753 performSelectAction(viewportPos);
756 if (((d->mStartCell.y() < d->mEndCell.y()) && (d->mEndCell.x() >= d->mStartCell.x())) || (d->mEndCell.x() > d->mStartCell.x())) {
757 indicatorPos = gridToContents(QPoint(d->mEndCell.x(), d->mEndCell.y() + 1));
759 indicatorPos = gridToContents(d->mEndCell);
763 Q_EMIT mousePosSignal(indicatorPos);
768 if (
object ==
this) {
773 if (doubleClickedItem) {
774 selectItem(doubleClickedItem);
775 Q_EMIT editIncidenceSignal(doubleClickedItem->incidence());
787bool Agenda::ptInSelection(QPoint gpos)
const
789 if (!d->mHasSelection) {
791 }
else if (gpos.
x() < d->mSelectionStartCell.x() || gpos.
x() > d->mSelectionEndCell.x()) {
793 }
else if ((gpos.
x() == d->mSelectionStartCell.x()) && (gpos.
y() < d->mSelectionStartCell.y())) {
795 }
else if ((gpos.
x() == d->mSelectionEndCell.x()) && (gpos.
y() > d->mSelectionEndCell.y())) {
801void Agenda::startSelectAction(QPoint viewportPos)
803 Q_EMIT newStartSelectSignal();
805 d->mActionType = SELECT;
806 d->mSelectionStartPoint = viewportPos;
807 d->mHasSelection =
true;
809 QPoint
pos = viewportPos;
810 QPoint gpos = contentsToGrid(
pos);
813 d->mStartCell = gpos;
815 d->mSelectionStartCell = gpos;
816 d->mSelectionEndCell = gpos;
821void Agenda::performSelectAction(QPoint pos)
823 const QPoint gpos = contentsToGrid(
pos);
826 if (
pos.y() - contentsY() < d->mScrollBorderWidth && contentsY() > 0) {
827 d->mScrollUpTimer.start(d->mScrollDelay);
828 }
else if (contentsY() + d->mScrollArea->viewport()->height() - d->mScrollBorderWidth <
pos.y()) {
829 d->mScrollDownTimer.start(d->mScrollDelay);
831 d->mScrollUpTimer.stop();
832 d->mScrollDownTimer.stop();
835 if (gpos != d->mEndCell) {
837 if (d->mStartCell.x() > d->mEndCell.x() || (d->mStartCell.x() == d->mEndCell.x() && d->mStartCell.y() > d->mEndCell.y())) {
839 d->mSelectionStartCell = d->mEndCell;
840 d->mSelectionEndCell = d->mStartCell;
842 d->mSelectionStartCell = d->mStartCell;
843 d->mSelectionEndCell = d->mEndCell;
850void Agenda::endSelectAction(
const QPoint ¤tPos)
852 d->mScrollUpTimer.stop();
853 d->mScrollDownTimer.stop();
855 d->mActionType = NOP;
857 Q_EMIT newTimeSpanSignal(d->mSelectionStartCell, d->mSelectionEndCell);
859 if (d->preferences()->selectionStartsEditor()) {
866Agenda::MouseActionType Agenda::isInResizeArea(
bool horizontal, QPoint pos,
const AgendaItem::QPtr &item)
871 QPoint gridpos = contentsToGrid(
pos);
875 int clXLeft = item->cellXLeft();
876 int clXRight = item->cellXRight();
882 int gridDistanceX = int(
pos.x() - contpos.
x());
883 if (gridDistanceX < d->mResizeBorderWidth && clXLeft == gridpos.
x()) {
889 }
else if ((d->mGridSpacingX - gridDistanceX) < d->mResizeBorderWidth && clXRight == gridpos.
x()) {
899 int gridDistanceY = int(
pos.y() - contpos.
y());
900 if (gridDistanceY < d->mResizeBorderWidth && item->cellYTop() == gridpos.
y() && !item->firstMultiItem()) {
902 }
else if ((d->mGridSpacingY - gridDistanceY) < d->mResizeBorderWidth && item->cellYBottom() == gridpos.
y() && !item->lastMultiItem()) {
910void Agenda::startItemAction(
const QPoint &pos)
912 Q_ASSERT(d->mActionItem);
914 d->mStartCell = contentsToGrid(
pos);
915 d->mEndCell = d->mStartCell;
917 bool noResize = CalendarSupport::hasTodo(d->mActionItem->incidence());
919 d->mActionType = MOVE;
921 d->mActionType = isInResizeArea(d->mAllDayMode,
pos, d->mActionItem);
924 d->mActionItem->startMove();
925 setActionCursor(d->mActionType,
true);
928void Agenda::performItemAction(QPoint pos)
930 QPoint gpos = contentsToGrid(
pos);
934 if (
pos.y() < 0 ||
pos.y() >= contentsY() + d->mScrollArea->viewport()->height() ||
pos.x() < 0 ||
pos.x() >=
width()) {
935 if (d->mActionType == MOVE) {
936 d->mScrollUpTimer.stop();
937 d->mScrollDownTimer.stop();
938 d->mActionItem->resetMove();
939 placeSubCells(d->mActionItem);
940 Q_EMIT startDragSignal(d->mActionItem->incidence());
947 d->mActionItem =
nullptr;
948 d->mActionType = NOP;
949 d->mItemMoved =
false;
953 setActionCursor(d->mActionType,
true);
957 const int distanceToTop =
pos.y() - contentsY();
958 if (distanceToTop < d->mScrollBorderWidth && distanceToTop > -d->mScrollBorderWidth) {
959 d->mScrollUpTimer.start(d->mScrollDelay);
960 }
else if (contentsY() + d->mScrollArea->viewport()->height() - d->mScrollBorderWidth <
pos.y()) {
961 d->mScrollDownTimer.start(d->mScrollDelay);
963 d->mScrollUpTimer.stop();
964 d->mScrollDownTimer.stop();
968 if (d->mEndCell != gpos) {
969 if (!d->mItemMoved) {
972 i18n(
"Unable to lock item for modification. "
973 "You cannot make any changes."),
974 i18nc(
"@title:window",
"Locking Failed"),
975 QStringLiteral(
"AgendaLockingFailed"));
976 d->mScrollUpTimer.stop();
977 d->mScrollDownTimer.stop();
978 d->mActionItem->resetMove();
979 placeSubCells(d->mActionItem);
983 d->mActionItem =
nullptr;
984 d->mActionType = NOP;
985 d->mItemMoved =
false;
988 d->mItemMoved =
true;
990 d->mActionItem->raise();
991 if (d->mActionType == MOVE) {
993 AgendaItem::QPtr firstItem = d->mActionItem->firstMultiItem();
995 firstItem = d->mActionItem;
997 AgendaItem::QPtr lastItem = d->mActionItem->lastMultiItem();
999 lastItem = d->mActionItem;
1001 QPoint deltapos = gpos - d->mEndCell;
1002 AgendaItem::QPtr moveItem = firstItem;
1004 bool changed =
false;
1005 if (deltapos.
x() != 0) {
1006 moveItem->moveRelative(deltapos.
x(), 0);
1010 if (moveItem == firstItem && !d->mAllDayMode) {
1011 int newY = deltapos.
y() + moveItem->cellYTop();
1013 if (newY < 0 && newY > d->mScrollBorderWidth) {
1014 moveItem->expandTop(-moveItem->cellYTop());
1016 AgendaItem::QPtr newFirst = firstItem->prevMoveItem();
1020 newFirst->setCellXY(moveItem->cellXLeft() - 1, rows() + newY, rows() - 1);
1021 d->mItems.append(newFirst);
1022 moveItem->resize(
int(d->mGridSpacingX * newFirst->cellWidth()),
int(d->mGridSpacingY * newFirst->cellHeight()));
1023 QPoint cpos = gridToContents(QPoint(newFirst->cellXLeft(), newFirst->cellYTop()));
1024 newFirst->setParent(
this);
1025 newFirst->move(cpos.
x(), cpos.
y());
1027 newFirst = insertItem(moveItem->incidence(),
1028 moveItem->occurrenceDateTime(),
1029 moveItem->cellXLeft() - 1,
1032 moveItem->itemPos(),
1033 moveItem->itemCount(),
1039 moveItem->prependMoveItem(newFirst);
1040 firstItem = newFirst;
1041 }
else if (newY >= rows()) {
1044 firstItem = moveItem->nextMultiItem();
1046 d->mItems.removeAll(moveItem);
1048 d->mActionItem->removeMoveItem(moveItem);
1049 moveItem = firstItem;
1052 moveItem->expandTop(rows() - newY);
1055 moveItem->expandTop(deltapos.
y(),
true);
1059 if (moveItem && !moveItem->lastMultiItem() && !d->mAllDayMode) {
1060 int newY = deltapos.
y() + moveItem->cellYBottom();
1063 lastItem = moveItem->prevMultiItem();
1065 d->mItems.removeAll(moveItem);
1067 moveItem->removeMoveItem(moveItem);
1068 moveItem = lastItem;
1069 moveItem->expandBottom(newY + 1);
1070 }
else if (newY >= rows()) {
1071 moveItem->expandBottom(rows() - moveItem->cellYBottom() - 1);
1073 AgendaItem::QPtr newLast = lastItem->nextMoveItem();
1075 newLast->setCellXY(moveItem->cellXLeft() + 1, 0, newY - rows() - 1);
1076 d->mItems.append(newLast);
1077 moveItem->resize(
int(d->mGridSpacingX * newLast->cellWidth()),
int(d->mGridSpacingY * newLast->cellHeight()));
1078 QPoint cpos = gridToContents(QPoint(newLast->cellXLeft(), newLast->cellYTop()));
1079 newLast->setParent(
this);
1080 newLast->move(cpos.
x(), cpos.
y());
1082 newLast = insertItem(moveItem->incidence(),
1083 moveItem->occurrenceDateTime(),
1084 moveItem->cellXLeft() + 1,
1087 moveItem->itemPos(),
1088 moveItem->itemCount(),
1091 moveItem->appendMoveItem(newLast);
1095 moveItem->expandBottom(deltapos.
y());
1100 adjustItemPosition(moveItem);
1103 moveItem = moveItem->nextMultiItem();
1106 }
else if (d->mActionType == RESIZETOP) {
1107 if (d->mEndCell.y() <= d->mActionItem->cellYBottom()) {
1108 d->mActionItem->expandTop(gpos.
y() - d->mEndCell.y());
1109 adjustItemPosition(d->mActionItem);
1111 }
else if (d->mActionType == RESIZEBOTTOM) {
1112 if (d->mEndCell.y() >= d->mActionItem->cellYTop()) {
1113 d->mActionItem->expandBottom(gpos.
y() - d->mEndCell.y());
1114 adjustItemPosition(d->mActionItem);
1116 }
else if (d->mActionType == RESIZELEFT) {
1117 if (d->mEndCell.x() <= d->mActionItem->cellXRight()) {
1118 d->mActionItem->expandLeft(gpos.
x() - d->mEndCell.x());
1119 adjustItemPosition(d->mActionItem);
1121 }
else if (d->mActionType == RESIZERIGHT) {
1122 if (d->mEndCell.x() >= d->mActionItem->cellXLeft()) {
1123 d->mActionItem->expandRight(gpos.
x() - d->mEndCell.x());
1124 adjustItemPosition(d->mActionItem);
1131void Agenda::endItemAction()
1134 d->mActionType = NOP;
1135 d->mScrollUpTimer.stop();
1136 d->mScrollDownTimer.stop();
1142 qCCritical(CALENDARVIEW_LOG) <<
"No IncidenceChanger set";
1146 bool multiModify =
false;
1149 const auto recurrenceId = d->mActionItem->occurrenceDateTime();
1151 d->mItemMoved = d->mItemMoved && !(d->mStartCell.x() == d->mEndCell.x() && d->mStartCell.y() == d->mEndCell.y());
1153 if (d->mItemMoved) {
1154 bool addIncidence =
false;
1155 bool modify =
false;
1161 if (CalendarSupport::hasEvent(incidence)) {
1162 mainIncidence = cal->event(
incidence->uid());
1163 }
else if (CalendarSupport::hasTodo(incidence)) {
1164 mainIncidence = cal->todo(
incidence->uid());
1169 Akonadi::Item item = d->mCalendar->item(incidence);
1171 const int res = d->mAgendaView->showMoveRecurDialog(incidence, recurrenceId.date());
1173 if (!d->mActionItem) {
1174 qCWarning(CALENDARVIEW_LOG) <<
"mActionItem was reset while the 'move' dialog was active";
1175 d->mItemMoved =
false;
1189 d->mChanger->startAtomicOperation(
i18n(
"Dissociate event from recurrence"));
1192 newInc->removeCustomProperty(
"VOLATILE",
"AKONADI-ID");
1193 Akonadi::Item newItem = d->mCalendar->item(newInc);
1195 if (newItem.
isValid() && newItem != item) {
1197 newInc->setCustomProperty(
"VOLATILE",
"AKONADI-ID",
QString::number(newItem.
id()));
1198 addIncidence =
false;
1200 addIncidence =
true;
1203 d->mAgendaView->enableAgendaUpdate(
false);
1205 d->mActionItem->setIncidence(newInc);
1206 d->mActionItem->dissociateFromMultiItem();
1208 d->mAgendaView->enableAgendaUpdate(
true);
1211 i18n(
"Unable to add the exception item to the calendar. "
1212 "No change will be done."),
1213 i18nc(
"@title:window",
"Error Occurred"));
1219 d->mActionItem->resetMove();
1220 placeSubCells(d->mActionItem);
1225 AgendaItem::QPtr placeItem = d->mActionItem->firstMultiItem();
1227 placeItem = d->mActionItem;
1242 d->mActionItem->endMove();
1244 AgendaItem::QPtr modif = placeItem;
1246 QList<AgendaItem::QPtr> oldconflictItems = placeItem->conflictItems();
1247 QList<AgendaItem::QPtr>::iterator it;
1248 for (it = oldconflictItems.
begin(); it != oldconflictItems.
end(); ++it) {
1254 placeSubCells(placeItem);
1255 placeItem = placeItem->nextMultiItem();
1266 d->mAgendaView->updateEventDates(modif, addIncidence, saveCollection);
1276 d->mAgendaView->updateEventDates(placeItem, addIncidence, saveCollection);
1281 d->mActionItem =
nullptr;
1282 d->mItemMoved =
false;
1285 d->mChanger->endAtomicOperation();
1289void Agenda::setActionCursor(
int actionType,
bool acting)
1292 switch (actionType) {
1314void Agenda::setNoActionCursor(
const AgendaItem::QPtr &moveItem, QPoint pos)
1318 const bool noResize = CalendarSupport::hasTodo(item);
1320 Agenda::MouseActionType resizeType = MOVE;
1322 resizeType = isInResizeArea(d->mAllDayMode,
pos, moveItem);
1324 setActionCursor(resizeType);
1329double Agenda::calcSubCellWidth(
const AgendaItem::QPtr &item)
1333 pt = gridToContents(QPoint(item->cellXLeft(), item->cellYTop()));
1334 pt1 = gridToContents(QPoint(item->cellXLeft(), item->cellYTop()) + QPoint(1, 1));
1336 int maxSubCells = item->subCells();
1337 double newSubCellWidth;
1338 if (d->mAllDayMode) {
1339 newSubCellWidth =
static_cast<double>(pt1.
y()) / maxSubCells;
1341 newSubCellWidth =
static_cast<double>(pt1.
x()) / maxSubCells;
1343 return newSubCellWidth;
1346void Agenda::adjustItemPosition(
const AgendaItem::QPtr &item)
1351 item->resize(
int(d->mGridSpacingX * item->cellWidth()),
int(d->mGridSpacingY * item->cellHeight()));
1352 int clXLeft = item->cellXLeft();
1354 clXLeft = item->cellXRight() + 1;
1356 QPoint cpos = gridToContents(QPoint(clXLeft, item->cellYTop()));
1357 item->move(cpos.
x(), cpos.
y());
1360void Agenda::placeAgendaItem(
const AgendaItem::QPtr &item,
double subCellWidth)
1364 QPoint pt = gridToContents(QPoint(item->cellXLeft(), item->cellYTop()));
1366 QPoint pt1 = gridToContents(QPoint(item->cellXLeft() + item->cellWidth(), item->cellYBottom() + 1));
1368 double subCellPos = item->subCell() * subCellWidth;
1372 double delta = 0.01;
1373 if (subCellWidth < 0) {
1380 if (d->mAllDayMode) {
1382 height = int(subCellPos + subCellWidth + delta) - int(subCellPos);
1384 ypos = pt.
y() + int(subCellPos);
1386 width = int(subCellPos + subCellWidth + delta) - int(subCellPos);
1388 xpos = pt.
x() + int(subCellPos);
1400 item->move(xpos, ypos);
1413void Agenda::placeSubCells(
const AgendaItem::QPtr &placeItem)
1416 qCDebug(CALENDARVIEW_LOG);
1420 qCDebug(CALENDARVIEW_LOG) <<
" event is 0";
1422 qCDebug(CALENDARVIEW_LOG) <<
" event:" <<
event->summary();
1425 qCDebug(CALENDARVIEW_LOG) <<
" placeItem is 0";
1427 qCDebug(CALENDARVIEW_LOG) <<
"Agenda::placeSubCells()...";
1430 QList<CalendarSupport::CellItem *> cells;
1431 for (CalendarSupport::CellItem *item : std::as_const(d->mItems)) {
1437 QList<CalendarSupport::CellItem *> items = CalendarSupport::CellItem::placeItem(cells, placeItem);
1439 placeItem->setConflictItems(QList<AgendaItem::QPtr>());
1440 double newSubCellWidth = calcSubCellWidth(placeItem);
1441 QList<CalendarSupport::CellItem *>::iterator it;
1442 for (it = items.
begin(); it != items.
end(); ++it) {
1444 AgendaItem::QPtr item =
static_cast<AgendaItem *
>(*it);
1445 placeAgendaItem(item, newSubCellWidth);
1446 item->addConflictItem(placeItem);
1447 placeItem->addConflictItem(item);
1451 placeAgendaItem(placeItem, newSubCellWidth);
1453 placeItem->update();
1456int Agenda::columnWidth(
int column)
const
1458 int start = gridToContents(QPoint(column, 0)).x();
1464 int end = gridToContents(QPoint(column, 0)).x();
1468void Agenda::paintEvent(QPaintEvent *)
1471 drawContents(&p, 0, -
y(), d->mGridSpacingX * d->mColumns, d->mGridSpacingY * d->mRows +
y());
1477void Agenda::drawContents(QPainter *p,
int cx,
int cy,
int cw,
int ch)
1487 if (!d->preferences()->useSystemColor()) {
1488 dbp.fillRect(0, 0, cw, ch, d->preferences()->agendaGridBackgroundColor());
1493 dbp.translate(-cx, -cy);
1495 double lGridSpacingY = d->mGridSpacingY * 2;
1501 const QList<bool> busyDayMask = d->mAgendaView->busyDayMask();
1504 if (d->mWorkingHoursEnable && d->mHolidayMask) {
1506 if (!d->preferences()->useSystemColor()) {
1507 workColor = d->preferences()->workingHoursColor();
1512 QPoint pt1(cx, d->mWorkingHoursYTop);
1513 QPoint pt2(cx + cw, d->mWorkingHoursYBottom);
1514 if (pt2.x() >= pt1.
x() ) {
1515 int gxStart = contentsToGrid(pt1).x();
1516 int gxEnd = contentsToGrid(pt2).x();
1518 if (gxStart > gxEnd) {
1524 while (gxStart <= gxEnd) {
1525 int xStart = gridToContents(QPoint(gxStart + xoffset, 0)).x();
1526 int xWidth = columnWidth(gxStart) + 1;
1528 if (pt2.y() < pt1.
y()) {
1530 if (((gxStart == 0) && !d->mHolidayMask->at(d->mHolidayMask->count() - 1))
1531 || ((gxStart > 0) && (gxStart <
int(d->mHolidayMask->count())) && (!d->mHolidayMask->at(gxStart - 1)))) {
1533 dbp.fillRect(xStart, cy, xWidth, pt2.y() - cy + 1, workColor);
1536 if ((gxStart <
int(d->mHolidayMask->count() - 1)) && (!d->mHolidayMask->at(gxStart))) {
1537 if (pt1.
y() < cy + ch - 1) {
1538 dbp.fillRect(xStart, pt1.
y(), xWidth, cy + ch - pt1.
y() + 1, workColor);
1544 if (gxStart <
int(d->mHolidayMask->count() - 1) && !d->mHolidayMask->at(gxStart)) {
1545 dbp.fillRect(xStart, pt1.
y(), xWidth, pt2.y() - pt1.
y() + 1, workColor);
1554 if (d->preferences()->colorAgendaBusyDays() && !d->mAllDayMode) {
1555 for (
int i = 0; i < busyDayMask.
count(); ++i) {
1556 if (busyDayMask[i]) {
1557 const QPoint pt1(cx + d->mGridSpacingX * i, 0);
1560 if (!d->preferences()->useSystemColor()) {
1561 busyColor = d->preferences()->viewBgBusyColor();
1564 if ((busyColor.
blue() + busyColor.
red() + busyColor.
green()) > (256 / 2 * 3)) {
1566 busyColor = busyColor.
lighter(140);
1569 busyColor = busyColor.
darker(140);
1572 busyColor.
setAlpha(EventViews::BUSY_BACKGROUND_ALPHA);
1573 dbp.fillRect(pt1.
x(), pt1.
y(), d->mGridSpacingX, cy + ch, busyColor);
1579 if (d->mHasSelection && d->mAgendaView->dateRangeSelectionEnabled()) {
1582 QColor highlightColor;
1583 if (!d->preferences()->useSystemColor()) {
1584 highlightColor = d->preferences()->agendaGridHighlightColor();
1589 if (d->mSelectionEndCell.x() > d->mSelectionStartCell.x()) {
1591 pt = gridToContents(d->mSelectionStartCell);
1592 pt1 = gridToContents(QPoint(d->mSelectionStartCell.x() + 1, d->mRows + 1));
1593 dbp.fillRect(QRect(pt, pt1), highlightColor);
1595 for (
int c = d->mSelectionStartCell.x() + 1; c < d->mSelectionEndCell.x(); ++c) {
1596 pt = gridToContents(QPoint(c, 0));
1597 pt1 = gridToContents(QPoint(c + 1, d->mRows + 1));
1598 dbp.fillRect(QRect(pt, pt1), highlightColor);
1601 pt = gridToContents(QPoint(d->mSelectionEndCell.x(), 0));
1602 pt1 = gridToContents(d->mSelectionEndCell + QPoint(1, 1));
1603 dbp.fillRect(QRect(pt, pt1), highlightColor);
1605 pt = gridToContents(d->mSelectionStartCell);
1606 pt1 = gridToContents(d->mSelectionEndCell + QPoint(1, 1));
1607 dbp.fillRect(QRect(pt, pt1), highlightColor);
1617 if (windowTextColor.
red() + windowTextColor.
green() + windowTextColor.
blue() < (256 / 2 * 3)) {
1619 hourPen = windowTextColor.
lighter(200);
1620 halfHourPen = windowTextColor.
lighter(500);
1623 hourPen = windowTextColor.
darker(150);
1624 halfHourPen = windowTextColor.
darker(200);
1627 dbp.setPen(hourPen);
1630 double x = (int(cx / d->mGridSpacingX)) * d->mGridSpacingX;
1631 while (
x < cx + cw) {
1632 dbp.drawLine(
int(
x), cy,
int(
x), cy + ch);
1633 x += d->mGridSpacingX;
1637 double y = (int(cy / (2 * lGridSpacingY))) * 2 * lGridSpacingY;
1638 while (
y < cy + ch) {
1639 dbp.drawLine(cx,
int(
y), cx + cw,
int(
y));
1640 y += 2 * lGridSpacingY;
1642 y = (2 * int(cy / (2 * lGridSpacingY)) + 1) * lGridSpacingY;
1643 dbp.setPen(halfHourPen);
1644 while (
y < cy + ch) {
1645 dbp.drawLine(cx,
int(
y), cx + cw,
int(
y));
1646 y += 2 * lGridSpacingY;
1654QPoint Agenda::contentsToGrid(QPoint pos)
const
1657 int gy = int(
pos.y() / d->mGridSpacingY);
1664QPoint Agenda::gridToContents(QPoint gpos)
const
1667 int y = int(gpos.
y() * d->mGridSpacingY);
1675int Agenda::timeToY(QTime time)
const
1677 int minutesPerCell = 24 * 60 / d->mRows;
1678 int timeMinutes = time.
hour() * 60 + time.
minute();
1679 int Y = (timeMinutes + (minutesPerCell / 2)) / minutesPerCell;
1688QTime Agenda::gyToTime(
int gy)
const
1690 int secondsPerCell = 24 * 60 * 60 / d->mRows;
1691 int timeSeconds = secondsPerCell * gy;
1693 QTime time(0, 0, 0);
1694 if (timeSeconds < 24 * 60 * 60) {
1695 time = time.
addSecs(timeSeconds);
1702QList<int> Agenda::minContentsY()
const
1704 QList<int> minArray;
1705 minArray.
fill(timeToY(QTime(23, 59)), d->mSelectedDates.count());
1706 for (
const AgendaItem::QPtr &item : std::as_const(d->mItems)) {
1708 int ymin = item->cellYTop();
1709 int index = item->cellXLeft();
1710 if (index >= 0 && index < (
int)(d->mSelectedDates.count())) {
1711 if (ymin < minArray[index] && !d->mItemsToDelete.contains(item)) {
1712 minArray[index] = ymin;
1721QList<int> Agenda::maxContentsY()
const
1723 QList<int> maxArray;
1724 maxArray.
fill(timeToY(QTime(0, 0)), d->mSelectedDates.count());
1725 for (
const AgendaItem::QPtr &item : std::as_const(d->mItems)) {
1727 int ymax = item->cellYBottom();
1729 int index = item->cellXLeft();
1730 if (index >= 0 && index < (
int)(d->mSelectedDates.count())) {
1731 if (ymax > maxArray[index] && !d->mItemsToDelete.contains(item)) {
1732 maxArray[index] = ymax;
1741void Agenda::setStartTime(QTime startHour)
1743 const double startPos = (startHour.
hour() / 24. + startHour.
minute() / 1440. + startHour.
second() / 86400.) * d->mRows * gridSpacingY();
1745 verticalScrollBar()->setValue(startPos);
1752 const QDateTime &recurrenceId,
1760 if (d->mAllDayMode) {
1761 qCDebug(CALENDARVIEW_LOG) <<
"using this in all-day mode is illegal.";
1765 d->mActionType = NOP;
1767 AgendaItem::QPtr agendaItem = createAgendaItem(incidence, itemPos, itemCount, recurrenceId, isSelected);
1772 if (YTop >= d->mRows) {
1773 YBottom -= YTop - (d->mRows - 1);
1774 YTop = d->mRows - 1;
1776 if (YBottom <= YTop) {
1777 qCDebug(CALENDARVIEW_LOG) <<
"Text:" << agendaItem->text() <<
" YSize<0";
1781 agendaItem->resize(
int((X + 1) * d->mGridSpacingX) -
int(X * d->mGridSpacingX),
int(YTop * d->mGridSpacingY) -
int((YBottom + 1) * d->mGridSpacingY));
1782 agendaItem->setCellXY(X, YTop, YBottom);
1783 agendaItem->setCellXRight(X);
1784 agendaItem->setResourceColor(d->mCalendar->resourceColor(incidence));
1785 agendaItem->installEventFilter(
this);
1787 agendaItem->move(
int(X * d->mGridSpacingX),
int(YTop * d->mGridSpacingY));
1789 d->mItems.append(agendaItem);
1791 placeSubCells(agendaItem);
1803AgendaItem::QPtr Agenda::insertAllDayItem(
const KCalendarCore::Incidence::Ptr &incidence,
const QDateTime &recurrenceId,
int XBegin,
int XEnd,
bool isSelected)
1805 if (!d->mAllDayMode) {
1806 qCCritical(CALENDARVIEW_LOG) <<
"using this in non all-day mode is illegal.";
1810 d->mActionType = NOP;
1812 AgendaItem::QPtr agendaItem = createAgendaItem(incidence, 1, 1, recurrenceId, isSelected);
1817 agendaItem->setCellXY(XBegin, 0, 0);
1818 agendaItem->setCellXRight(XEnd);
1820 const double startIt = d->mGridSpacingX * (agendaItem->cellXLeft());
1821 const double endIt = d->mGridSpacingX * (agendaItem->cellWidth() + agendaItem->cellXLeft());
1823 agendaItem->resize(
int(endIt) -
int(startIt),
int(d->mGridSpacingY));
1825 agendaItem->installEventFilter(
this);
1826 agendaItem->setResourceColor(d->mCalendar->resourceColor(incidence));
1827 agendaItem->move(
int(XBegin * d->mGridSpacingX), 0);
1828 d->mItems.append(agendaItem);
1830 placeSubCells(agendaItem);
1838Agenda::createAgendaItem(
const KCalendarCore::Incidence::Ptr &incidence,
int itemPos,
int itemCount,
const QDateTime &recurrenceId,
bool isSelected)
1841 qCWarning(CALENDARVIEW_LOG) <<
"Agenda::createAgendaItem() item is invalid.";
1845 AgendaItem::QPtr agendaItem =
new AgendaItem(d->mAgendaView, d->mCalendar, incidence, itemPos, itemCount, recurrenceId, isSelected,
this);
1847 connect(agendaItem.
data(), &AgendaItem::removeAgendaItem,
this, &Agenda::removeAgendaItem);
1848 connect(agendaItem.
data(), &AgendaItem::showAgendaItem,
this, &Agenda::showAgendaItem);
1850 d->mAgendaItemsById.insert(
incidence->uid(), agendaItem);
1856 const QDateTime &recurrenceId,
1865 if (d->mAllDayMode) {
1866 qCDebug(CALENDARVIEW_LOG) <<
"using this in all-day mode is illegal.";
1870 d->mActionType = NOP;
1875 int width = XEnd - XBegin + 1;
1877 AgendaItem::QPtr current =
nullptr;
1878 QList<AgendaItem::QPtr> multiItems;
1879 int visibleCount = d->mSelectedDates.first().daysTo(d->mSelectedDates.last());
1880 for (cellX = XBegin; cellX <= XEnd; ++cellX) {
1883 if (cellX >= 0 && cellX <= visibleCount) {
1884 if (cellX == XBegin) {
1889 if (cellX == XEnd) {
1890 cellYBottom = YBottom;
1892 cellYBottom = rows() - 1;
1894 newtext = QStringLiteral(
"(%1/%2): ").
arg(count).
arg(
width);
1895 newtext.
append(ev->summary());
1897 current = insertItem(
event, recurrenceId, cellX, cellYTop, cellYBottom, count,
width, isSelected);
1899 current->setText(newtext);
1900 multiItems.
append(current);
1904 QList<AgendaItem::QPtr>::iterator it = multiItems.
begin();
1905 QList<AgendaItem::QPtr>::iterator e = multiItems.
end();
1908 AgendaItem::QPtr first = multiItems.
first();
1909 AgendaItem::QPtr last = multiItems.
last();
1910 AgendaItem::QPtr prev =
nullptr;
1911 AgendaItem::QPtr
next =
nullptr;
1914 AgendaItem::QPtr item = *it;
1916 next = (it == e) ?
nullptr : (*it);
1918 item->setMultiItem((item == first) ?
nullptr : first, prev, next, (item == last) ?
nullptr : last);
1930 qCWarning(CALENDARVIEW_LOG) <<
"Agenda::removeIncidence() incidence is invalid" <<
incidence->uid();
1934 if (d->isQueuedForDeletion(
incidence->uid())) {
1938 const AgendaItem::List agendaItems = d->mAgendaItemsById.values(
incidence->uid());
1939 if (agendaItems.isEmpty()) {
1944 for (
const AgendaItem::QPtr &agendaItem : agendaItems) {
1946 if (
incidence->instanceIdentifier() != agendaItem->incidence()->instanceIdentifier()) {
1949 if (!removeAgendaItem(agendaItem)) {
1950 qCWarning(CALENDARVIEW_LOG) <<
"Agenda::removeIncidence() Failed to remove " <<
incidence->uid();
1956void Agenda::showAgendaItem(
const AgendaItem::QPtr &agendaItem)
1959 qCCritical(CALENDARVIEW_LOG) <<
"Show what?";
1965 agendaItem->setParent(
this);
1967 if (!d->mItems.contains(agendaItem)) {
1968 d->mItems.append(agendaItem);
1970 placeSubCells(agendaItem);
1975bool Agenda::removeAgendaItem(
const AgendaItem::QPtr &agendaItem)
1977 Q_ASSERT(agendaItem);
1979 QList<AgendaItem::QPtr> conflictItems = agendaItem->conflictItems();
1982 bool taken = d->mItems.removeAll(agendaItem) > 0;
1983 d->mAgendaItemsById.remove(agendaItem->incidence()->uid(), agendaItem);
1985 QList<AgendaItem::QPtr>::iterator it;
1986 for (it = conflictItems.
begin(); it != conflictItems.
end(); ++it) {
1988 (*it)->setSubCells((*it)->subCells() - 1);
1992 for (it = conflictItems.
begin(); it != conflictItems.
end(); ++it) {
1994 if (*it && *it != agendaItem) {
1998 d->mItemsToDelete.append(agendaItem);
1999 d->mItemsQueuedForDeletion.insert(agendaItem->incidence()->uid());
2000 agendaItem->setVisible(
false);
2005void Agenda::deleteItemsToDelete()
2007 qDeleteAll(d->mItemsToDelete);
2008 d->mItemsToDelete.clear();
2009 d->mItemsQueuedForDeletion.clear();
2029void Agenda::resizeEvent(QResizeEvent *ev)
2031 QSize newSize(ev->
size());
2033 if (d->mAllDayMode) {
2034 d->mGridSpacingX =
static_cast<double>(newSize.width()) / d->mColumns;
2035 d->mGridSpacingY = newSize.height();
2037 d->mGridSpacingX =
static_cast<double>(newSize.width()) / d->mColumns;
2039 d->mGridSpacingY =
static_cast<double>(newSize.height()) / d->mRows;
2040 if (d->mGridSpacingY < d->mDesiredGridSpacingY) {
2041 d->mGridSpacingY = d->mDesiredGridSpacingY;
2044 calculateWorkingHours();
2047 Q_EMIT gridSpacingYChanged(d->mGridSpacingY * 4);
2053void Agenda::resizeAllContents()
2055 double subCellWidth;
2056 for (
const AgendaItem::QPtr &item : std::as_const(d->mItems)) {
2058 subCellWidth = calcSubCellWidth(item);
2059 placeAgendaItem(item, subCellWidth);
2079 checkScrollBoundaries();
2084void Agenda::scrollUp()
2086 int currentValue = verticalScrollBar()->value();
2087 verticalScrollBar()->setValue(currentValue - d->mScrollOffset);
2090void Agenda::scrollDown()
2092 int currentValue = verticalScrollBar()->value();
2093 verticalScrollBar()->setValue(currentValue + d->mScrollOffset);
2096QSize Agenda::minimumSize()
const
2101QSize Agenda::minimumSizeHint()
const
2106int Agenda::minimumHeight()
const
2111 if (d->mAllDayMode) {
2114 return d->mGridSpacingY * d->mRows;
2118void Agenda::updateConfig()
2120 const double oldGridSpacingY = d->mGridSpacingY;
2122 if (!d->mAllDayMode) {
2123 d->mDesiredGridSpacingY = d->preferences()->hourSize();
2124 if (d->mDesiredGridSpacingY < 4 || d->mDesiredGridSpacingY > 30) {
2125 d->mDesiredGridSpacingY = 10;
2137 if (fabs(oldGridSpacingY - d->mDesiredGridSpacingY) > 0.1) {
2138 d->mGridSpacingY = d->mDesiredGridSpacingY;
2143 calculateWorkingHours();
2148void Agenda::checkScrollBoundaries()
2151 d->mOldLowerScrollValue = -1;
2152 d->mOldUpperScrollValue = -1;
2154 checkScrollBoundaries(verticalScrollBar()->value());
2157void Agenda::checkScrollBoundaries(
int v)
2159 int yMin = int((v) / d->mGridSpacingY);
2160 int yMax = int((v + d->mScrollArea->height()) / d->mGridSpacingY);
2162 if (yMin != d->mOldLowerScrollValue) {
2163 d->mOldLowerScrollValue = yMin;
2164 Q_EMIT lowerYChanged(yMin);
2166 if (yMax != d->mOldUpperScrollValue) {
2167 d->mOldUpperScrollValue = yMax;
2168 Q_EMIT upperYChanged(yMax);
2172int Agenda::visibleContentsYMin()
const
2174 int v = verticalScrollBar()->value();
2175 return int(v / d->mGridSpacingY);
2178int Agenda::visibleContentsYMax()
const
2180 int v = verticalScrollBar()->value();
2181 return int((v + d->mScrollArea->height()) / d->mGridSpacingY);
2184void Agenda::deselectItem()
2186 if (d->mSelectedItem.isNull()) {
2192 for (AgendaItem::QPtr item : std::as_const(d->mItems)) {
2195 if (itemInc && selectedItem && itemInc->uid() == selectedItem->uid()) {
2196 item->select(
false);
2201 d->mSelectedItem =
nullptr;
2204void Agenda::selectItem(
const AgendaItem::QPtr &item)
2206 if ((AgendaItem::QPtr)d->mSelectedItem == item) {
2210 if (item ==
nullptr) {
2214 d->mSelectedItem = item;
2215 d->mSelectedItem->select();
2216 Q_ASSERT(d->mSelectedItem->incidence());
2217 d->mSelectedId = d->mSelectedItem->incidence()->uid();
2219 for (AgendaItem::QPtr item : std::as_const(d->mItems)) {
2220 if (item && item->incidence()->uid() == d->mSelectedId) {
2224 Q_EMIT incidenceSelected(d->mSelectedItem->incidence(), d->mSelectedItem->occurrenceDate());
2227void Agenda::selectIncidenceByUid(
const QString &uid)
2229 for (
const AgendaItem::QPtr &item : std::as_const(d->mItems)) {
2230 if (item && item->incidence()->uid() == uid) {
2237void Agenda::selectItem(
const Akonadi::Item &item)
2243void Agenda::keyPressEvent(QKeyEvent *kev)
2245 switch (kev->
key()) {
2262void Agenda::calculateWorkingHours()
2264 d->mWorkingHoursEnable = !d->mAllDayMode;
2266 QTime tmp = d->preferences()->workingHoursStart().time();
2267 d->mWorkingHoursYTop = int(4 * d->mGridSpacingY * (tmp.
hour() + tmp.
minute() / 60. + tmp.
second() / 3600.));
2268 tmp = d->preferences()->workingHoursEnd().time();
2269 d->mWorkingHoursYBottom = int(4 * d->mGridSpacingY * (tmp.
hour() + tmp.
minute() / 60. + tmp.
second() / 3600.) - 1);
2274 d->mSelectedDates = selectedDates;
2280 return d->mSelectedDates;
2283void Agenda::setCalendar(
const MultiViewCalendar::Ptr &cal)
2288void Agenda::setIncidenceChanger(Akonadi::IncidenceChanger *changer)
2290 d->mChanger = changer;
2293void Agenda::setHolidayMask(QList<bool> *mask)
2295 d->mHolidayMask =
mask;
2298void Agenda::contentsMousePressEvent(QMouseEvent *event)
2303QSize Agenda::sizeHint()
const
2305 if (d->mAllDayMode) {
2308 return {
parentWidget()->
width(),
static_cast<int>(d->mGridSpacingY * d->mRows)};
2312QScrollBar *Agenda::verticalScrollBar()
const
2314 return d->mScrollArea->verticalScrollBar();
2317QScrollArea *Agenda::scrollArea()
const
2319 return d->mScrollArea;
2322AgendaItem::List Agenda::agendaItems(
const QString &uid)
const
2324 return d->mAgendaItemsById.values(uid);
2327AgendaScrollArea::AgendaScrollArea(
bool isAllDay,
AgendaView *agendaView,
bool isInteractive, QWidget *parent)
2328 : QScrollArea(parent)
2331 mAgenda =
new Agenda(agendaView,
this, 1, isInteractive);
2334 mAgenda =
new Agenda(agendaView,
this, 1, 96, agendaView->preferences()->hourSize(), isInteractive);
2337 setWidgetResizable(
true);
2341 mAgenda->setStartTime(agendaView->preferences()->dayBegins().time());
2344AgendaScrollArea::~AgendaScrollArea() =
default;
2346Agenda *AgendaScrollArea::agenda()
const
2351#include "moc_agenda.cpp"
Collection & parentCollection()
Collection::Id storageCollectionId() const
AgendaView is the agenda-like view that displays events in a single or multi-day view.
EventView is the abstract base class from which all other calendar views for event data are derived.
QSharedPointer< Calendar > Ptr
static Incidence::Ptr createException(const Incidence::Ptr &incidence, const QDateTime &recurrenceId, bool thisAndFuture=false)
QSharedPointer< Event > Ptr
QSharedPointer< Incidence > Ptr
Q_SCRIPTABLE Q_NOREPLY void start()
QString i18nc(const char *context, const char *text, const TYPE &arg...)
QString i18n(const char *text, const TYPE &arg...)
AKONADI_CALENDAR_EXPORT KCalendarCore::Incidence::Ptr incidence(const Akonadi::Item &item)
char * toString(const EngineQuery &query)
Namespace EventViews provides facilities for displaying incidences, including events,...
void init(KXmlGuiWindow *window, KGameDifficulty *difficulty=nullptr)
QAction * end(const QObject *recvr, const char *slot, QObject *parent)
void information(QWidget *parent, const QString &text, const QString &title=QString(), const QString &dontShowAgainName=QString(), Options options=Notify)
void error(QWidget *parent, const QString &text, const QString &title, const KGuiItem &buttonOk, Options options=Notify)
const QList< QKeySequence > & next()
const QList< QKeySequence > & preferences()
void valueChanged(int value)
QColor darker(int factor) const const
QColor lighter(int factor) const const
bool sendEvent(QObject *receiver, QEvent *event)
QDateTime currentDateTime()
const QMimeData * mimeData() const const
QPointF position() const const
void setDropAction(Qt::DropAction action)
void setFrameStyle(int style)
void append(QList< T > &&value)
qsizetype count() const const
QList< T > & fill(parameter_type value, qsizetype size)
bool isEmpty() const const
QMetaObject::Connection connect(const QObject *sender, PointerToMemberFunction signal, Functor functor)
virtual bool event(QEvent *e)
virtual bool eventFilter(QObject *watched, QEvent *event)
void installEventFilter(QObject *filterObj)
T qobject_cast(QObject *object)
void drawPixmap(const QPoint &point, const QPixmap &pixmap)
void setColor(ColorGroup group, ColorRole role, const QColor &color)
QPoint toPoint() const const
const QSize & size() const const
QPointF position() const const
QString & append(QChar ch)
QString arg(Args &&... args) const const
QString number(double n, char format, int precision)
QFuture< ArgsType< Signal > > connect(Sender *sender, Signal signal)
QTime addSecs(int s) const const
bool setHMS(int h, int m, int s, int ms)
QPoint angleDelta() const const