2 This file is part of KOrganizer.
4 Copyright (c) 1997, 1998, 1999 Preston Brown <preston.brown@yale.edu>
5 Fester Zigterman <F.J.F.ZigtermanRustenburg@student.utwente.nl>
6 Ian Dawes <iadawes@globalserve.net>
7 Laszlo Boloni <boloni@cs.purdue.edu>
9 Copyright (C) 2000-2004 Cornelius Schumacher <schumacher@kde.org>
10 Copyright (C) 2003-2004 Reinhold Kainhofer <reinhold@kainhofer.com>
11 Copyright (C) 2005 Rafal Rzepecki <divide@users.sourceforge.net>
13 This program is free software; you can redistribute it and/or modify
14 it under the terms of the GNU General Public License as published by
15 the Free Software Foundation; either version 2 of the License, or
16 (at your option) any later version.
18 This program is distributed in the hope that it will be useful,
19 but WITHOUT ANY WARRANTY; without even the implied warranty of
20 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 GNU General Public License for more details.
23 You should have received a copy of the GNU General Public License along
24 with this program; if not, write to the Free Software Foundation, Inc.,
25 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
27 As a special exception, permission is given to link this program
28 with any edition of Qt, and distribute the resulting executable,
29 without including the source code for Qt in the source distribution.
32 #include "calendarview.h"
33 #include "datechecker.h"
34 #include "datenavigator.h"
35 #include "datenavigatorcontainer.h"
36 #include "exportwebdialog.h"
37 #include "kocorehelper.h"
38 #include "kodaymatrix.h"
39 #include "kodialogmanager.h"
40 #include "koeventviewerdialog.h"
41 #include "koglobals.h"
44 #include "koviewmanager.h"
45 #include "htmlexportsettings.h"
46 #include "navigatorbar.h"
47 #include "views/agendaview/koagendaview.h"
48 #include "views/monthview/monthview.h"
49 #include "views/multiagendaview/multiagendaview.h"
50 #include "views/todoview/kotodoview.h"
51 #include "kocheckableproxymodel.h"
52 #include "akonadicollectionview.h"
53 #include <incidenceeditor-ng/globalsettings.h>
55 #include <KHolidays/kholidays/Holidays>
57 #include <calendarsupport/collectiongeneralpage.h>
58 #include <calendarsupport/collectionselection.h>
59 #include <calendarsupport/kcalprefs.h>
60 #include <calendarsupport/utils.h>
61 #include <calendarsupport/next/incidenceviewer.h>
62 #include <calendarsupport/printing/calprinter.h>
63 #include <calendarsupport/calendarsingleton.h>
65 #include <incidenceeditor-ng/incidencedefaults.h>
66 #include <incidenceeditor-ng/incidencedialog.h>
67 #include <incidenceeditor-ng/incidencedialogfactory.h>
68 #include <incidenceeditor-ng/individualmailcomponentfactory.h>
70 #include <libkdepim/widgets/pimmessagebox.h>
71 #include <Akonadi/Calendar/FreeBusyManager>
72 #include <Akonadi/Calendar/History>
73 #include <Akonadi/Calendar/IncidenceChanger>
74 #include <akonadi/calendar/calendarsettings.h>
75 #include <Akonadi/Calendar/CalendarClipboard>
77 #include <pimcommon/acl/collectionaclpage.h>
78 #include <pimcommon/acl/imapaclattribute.h>
80 #include <AkonadiWidgets/CollectionPropertiesDialog>
81 #include <AkonadiCore/Control>
82 #include <AkonadiCore/AttributeFactory>
83 #include <Akonadi/Calendar/TodoPurger>
85 #include <KCalCore/CalFilter>
86 #include <KCalCore/FileStorage>
87 #include <KCalCore/ICalFormat>
88 #include <KCalCore/VCalFormat>
90 #include <KCalUtils/ICalDrag>
91 #include <KCalUtils/Stringify>
92 #include <KCalUtils/DndFactory>
94 #include <KFileDialog>
95 #include <KNotification>
97 #include <QVBoxLayout>
98 #include "korganizer_debug.h"
99 #include <QPushButton>
101 #include <QApplication>
102 #include <QClipboard>
104 #include <QStackedWidget>
105 #include <QVBoxLayout>
108 CalendarView::CalendarView(QWidget
*parent
) : CalendarViewBase(parent
),
109 mCheckableProxyModel(0),
110 mETMCollectionView(0)
112 Akonadi::Control::widgetNeedsAkonadi(this);
113 mChanger
= new Akonadi::IncidenceChanger(new IncidenceEditorNG::IndividualMailComponentFactory(this), this);
114 mChanger
->setDefaultCollection(Akonadi::Collection(CalendarSupport::KCalPrefs::instance()->defaultCalendarId()));
116 mChanger
->setDestinationPolicy(static_cast<Akonadi::IncidenceChanger::DestinationPolicy
>(KOPrefs::instance()->destination()));
118 // We reuse the EntityTreeModel from the calendar singleton to save memory.
119 // We don't reuse the entire ETMCalendar because we want a different selection model. Checking/unchecking
120 // calendars in korganizer shouldn't affect kontact's summary view
121 mCalendar
= Akonadi::ETMCalendar::Ptr(new Akonadi::ETMCalendar(CalendarSupport::calendarSingleton().data()));
123 mCalendar
->setObjectName(QLatin1String("KOrg Calendar"));
124 mCalendarClipboard
= new Akonadi::CalendarClipboard(mCalendar
, mChanger
, this);
125 mITIPHandler
= new Akonadi::ITIPHandler(this);
126 mITIPHandler
->setCalendar(mCalendar
);
127 connect(mCalendarClipboard
, &Akonadi::CalendarClipboard::cutFinished
, this, &CalendarView::onCutFinished
);
129 Akonadi::AttributeFactory::registerAttribute
<PimCommon::ImapAclAttribute
>();
131 mViewManager
= new KOViewManager(this);
132 mDialogManager
= new KODialogManager(this);
133 mTodoPurger
= new Akonadi::TodoPurger(this);
134 mTodoPurger
->setCalendar(mCalendar
);
135 mTodoPurger
->setIncidenceChager(mChanger
);
136 connect(mTodoPurger
, SIGNAL(todosPurged(bool,int,int)),
137 SLOT(onTodosPurged(bool,int,int)));
140 mSplitterSizesValid
= false;
144 mDateNavigator
= new DateNavigator(this);
145 mDateChecker
= new DateChecker(this);
147 QVBoxLayout
*topLayout
= new QVBoxLayout(this);
148 topLayout
->setMargin(0);
150 // create the main layout frames.
151 mPanner
= new QSplitter(Qt::Horizontal
, this);
152 mPanner
->setObjectName(QLatin1String("CalendarView::Panner"));
153 topLayout
->addWidget(mPanner
);
155 mLeftSplitter
= new QSplitter(Qt::Vertical
, mPanner
);
156 mLeftSplitter
->setObjectName(QLatin1String("CalendarView::LeftFrame"));
157 // The GUI checkboxes of "show widget XYZ" are confusing when the QSplitter
158 // hides the widget magically. I know I blamed Akonadi for not showing my
159 // calendar more than once.
160 mLeftSplitter
->setChildrenCollapsible(false);
162 mDateNavigatorContainer
= new DateNavigatorContainer(mLeftSplitter
);
163 mDateNavigatorContainer
->setObjectName(QLatin1String("CalendarView::DateNavigator"));
165 mTodoList
= new KOTodoView(true/*sidebar*/, mLeftSplitter
);
166 mTodoList
->setObjectName(QLatin1String("todolist"));
168 mEventViewerBox
= new QWidget(mLeftSplitter
);
169 QVBoxLayout
*mEventViewerBoxVBoxLayout
= new QVBoxLayout(mEventViewerBox
);
170 mEventViewerBoxVBoxLayout
->setMargin(0);
171 mEventViewerBoxVBoxLayout
->setMargin(0);
172 mEventViewer
= new CalendarSupport::IncidenceViewer(mCalendar
.data(), mEventViewerBox
);
173 mEventViewer
->setObjectName(QLatin1String("EventViewer"));
174 mEventViewerBoxVBoxLayout
->addWidget(mEventViewer
);
176 QWidget
*rightBox
= new QWidget(mPanner
);
177 QVBoxLayout
*rightBoxVBoxLayout
= new QVBoxLayout(rightBox
);
178 rightBoxVBoxLayout
->setMargin(0);
179 rightBox
->layout()->setMargin(0);
180 mNavigatorBar
= new NavigatorBar(rightBox
);
181 rightBoxVBoxLayout
->addWidget(mNavigatorBar
);
182 mRightFrame
= new QStackedWidget(rightBox
);
183 rightBoxVBoxLayout
->addWidget(mRightFrame
);
184 mMessageWidget
= new CalendarSupport::MessageWidget(rightBox
);
186 rightBoxVBoxLayout
->setStretchFactor(mRightFrame
, 1);
188 mLeftFrame
= mLeftSplitter
;
189 mLeftFrame
->installEventFilter(this);
191 mChanger
->setGroupwareCommunication(CalendarSupport::KCalPrefs::instance()->useGroupwareCommunication());
193 SIGNAL(createFinished(int,Akonadi::Item
,Akonadi::IncidenceChanger::ResultCode
,QString
)),
194 SLOT(slotCreateFinished(int,Akonadi::Item
,Akonadi::IncidenceChanger::ResultCode
,QString
)));
197 SIGNAL(deleteFinished(int,QVector
<Akonadi::Item::Id
>,Akonadi::IncidenceChanger::ResultCode
,QString
)),
198 SLOT(slotDeleteFinished(int,QVector
<Akonadi::Item::Id
>,Akonadi::IncidenceChanger::ResultCode
,QString
)));
201 SIGNAL(modifyFinished(int,Akonadi::Item
,Akonadi::IncidenceChanger::ResultCode
,QString
)),
202 SLOT(slotModifyFinished(int,Akonadi::Item
,Akonadi::IncidenceChanger::ResultCode
,QString
)));
204 // Signals emitted by mDateNavigator
205 connect(mDateNavigator
, SIGNAL(datesSelected(KCalCore::DateList
,QDate
)),
206 SLOT(showDates(KCalCore::DateList
,QDate
)));
208 connect(mDateNavigatorContainer
, SIGNAL(newEventSignal(QDate
)),
209 SLOT(newEvent(QDate
)));
210 connect(mDateNavigatorContainer
, SIGNAL(newTodoSignal(QDate
)),
211 SLOT(newTodo(QDate
)));
212 connect(mDateNavigatorContainer
, SIGNAL(newJournalSignal(QDate
)),
213 SLOT(newJournal(QDate
)));
215 // Signals emitted by mNavigatorBar
216 connect(mNavigatorBar
, SIGNAL(prevYearClicked()),
217 mDateNavigator
, SLOT(selectPreviousYear()));
218 connect(mNavigatorBar
, SIGNAL(nextYearClicked()),
219 mDateNavigator
, SLOT(selectNextYear()));
220 connect(mNavigatorBar
, SIGNAL(prevMonthClicked()),
221 mDateNavigator
, SLOT(selectPreviousMonth()));
222 connect(mNavigatorBar
, SIGNAL(nextMonthClicked()),
223 mDateNavigator
, SLOT(selectNextMonth()));
224 connect(mNavigatorBar
, SIGNAL(monthSelected(int)),
225 mDateNavigator
, SLOT(selectMonth(int)));
226 connect(mNavigatorBar
, SIGNAL(yearSelected(int)),
227 mDateNavigator
, SLOT(selectYear(int)));
229 // Signals emitted by mDateNavigatorContainer
230 connect(mDateNavigatorContainer
, SIGNAL(weekClicked(QDate
,QDate
)),
231 SLOT(selectWeek(QDate
,QDate
)));
233 connect(mDateNavigatorContainer
, SIGNAL(prevMonthClicked(QDate
,QDate
,QDate
)),
234 mDateNavigator
, SLOT(selectPreviousMonth(QDate
,QDate
,QDate
)));
235 connect(mDateNavigatorContainer
, SIGNAL(nextMonthClicked(QDate
,QDate
,QDate
)),
236 mDateNavigator
, SLOT(selectNextMonth(QDate
,QDate
,QDate
)));
237 connect(mDateNavigatorContainer
, SIGNAL(prevYearClicked()),
238 mDateNavigator
, SLOT(selectPreviousYear()));
239 connect(mDateNavigatorContainer
, SIGNAL(nextYearClicked()),
240 mDateNavigator
, SLOT(selectNextYear()));
241 connect(mDateNavigatorContainer
, SIGNAL(monthSelected(int)),
242 mDateNavigator
, SLOT(selectMonth(int)));
243 connect(mDateNavigatorContainer
, SIGNAL(yearSelected(int)),
244 mDateNavigator
, SLOT(selectYear(int)));
245 connect(mDateNavigatorContainer
, SIGNAL(goPrevious()),
246 mDateNavigator
, SLOT(selectPrevious()));
247 connect(mDateNavigatorContainer
, SIGNAL(goNext()),
248 mDateNavigator
, SLOT(selectNext()));
250 connect(mDateNavigatorContainer
, SIGNAL(datesSelected(KCalCore::DateList
,QDate
)),
251 mDateNavigator
, SLOT(selectDates(KCalCore::DateList
,QDate
)));
253 connect(mViewManager
, SIGNAL(datesSelected(KCalCore::DateList
)),
254 mDateNavigator
, SLOT(selectDates(KCalCore::DateList
)));
256 connect(mDateNavigatorContainer
, SIGNAL(incidenceDropped(Akonadi::Item
,QDate
)),
257 SLOT(addIncidenceOn(Akonadi::Item
,QDate
)));
258 connect(mDateNavigatorContainer
, SIGNAL(incidenceDroppedMove(Akonadi::Item
,QDate
)),
259 SLOT(moveIncidenceTo(Akonadi::Item
,QDate
)));
261 connect(mDateChecker
, SIGNAL(dayPassed(QDate
)),
262 mTodoList
, SLOT(dayPassed(QDate
)));
263 connect(mDateChecker
, SIGNAL(dayPassed(QDate
)),
264 SIGNAL(dayPassed(QDate
)));
265 connect(mDateChecker
, SIGNAL(dayPassed(QDate
)),
266 mDateNavigatorContainer
, SLOT(updateToday()));
268 connect(this, SIGNAL(configChanged()),
269 mDateNavigatorContainer
, SLOT(updateConfig()));
271 connect(this, SIGNAL(incidenceSelected(Akonadi::Item
,QDate
)),
272 mEventViewer
, SLOT(setIncidence(Akonadi::Item
,QDate
)));
274 //TODO: do a pretty Summary,
276 s
= i18n("<p><em>No Item Selected</em></p>"
277 "<p>Select an event, to-do or journal entry to view its details "
280 mEventViewer
->setDefaultMessage(s
);
281 mEventViewer
->setWhatsThis(
282 i18n("View the details of events, journal entries or to-dos "
283 "selected in KOrganizer's main view here."));
284 mEventViewer
->setIncidence(Akonadi::Item(), QDate());
286 mViewManager
->connectTodoView(mTodoList
);
287 mViewManager
->connectView(mTodoList
);
289 KOGlobals::self()->setHolidays(new KHolidays::HolidayRegion(KOPrefs::instance()->mHolidays
));
291 connect(QApplication::clipboard(), SIGNAL(dataChanged()), SLOT(checkClipboard()));
293 connect(mTodoList
, SIGNAL(incidenceSelected(Akonadi::Item
,QDate
)),
294 this, SLOT(processTodoListSelection(Akonadi::Item
,QDate
)));
295 disconnect(mTodoList
, SIGNAL(incidenceSelected(Akonadi::Item
,QDate
)),
296 this, SLOT(processMainViewSelection(Akonadi::Item
,QDate
)));
299 static bool pageRegistered
= false;
301 if (!pageRegistered
) {
302 Akonadi::CollectionPropertiesDialog::registerPage(
303 new CalendarSupport::CollectionGeneralPageFactory
);
304 Akonadi::CollectionPropertiesDialog::registerPage(new PimCommon::CollectionAclPageFactory
);
305 pageRegistered
= true;
309 Akonadi::FreeBusyManager::self()->setCalendar(mCalendar
);
311 mCalendar
->registerObserver(this);
312 mDateNavigatorContainer
->setCalendar(mCalendar
);
313 mTodoList
->setCalendar(mCalendar
);
314 mEventViewer
->setCalendar(mCalendar
.data());
317 CalendarView::~CalendarView()
319 mCalendar
->unregisterObserver(this);
320 mCalendar
->setFilter(0); // So calendar doesn't deleted it twice
321 qDeleteAll(mFilters
);
322 qDeleteAll(mExtensions
);
324 delete mDialogManager
;
329 Akonadi::ETMCalendar::Ptr
CalendarView::calendar() const
334 QDate
CalendarView::activeDate(bool fallbackToToday
)
336 KOrg::BaseView
*curView
= mViewManager
->currentView();
338 if (curView
->selectionStart().isValid()) {
339 return curView
->selectionStart().date();
342 // Try the view's selectedIncidenceDates()
343 if (!curView
->selectedIncidenceDates().isEmpty()) {
344 if (curView
->selectedIncidenceDates().first().isValid()) {
345 return curView
->selectedIncidenceDates().first();
350 // When all else fails, use the navigator start date, or today.
351 if (fallbackToToday
) {
352 return QDate::currentDate();
354 return mDateNavigator
->selectedDates().first();
358 QDate
CalendarView::activeIncidenceDate()
360 KOrg::BaseView
*curView
= mViewManager
->currentView();
362 KCalCore::DateList dates
= curView
->selectedIncidenceDates();
363 if (!dates
.isEmpty()) {
364 return dates
.first();
371 QDate
CalendarView::startDate()
373 KCalCore::DateList dates
= mDateNavigator
->selectedDates();
374 return dates
.first();
377 QDate
CalendarView::endDate()
379 KCalCore::DateList dates
= mDateNavigator
->selectedDates();
383 void CalendarView::createPrinter()
386 mCalPrinter
= new CalendarSupport::CalPrinter(this, mCalendar
);
387 connect(this, &CalendarView::configChanged
, mCalPrinter
, &CalendarSupport::CalPrinter::updateConfig
);
391 bool CalendarView::saveCalendar(const QString
&filename
)
393 // Store back all unsaved data into calendar object
394 mViewManager
->currentView()->flushView();
396 KCalCore::FileStorage
storage(mCalendar
);
397 storage
.setFileName(filename
);
398 storage
.setSaveFormat(new KCalCore::ICalFormat
);
400 return storage
.save();
403 void CalendarView::archiveCalendar()
405 mDialogManager
->showArchiveDialog();
408 void CalendarView::readSettings()
412 // read settings from the KConfig, supplying reasonable
413 // defaults where none are to be found
415 KConfig
*config
= KOGlobals::self()->config();
417 KConfigGroup
geometryConfig(config
, "KOrganizer Geometry");
419 QList
<int> sizes
= geometryConfig
.readEntry("Separator1", QList
<int>());
420 if (sizes
.count() != 2 || sizes
.count() == sizes
.count(0)) {
421 sizes
<< mDateNavigatorContainer
->minimumSizeHint().width();
424 mPanner
->setSizes(sizes
);
426 sizes
= geometryConfig
.readEntry("Separator2", QList
<int>());
427 if (!sizes
.isEmpty() && sizes
.count() != sizes
.count(0)) {
428 mLeftSplitter
->setSizes(sizes
);
431 mViewManager
->readSettings(config
);
432 mTodoList
->restoreLayout(config
, QLatin1String("Sidebar Todo View"), true);
434 readFilterSettings(config
);
436 KConfigGroup
viewConfig(config
, "Views");
437 int dateCount
= viewConfig
.readEntry("ShownDatesCount", 7);
438 if (dateCount
== 7) {
439 mDateNavigator
->selectWeek();
441 mDateNavigator
->selectDates(mDateNavigator
->selectedDates().first(), dateCount
);
445 void CalendarView::writeSettings()
447 KConfig
*config
= KOGlobals::self()->config();
449 KConfigGroup
geometryConfig(config
, "KOrganizer Geometry");
451 QList
<int> list
= mMainSplitterSizes
.isEmpty() ? mPanner
->sizes() : mMainSplitterSizes
;
452 // splitter sizes are invalid (all zero) unless we have been shown once
453 if (list
.count() != list
.count(0) && mSplitterSizesValid
) {
454 geometryConfig
.writeEntry("Separator1", list
);
457 list
= mLeftSplitter
->sizes();
458 if (list
.count() != list
.count(0) && mSplitterSizesValid
) {
459 geometryConfig
.writeEntry("Separator2", list
);
462 mViewManager
->writeSettings(config
);
463 mTodoList
->saveLayout(config
, QLatin1String("Sidebar Todo View"));
465 Akonadi::CalendarSettings::self()->save();
466 KOPrefs::instance()->save();
467 CalendarSupport::KCalPrefs::instance()->save();
469 writeFilterSettings(config
);
471 KConfigGroup
viewConfig(config
, "Views");
472 viewConfig
.writeEntry("ShownDatesCount", mDateNavigator
->selectedDates().count());
477 void CalendarView::readFilterSettings(KConfig
*config
)
479 qDeleteAll(mFilters
);
482 KConfigGroup
generalConfig(config
, "General");
483 // FIXME: Move the filter loading and saving to the CalFilter class in libkcal
484 QStringList filterList
= generalConfig
.readEntry("CalendarFilters", QStringList());
485 QString currentFilter
= generalConfig
.readEntry("Current Filter");
487 QStringList::ConstIterator it
= filterList
.constBegin();
488 QStringList::ConstIterator end
= filterList
.constEnd();
490 KCalCore::CalFilter
*filter
= new KCalCore::CalFilter(*it
);
491 KConfigGroup
filterConfig(config
, QLatin1String("Filter_") + (*it
));
492 filter
->setCriteria(filterConfig
.readEntry("Criteria", 0));
493 filter
->setCategoryList(filterConfig
.readEntry("CategoryList", QStringList()));
494 if (filter
->criteria() & KCalCore::CalFilter::HideNoMatchingAttendeeTodos
) {
495 filter
->setEmailList(CalendarSupport::KCalPrefs::instance()->allEmails());
497 filter
->setCompletedTimeSpan(filterConfig
.readEntry("HideTodoDays", 0));
498 mFilters
.append(filter
);
503 int pos
= filterList
.indexOf(currentFilter
);
506 mCurrentFilter
= mFilters
.at(pos
);
511 void CalendarView::writeFilterSettings(KConfig
*config
)
513 QStringList filterList
;
515 foreach (KCalCore::CalFilter
*filter
, mFilters
) {
516 filterList
<< filter
->name();
517 KConfigGroup
filterConfig(config
, QLatin1String("Filter_") + filter
->name());
518 filterConfig
.writeEntry("Criteria", filter
->criteria());
519 filterConfig
.writeEntry("CategoryList", filter
->categoryList());
520 filterConfig
.writeEntry("HideTodoDays", filter
->completedTimeSpan());
522 KConfigGroup
generalConfig(config
, "General");
523 generalConfig
.writeEntry("CalendarFilters", filterList
);
524 if (mCurrentFilter
) {
525 generalConfig
.writeEntry("Current Filter", mCurrentFilter
->name());
527 generalConfig
.writeEntry("Current Filter", QString());
531 void CalendarView::goDate(const QDate
&date
)
533 mDateNavigator
->selectDate(date
);
536 void CalendarView::showDate(const QDate
&date
)
538 int dateCount
= mDateNavigator
->datesCount();
539 if (dateCount
== 7) {
540 mDateNavigator
->selectWeek(date
);
542 mDateNavigator
->selectDates(date
, dateCount
);
546 void CalendarView::goToday()
548 mDateNavigator
->selectToday();
551 void CalendarView::goNext()
553 if (dynamic_cast<MonthView
*>(mViewManager
->currentView())) {
554 const QDate month
= mDateNavigatorContainer
->monthOfNavigator(0);
555 QPair
<QDate
, QDate
> limits
= KODayMatrix::matrixLimits(month
);
556 mDateNavigator
->selectNextMonth(month
, limits
.first
, limits
.second
);
558 mDateNavigator
->selectNext();
562 void CalendarView::goPrevious()
564 if (dynamic_cast<MonthView
*>(mViewManager
->currentView())) {
565 const QDate month
= mDateNavigatorContainer
->monthOfNavigator(0);
566 QPair
<QDate
, QDate
> limits
= KODayMatrix::matrixLimits(month
);
567 mDateNavigator
->selectPreviousMonth(month
, limits
.first
, limits
.second
);
569 mDateNavigator
->selectPrevious();
573 void CalendarView::updateConfig()
575 updateConfig(QByteArray("korganizer"));
578 void CalendarView::updateConfig(const QByteArray
&receiver
)
580 if (receiver
!= "korganizer") {
585 mCalPrinter
->deleteLater();
589 KOGlobals::self()->setHolidays(new KHolidays::HolidayRegion(KOPrefs::instance()->mHolidays
));
591 // Only set a new time zone if it changed. This prevents the window
592 // from being modified on start
593 KDateTime::Spec newTimeSpec
= CalendarSupport::KCalPrefs::instance()->timeSpec();
594 if (mCalendar
->viewTimeSpec() != newTimeSpec
) {
596 const QString
question(i18n("The time zone setting was changed. "
597 "Do you want to keep the absolute time of "
598 "the items in your calendar, which will show "
599 "them to be at a different time than "
600 "before, or move them to be at the old time "
601 "also in the new time zone?"));
602 int rc
= KMessageBox::questionYesNo(this, question
,
603 i18n("Keep Absolute Times?"),
604 KGuiItem(i18n("Keep Times")),
605 KGuiItem(i18n("Move Times")),
606 QLatin1String("calendarKeepAbsoluteTimes"));
607 if (rc
== KMessageBox::Yes
) {
608 // keep the absolute time - note the new viewing time zone in the calendar
609 mCalendar
->setViewTimeSpec(newTimeSpec
);
611 // only set the new timezone, wihtout shifting events, they will be
612 // interpreted as being in the new timezone now
613 mCalendar
->shiftTimes(mCalendar
->viewTimeSpec(), newTimeSpec
);
617 // config changed lets tell the date navigator the new modes
618 // if there weren't changed they are ignored
619 updateHighlightModes();
621 emit
configChanged();
623 //switch beetween merged, side by side and tabbed agenda if needed
624 mViewManager
->updateMultiCalendarDisplay();
626 // To make the "fill window" configurations work
627 mViewManager
->raiseCurrentView();
629 mChanger
->setDestinationPolicy(
630 static_cast<Akonadi::IncidenceChanger::DestinationPolicy
>(
631 KOPrefs::instance()->destination()));
633 mChanger
->setGroupwareCommunication(CalendarSupport::KCalPrefs::instance()->useGroupwareCommunication());
636 void CalendarView::slotCreateFinished(int changeId
,
637 const Akonadi::Item
&item
,
638 Akonadi::IncidenceChanger::ResultCode resultCode
,
639 const QString
&errorString
)
642 if (resultCode
== Akonadi::IncidenceChanger::ResultCodeSuccess
) {
643 changeIncidenceDisplay(item
, Akonadi::IncidenceChanger::ChangeTypeCreate
);
644 updateUnmanagedViews();
645 checkForFilteredChange(item
);
647 qCritical() << "Incidence not added, job reported error: " << errorString
;
651 void CalendarView::slotModifyFinished(int changeId
,
652 const Akonadi::Item
&item
,
653 Akonadi::IncidenceChanger::ResultCode resultCode
,
654 const QString
&errorString
)
657 if (resultCode
!= Akonadi::IncidenceChanger::ResultCodeSuccess
) {
658 qCritical() << "Incidence not modified, job reported error: " << errorString
;
662 Q_ASSERT(item
.isValid());
663 KCalCore::Incidence::Ptr incidence
= CalendarSupport::incidence(item
);
665 QSet
<KCalCore::IncidenceBase::Field
> dirtyFields
= incidence
->dirtyFields();
666 incidence
->resetDirtyFields();
667 // Record completed todos in journals, if enabled. we should to this here in
668 // favor of the todolist. users can mark a task as completed in an editor
670 if (incidence
->type() == KCalCore::Incidence::TypeTodo
&&
671 KOPrefs::instance()->recordTodosInJournals() &&
672 (dirtyFields
.contains(KCalCore::Incidence::FieldCompleted
))) {
673 KCalCore::Todo::Ptr todo
= incidence
.dynamicCast
<KCalCore::Todo
>();
674 if (todo
->isCompleted() || todo
->recurs()) {
675 QString timeStr
= KLocale::global()->formatTime(QTime::currentTime());
676 QString description
= i18n("Todo completed: %1 (%2)", incidence
->summary(), timeStr
);
678 KCalCore::Journal::List journals
= calendar()->journals(QDate::currentDate());
680 if (journals
.isEmpty()) {
681 KCalCore::Journal::Ptr
journal(new KCalCore::Journal
);
683 KDateTime::currentDateTime(CalendarSupport::KCalPrefs::instance()->timeSpec()));
685 QString dateStr
= KLocale::global()->formatDate(QDate::currentDate());
686 journal
->setSummary(i18n("Journal of %1", dateStr
));
687 journal
->setDescription(description
);
689 if (mChanger
->createIncidence(journal
, item
.parentCollection(), this) == -1) {
690 qCritical() << "Unable to add Journal";
694 } else { // journal list is not empty
695 Akonadi::Item journalItem
= mCalendar
->item(journals
.first()->uid());
696 KCalCore::Journal::Ptr journal
= CalendarSupport::journal(journalItem
);
697 KCalCore::Journal::Ptr
oldJournal(journal
->clone());
698 journal
->setDescription(journal
->description().append(QLatin1Char('\n') + description
));
699 mChanger
->modifyIncidence(journalItem
, oldJournal
, this);
705 changeIncidenceDisplay(item
, Akonadi::IncidenceChanger::ChangeTypeCreate
);
706 updateUnmanagedViews();
707 checkForFilteredChange(item
);
710 void CalendarView::slotDeleteFinished(int changeId
,
711 const QVector
<Akonadi::Item::Id
> &itemIdList
,
712 Akonadi::IncidenceChanger::ResultCode resultCode
,
713 const QString
&errorString
)
716 if (resultCode
== Akonadi::IncidenceChanger::ResultCodeSuccess
) {
717 foreach (Akonadi::Item::Id id
, itemIdList
) {
718 Akonadi::Item item
= mCalendar
->item(id
);
719 if (item
.isValid()) {
720 changeIncidenceDisplay(item
, Akonadi::IncidenceChanger::ChangeTypeDelete
);
723 updateUnmanagedViews();
725 qCritical() << "Incidence not deleted, job reported error: " << errorString
;
729 void CalendarView::checkForFilteredChange(const Akonadi::Item
&item
)
731 KCalCore::Incidence::Ptr incidence
= CalendarSupport::incidence(item
);
732 KCalCore::CalFilter
*filter
= calendar()->filter();
733 if (filter
&& !filter
->filterIncidence(incidence
)) {
734 // Incidence is filtered and thus not shown in the view, tell the
735 // user so that he isn't surprised if his new event doesn't show up
736 mMessageWidget
->setText(i18n("The item \"%1\" is filtered by your current filter rules, "
737 "so it will be hidden and not appear in the view.",
738 incidence
->summary()));
739 mMessageWidget
->show();
743 void CalendarView::startMultiModify(const QString
&text
)
745 mChanger
->startAtomicOperation(text
);
748 void CalendarView::endMultiModify()
750 mChanger
->endAtomicOperation();
753 void CalendarView::changeIncidenceDisplay(const Akonadi::Item
&item
,
754 Akonadi::IncidenceChanger::ChangeType changeType
)
756 if (mDateNavigatorContainer
->isVisible()) {
757 mDateNavigatorContainer
->updateView();
760 mDialogManager
->updateSearchDialog();
762 if (CalendarSupport::hasIncidence(item
)) {
763 // If there is an event view visible update the display
764 mViewManager
->currentView()->changeIncidenceDisplay(item
, changeType
);
766 mViewManager
->currentView()->updateView();
770 void CalendarView::updateView(const QDate
&start
, const QDate
&end
,
771 const QDate
&preferredMonth
,
772 const bool updateTodos
)
774 const bool currentViewIsTodoView
= mViewManager
->currentView()->identifier() == "DefaultTodoView";
776 if (updateTodos
&& !currentViewIsTodoView
&& mTodoList
->isVisible()) {
777 // Update the sidepane todoView
778 mTodoList
->updateView();
781 if (start
.isValid() && end
.isValid() && !(currentViewIsTodoView
&& !updateTodos
)) {
782 mViewManager
->updateView(start
, end
, preferredMonth
);
785 if (mDateNavigatorContainer
->isVisible()) {
786 mDateNavigatorContainer
->updateView();
790 void CalendarView::updateView()
792 const KCalCore::DateList tmpList
= mDateNavigator
->selectedDates();
793 const QDate month
= mDateNavigatorContainer
->monthOfNavigator();
795 // We assume that the navigator only selects consecutive days.
796 updateView(tmpList
.first(), tmpList
.last(), month
/**preferredMonth*/);
799 void CalendarView::updateUnmanagedViews()
801 if (mDateNavigatorContainer
->isVisible()) {
802 mDateNavigatorContainer
->updateDayMatrix();
806 int CalendarView::msgItemDelete(const Akonadi::Item
&item
)
808 return KMessageBox::warningContinueCancel(
811 "Do you really want to permanently remove the item \"%1\"?",
812 CalendarSupport::incidence(item
)->summary()),
813 i18nc("@title:window", "Delete Item?"),
814 KStandardGuiItem::del());
817 void CalendarView::edit_cut()
819 const Akonadi::Item item
= selectedIncidence();
820 KCalCore::Incidence::Ptr incidence
= CalendarSupport::incidence(item
);
822 qCritical() << "Null incidence";
826 mCalendarClipboard
->cutIncidence(incidence
, Akonadi::CalendarClipboard::AskMode
);
829 void CalendarView::edit_copy()
831 const Akonadi::Item item
= selectedIncidence();
833 if (!item
.isValid()) {
834 KNotification::beep();
835 qCritical() << "Invalid item";
839 KCalCore::Incidence::Ptr incidence
= CalendarSupport::incidence(item
);
841 if (!mCalendarClipboard
->copyIncidence(incidence
, Akonadi::CalendarClipboard::AskMode
)) {
842 qCritical() << "Error copying incidence";
848 void CalendarView::edit_paste()
850 // If in agenda and month view, use the selected time and date from there.
851 // In all other cases, use the navigator's selected date.
854 KDateTime finalDateTime
;
855 bool useEndTime
= false;
856 KCalUtils::DndFactory::PasteFlags pasteFlags
= 0;
858 KOrg::BaseView
*curView
= mViewManager
->currentView();
859 KOAgendaView
*agendaView
= mViewManager
->agendaView();
860 MonthView
*monthView
= mViewManager
->monthView();
863 qCWarning(KORGANIZER_LOG
) << "No view is selected, can't paste";
867 if (curView
== agendaView
&& agendaView
->selectionStart().isValid()) {
868 const QDate date
= agendaView
->selectionStart().date();
869 endDT
= agendaView
->selectionEnd();
870 useEndTime
= !agendaView
->selectedIsSingleCell();
871 if (agendaView
->selectedIsAllDay()) {
872 finalDateTime
= KDateTime(date
);
874 finalDateTime
= KDateTime(date
, agendaView
->selectionStart().time());
876 } else if (curView
== monthView
&& monthView
->selectionStart().isValid()) {
877 finalDateTime
= KDateTime(monthView
->selectionStart().date());
878 pasteFlags
= KCalUtils::DndFactory::FlagPasteAtOriginalTime
;
879 } else if (!mDateNavigator
->selectedDates().isEmpty() &&
880 curView
->supportsDateNavigation()) {
881 // default to the selected date from the navigator
882 finalDateTime
= KDateTime(mDateNavigator
->selectedDates().first());
883 pasteFlags
= KCalUtils::DndFactory::FlagPasteAtOriginalTime
;
886 if (!finalDateTime
.isValid() && curView
->supportsDateNavigation()) {
889 i18n("Paste failed: unable to determine a valid target date."));
893 KCalUtils::DndFactory
factory(mCalendar
);
895 KCalCore::Incidence::List pastedIncidences
= factory
.pasteIncidences(finalDateTime
, pasteFlags
);
896 KCalCore::Incidence::List::Iterator it
;
898 for (it
= pastedIncidences
.begin(); it
!= pastedIncidences
.end(); ++it
) {
899 // FIXME: use a visitor here
900 if ((*it
)->type() == KCalCore::Incidence::TypeEvent
) {
901 KCalCore::Event::Ptr pastedEvent
= (*it
).staticCast
<KCalCore::Event
>();
902 // only use selected area if event is of the same type (all-day or non-all-day
903 // as the current selection is
904 if (agendaView
&& endDT
.isValid() && useEndTime
) {
905 if ((pastedEvent
->allDay() && agendaView
->selectedIsAllDay()) ||
906 (!pastedEvent
->allDay() && !agendaView
->selectedIsAllDay())) {
907 KDateTime
kdt(endDT
, CalendarSupport::KCalPrefs::instance()->timeSpec());
908 pastedEvent
->setDtEnd(kdt
.toTimeSpec(pastedEvent
->dtEnd().timeSpec()));
912 pastedEvent
->setRelatedTo(QString());
913 mChanger
->createIncidence(KCalCore::Event::Ptr(pastedEvent
->clone()),
914 Akonadi::Collection(), this);
915 } else if ((*it
)->type() == KCalCore::Incidence::TypeTodo
) {
916 KCalCore::Todo::Ptr pastedTodo
= (*it
).staticCast
<KCalCore::Todo
>();
917 Akonadi::Item _selectedTodoItem
= selectedTodo();
919 // if we are cutting a hierarchy only the root
920 // should be son of _selectedTodo
921 KCalCore::Todo::Ptr _selectedTodo
= CalendarSupport::todo(_selectedTodoItem
);
922 if (_selectedTodo
&& pastedTodo
->relatedTo().isEmpty()) {
923 pastedTodo
->setRelatedTo(_selectedTodo
->uid());
926 // When pasting multiple incidences, don't ask which collection to use, for each one
927 mChanger
->createIncidence(KCalCore::Todo::Ptr(pastedTodo
->clone()),
928 Akonadi::Collection(), this);
929 } else if ((*it
)->type() == KCalCore::Incidence::TypeJournal
) {
930 // When pasting multiple incidences, don't ask which collection to use, for each one
931 mChanger
->createIncidence(KCalCore::Incidence::Ptr((*it
)->clone()),
932 Akonadi::Collection(), this);
937 void CalendarView::edit_options()
939 mDialogManager
->showOptionsDialog();
942 void CalendarView::dateTimesForNewEvent(QDateTime
&startDt
, QDateTime
&endDt
,
945 mViewManager
->currentView()->eventDurationHint(startDt
, endDt
, allDay
);
947 if (!startDt
.isValid() || !endDt
.isValid()) {
948 startDt
.setDate(activeDate(true));
949 startDt
.setTime(CalendarSupport::KCalPrefs::instance()->mStartTime
.time());
952 (CalendarSupport::KCalPrefs::instance()->mDefaultDuration
.time().hour() * 3600) +
953 (CalendarSupport::KCalPrefs::instance()->mDefaultDuration
.time().minute() * 60);
954 endDt
= startDt
.addSecs(addSecs
);
958 IncidenceEditorNG::IncidenceDialog
*CalendarView::incidenceDialog(const Akonadi::Item
&item
)
960 IncidenceEditorNG::IncidenceDialog
*dialog
= mDialogManager
->createDialog(item
);
961 connect(dialog
, &IncidenceEditorNG::IncidenceDialog::incidenceCreated
, this, &CalendarView::handleIncidenceCreated
);
965 IncidenceEditorNG::IncidenceDialog
*CalendarView::newEventEditor(const KCalCore::Event::Ptr
&event
)
968 item
.setPayload(event
);
969 IncidenceEditorNG::IncidenceDialog
*dialog
= incidenceDialog(item
);
973 mDialogManager
->connectTypeAhead(
974 dialog
, qobject_cast
<KOEventView
*>(viewManager()->currentView()));
979 void CalendarView::newEvent()
981 newEvent(QDateTime(), QDateTime());
984 void CalendarView::newEvent(const QDate
&dt
)
986 QDateTime
startDt(dt
, CalendarSupport::KCalPrefs::instance()->mStartTime
.time());
987 QTime duration
= CalendarSupport::KCalPrefs::instance()->defaultDuration().time();
988 QTime time
= startDt
.time();
990 time
= time
.addSecs(duration
.hour() * 3600 +
991 duration
.minute() * 60 +
993 QDateTime
endDt(startDt
);
995 newEvent(startDt
, endDt
);
998 void CalendarView::newEvent(const QDateTime
&startDt
)
1000 newEvent(startDt
, startDt
);
1003 void CalendarView::newEvent(const QDateTime
&startDtParam
, const QDateTime
&endDtParam
,
1006 // Let the current view change the default start/end datetime
1007 QDateTime
startDt(startDtParam
);
1008 QDateTime
endDt(endDtParam
);
1010 // Adjust the start/end date times (i.e. replace invalid values by defaults,
1011 // and let the view adjust the type.
1012 dateTimesForNewEvent(startDt
, endDt
, allDay
);
1014 IncidenceEditorNG::IncidenceDefaults defaults
=
1015 IncidenceEditorNG::IncidenceDefaults::minimalIncidenceDefaults();
1016 defaults
.setStartDateTime(KDateTime(startDt
));
1017 defaults
.setEndDateTime(KDateTime(endDt
));
1019 KCalCore::Event::Ptr
event(new KCalCore::Event
);
1020 defaults
.setDefaults(event
);
1021 event
->setAllDay(allDay
);
1023 IncidenceEditorNG::IncidenceDialog
*eventEditor
= newEventEditor(event
);
1024 Q_ASSERT(eventEditor
);
1026 // Fallsback to the default collection defined in config
1027 eventEditor
->selectCollection(defaultCollection(KCalCore::Event::eventMimeType()));
1030 void CalendarView::newEvent(const QString
&summary
, const QString
&description
,
1031 const QStringList
&attachments
, const QStringList
&attendees
,
1032 const QStringList
&attachmentMimetypes
, bool inlineAttachment
)
1034 // Adjust the start/end date times (i.e. replace invalid values by defaults,
1035 // and let the view adjust the type.
1038 bool allDay
= false;
1039 dateTimesForNewEvent(startDt
, endDt
, allDay
);
1041 IncidenceEditorNG::IncidenceDefaults defaults
=
1042 IncidenceEditorNG::IncidenceDefaults::minimalIncidenceDefaults();
1043 defaults
.setStartDateTime(KDateTime(startDt
));
1044 defaults
.setEndDateTime(KDateTime(endDt
));
1045 // if attach or attendee list is empty, these methods don't do anything, so
1046 // it's safe to call them in every case
1047 defaults
.setAttachments(attachments
, attachmentMimetypes
, QStringList(), inlineAttachment
);
1048 defaults
.setAttendees(attendees
);
1050 KCalCore::Event::Ptr
event(new KCalCore::Event
);
1051 defaults
.setDefaults(event
);
1053 event
->setSummary(summary
);
1054 event
->setDescription(description
);
1055 event
->setAllDay(allDay
);
1056 newEventEditor(event
);
1059 void CalendarView::newTodo(const QString
&summary
, const QString
&description
,
1060 const QStringList
&attachments
, const QStringList
&attendees
,
1061 const QStringList
&attachmentMimetypes
,
1062 bool inlineAttachment
)
1064 Akonadi::Collection defaultCol
= defaultCollection(KCalCore::Todo::todoMimeType());
1066 IncidenceEditorNG::IncidenceDialogFactory::createTodoEditor(
1067 summary
, description
, attachments
,
1068 attendees
, attachmentMimetypes
,
1069 QStringList()/* attachment labels */,
1070 inlineAttachment
, defaultCol
,
1074 void CalendarView::newTodo()
1076 newTodo(Akonadi::Collection());
1079 void CalendarView::newTodo(const Akonadi::Collection
&collection
)
1081 IncidenceEditorNG::IncidenceDefaults defaults
=
1082 IncidenceEditorNG::IncidenceDefaults::minimalIncidenceDefaults();
1085 if (mViewManager
->currentView()->isEventView()) {
1088 dateTimesForNewEvent(startDt
, endDt
, allDay
);
1090 defaults
.setStartDateTime(KDateTime(startDt
));
1091 defaults
.setEndDateTime(KDateTime(endDt
));
1094 KCalCore::Todo::Ptr
todo(new KCalCore::Todo
);
1095 defaults
.setDefaults(todo
);
1096 todo
->setAllDay(allDay
);
1099 item
.setPayload(todo
);
1101 IncidenceEditorNG::IncidenceDialog
*dialog
= createIncidenceEditor(item
, collection
);
1106 void CalendarView::newTodo(const QDate
&date
)
1108 IncidenceEditorNG::IncidenceDefaults defaults
=
1109 IncidenceEditorNG::IncidenceDefaults::minimalIncidenceDefaults();
1110 defaults
.setEndDateTime(KDateTime(date
, QTime::currentTime()));
1112 KCalCore::Todo::Ptr
todo(new KCalCore::Todo
);
1113 defaults
.setDefaults(todo
);
1114 todo
->setAllDay(true);
1117 item
.setPayload(todo
);
1119 IncidenceEditorNG::IncidenceDialog
*dialog
= createIncidenceEditor(item
);
1123 void CalendarView::newJournal()
1125 newJournal(QString(), activeDate(true));
1128 void CalendarView::newJournal(const QDate
&date
)
1130 newJournal(QString(), date
.isValid() ? date
: activeDate(true));
1133 void CalendarView::newJournal(const Akonadi::Collection
&collection
)
1135 IncidenceEditorNG::IncidenceDefaults defaults
=
1136 IncidenceEditorNG::IncidenceDefaults::minimalIncidenceDefaults();
1138 if (mViewManager
->currentView()->isEventView()) {
1142 dateTimesForNewEvent(startDt
, endDt
, allDay
);
1144 defaults
.setStartDateTime(KDateTime(startDt
));
1145 defaults
.setEndDateTime(KDateTime(endDt
));
1148 KCalCore::Journal::Ptr
journal(new KCalCore::Journal
);
1149 defaults
.setDefaults(journal
);
1152 item
.setPayload(journal
);
1153 IncidenceEditorNG::IncidenceDialog
*dialog
= createIncidenceEditor(item
, collection
);
1157 void CalendarView::newJournal(const QString
&text
, const QDate
&date
)
1159 IncidenceEditorNG::IncidenceDefaults defaults
=
1160 IncidenceEditorNG::IncidenceDefaults::minimalIncidenceDefaults();
1162 KCalCore::Journal::Ptr
journal(new KCalCore::Journal
);
1163 defaults
.setStartDateTime(KDateTime(date
));
1164 defaults
.setDefaults(journal
);
1166 journal
->setSummary(text
);
1169 item
.setPayload(journal
);
1171 IncidenceEditorNG::IncidenceDialog
*dialog
= createIncidenceEditor(item
);
1175 KOrg::BaseView
*CalendarView::currentView() const
1177 return mViewManager
->currentView();
1180 void CalendarView::configureCurrentView()
1182 KOrg::BaseView
*const view
= currentView();
1183 if (view
&& view
->hasConfigurationDialog()) {
1184 view
->showConfigurationDialog(this);
1188 void CalendarView::newSubTodo()
1190 const Akonadi::Item item
= selectedTodo();
1191 if (CalendarSupport::hasTodo(item
)) {
1196 void CalendarView::newSubTodo(const Akonadi::Collection
&collection
)
1198 if (!CalendarSupport::hasTodo(selectedTodo())) {
1199 qCWarning(KORGANIZER_LOG
) << "CalendarSupport::hasTodo() is false";
1203 IncidenceEditorNG::IncidenceDefaults defaults
=
1204 IncidenceEditorNG::IncidenceDefaults::minimalIncidenceDefaults();
1205 defaults
.setRelatedIncidence(CalendarSupport::incidence(selectedTodo()));
1207 KCalCore::Todo::Ptr
todo(new KCalCore::Todo
);
1208 defaults
.setDefaults(todo
);
1211 item
.setPayload(todo
);
1213 IncidenceEditorNG::IncidenceDialog
*dialog
= createIncidenceEditor(item
, collection
);
1217 void CalendarView::newSubTodo(const Akonadi::Item
&parentTodo
)
1219 IncidenceEditorNG::IncidenceDefaults defaults
=
1220 IncidenceEditorNG::IncidenceDefaults::minimalIncidenceDefaults();
1221 defaults
.setRelatedIncidence(CalendarSupport::incidence(parentTodo
));
1223 KCalCore::Todo::Ptr
todo(new KCalCore::Todo
);
1224 defaults
.setDefaults(todo
);
1226 Q_ASSERT(!todo
->relatedTo().isEmpty());
1229 item
.setPayload(todo
);
1231 // Don't use parentTodo.parentCollection() because that can be a search folder.
1232 Akonadi::Collection collection
= mCalendar
->collection(parentTodo
.storageCollectionId());
1233 IncidenceEditorNG::IncidenceDialog
*dialog
= createIncidenceEditor(item
, collection
);
1237 void CalendarView::newFloatingEvent()
1239 const QDate date
= activeDate();
1240 newEvent(QDateTime(date
, QTime(12, 0, 0)),
1241 QDateTime(date
, QTime(12, 0, 0)), true);
1244 bool CalendarView::addIncidence(const QString
&ical
)
1246 KCalCore::ICalFormat format
;
1247 format
.setTimeSpec(mCalendar
->timeSpec());
1248 KCalCore::Incidence::Ptr
incidence(format
.fromString(ical
));
1249 return addIncidence(incidence
);
1252 bool CalendarView::addIncidence(const KCalCore::Incidence::Ptr
&incidence
)
1254 return incidence
? mChanger
->createIncidence(incidence
, Akonadi::Collection(), this) != -1 : false;
1257 void CalendarView::appointment_show()
1259 const Akonadi::Item item
= selectedIncidence();
1260 if (CalendarSupport::hasIncidence(item
)) {
1261 showIncidence(item
);
1263 KNotification::beep();
1267 void CalendarView::appointment_edit()
1269 const Akonadi::Item item
= selectedIncidence();
1270 if (CalendarSupport::hasIncidence(item
)) {
1271 editIncidence(item
);
1273 KNotification::beep();
1277 void CalendarView::appointment_delete()
1279 const Akonadi::Item item
= selectedIncidence();
1280 if (CalendarSupport::hasIncidence(item
)) {
1281 deleteIncidence(item
);
1283 KNotification::beep();
1287 void CalendarView::todo_unsub()
1289 const Akonadi::Item aTodo
= selectedTodo();
1290 if (incidence_unsub(aTodo
)) {
1295 bool CalendarView::incidence_unsub(const Akonadi::Item
&item
)
1297 const KCalCore::Incidence::Ptr inc
= CalendarSupport::incidence(item
);
1299 if (!inc
|| inc
->relatedTo().isEmpty()) {
1300 qCDebug(KORGANIZER_LOG
) << "Refusing to unparent this to-do" << inc
;
1304 KCalCore::Incidence::Ptr
oldInc(inc
->clone());
1305 inc
->setRelatedTo(QString());
1306 mChanger
->modifyIncidence(item
, oldInc
, this);
1311 bool CalendarView::makeSubTodosIndependent()
1313 bool status
= false;
1314 const Akonadi::Item aTodo
= selectedTodo();
1316 if (makeChildrenIndependent(aTodo
)) {
1323 bool CalendarView::makeChildrenIndependent(const Akonadi::Item
&item
)
1325 const KCalCore::Incidence::Ptr inc
= CalendarSupport::incidence(item
);
1327 Akonadi::Item::List subIncs
= mCalendar
->childItems(item
.id());
1329 if (!inc
|| subIncs
.isEmpty()) {
1330 qCDebug(KORGANIZER_LOG
) << "Refusing to make children independent" << inc
;
1333 startMultiModify(i18n("Make sub-to-dos independent"));
1335 foreach (const Akonadi::Item
&item
, subIncs
) {
1336 incidence_unsub(item
);
1343 bool CalendarView::deleteIncidence(Akonadi::Item::Id id
, bool force
)
1345 Akonadi::Item item
= mCalendar
->item(id
);
1346 if (!CalendarSupport::hasIncidence(item
)) {
1347 qCritical() << "CalendarView::deleteIncidence(): Item does not contain incidence.";
1350 return deleteIncidence(item
, force
);
1353 void CalendarView::toggleAlarm(const Akonadi::Item
&item
)
1355 const KCalCore::Incidence::Ptr incidence
= CalendarSupport::incidence(item
);
1357 qCritical() << "Null incidence";
1360 KCalCore::Incidence::Ptr
oldincidence(incidence
->clone());
1362 KCalCore::Alarm::List alarms
= incidence
->alarms();
1363 KCalCore::Alarm::List::ConstIterator it
;
1364 for (it
= alarms
.constBegin(); it
!= alarms
.constEnd(); ++it
) {
1365 (*it
)->toggleAlarm();
1367 if (alarms
.isEmpty()) {
1368 // Add an alarm if it didn't have one
1369 KCalCore::Alarm::Ptr alm
= incidence
->newAlarm();
1370 alm
->setType(KCalCore::Alarm::Display
);
1371 alm
->setEnabled(true);
1372 int duration
; // in secs
1373 switch (CalendarSupport::KCalPrefs::instance()->mReminderTimeUnits
) {
1376 duration
= CalendarSupport::KCalPrefs::instance()->mReminderTime
* 60;
1379 duration
= CalendarSupport::KCalPrefs::instance()->mReminderTime
* 60 * 60;
1382 duration
= CalendarSupport::KCalPrefs::instance()->mReminderTime
* 60 * 60 * 24;
1385 if (incidence
->type() == KCalCore::Incidence::TypeEvent
) {
1386 alm
->setStartOffset(KCalCore::Duration(-duration
));
1388 alm
->setEndOffset(KCalCore::Duration(-duration
));
1391 mChanger
->startAtomicOperation(i18n("Toggle Reminder"));
1392 mChanger
->modifyIncidence(item
, oldincidence
, this);
1393 mChanger
->endAtomicOperation();
1396 void CalendarView::toggleTodoCompleted(const Akonadi::Item
&todoItem
)
1398 const KCalCore::Incidence::Ptr incidence
= CalendarSupport::incidence(todoItem
);
1401 qCritical() << "Null incidence";
1404 if (incidence
->type() != KCalCore::Incidence::TypeTodo
) {
1405 qCDebug(KORGANIZER_LOG
) << "called for a non-Todo incidence";
1409 KCalCore::Todo::Ptr todo
= CalendarSupport::todo(todoItem
);
1411 KCalCore::Todo::Ptr
oldtodo(todo
->clone());
1413 if (todo
->isCompleted()) {
1414 todo
->setPercentComplete(0);
1416 todo
->setCompleted(KDateTime::currentDateTime(
1417 CalendarSupport::KCalPrefs::instance()->timeSpec()));
1420 mChanger
->startAtomicOperation(i18n("Toggle To-do Completed"));
1421 mChanger
->modifyIncidence(todoItem
, oldtodo
, this);
1422 mChanger
->endAtomicOperation();
1425 void CalendarView::copyIncidenceToResource(const Akonadi::Item
&item
, const Akonadi::Collection
&col
)
1427 #ifdef AKONADI_PORT_DISABLED
1429 qCritical() << "Null incidence";
1433 KCalCore::CalendarResources
*const resources
= KOrg::StdCalendar::self();
1434 KCalCore::CalendarResourceManager
*const manager
= resources
->resourceManager();
1436 // Find the resource the incidence should be copied to
1437 ResourceCalendar
*newCal
= 0;
1438 KCalCore::CalendarResourceManager::iterator it
;
1439 for (it
= manager
->begin(); it
!= manager
->end(); ++it
) {
1440 ResourceCalendar
*const resource
= *it
;
1441 if (resource
->identifier() == resourceId
) {
1450 // Clone a new Incidence from the selected Incidence and give it a new Uid.
1451 KCalCore::Incidence::Ptr newInc
;
1452 if (incidence
->type() == KCalCore::Incidence::TypeEvent
) {
1453 KCalCore::Event::Ptr
nEvent(static_cast<KCalCore::Event::Ptr
>(incidence
)->clone());
1454 nEvent
->setUid(KCalCore::CalFormat::createUniqueId());
1456 } else if (incidence
->type() == KCalCore::Incidence::TypeTodo
) {
1457 KCalCore::Todo::Ptr
nTodo(static_cast<KCalCore::Todo::Ptr
>(incidence
)->clone());
1458 nTodo
->setUid(KCalCore::CalFormat::createUniqueId());
1460 } else if (incidence
->type() == KCalCore::Incidence::TypeJournal
) {
1461 KCalCore::Journal::Ptr
nJournal(static_cast<KCalCore::Journal::Ptr
>(incidence
)->clone());
1462 nJournal
->setUid(KCalCore::CalFormat::createUniqueId());
1465 qCWarning(KORGANIZER_LOG
) << "Trying to copy an incidence type that cannot be copied";
1469 if (resources
->addIncidence(newInc
, newCal
)) {
1470 incidenceAddFinished(newInc
, true);
1471 KMessageBox::information(
1474 "\"%1\" was successfully copied to %2.",
1475 incidence
->summary(),
1476 newCal
->resourceName()),
1477 i18nc("@title:window", "Copying Succeeded"),
1478 "CalendarIncidenceCopy");
1483 "Unable to copy the item \"%1\" to %2.",
1484 incidence
->summary(),
1485 newCal
->resourceName()),
1486 i18nc("@title:window", "Copying Failed"));
1491 qCDebug(KORGANIZER_LOG
) << "AKONADI PORT: Disabled code in " << Q_FUNC_INFO
;
1495 void CalendarView::moveIncidenceToResource(const Akonadi::Item
&item
, const Akonadi::Collection
&col
)
1497 #ifdef AKONADI_PORT_DISABLED
1499 qCritical() << "Null incidence";
1503 KCalCore::CalendarResources
*const resources
= KOrg::StdCalendar::self();
1504 KCalCore::CalendarResourceManager
*const manager
= resources
->resourceManager();
1506 // Find the resource the incidence should be moved to
1507 ResourceCalendar
*newCal
= 0;
1508 KCalCore::CalendarResourceManager::iterator it
;
1509 for (it
= manager
->begin(); it
!= manager
->end(); ++it
) {
1510 ResourceCalendar
*const resource
= *it
;
1511 if (resource
->identifier() == resourceId
) {
1520 // Clone a new Incidence from the selected Incidence and give it a new Uid.
1521 KCalCore::Incidence
*newInc
;
1522 if (incidence
->type() == KCalCore::Incidence::TypeEvent
) {
1523 KCalCore::Event::Ptr nEvent
= static_cast<KCalCore::Event::Ptr
>(incidence
)->clone();
1524 nEvent
->setUid(KCalCore::CalFormat::createUniqueId());
1526 } else if (incidence
->type() == KCalCore::Incidence::TypeTodo
) {
1527 KCalCore::Todo::Ptr nTodo
= static_cast<KCalCore::Todo::Ptr
>(incidence
)->clone();
1528 nTodo
->setUid(KCalCore::CalFormat::createUniqueId());
1530 } else if (incidence
->type() == KCalCore::Incidence::TypeJournal
) {
1531 KCalCore::Journal::Ptr nJournal
= static_cast<KCalCore::Journal::Ptr
>(incidence
)->clone();
1532 nJournal
->setUid(KCalCore::CalFormat::createUniqueId());
1535 qCWarning(KORGANIZER_LOG
) << "Trying to move an incidence type that cannot be moved";
1539 if (resources
->addIncidence(newInc
, newCal
)) {
1540 incidenceAddFinished(newInc
, true);
1541 ResourceCalendar
*const oldCal
= resources
->resource(incidence
);
1542 if (!oldCal
|| resources
->deleteIncidence(incidence
)) {
1546 "Unable to remove the item \"%1\" from %2. "
1547 "However, a copy of this item has been put into %3.",
1548 incidence
->summary(),
1549 oldCal
->resourceName(),
1550 newCal
->resourceName()),
1551 i18nc("@title:window", "Moving Failed"));
1553 incidenceDeleteFinished(incidence
, true);
1554 KMessageBox::information(
1557 "\"%1\" was successfully moved from %2 to %3.",
1558 incidence
->summary(),
1559 oldCal
->resourceName(),
1560 newCal
->resourceName()),
1561 i18nc("@title:window", "Moving Succeeded"),
1562 "CalendarIncidenceMove");
1568 "Unable to add the item \"%1\" into %2. "
1569 "This item has not been moved.",
1570 incidence
->summary(),
1571 newCal
->resourceName()),
1572 i18nc("@title:window", "Moving Failed"));
1577 qCDebug(KORGANIZER_LOG
) << "AKONADI PORT: Disabled code in " << Q_FUNC_INFO
;
1581 void CalendarView::dissociateOccurrences(const Akonadi::Item
&item
, const QDate
&date
)
1583 const KCalCore::Incidence::Ptr incidence
= CalendarSupport::incidence(item
);
1586 qCritical() << "Null incidence";
1590 KDateTime
thisDateTime(date
, CalendarSupport::KCalPrefs::instance()->timeSpec());
1591 bool isFirstOccurrence
= !incidence
->recurrence()->getPreviousDateTime(thisDateTime
).isValid();
1594 bool doOnlyThis
= false;
1595 bool doFuture
= false;
1597 if (isFirstOccurrence
) {
1598 answer
= KMessageBox::questionYesNo(
1600 i18n("Do you want to dissociate "
1601 "the occurrence on %1 "
1602 "from the recurrence?",
1603 KLocale::global()->formatDate(date
)),
1604 i18n("KOrganizer Confirmation"),
1605 KGuiItem(i18n("&Dissociate")),
1606 KStandardGuiItem::cancel());
1608 doOnlyThis
= (answer
== KMessageBox::Yes
);
1610 answer
= KMessageBox::questionYesNoCancel(
1612 i18n("Do you want to dissociate "
1613 "the occurrence on %1 "
1614 "from the recurrence or also "
1615 "dissociate future ones?",
1616 KLocale::global()->formatDate(date
)),
1617 i18n("KOrganizer Confirmation"),
1618 KGuiItem(i18n("&Only Dissociate This One")),
1619 KGuiItem(i18n("&Also Dissociate Future Ones")));
1621 doOnlyThis
= (answer
== KMessageBox::Yes
);
1622 doFuture
= (answer
== KMessageBox::No
);
1626 dissociateOccurrence(item
, date
, false);
1627 } else if (doFuture
) {
1628 dissociateOccurrence(item
, date
, true);
1631 void CalendarView::dissociateOccurrence(const Akonadi::Item
&item
, const QDate
&date
, bool thisAndFuture
)
1633 const KCalCore::Incidence::Ptr incidence
= CalendarSupport::incidence(item
);
1635 if (thisAndFuture
) {
1636 startMultiModify(i18n("Dissociate future occurrences"));
1638 startMultiModify(i18n("Dissociate occurrence"));
1640 KDateTime
occurrenceDate(incidence
->dtStart());
1641 occurrenceDate
.setDate(date
);
1642 #pragma message("port QT5")
1643 //QT5 qCDebug(KORGANIZER_LOG) << "create exception: " << occurrenceDate;
1644 KCalCore::Incidence::Ptr
newInc(KCalCore::Calendar::createException(
1645 incidence
, occurrenceDate
, thisAndFuture
));
1647 mChanger
->createIncidence(newInc
, item
.parentCollection(), this);
1649 if (thisAndFuture
) {
1652 i18n("Dissociating the future occurrences failed."),
1653 i18n("Dissociating Failed"));
1657 i18n("Dissociating the occurrence failed."),
1658 i18n("Dissociating Failed"));
1664 void CalendarView::schedule_publish(const Akonadi::Item
&item
)
1666 Akonadi::Item selectedItem
= item
;
1667 if (!item
.hasPayload
<KCalCore::Incidence::Ptr
>()) {
1668 selectedItem
= selectedIncidence();
1671 KCalCore::Incidence::Ptr incidence
= CalendarSupport::incidence(selectedItem
);
1673 mITIPHandler
->publishInformation(incidence
, this);
1677 void CalendarView::schedule_request(const Akonadi::Item
&incidence
)
1679 schedule(KCalCore::iTIPRequest
, incidence
);
1682 void CalendarView::schedule_refresh(const Akonadi::Item
&incidence
)
1684 schedule(KCalCore::iTIPRefresh
, incidence
);
1687 void CalendarView::schedule_cancel(const Akonadi::Item
&incidence
)
1689 schedule(KCalCore::iTIPCancel
, incidence
);
1692 void CalendarView::schedule_add(const Akonadi::Item
&incidence
)
1694 schedule(KCalCore::iTIPAdd
, incidence
);
1697 void CalendarView::schedule_reply(const Akonadi::Item
&incidence
)
1699 schedule(KCalCore::iTIPReply
, incidence
);
1702 void CalendarView::schedule_counter(const Akonadi::Item
&incidence
)
1704 schedule(KCalCore::iTIPCounter
, incidence
);
1707 void CalendarView::schedule_declinecounter(const Akonadi::Item
&incidence
)
1709 schedule(KCalCore::iTIPDeclineCounter
, incidence
);
1712 void CalendarView::schedule_forward(const Akonadi::Item
&item
)
1714 Akonadi::Item selectedItem
= item
;
1715 if (!item
.hasPayload
<KCalCore::Incidence::Ptr
>()) {
1716 selectedItem
= selectedIncidence();
1719 KCalCore::Incidence::Ptr incidence
= CalendarSupport::incidence(selectedItem
);
1722 mITIPHandler
->sendAsICalendar(incidence
, this);
1726 void CalendarView::mailFreeBusy(int daysToPublish
)
1728 Akonadi::FreeBusyManager::self()->mailFreeBusy(daysToPublish
, this);
1731 void CalendarView::uploadFreeBusy()
1733 Akonadi::FreeBusyManager::self()->publishFreeBusy(this);
1736 void CalendarView::schedule(KCalCore::iTIPMethod method
, const Akonadi::Item
&item
)
1738 Akonadi::Item selectedItem
= item
;
1739 if (!item
.hasPayload
<KCalCore::Incidence::Ptr
>()) {
1740 selectedItem
= selectedIncidence();
1743 KCalCore::Incidence::Ptr incidence
= CalendarSupport::incidence(selectedItem
);
1746 mITIPHandler
->sendiTIPMessage(method
, incidence
, this);
1750 void CalendarView::openAddressbook()
1752 KRun::runCommand(QLatin1String("kaddressbook"), topLevelWidget());
1755 bool CalendarView::isReadOnly() const
1760 void CalendarView::setReadOnly(bool readOnly
)
1762 if (mReadOnly
!= readOnly
) {
1763 mReadOnly
= readOnly
;
1764 emit
readOnlyChanged(mReadOnly
);
1768 void CalendarView::print()
1772 KOrg::BaseView
*currentView
= mViewManager
->currentView();
1774 CalendarSupport::CalPrinter::PrintType printType
= CalendarSupport::CalPrinter::Month
;
1776 KCalCore::Incidence::List selectedIncidences
;
1778 printType
= currentView
->printType();
1779 Akonadi::Item::List selectedViewIncidences
= currentView
->selectedIncidences();
1780 foreach (const Akonadi::Item
&item
, selectedViewIncidences
) {
1781 if (item
.hasPayload
<KCalCore::Incidence::Ptr
>()) {
1782 selectedIncidences
.append(item
.payload
<KCalCore::Incidence::Ptr
>());
1787 KCalCore::DateList tmpDateList
= mDateNavigator
->selectedDates();
1788 mCalPrinter
->print(printType
, tmpDateList
.first(), tmpDateList
.last(), selectedIncidences
);
1791 void CalendarView::printPreview()
1795 KOrg::BaseView
*currentView
= mViewManager
->currentView();
1797 CalendarSupport::CalPrinter::PrintType printType
= CalendarSupport::CalPrinter::Month
;
1799 KCalCore::Incidence::List selectedIncidences
;
1801 printType
= currentView
->printType();
1802 Akonadi::Item::List selectedViewIncidences
= currentView
->selectedIncidences();
1803 foreach (const Akonadi::Item
&item
, selectedViewIncidences
) {
1804 if (item
.hasPayload
<KCalCore::Incidence::Ptr
>()) {
1805 selectedIncidences
.append(item
.payload
<KCalCore::Incidence::Ptr
>());
1810 KCalCore::DateList tmpDateList
= mDateNavigator
->selectedDates();
1811 mCalPrinter
->print(printType
, tmpDateList
.first(), tmpDateList
.last(),
1812 selectedIncidences
, true);
1815 void CalendarView::exportWeb()
1817 KOrg::HTMLExportSettings
*settings
= new KOrg::HTMLExportSettings(QLatin1String("KOrganizer"));
1819 // Manually read in the config, because parameterized kconfigxt objects don't
1820 // seem to load the config theirselves
1822 ExportWebDialog
*dlg
= new ExportWebDialog(settings
, this);
1823 connect(dlg
, SIGNAL(exportHTML(KOrg::HTMLExportSettings
*)),
1824 this, SIGNAL(exportHTML(KOrg::HTMLExportSettings
*)));
1828 void CalendarView::exportICalendar()
1831 KFileDialog::getSaveFileName(QUrl(QLatin1String("icalout.ics")), i18n("*.ics|iCalendars"), this);
1832 if (!filename
.isEmpty()) {
1833 // Force correct extension
1834 if (filename
.right(4) != QLatin1String(".ics")) {
1835 filename
+= QLatin1String(".ics");
1838 if (QFile(filename
).exists()) {
1839 if (KMessageBox::No
== KMessageBox::warningYesNo(
1841 i18n("Do you want to overwrite %1?", filename
))) {
1845 KCalCore::ICalFormat
*format
= new KCalCore::ICalFormat
;
1847 KCalCore::FileStorage
storage(mCalendar
, filename
, format
);
1848 if (!storage
.save()) {
1850 if (format
->exception()) {
1851 errmess
= KCalUtils::Stringify::errorMessage(*format
->exception());
1853 errmess
= i18nc("save failure cause unknown", "Reason unknown");
1858 "Cannot write iCalendar file %1. %2",
1859 filename
, errmess
));
1864 void CalendarView::exportVCalendar()
1866 if (!mCalendar
->journals().isEmpty()) {
1867 int result
= KMessageBox::warningContinueCancel(
1869 i18n("The journal entries cannot be exported to a vCalendar file."),
1870 i18n("Data Loss Warning"),
1871 KGuiItem(i18n("Proceed")),
1872 KStandardGuiItem::cancel(),
1873 QLatin1String("dontaskVCalExport"),
1874 KMessageBox::Notify
);
1875 if (result
!= KMessageBox::Continue
) {
1880 QString filename
= KFileDialog::getSaveFileName(QUrl(QLatin1String("vcalout.vcs")),
1881 i18n("*.vcs|vCalendars"), this);
1882 if (!filename
.isEmpty()) {
1883 // Force correct extension
1884 if (filename
.right(4) != QLatin1String(".vcs")) {
1885 filename
+= QLatin1String(".vcs");
1887 if (QFile(filename
).exists()) {
1888 if (KMessageBox::No
== KMessageBox::warningYesNo(
1890 i18n("Do you want to overwrite %1?", filename
))) {
1894 KCalCore::VCalFormat
*format
= new KCalCore::VCalFormat
;
1896 KCalCore::FileStorage
storage(mCalendar
, filename
, format
);
1897 if (!storage
.save()) {
1899 if (format
->exception()) {
1900 errmess
= KCalUtils::Stringify::errorMessage(*format
->exception());
1902 errmess
= i18nc("save failure cause unknown", "Reason unknown");
1907 "Cannot write vCalendar file %1. %2",
1908 filename
, errmess
));
1913 void CalendarView::eventUpdated(const Akonadi::Item
&)
1915 // Don't call updateView here. The code, which has caused the update of the
1916 // event is responsible for updating the view.
1920 void CalendarView::adaptNavigationUnits()
1922 if (mViewManager
->currentView()->isEventView()) {
1923 int days
= mViewManager
->currentView()->currentDateCount();
1925 emit
changeNavStringPrev(i18n("&Previous Day"));
1926 emit
changeNavStringNext(i18n("&Next Day"));
1928 emit
changeNavStringPrev(i18n("&Previous Week"));
1929 emit
changeNavStringNext(i18n("&Next Week"));
1934 void CalendarView::processMainViewSelection(const Akonadi::Item
&item
, const QDate
&date
)
1936 if (CalendarSupport::hasIncidence(item
)) {
1937 mTodoList
->clearSelection();
1939 processIncidenceSelection(item
, date
);
1942 void CalendarView::processTodoListSelection(const Akonadi::Item
&item
, const QDate
&date
)
1944 if (CalendarSupport::hasIncidence(item
) && mViewManager
->currentView()) {
1945 mViewManager
->currentView()->clearSelection();
1947 processIncidenceSelection(item
, date
);
1950 void CalendarView::processIncidenceSelection(const Akonadi::Item
&item
, const QDate
&date
)
1952 KCalCore::Incidence::Ptr incidence
= CalendarSupport::incidence(item
);
1953 if (item
!= mSelectedIncidence
) {
1954 // This signal also must be emitted if incidence is 0
1955 emit
incidenceSelected(item
, date
);
1959 mSelectedIncidence
= item
;
1962 if (item
== mSelectedIncidence
) {
1963 if (!incidence
->recurs() || mSaveDate
== date
) {
1968 mSelectedIncidence
= item
;
1972 bool subtodo
= false;
1974 const bool organizerEvents
=
1975 CalendarSupport::KCalPrefs::instance()->thatIsMe(incidence
->organizer()->email());
1976 const bool groupEvents
= incidence
->attendeeByMails(CalendarSupport::KCalPrefs::instance()->allEmails());
1978 if (incidence
->type() == KCalCore::Incidence::TypeTodo
) {
1980 subtodo
= (incidence
->relatedTo() != QString());
1982 emit
todoSelected(todo
);
1983 emit
subtodoSelected(subtodo
);
1984 emit
organizerEventsSelected(organizerEvents
);
1985 emit
groupEventsSelected(groupEvents
);
1988 void CalendarView::checkClipboard()
1990 emit
pasteEnabled(mCalendarClipboard
->pasteAvailable());
1993 void CalendarView::showDates(const KCalCore::DateList
&selectedDates
, const QDate
&preferredMonth
)
1995 mDateNavigatorContainer
->selectDates(selectedDates
, preferredMonth
);
1996 mNavigatorBar
->selectDates(selectedDates
);
1998 if (mViewManager
->currentView()) {
1999 updateView(selectedDates
.first(), selectedDates
.last(), preferredMonth
, false);
2001 mViewManager
->showAgendaView();
2005 void CalendarView::editFilters()
2007 mDialogManager
->showFilterEditDialog(&mFilters
);
2010 void CalendarView::updateFilter()
2012 QStringList filters
;
2014 int pos
= mFilters
.indexOf(mCurrentFilter
);
2019 filters
<< i18n("No filter");
2020 foreach (KCalCore::CalFilter
*filter
, mFilters
) {
2022 filters
<< filter
->name();
2026 // account for the additional "No filter" at the beginning! if the
2027 // filter is not in the list, pos == -1...
2028 emit
filtersUpdated(filters
, pos
+ 1);
2030 mCalendar
->setFilter(mCurrentFilter
);
2033 void CalendarView::filterActivated(int filterNo
)
2035 KCalCore::CalFilter
*newFilter
= 0;
2036 if (filterNo
> 0 && filterNo
<= int(mFilters
.count())) {
2037 newFilter
= mFilters
.at(filterNo
- 1);
2039 if (newFilter
!= mCurrentFilter
) {
2040 mCurrentFilter
= newFilter
;
2041 mCalendar
->setFilter(mCurrentFilter
);
2042 mViewManager
->addChange(EventViews::EventView::FilterChanged
);
2045 emit
filterChanged();
2048 bool CalendarView::isFiltered() const
2050 return mCurrentFilter
!= 0;
2053 QString
CalendarView::currentFilterName() const
2055 if (mCurrentFilter
) {
2056 return mCurrentFilter
->name();
2058 return i18n("No filter");
2062 void CalendarView::takeOverEvent()
2064 const Akonadi::Item item
= currentSelection();
2065 KCalCore::Incidence::Ptr incidence
= CalendarSupport::incidence(item
);
2071 incidence
->setOrganizer(
2072 KCalCore::Person::Ptr(new KCalCore::Person(
2073 CalendarSupport::KCalPrefs::instance()->fullName(),
2074 CalendarSupport::KCalPrefs::instance()->email())));
2075 incidence
->recreate();
2076 incidence
->setReadOnly(false);
2078 //PENDING(AKONADI_PORT) call mChanger?
2083 void CalendarView::showIntro()
2085 qCDebug(KORGANIZER_LOG
) << "To be implemented.";
2088 void CalendarView::showDateNavigator(bool show
)
2091 mDateNavigatorContainer
->show();
2092 mDateNavigatorContainer
->updateView();
2094 mDateNavigatorContainer
->hide();
2098 void CalendarView::showTodoView(bool show
)
2102 mTodoList
->updateView();
2108 void CalendarView::showEventViewer(bool show
)
2111 mEventViewerBox
->show();
2113 mEventViewerBox
->hide();
2117 void CalendarView::addView(KOrg::BaseView
*view
)
2119 mViewManager
->addView(view
);
2122 void CalendarView::showView(KOrg::BaseView
*view
)
2124 mViewManager
->showView(view
);
2127 void CalendarView::addExtension(CalendarViewExtension::Factory
*factory
)
2129 CalendarViewExtension
*extension
= factory
->create(mLeftSplitter
);
2130 mExtensions
.append(extension
);
2131 if (!mETMCollectionView
) {
2132 mETMCollectionView
= qobject_cast
<AkonadiCollectionView
*>(extension
);
2136 void CalendarView::showLeftFrame(bool show
)
2139 mMainSplitterSizes
.clear();
2141 emit
calendarViewExpanded(false);
2143 // mPanner splitter sizes are useless if mLeftFrame is hidden, so remember them beforehand.
2144 if (mMainSplitterSizes
.isEmpty()) {
2145 mMainSplitterSizes
= mPanner
->sizes();
2149 emit
calendarViewExpanded(true);
2153 Akonadi::Item
CalendarView::selectedTodo()
2155 const Akonadi::Item item
= currentSelection();
2156 if (const KCalCore::Todo::Ptr t
= CalendarSupport::todo(item
)) {
2160 Akonadi::Item incidence
;
2162 const Akonadi::Item::List selectedIncidences
= mTodoList
->selectedIncidences();
2163 if (!selectedIncidences
.isEmpty()) {
2164 incidence
= selectedIncidences
.first();
2166 if (const KCalCore::Todo::Ptr t
= CalendarSupport::todo(item
)) {
2169 return Akonadi::Item();
2172 void CalendarView::dialogClosing(const Akonadi::Item
&)
2176 Akonadi::Item
CalendarView::currentSelection()
2178 return mViewManager
->currentSelection();
2181 Akonadi::Item
CalendarView::selectedIncidence()
2183 Akonadi::Item item
= currentSelection();
2184 if (!item
.isValid()) {
2185 Akonadi::Item::List selectedIncidences
= mTodoList
->selectedIncidences();
2186 if (!selectedIncidences
.isEmpty()) {
2187 item
= selectedIncidences
.first();
2193 void CalendarView::showIncidence()
2195 showIncidence(selectedIncidence());
2198 void CalendarView::editIncidence()
2200 editIncidence(selectedIncidence());
2203 bool CalendarView::editIncidence(Akonadi::Item::Id id
)
2205 Akonadi::Item item
= mCalendar
->item(id
);
2206 return editIncidence(item
);
2209 bool CalendarView::showIncidence(Akonadi::Item::Id id
)
2211 Akonadi::Item item
= mCalendar
->item(id
);
2212 if (!CalendarSupport::hasIncidence(item
)) {
2215 showIncidence(item
);
2219 bool CalendarView::showIncidenceContext(Akonadi::Item::Id id
)
2221 Akonadi::Item item
= mCalendar
->item(id
);
2222 if (!CalendarSupport::hasIncidence(item
)) {
2225 showIncidenceContext(item
);
2229 void CalendarView::deleteIncidence()
2231 deleteIncidence(selectedIncidence());
2234 void CalendarView::cutIncidence(const Akonadi::Item
&incidence
)
2236 Q_UNUSED(incidence
);
2240 void CalendarView::copyIncidence(const Akonadi::Item
&incidence
)
2242 Q_UNUSED(incidence
);
2246 void CalendarView::pasteIncidence()
2251 void CalendarView::showIncidence(const Akonadi::Item
&item
)
2253 KOEventViewerDialog
*eventViewer
= new KOEventViewerDialog(mCalendar
.data(), this);
2254 eventViewer
->setIncidence(item
, QDate());
2255 // Disable the Edit button for read-only Incidences.
2256 if (!mCalendar
->hasRight(item
, Akonadi::Collection::CanChangeItem
)) {
2257 eventViewer
->editButton()->setEnabled(false);
2260 eventViewer
->show();
2263 void CalendarView::showIncidenceContext(const Akonadi::Item
&item
)
2265 KCalCore::Incidence::Ptr incidence
= CalendarSupport::incidence(item
);
2266 if (CalendarSupport::hasEvent(item
)) {
2267 if (!viewManager()->currentView()->inherits("KOEventView")) {
2268 viewManager()->showAgendaView();
2270 // just select the appropriate date
2271 mDateNavigator
->selectWeek(
2272 incidence
->dtStart().toTimeSpec(
2273 CalendarSupport::KCalPrefs::instance()->timeSpec()).date());
2275 } else if (CalendarSupport::hasJournal(item
)) {
2276 if (!viewManager()->currentView()->inherits("KOJournalView")) {
2277 viewManager()->showJournalView();
2279 } else if (CalendarSupport::hasTodo(item
)) {
2280 if (!viewManager()->currentView()->inherits("KOTodoView")) {
2281 viewManager()->showTodoView();
2284 Akonadi::Item::List list
;
2286 viewManager()->currentView()->showIncidences(list
, QDate());
2289 bool CalendarView::editIncidence(const Akonadi::Item
&item
, bool isCounter
)
2291 Q_UNUSED(isCounter
);
2292 KCalCore::Incidence::Ptr incidence
= CalendarSupport::incidence(item
);
2294 qCritical() << "Null incidence";
2295 KNotification::beep();
2299 if (!mCalendar
->hasRight(item
, Akonadi::Collection::CanChangeItem
)) {
2300 showIncidence(item
);
2304 IncidenceEditorNG::IncidenceDialog
*dialog
= incidenceDialog(item
);
2306 // connectIncidenceEditor( dialog ); // TODO: This as well
2307 dialog
->load(item
, activeIncidenceDate()); // Show the dialog as soon as it loads the item.
2312 void CalendarView::deleteSubTodosIncidence(const Akonadi::Item
&todoItem
)
2314 const KCalCore::Todo::Ptr todo
= CalendarSupport::todo(todoItem
);
2318 Akonadi::Item::List subTodos
= mCalendar
->childItems(todoItem
.id());
2319 foreach (const Akonadi::Item
&item
, subTodos
) {
2320 if (CalendarSupport::hasTodo(item
)) {
2321 deleteSubTodosIncidence(item
);
2325 if (!mChanger
->deletedRecently(todoItem
.id())) {
2326 mChanger
->deleteIncidence(todoItem
, this);
2330 void CalendarView::deleteTodoIncidence(const Akonadi::Item
&todoItem
, bool force
)
2332 const KCalCore::Todo::Ptr todo
= CalendarSupport::todo(todoItem
);
2337 // it a simple todo, ask and delete it.
2338 if (mCalendar
->childItems(todoItem
.id()).isEmpty()) {
2339 bool doDelete
= true;
2340 if (!force
&& KOPrefs::instance()->mConfirm
) {
2341 doDelete
= (msgItemDelete(todoItem
) == KMessageBox::Continue
);
2343 if (doDelete
&& !mChanger
->deletedRecently(todoItem
.id())) {
2344 mChanger
->deleteIncidence(todoItem
, this);
2349 /* Ok, this to-do has sub-to-dos, ask what to do */
2350 int km
= KMessageBox::No
;
2352 km
= KMessageBox::questionYesNoCancel(
2354 i18n("The item \"%1\" has sub-to-dos. "
2355 "Do you want to delete just this item and "
2356 "make all its sub-to-dos independent, or "
2357 "delete the to-do with all its sub-to-dos?",
2359 i18n("KOrganizer Confirmation"),
2360 KGuiItem(i18n("Delete Only This")),
2361 KGuiItem(i18n("Delete All")));
2363 // Delete only the father
2364 if (km
== KMessageBox::Yes
) {
2365 startMultiModify(i18n("Delete parent to-do"));
2366 makeChildrenIndependent(todoItem
);
2367 if (!mChanger
->deletedRecently(todoItem
.id())) {
2368 mChanger
->deleteIncidence(todoItem
, this);
2370 } else if (km
== KMessageBox::No
) {
2371 startMultiModify(i18n("Delete parent to-do and sub-to-dos"));
2373 // we have to hide the delete confirmation for each itemDate
2374 deleteSubTodosIncidence(todoItem
);
2379 bool CalendarView::deleteIncidence(const Akonadi::Item
&item
, bool force
)
2381 KCalCore::Incidence::Ptr incidence
= CalendarSupport::incidence(item
);
2384 qCritical() << "Null incidence";
2385 KNotification::beep();
2387 qCritical() << "CalendarView::deleteIncidence(): Unable do delete, incidence is null.";
2391 if (mChanger
->deletedRecently(item
.id())) {
2392 // it was deleted already but the etm wasn't notified yet
2393 qCWarning(KORGANIZER_LOG
) << "CalendarView::deleteIncidence(): item with id" << item
.id()
2394 << "was deleted recently, skipping";
2398 if (!mCalendar
->hasRight(item
, Akonadi::Collection::CanDeleteItem
)) {
2400 KMessageBox::information(
2402 i18n("The item \"%1\" is marked read-only "
2403 "and cannot be deleted; it probably "
2404 "belongs to a read-only calendar.",
2405 incidence
->summary()),
2406 i18n("Removing not possible"),
2407 QLatin1String("deleteReadOnlyIncidence"));
2409 qCWarning(KORGANIZER_LOG
) << "CalendarView::deleteIncidence(): No rights to delete item";
2413 //If it is a todo, there are specific delete function
2415 if (incidence
&& incidence
->type() == KCalCore::Incidence::TypeTodo
) {
2416 deleteTodoIncidence(item
, force
);
2420 if (incidence
->recurs()) {
2421 QDate itemDate
= mViewManager
->currentSelectionDate();
2422 int km
= KMessageBox::Ok
;
2424 if (!itemDate
.isValid()) {
2425 qCDebug(KORGANIZER_LOG
) << "Date Not Valid";
2426 km
= KMessageBox::warningContinueCancel(
2428 i18n("The calendar item \"%1\" recurs over multiple dates; "
2429 "are you sure you want to delete it "
2430 "and all its recurrences?", incidence
->summary()),
2431 i18n("KOrganizer Confirmation"),
2432 KGuiItem(i18n("Delete All")));
2434 KDateTime
itemDateTime(itemDate
, CalendarSupport::KCalPrefs::instance()->timeSpec());
2435 bool isFirst
= !incidence
->recurrence()->getPreviousDateTime(itemDateTime
).isValid();
2436 bool isLast
= !incidence
->recurrence()->getNextDateTime(itemDateTime
).isValid();
2439 QString
itemFuture(i18n("Also Delete &Future")); //QT5 was a KGuiItem
2441 if (!isFirst
&& !isLast
) {
2442 #pragma message("port QT5")
2443 //QT5 itemFuture.setEnabled( true );
2444 message
= i18n("The calendar item \"%1\" recurs over multiple dates. "
2445 "Do you want to delete only the current one on %2, also "
2446 "future occurrences, or all its occurrences?",
2447 incidence
->summary(),
2448 KLocale::global()->formatDate(itemDate
));
2450 #pragma message("port QT5")
2451 //QT5 itemFuture.setEnabled( false );
2452 message
= i18n("The calendar item \"%1\" recurs over multiple dates. "
2453 "Do you want to delete only the current one on %2 "
2454 "or all its occurrences?",
2455 incidence
->summary(),
2456 KLocale::global()->formatDate(itemDate
));
2459 if (!(isFirst
&& isLast
)) {
2460 QDialogButtonBox::StandardButton returnValue
= PIMMessageBox::fourBtnMsgBox(
2462 QMessageBox::Warning
,
2464 i18n("KOrganizer Confirmation"),
2465 i18n("Delete C&urrent"),
2467 i18n("Delete &All"));
2468 switch (returnValue
) {
2469 case QDialogButtonBox::Ok
:
2470 km
= KMessageBox::Ok
;
2472 case QDialogButtonBox::Yes
:
2473 km
= KMessageBox::Yes
;
2475 case QDialogButtonBox::No
:
2476 km
= KMessageBox::No
;
2478 case QDialogButtonBox::Cancel
:
2480 km
= KMessageBox::Cancel
;
2484 km
= msgItemDelete(item
);
2488 KCalCore::Incidence::Ptr
oldIncidence(incidence
->clone());
2490 case KMessageBox::Ok
: // Continue // all
2491 case KMessageBox::Continue
:
2492 mChanger
->deleteIncidence(item
, this);
2495 case KMessageBox::Yes
: // just this one
2496 incidence
->recurrence()->addExDate(itemDate
);
2497 mChanger
->modifyIncidence(item
, oldIncidence
, this);
2500 case KMessageBox::No
: // all future items
2501 KCalCore::Recurrence
*recur
= incidence
->recurrence();
2502 recur
->setEndDate(itemDate
.addDays(-1));
2503 mChanger
->modifyIncidence(item
, oldIncidence
, this);
2507 bool doDelete
= true;
2508 if (!force
&& KOPrefs::instance()->mConfirm
) {
2509 doDelete
= (msgItemDelete(item
) == KMessageBox::Continue
);
2512 mChanger
->deleteIncidence(item
, this);
2513 processIncidenceSelection(Akonadi::Item(), QDate());
2519 void CalendarView::purgeCompleted()
2521 if (checkedCollections().isEmpty()) {
2522 showMessage(i18n("All calendars are unchecked in the Calendar Manager. No to-do was purged."), KMessageWidget::Warning
);
2526 if (mCalendar
->rawTodos().isEmpty()) {
2527 showMessage(i18n("There are no completed to-dos to purge."), KMessageWidget::Information
);
2531 int result
= KMessageBox::warningContinueCancel(
2533 i18n("Delete all completed to-dos from checked calendars?"),
2534 i18n("Purge To-dos"),
2535 KGuiItem(i18n("Purge")));
2537 if (result
== KMessageBox::Continue
) {
2538 mTodoPurger
->purgeCompletedTodos();
2542 void CalendarView::warningChangeFailed(const Akonadi::Item
&item
)
2544 KCalCore::Incidence::Ptr incidence
= CalendarSupport::incidence(item
);
2549 "Unable to edit \"%1\" because it is locked by another process.",
2550 incidence
->summary()));
2554 void CalendarView::showErrorMessage(const QString
&msg
)
2556 KMessageBox::error(this, msg
);
2559 void CalendarView::addIncidenceOn(const Akonadi::Item
&itemadd
, const QDate
&dt
)
2561 if (!CalendarSupport::hasIncidence(itemadd
)) {
2564 i18n("Unable to copy the item to %1.", dt
.toString()),
2565 i18n("Copying Failed"));
2568 Akonadi::Item item
= mCalendar
->item(itemadd
.id());
2569 if (!item
.isValid()) {
2572 // Create a copy of the incidence, since the incadd doesn't belong to us.
2573 KCalCore::Incidence::Ptr
incidence(CalendarSupport::incidence(item
)->clone());
2574 incidence
->recreate();
2576 if (const KCalCore::Event::Ptr event
= incidence
.dynamicCast
<KCalCore::Event
>()) {
2579 KDateTime start
= event
->dtStart();
2580 KDateTime end
= event
->dtEnd();
2582 int duration
= start
.daysTo(end
);
2584 end
.setDate(dt
.addDays(duration
));
2586 event
->setDtStart(start
);
2587 event
->setDtEnd(end
);
2589 } else if (const KCalCore::Todo::Ptr todo
= incidence
.dynamicCast
<KCalCore::Todo
>()) {
2590 KDateTime due
= todo
->dtDue();
2593 todo
->setDtDue(due
);
2596 mChanger
->createIncidence(incidence
, Akonadi::Collection(), this);
2599 void CalendarView::moveIncidenceTo(const Akonadi::Item
&itemmove
, const QDate
&dt
)
2601 if (!CalendarSupport::hasIncidence(itemmove
)) {
2604 i18n("Unable to move the item to %1.", dt
.toString()),
2605 i18n("Moving Failed"));
2608 Akonadi::Item item
= mCalendar
->item(itemmove
.id());
2609 if (!item
.isValid()) {
2610 addIncidenceOn(itemmove
, dt
);
2613 KCalCore::Incidence::Ptr incidence
= CalendarSupport::incidence(itemmove
);
2615 KCalCore::Incidence::Ptr
oldIncidence(incidence
->clone());
2617 if (const KCalCore::Event::Ptr event
= incidence
.dynamicCast
<KCalCore::Event
>()) {
2619 KDateTime start
= event
->dtStart();
2620 KDateTime end
= event
->dtEnd();
2622 int duration
= start
.daysTo(end
);
2624 end
.setDate(dt
.addDays(duration
));
2626 event
->setDtStart(start
);
2627 event
->setDtEnd(end
);
2629 } if (const KCalCore::Todo::Ptr todo
= incidence
.dynamicCast
<KCalCore::Todo
>()) {
2630 KDateTime due
= todo
->dtDue();
2633 todo
->setDtDue(due
);
2635 mChanger
->modifyIncidence(itemmove
, oldIncidence
, this);
2638 void CalendarView::resourcesChanged()
2640 mViewManager
->addChange(EventViews::EventView::ResourcesChanged
);
2644 bool CalendarView::eventFilter(QObject
*watched
, QEvent
*event
)
2646 if (watched
== mLeftFrame
&& event
->type() == QEvent::Show
) {
2647 mSplitterSizesValid
= true;
2649 return KOrg::CalendarViewBase::eventFilter(watched
, event
);
2652 void CalendarView::updateHighlightModes()
2655 KOrg::BaseView
*view
= mViewManager
->currentView();
2661 view
->getHighlightMode(hiEvents
, hiTodos
, hiJournals
);
2662 mDateNavigatorContainer
->setHighlightMode(hiEvents
,
2668 void CalendarView::selectWeek(const QDate
&date
, const QDate
&preferredMonth
)
2670 if (KOPrefs::instance()->mWeekNumbersShowWork
&&
2671 mViewManager
->rangeMode() == KOViewManager::WORK_WEEK_RANGE
) {
2672 mDateNavigator
->selectWorkWeek(date
);
2674 mDateNavigator
->selectWeek(date
, preferredMonth
);
2678 void CalendarView::changeFullView(bool fullView
)
2680 if (mViewManager
->currentView()) {
2681 if (mViewManager
->currentView()->identifier() == "DefaultTodoView") {
2682 showLeftFrame(!fullView
);
2683 } else if (mViewManager
->currentView()->identifier() == "DefaultMonthView") {
2684 showLeftFrame(!fullView
);
2685 fullView
? mNavigatorBar
->show() : mNavigatorBar
->hide();
2690 Akonadi::Collection
CalendarView::defaultCollection(const QLatin1String
&mimeType
) const
2692 // 1. Try the view collection ( used in multi-agenda view )
2693 Akonadi::Collection collection
= mCalendar
->collection(mViewManager
->currentView()->collectionId());
2694 bool supportsMimeType
= collection
.contentMimeTypes().contains(mimeType
) || mimeType
== QLatin1String("");
2695 bool hasRights
= collection
.rights() & Akonadi::Collection::CanCreateItem
;
2696 if (collection
.isValid() && supportsMimeType
&& hasRights
) {
2700 // 2. Try the configured default collection
2701 collection
= mCalendar
->collection(CalendarSupport::KCalPrefs::instance()->defaultCalendarId());
2702 supportsMimeType
= collection
.contentMimeTypes().contains(mimeType
) || mimeType
== QLatin1String("");
2703 hasRights
= collection
.rights() & Akonadi::Collection::CanCreateItem
;
2704 if (collection
.isValid() && supportsMimeType
&& hasRights
) {
2708 // 3. Try last selected folder
2709 collection
= mCalendar
->collection(IncidenceEditorNG::GlobalSettings::self()->lastSelectedFolder());
2710 supportsMimeType
= collection
.contentMimeTypes().contains(mimeType
) || mimeType
== QLatin1String("");
2711 hasRights
= collection
.rights() & Akonadi::Collection::CanCreateItem
;
2712 if (collection
.isValid() && supportsMimeType
&& hasRights
) {
2716 // 4. Try the selected collection
2717 collection
= selectedCollection();
2718 supportsMimeType
= collection
.contentMimeTypes().contains(mimeType
) || mimeType
== QLatin1String("");
2719 hasRights
= collection
.rights() & Akonadi::Collection::CanCreateItem
;
2720 if (collection
.isValid() && supportsMimeType
&& hasRights
) {
2724 // 5. Try the checked collections
2725 Akonadi::Collection::List collections
= checkedCollections();
2726 foreach (const Akonadi::Collection
&checkedCollection
, collections
) {
2727 supportsMimeType
= checkedCollection
.contentMimeTypes().contains(mimeType
) || mimeType
== QLatin1String("");
2728 hasRights
= checkedCollection
.rights() & Akonadi::Collection::CanCreateItem
;
2729 if (checkedCollection
.isValid() && supportsMimeType
&& hasRights
) {
2730 return checkedCollection
;
2734 // 5. Return a invalid collection, the editor will use the first one in the combo
2735 return Akonadi::Collection();
2738 IncidenceEditorNG::IncidenceDialog
*CalendarView::createIncidenceEditor(
2739 const Akonadi::Item
&item
, const Akonadi::Collection
&collection
)
2741 IncidenceEditorNG::IncidenceDialog
*dialog
= incidenceDialog(item
);
2742 KCalCore::Incidence::Ptr incidence
= CalendarSupport::incidence(item
);
2743 Q_ASSERT(incidence
);
2745 if (collection
.isValid()) {
2746 dialog
->selectCollection(collection
);
2748 dialog
->selectCollection(defaultCollection(incidence
->mimeType()));
2754 Akonadi::History
*CalendarView::history() const
2756 return mChanger
->history();
2759 void CalendarView::onCutFinished()
2764 void CalendarView::setCheckableProxyModel(KOCheckableProxyModel
*model
)
2766 if (mCheckableProxyModel
) {
2767 mCheckableProxyModel
->disconnect(this);
2770 mCheckableProxyModel
= model
;
2771 connect(model
, SIGNAL(aboutToToggle(bool)), SLOT(onCheckableProxyAboutToToggle(bool)));
2772 connect(model
, SIGNAL(toggled(bool)), SLOT(onCheckableProxyToggled(bool)));
2775 void CalendarView::onCheckableProxyAboutToToggle(bool newState
)
2777 // Someone unchecked a collection, save the view state now.
2779 mTodoList
->saveViewState();
2780 KOTodoView
*todoView
= mViewManager
->todoView();
2782 todoView
->saveViewState();
2787 void CalendarView::onCheckableProxyToggled(bool newState
)
2789 // Someone checked a collection, restore the view state now.
2791 mTodoList
->restoreViewState();
2792 KOTodoView
*todoView
= mViewManager
->todoView();
2794 todoView
->restoreViewState();
2799 void CalendarView::onTodosPurged(bool success
, int numDeleted
, int numIgnored
)
2802 KMessageWidget::MessageType type
= KMessageWidget::Information
;
2804 if (numDeleted
== 0 && numIgnored
> 0) {
2805 type
= KMessageWidget::Warning
;
2806 message
= i18n("0 completed to-dos were purged.") + QLatin1Char('\n') +
2807 i18np("%1 to-do was ignored because it has uncompleted or read-only children.",
2808 "%1 to-dos were ignored because they have uncompleted or read-only children.", numIgnored
);
2809 } else if (numDeleted
> 0 && numIgnored
== 0) {
2810 message
= i18np("%1 completed to-do was purged.", "%1 completed to-dos were purged.", numDeleted
);
2811 } else if (numDeleted
== 0 && numIgnored
== 0) {
2812 message
= i18n("There are no completed to-dos to purge.");
2814 type
= KMessageWidget::Warning
;
2815 message
= i18np("%1 completed to-do was purged.", "%1 completed to-dos were purged.", numDeleted
) + QLatin1Char('\n') +
2816 i18np("%1 to-do was ignored because it has uncompleted or read-only children.",
2817 "%1 to-dos were ignored because they have uncompleted or read-only children.", numIgnored
);
2820 message
= i18n("An error occurred while purging completed to-dos: %1", mTodoPurger
->lastError());
2821 type
= KMessageWidget::Error
;
2824 showMessage(message
, type
);
2827 void CalendarView::showMessage(const QString
&message
, KMessageWidget::MessageType type
)
2829 mMessageWidget
->setText(message
);
2830 mMessageWidget
->setMessageType(type
);
2831 mMessageWidget
->show();
2834 Akonadi::Collection
CalendarView::selectedCollection() const
2836 return mETMCollectionView
? mETMCollectionView
->selectedCollection() : Akonadi::Collection();
2839 Akonadi::Collection::List
CalendarView::checkedCollections() const
2841 Akonadi::Collection::List collections
;
2842 if (mETMCollectionView
) {
2843 collections
= mETMCollectionView
->checkedCollections();
2846 // If the default calendar is here, it should be first.
2847 int count
= collections
.count();
2848 Akonadi::Collection::Id id
= CalendarSupport::KCalPrefs::instance()->defaultCalendarId();
2849 for (int i
= 0; i
< count
; ++i
) {
2850 if (id
== collections
[i
].id()) {
2851 collections
.move(i
, 0);
2859 void CalendarView::handleIncidenceCreated(const Akonadi::Item
&item
)
2861 Akonadi::Collection collection
= item
.parentCollection();
2862 if (!collection
.isValid()) {
2863 qCWarning(KORGANIZER_LOG
) << "Item was creating in an invalid collection !? item id=" << item
.id();
2867 const bool collectionIsChecked
= mETMCollectionView
->isChecked(collection
);
2869 if (!collectionIsChecked
) {
2871 if (mETMCollectionView
->isVisible()) {
2872 message
= i18n("You created an incidence in a calendar that is currently filtered out.\n"
2873 "On the left sidebar, enable it in the calendar manager to see the incidence.");
2875 message
= i18n("You created an incidence in a calendar that is currently filtered out.\n"
2876 "You can enable it through the calendar manager (Settings->Sidebar->Show Calendar Manager)");
2879 mMessageWidget
->setText(message
);
2880 mMessageWidget
->setMessageType(KMessageWidget::Information
);
2881 mMessageWidget
->show();