33 #include <calendarsupport/utils.h>
35 #include <Akonadi/ItemFetchJob>
36 #include <Akonadi/ItemFetchScope>
38 #include <KCalendarSystem>
42 #include <QMouseEvent>
50 const int KODayMatrix::NOSELECTION = -1000;
51 const int KODayMatrix::NUMDAYS = 42;
54 :
QFrame( parent ), mStartDate(), mPendingChanges( false )
57 mDays =
new QDate[NUMDAYS];
58 mDayLabels =
new QString[NUMDAYS];
60 mTodayMarginWidth = 2;
61 mSelEnd = mSelStart = NOSELECTION;
65 mHighlightEvents =
true;
66 mHighlightTodos =
false;
67 mHighlightJournals =
false;
73 mCalendar->unregisterObserver(
this );
74 mCalendar->disconnect(
this );
78 mCalendar->registerObserver(
this );
84 QColor KODayMatrix::getShadedColor(
const QColor &color )
const
90 color.
getHsv( &h, &s, &v );
101 mCalendar->unregisterObserver(
this );
105 delete [] mDayLabels;
110 if ( mSelStart == NOSELECTION ) {
117 for (
int i = i0; i < 0; ++i ) {
118 selDays.append( mDays[0].addDays( i ) );
124 if ( mSelEnd > NUMDAYS-1 ) {
125 for (
int i = i0; i <= NUMDAYS - 1; ++i ) {
126 selDays.append( mDays[i] );
128 for (
int i = NUMDAYS; i < mSelEnd; ++i ) {
129 selDays.append( mDays[0].addDays( i ) );
133 for (
int i = i0; i <= mSelEnd; ++i ) {
134 selDays.append( mDays[i] );
142 mSelStart = mStartDate.
daysTo( start );
143 mSelEnd = mStartDate.
daysTo( end );
149 mSelEnd = mSelStart = NOSELECTION;
159 for (
int i = 0; i < NUMDAYS; ++i ) {
160 mDays[i] = mStartDate.
addDays( i );
179 mPendingChanges =
true;
184 if ( !actdate.
isValid() || NUMDAYS < 1 ) {
188 bool daychanged =
false;
192 if ( actdate != mStartDate ) {
195 if ( mSelStart != NOSELECTION ) {
196 int tmp = actdate.
daysTo( mStartDate );
198 if ( mSelStart + tmp < NUMDAYS && mSelEnd + tmp >= 0 ) {
202 if ( mSelStart > NUMDAYS || mSelStart < 0 ) {
203 mSelStart = mSelStart + tmp;
205 if ( mSelEnd > NUMDAYS || mSelEnd < 0 ) {
206 mSelEnd = mSelEnd + tmp;
211 mStartDate = actdate;
221 if ( !daychanged && !mPendingChanges ) {
230 for (
int i = 0; i < NUMDAYS; ++i ) {
236 KGlobal::locale()->weekDayOfPray() ) ||
239 holiStr = holidays.
join( i18nc(
"delimiter for joining holiday names",
"," ) );
245 mHolidays[i] = holiStr;
257 if ( mHighlightEvents ) {
261 if ( mHighlightTodos ) {
265 if ( mHighlightJournals ) {
269 mPendingChanges =
false;
272 void KODayMatrix::updateJournals()
274 const KCalCore::Incidence::List incidences = mCalendar->incidences();
276 foreach (
const KCalCore::Incidence::Ptr &inc, incidences ) {
278 QDate d = inc->dtStart().toTimeSpec( mCalendar->timeSpec() ).date();
279 if ( inc->type() == KCalCore::Incidence::TypeJournal &&
281 d <= mDays[NUMDAYS-1] &&
285 if ( mEvents.
count() == NUMDAYS ) {
301 void KODayMatrix::updateTodos()
303 const KCalCore::Todo::List incidences = mCalendar->todos();
305 foreach (
const KCalCore::Todo::Ptr &t, incidences ) {
306 if ( mEvents.
count() == NUMDAYS ) {
311 if ( t->hasDueDate() ) {
312 ushort recurType = t->recurrenceType();
315 !( recurType == KCalCore::Recurrence::rDaily && !
KOPrefs::instance()->mDailyRecur ) &&
316 !( recurType == KCalCore::Recurrence::rWeekly && !
KOPrefs::instance()->mWeeklyRecur ) ) {
319 KCalCore::DateTimeList timeDateList =
320 t->recurrence()->timesInInterval(
321 KDateTime( mDays[0], mCalendar->timeSpec() ),
322 KDateTime( mDays[NUMDAYS-1], mCalendar->timeSpec() ) );
324 foreach (
const KDateTime &dt, timeDateList ) {
325 d = dt.toTimeSpec( mCalendar->timeSpec() ).date();
332 d = t->dtDue().toTimeSpec( mCalendar->timeSpec() ).date();
333 if ( d >= mDays[0] && d <= mDays[NUMDAYS-1] && !mEvents.
contains( d ) ) {
341 void KODayMatrix::updateEvents()
343 if ( mEvents.
count() == NUMDAYS ) {
344 mPendingChanges =
false;
348 KCalCore::Event::List eventlist = mCalendar->events( mDays[0], mDays[NUMDAYS-1],
349 mCalendar->timeSpec() );
351 Q_FOREACH (
const KCalCore::Event::Ptr &
event, eventlist ) {
352 if ( mEvents.
count() == NUMDAYS ) {
358 const ushort recurType =
event->recurrenceType();
359 const KDateTime dtStart =
event->dtStart().toTimeSpec( mCalendar->timeSpec() );
364 const int secsToAdd =
event->allDay() ? 0 : -1;
365 const KDateTime dtEnd =
event->dtEnd().toTimeSpec( mCalendar->timeSpec() ).addSecs( secsToAdd );
367 if ( !( recurType == KCalCore::Recurrence::rDaily && !
KOPrefs::instance()->mDailyRecur ) &&
368 !( recurType == KCalCore::Recurrence::rWeekly && !
KOPrefs::instance()->mWeeklyRecur ) ) {
370 KCalCore::DateTimeList timeDateList;
371 const bool isRecurrent =
event->recurs();
372 const int eventDuration = dtStart.daysTo( dtEnd );
376 timeDateList =
event->recurrence()->timesInInterval(
377 KDateTime( mDays[0], mCalendar->timeSpec() ),
378 KDateTime( mDays[NUMDAYS-1], mCalendar->timeSpec() ) );
380 if ( dtStart.date() >= mDays[0] ) {
381 timeDateList.append( dtStart );
384 timeDateList.append( KDateTime( mDays[0], mCalendar->timeSpec() ) );
388 KCalCore::DateTimeList::iterator t;
389 for ( t=timeDateList.begin(); t != timeDateList.end(); ++t ) {
391 QDate d = t->toTimeSpec( mCalendar->timeSpec() ).date();
396 occurrenceEnd = d.
addDays( eventDuration );
398 occurrenceEnd = dtEnd.date();
405 }
while ( d <= occurrenceEnd && j < NUMDAYS );
409 mPendingChanges =
false;
414 if ( offset < 0 || offset > NUMDAYS - 1 ) {
417 return mDays[offset];
422 if ( offset < 0 || offset > NUMDAYS - 1 ) {
425 return mHolidays[offset];
428 int KODayMatrix::getDayIndexFrom(
int x,
int y )
const
430 return 7 * ( y / mDaySize.
height() ) +
432 6 - x / mDaySize.
width() : x / mDaySize.
width() );
437 Q_UNUSED( incidence );
438 mPendingChanges =
true;
443 Q_UNUSED( incidence );
444 mPendingChanges =
true;
449 Q_UNUSED( incidence );
450 mPendingChanges =
true;
455 bool highlightJournals ) {
458 if ( highlightTodos != mHighlightTodos ||
459 highlightEvents != mHighlightEvents ||
460 highlightJournals != mHighlightJournals ) {
461 mHighlightEvents = highlightEvents;
462 mHighlightTodos = highlightTodos;
463 mHighlightJournals = highlightJournals;
464 mPendingChanges =
true;
470 mPendingChanges =
true;
484 int dheight = sz.
height() * 7 / 42;
485 int dwidth = sz.
width() / 7;
486 int row = helpEvent->
pos().
y() / dheight;
487 int col = helpEvent->
pos().
x() / dwidth;
502 mSelStart = getDayIndexFrom( e->
x(), e->
y() );
503 if ( e->
button() == Qt::RightButton ) {
504 popupMenu( mDays[mSelStart] ) ;
505 }
else if ( e->
button() == Qt::LeftButton ) {
506 if ( mSelStart > NUMDAYS - 1 ) {
507 mSelStart = NUMDAYS - 1;
509 mSelInit = mSelStart;
513 void KODayMatrix::popupMenu(
const QDate &date )
517 QAction *newEventAction = popup.addAction(
518 KIcon(
QLatin1String(
"appointment-new") ), i18n(
"New E&vent..." ) );
519 QAction *newTodoAction = popup.addAction(
520 KIcon(
QLatin1String(
"task-new") ), i18n(
"New &To-do..." ) );
521 QAction *newJournalAction = popup.addAction(
522 KIcon(
QLatin1String(
"journal-new") ), i18n(
"New &Journal..." ) );
524 if ( ret == newEventAction ) {
526 }
else if ( ret == newTodoAction ) {
528 }
else if ( ret == newJournalAction ) {
535 if ( e->
button() != Qt::LeftButton ) {
539 int tmp = getDayIndexFrom( e->
x(), e->
y() );
540 if ( tmp > NUMDAYS - 1 ) {
544 if ( mSelInit > tmp ) {
546 if ( tmp != mSelStart ) {
551 mSelStart = mSelInit;
554 if ( tmp != mSelEnd ) {
560 KCalCore::DateList daylist;
561 if ( mSelStart < 0 ) {
564 for (
int i = mSelStart; i <= mSelEnd; ++i ) {
565 daylist.append( mDays[i] );
567 emit
selected( static_cast<const KCalCore::DateList>(daylist) );
572 int tmp = getDayIndexFrom( e->
x(), e->
y() );
573 if ( tmp > NUMDAYS - 1 ) {
577 if ( mSelInit > tmp ) {
579 if ( tmp != mSelStart ) {
584 mSelStart = mSelInit;
587 if ( tmp != mSelEnd ) {
611 if ( !CalendarSupport::canDecode( md ) ) {
625 if ( !CalendarSupport::canDecode( md ) ) {
653 if ( urls.
count() >= 1 ) {
654 KUrl res = urls.
at( 0 );
656 Akonadi::ItemFetchJob *job =
new Akonadi::ItemFetchJob( Akonadi::Item::fromUrl( res ) );
657 job->fetchScope().setAncestorRetrieval( Akonadi::ItemFetchScope::Parent );
658 job->fetchScope().fetchFullPayload();
659 Akonadi::Item::List items;
661 items = job->items();
663 bool exist = items.at( 0 ).isValid();
668 if ( keyboardModifiers & Qt::ControlModifier ) {
670 }
else if ( keyboardModifiers & Qt::ShiftModifier ) {
674 KMenu *menu =
new KMenu(
this );
683 menu->addSeparator();
689 }
else if ( a ==
move ) {
697 int idx = getDayIndexFrom( e->
pos().
x(), e->
pos().
y() );
716 const int dayHeight = mDaySize.
height();
717 const int dayWidth = mDaySize.
width();
719 int selectionWidth, selectionHeight;
736 if ( mSelStart != NOSELECTION ) {
740 if ( row < 0 && mSelEnd > 0 ) {
743 column = mSelStart - row * 7;
746 if ( row < 6 && row >= 0 ) {
747 if ( row == mSelEnd / 7 ) {
750 ( 7 - ( mSelEnd - mSelStart + 1 ) - column ) * dayWidth :
753 ( mSelEnd - mSelStart + 1 ) * dayWidth, dayHeight, selectionColor );
756 p.
fillRect( isRTL ? 0 : column * dayWidth, row * dayHeight,
757 ( 7 - column ) * dayWidth, dayHeight, selectionColor );
759 selectionHeight = mSelEnd / 7 - row;
760 if ( selectionHeight + row >= 6 ) {
761 selectionHeight = 6 - row;
763 if ( selectionHeight > 1 ) {
764 p.
fillRect( 0, ( row + 1 ) * dayHeight, 7 * dayWidth,
765 ( selectionHeight - 1 ) * dayHeight, selectionColor );
768 if ( mSelEnd / 7 < 6 ) {
769 selectionWidth = mSelEnd - 7 * ( mSelEnd / 7 ) + 1;
771 ( 7 - selectionWidth ) * dayWidth :
773 ( row + selectionHeight ) * dayHeight,
774 selectionWidth * dayWidth, dayHeight, selectionColor );
781 const QColor textColor = pal.
color( QPalette::Text );
782 const QColor textColorShaded = getShadedColor( textColor );
783 QColor actcol = textColorShaded;
788 for (
int i = 0; i < NUMDAYS; ++i ) {
790 column = isRTL ? 6 - ( i - row * 7 ) : i - row * 7;
794 if ( actcol == textColorShaded ) {
797 actcol = textColorShaded;
803 if ( i == mSelEnd + 1 ) {
807 const bool holiday = !workDays.
contains( mDays[i] );
809 const QColor holidayColorShaded =
817 todayPen.
setWidth( mTodayMarginWidth );
820 if ( actcol == textColor ) {
823 todayPen.setColor( holidayColorShaded );
827 if ( i >= mSelStart && i <= mSelEnd ) {
829 todayPen.setColor( grey );
832 p.
drawRect( column * dayWidth, row * dayHeight, dayWidth, dayHeight );
837 if ( mEvents.
contains( mDays[i] ) ) {
845 if ( actcol == textColor ) {
848 p.
setPen( holidayColorShaded );
853 if ( i >= mSelStart && i <= mSelEnd && !holiday ) {
857 p.
drawText( column * dayWidth, row * dayHeight, dayWidth, dayHeight,
858 Qt::AlignHCenter | Qt::AlignVCenter, mDayLabels[i]);
865 if ( mEvents.
contains( mDays[i] ) > 0 ) {
890 calSys->
setDate( d, calSys->
year( month ), calSys->month( month ), 1 );
892 const int dayOfWeek = calSys->dayOfWeek( d );
893 const int weekstart = KGlobal::locale()->weekStartDay();
895 d = d.
addDays( -( 7 + dayOfWeek - weekstart ) % 7 );
897 if ( dayOfWeek == weekstart ) {
901 return qMakePair( d, d.
addDays( NUMDAYS-1 ) );
int daysTo(const QDate &d) const
void clearSelection()
Clear all selections.
~KODayMatrix()
destructor that deallocates all dynamically allocated private members.
void incidenceDropped(const Akonadi::Item &item, const QDate &dt)
Emitted if the user has dropped an incidence (event or todo) inside the matrix.
const QMimeData * mimeData() const
void fillRect(const QRectF &rectangle, const QBrush &brush)
static QPair< QDate, QDate > matrixLimits(const QDate &month)
returns the first and last date of the 6*7 matrix that displays month
QString toString(Qt::DateFormat format) const
void resizeEvent(QResizeEvent *)
QMap< QDate, QStringList > holiday(const QDate &start, const QDate &end) const
void dragLeaveEvent(QDragLeaveEvent *e)
void newTodoSignal(const QDate &date)
const QDate & getDate(int offset) const
Returns the QDate object associated with day indexed by the supplied offset.
const QColor & color(ColorGroup group, ColorRole role) const
const T & at(int i) const
void calendarIncidenceDeleted(const KCalCore::Incidence::Ptr &incidence)
const QPoint & pos() const
const QPoint & pos() const
void dragEnterEvent(QDragEnterEvent *e)
QString join(const QString &separator) const
void acceptProposedAction()
void showText(const QPoint &pos, const QString &text, QWidget *w)
void getHsv(int *h, int *s, int *v, int *a) const
void setHighlightMode(bool highlightEvents, bool highlightTodos, bool highlightJournals)
Sets which incidences should be highlighted.
void setBold(bool enable)
void calendarIncidenceAdded(const KCalCore::Incidence::Ptr &incidence)
Reimplemented from Akonadi::ETMCalendar They set mPendingChanges to true.
void drawRect(const QRectF &rectangle)
void setFont(const QFont &font)
void updateIncidences()
Update incidence states of dates.
QString number(int n, int base)
int count(const T &value) const
void append(const T &value)
void setPen(const QColor &color)
const QPoint & globalPos() const
void setSelectedDaysFrom(const QDate &start, const QDate &end)
Sets the actual to be displayed selection in the day matrix starting from start and ending with end...
QString getHolidayLabel(int offset) const
Returns the official name of this holy day or 0 if there is no label for this day.
void mouseReleaseEvent(QMouseEvent *e)
void drawText(const QPointF &position, const QString &text)
void mousePressEvent(QMouseEvent *e)
void calendarIncidenceChanged(const KCalCore::Incidence::Ptr &incidence)
void updateView()
Recalculates all the flags of the days in the matrix like holidays or events on a day (Actually calls...
void selected(const KCalCore::DateList &daylist)
Emitted if the user selects a block of days with the mouse by dragging a rectangle inside the matrix...
void dropEvent(QDropEvent *e)
void incidenceDroppedMove(const Akonadi::Item &item, const QDate &dt)
Emitted if the user has dropped an event inside the matrix and chose to move it instead of copy...
bool contains(const T &value) const
void dragMoveEvent(QDragMoveEvent *e)
void resourcesChanged()
Handle resource changes.
const KCalendarSystem * calendarSystem() const
static KOGlobals * self()
QList< QDate > workDays(const QDate &start, const QDate &end) const
Returns a list containing work days between start and .
bool setDate(int year, int month, int day)
static bool reverseLayout()
void setCalendar(const Akonadi::ETMCalendar::Ptr &)
Associate a calendar with this day matrix.
void paintEvent(QPaintEvent *ev)
QList< QUrl > urls() const
void setHeight(int height)
void translate(const QPointF &offset)
static KOPrefs * instance()
Get instance of KOPrefs.
void addSelectedDaysTo(KCalCore::DateList &)
Adds all actual selected days from mSelStart to mSelEnd to the supplied DateList. ...
void setHsv(int h, int s, int v, int a)
KODayMatrix(QWidget *parent)
constructor to create a day matrix widget.
QDate addDays(int ndays) const
void newEventSignal(const QDate &date)
bool begin(QPaintDevice *device)
void recalculateToday()
Calculates which square in the matrix should be hiighted to indicate the square is on "today"...
void mouseMoveEvent(QMouseEvent *e)
Qt::KeyboardModifiers keyboardModifiers() const
void newJournalSignal(const QDate &date)
typedef KeyboardModifiers