Better wording
[kdepim.git] / incidenceeditor-ng / eventortododialog.cpp
blob782a01c911dc0a627928190d67485990026df21a
1 /*
2 Copyright (c) 2010 Bertjan Broeksema <broeksema@kde.org>
3 Copyright (c) 2010 Klarälvdalens Datakonsult AB, a KDAB Group company <info@kdab.com>
5 This library is free software; you can redistribute it and/or modify it
6 under the terms of the GNU Library General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or (at your
8 option) any later version.
10 This library is distributed in the hope that it will be useful, but WITHOUT
11 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
13 License for more details.
15 You should have received a copy of the GNU Library General Public License
16 along with this library; see the file COPYING.LIB. If not, write to the
17 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
18 02110-1301, USA.
21 #include "eventortododialog.h"
22 #include "combinedincidenceeditor.h"
23 #include "editorconfig.h"
24 #include "incidencealarm.h"
25 #include "incidenceattachment.h"
26 #include "incidenceattendee.h"
27 #include "incidencecategories.h"
28 #include "incidencecompletionpriority.h"
29 #include "incidencedatetime.h"
30 #include "incidencedescription.h"
31 #include "incidencerecurrence.h"
32 #include "incidencesecrecy.h"
33 #include "incidencewhatwhere.h"
34 #include "invitationdispatcher.h"
35 #include "templatemanagementdialog.h"
36 #include "ui_eventortododesktop.h"
38 #include <calendarsupport/kcalprefs.h>
39 #include <calendarsupport/utils.h>
41 #include <Akonadi/CollectionComboBox>
42 #include <Akonadi/Item>
44 #include <KCalCore/ICalFormat>
45 #include <KCalCore/MemoryCalendar>
46 #include <KCalUtils/Stringify>
48 #include <KMessageBox>
49 #include <KStandardDirs>
50 #include <KSystemTimeZones>
52 using namespace IncidenceEditorNG;
54 namespace IncidenceEditorNG {
56 enum Tabs {
57 GeneralTab = 0,
58 AttendeesTab,
59 AlarmsTab,
60 RecurrenceTab,
61 AttachmentsTab
64 class EventOrTodoDialogPrivate : public ItemEditorUi
66 EventOrTodoDialog *q_ptr;
67 Q_DECLARE_PUBLIC( EventOrTodoDialog )
69 public:
70 Ui::EventOrTodoDesktop *mUi;
71 Akonadi::CollectionComboBox *mCalSelector;
72 bool mCloseOnSave;
74 EditorItemManager *mItemManager;
75 InvitationDispatcher *mInvitationDispatcher;
77 CombinedIncidenceEditor *mEditor;
78 IncidenceDateTime *mIeDateTime;
79 IncidenceAttendee *mIeAttendee;
80 IncidenceRecurrence *mIeRecurrence;
81 bool mInitiallyDirty;
82 Akonadi::Item mItem;
83 QString typeToString( const int type ) const;
85 public:
86 EventOrTodoDialogPrivate( EventOrTodoDialog *qq );
87 ~EventOrTodoDialogPrivate();
89 /// General methods
90 void handleAlarmCountChange( int newCount );
91 void handleRecurrenceChange( IncidenceEditorNG::RecurrenceType type );
92 void loadTemplate( const QString &templateName );
93 void manageTemplates();
94 void saveTemplate( const QString &templateName );
95 void storeTemplatesInConfig( const QStringList &newTemplates );
96 void updateAttachmentCount( int newCount );
97 void updateAttendeeCount( int newCount );
98 void updateButtonStatus( bool isDirty );
100 /// ItemEditorUi methods
101 virtual bool containsPayloadIdentifiers( const QSet<QByteArray> &partIdentifiers ) const;
102 void handleItemSaveFinish( EditorItemManager::SaveAction );
103 void handleItemSaveFail( EditorItemManager::SaveAction, const QString &errorMessage );
104 virtual bool hasSupportedPayload( const Akonadi::Item &item ) const;
105 virtual bool isDirty() const;
106 virtual bool isValid() const;
107 virtual void load( const Akonadi::Item &item );
108 virtual Akonadi::Item save( const Akonadi::Item &item );
109 virtual Akonadi::Collection selectedCollection() const;
110 void slotButtonClicked( int button );
112 virtual void reject( RejectReason reason, const QString &errorMessage = QString() );
117 EventOrTodoDialogPrivate::EventOrTodoDialogPrivate( EventOrTodoDialog *qq )
118 : q_ptr( qq ),
119 mUi( new Ui::EventOrTodoDesktop ),
120 mCalSelector( new Akonadi::CollectionComboBox ),
121 mCloseOnSave( false ),
122 mItemManager( new EditorItemManager( this ) ),
123 mInvitationDispatcher( 0 ),
124 mEditor( new CombinedIncidenceEditor ),
125 mInitiallyDirty( false )
127 Q_Q( EventOrTodoDialog );
128 mUi->setupUi( q->mainWidget() );
129 QGridLayout *layout = new QGridLayout( mUi->mCalSelectorPlaceHolder );
130 layout->setSpacing( 0 );
131 layout->addWidget( mCalSelector );
133 mCalSelector->setAccessRightsFilter( Akonadi::Collection::CanCreateItem );
135 q->connect( mCalSelector, SIGNAL(currentChanged(Akonadi::Collection)),
136 SLOT(handleSelectedCollectionChange(Akonadi::Collection)) );
138 if ( CalendarSupport::KCalPrefs::instance()->useGroupwareCommunication() ) {
139 mInvitationDispatcher = new InvitationDispatcher( 0, q );
140 mInvitationDispatcher->setItemManager( mItemManager );
143 // Now instantiate the logic of the dialog. These editors update the ui, validate
144 // fields and load/store incidences in the ui.
145 IncidenceWhatWhere *ieGeneral = new IncidenceWhatWhere( mUi );
146 mEditor->combine( ieGeneral );
148 IncidenceCategories *ieCategories = new IncidenceCategories( mUi );
149 mEditor->combine( ieCategories );
151 mIeDateTime = new IncidenceDateTime( mUi );
152 mEditor->combine( mIeDateTime );
154 IncidenceCompletionPriority *ieCompletionPriority = new IncidenceCompletionPriority( mUi );
155 mEditor->combine( ieCompletionPriority );
157 IncidenceDescription *ieDescription = new IncidenceDescription( mUi );
158 mEditor->combine( ieDescription );
160 IncidenceAlarm *ieAlarm = new IncidenceAlarm( mIeDateTime, mUi );
161 mEditor->combine( ieAlarm );
163 IncidenceAttachment *ieAttachments = new IncidenceAttachment( mUi );
164 mEditor->combine( ieAttachments );
166 mIeRecurrence = new IncidenceRecurrence( mIeDateTime, mUi );
167 mEditor->combine( mIeRecurrence );
169 IncidenceSecrecy *ieSecrecy = new IncidenceSecrecy( mUi );
170 mEditor->combine( ieSecrecy );
172 mIeAttendee = new IncidenceAttendee( qq, mIeDateTime, mUi );
173 mEditor->combine( mIeAttendee );
175 q->connect( mEditor, SIGNAL(dirtyStatusChanged(bool)),
176 SLOT(updateButtonStatus(bool)) );
177 q->connect( mItemManager,
178 SIGNAL(itemSaveFinished(IncidenceEditorNG::EditorItemManager::SaveAction)),
179 SLOT(handleItemSaveFinish(IncidenceEditorNG::EditorItemManager::SaveAction)));
180 q->connect( mItemManager,
181 SIGNAL(itemSaveFailed(IncidenceEditorNG::EditorItemManager::SaveAction,QString)),
182 SLOT(handleItemSaveFail(IncidenceEditorNG::EditorItemManager::SaveAction,QString)));
183 q->connect( ieAlarm, SIGNAL(alarmCountChanged(int)),
184 SLOT(handleAlarmCountChange(int)) );
185 q->connect( mIeRecurrence, SIGNAL(recurrenceChanged(IncidenceEditorNG::RecurrenceType)),
186 SLOT(handleRecurrenceChange(IncidenceEditorNG::RecurrenceType)) );
187 q->connect( ieAttachments, SIGNAL(attachmentCountChanged(int)),
188 SLOT(updateAttachmentCount(int)) );
189 q->connect( mIeAttendee, SIGNAL(attendeeCountChanged(int)),
190 SLOT(updateAttendeeCount(int)) );
193 EventOrTodoDialogPrivate::~EventOrTodoDialogPrivate()
195 delete mItemManager;
196 delete mEditor;
197 delete mUi;
200 void EventOrTodoDialogPrivate::handleAlarmCountChange( int newCount )
202 QString tabText;
203 if ( newCount > 0 ) {
204 tabText =
205 i18nc( "@title:tab Tab to configure the reminders of an event or todo",
206 "Reminder (%1)", newCount );
207 } else {
208 tabText =
209 i18nc( "@title:tab Tab to configure the reminders of an event or todo",
210 "Reminder" );
213 mUi->mTabWidget->setTabText( AlarmsTab, tabText );
216 void EventOrTodoDialogPrivate::handleRecurrenceChange( IncidenceEditorNG::RecurrenceType type )
218 QString tabText =
219 i18nc( "@title:tab Tab to configure the recurrence of an event or todo",
220 "Rec&urrence" );
222 // Keep this numbers in sync with the items in mUi->mRecurrenceTypeCombo. I
223 // tried adding an enum to IncidenceRecurrence but for whatever reason I could
224 // Qt not play nice with namespaced enums in signal/slot connections.
225 // Anyways, I don't expect these values to change.
226 switch ( type ) {
227 case RecurrenceTypeNone:
228 break;
229 case RecurrenceTypeDaily:
230 tabText += i18nc( "@title:tab Daily recurring event, capital first letter only", " (D)" );
231 break;
232 case RecurrenceTypeWeekly:
233 tabText += i18nc( "@title:tab Weekly recurring event, capital first letter only", " (W)" );
234 break;
235 case RecurrenceTypeMonthly:
236 tabText += i18nc( "@title:tab Monthly recurring event, capital first letter only", " (M)" );
237 break;
238 case RecurrenceTypeYearly:
239 tabText += i18nc( "@title:tab Yearly recurring event, capital first letter only", " (Y)" );
240 break;
241 default:
242 Q_ASSERT_X( false, "handleRecurrenceChange", "Fix your program" );
245 mUi->mTabWidget->setTabText( RecurrenceTab, tabText );
248 QString EventOrTodoDialogPrivate::typeToString( const int type ) const
250 // Do not translate.
251 switch( type ) {
252 case KCalCore::Incidence::TypeEvent:
253 return "Event";
254 case KCalCore::Incidence::TypeTodo:
255 return "Todo";
256 case KCalCore::Incidence::TypeJournal:
257 return "Journal";
258 default:
259 return "Unknown";
263 void EventOrTodoDialogPrivate::loadTemplate( const QString &templateName )
265 Q_Q( EventOrTodoDialog );
267 KCalCore::MemoryCalendar::Ptr cal( new KCalCore::MemoryCalendar( KSystemTimeZones::local() ) );
269 const QString fileName = KStandardDirs::locateLocal(
270 "data",
271 "korganizer/templates/" +
272 typeToString( mEditor->type() ) + '/' +
273 templateName );
275 if ( fileName.isEmpty() ) {
276 KMessageBox::error(
278 i18nc( "@info", "Unable to find template '%1'.", fileName ) );
279 return;
282 KCalCore::ICalFormat format;
283 if ( !format.load( cal, fileName ) ) {
284 KMessageBox::error(
286 i18nc( "@info", "Error loading template file '%1'.", fileName ) );
287 return;
290 KCalCore::Incidence::List incidences = cal->incidences();
291 if ( incidences.isEmpty() ) {
292 KMessageBox::error(
294 i18nc( "@info", "Template does not contain a valid incidence." ) );
295 return;
298 mIeDateTime->setActiveDate( QDate() );
299 KCalCore::Incidence::Ptr newInc = KCalCore::Incidence::Ptr( incidences.first()->clone() );
300 newInc->setUid( KCalCore::CalFormat::createUniqueId() );
301 mEditor->load( newInc );
304 void EventOrTodoDialogPrivate::manageTemplates()
306 Q_Q( EventOrTodoDialog );
308 QStringList &templates =
309 IncidenceEditorNG::EditorConfig::instance()->templates( mEditor->type() );
311 QPointer<IncidenceEditorNG::TemplateManagementDialog> dialog(
312 new IncidenceEditorNG::TemplateManagementDialog(
313 q, templates, KCalUtils::Stringify::incidenceType( mEditor->type() ) ) );
315 q->connect( dialog, SIGNAL(loadTemplate(QString)),
316 SLOT(loadTemplate(QString)) );
317 q->connect( dialog, SIGNAL(templatesChanged(QStringList)),
318 SLOT(storeTemplatesInConfig(QStringList)) );
319 q->connect( dialog, SIGNAL(saveTemplate(QString)),
320 SLOT(saveTemplate(QString)) );
321 dialog->exec();
322 delete dialog;
325 void EventOrTodoDialogPrivate::saveTemplate( const QString &templateName )
327 Q_ASSERT( ! templateName.isEmpty() );
329 KCalCore::MemoryCalendar::Ptr cal( new KCalCore::MemoryCalendar( KSystemTimeZones::local() ) );
331 switch( mEditor->type() ) {
332 case KCalCore::Incidence::TypeEvent:
334 KCalCore::Event::Ptr event( new KCalCore::Event() );
335 mEditor->save( event );
336 cal->addEvent( KCalCore::Event::Ptr( event->clone() ) );
337 break;
339 case KCalCore::Incidence::TypeTodo:
341 KCalCore::Todo::Ptr todo( new KCalCore::Todo );
342 mEditor->save( todo );
343 cal->addTodo( KCalCore::Todo::Ptr( todo->clone() ) );
344 break;
346 case KCalCore::Incidence::TypeJournal:
348 KCalCore::Journal::Ptr journal( new KCalCore::Journal );
349 mEditor->save( journal );
350 cal->addJournal( KCalCore::Journal::Ptr( journal->clone() ) );
351 break;
353 default:
354 Q_ASSERT_X( false, "saveTemplate", "Fix your program" );
357 const QString fileName = KStandardDirs::locateLocal(
358 "data",
359 "korganizer/templates/" +
360 typeToString( mEditor->type() ) + '/' +
361 templateName );
363 KCalCore::ICalFormat format;
364 format.save( cal, fileName );
367 void EventOrTodoDialogPrivate::storeTemplatesInConfig( const QStringList &templateNames )
369 // I find this somewhat broken. templates() returns a reference, maybe it should
370 // be changed by adding a setTemplates method.
371 IncidenceEditorNG::EditorConfig::instance()->templates( mEditor->type() ) = templateNames;
372 IncidenceEditorNG::EditorConfig::instance()->config()->writeConfig();
375 void EventOrTodoDialogPrivate::updateAttachmentCount( int newCount )
377 if ( newCount > 0 ) {
378 mUi->mTabWidget->setTabText(
379 AttachmentsTab,
380 i18nc( "@title:tab Tab to modify attachments of an event or todo",
381 "Attac&hments (%1)", newCount ) );
382 } else {
383 mUi->mTabWidget->setTabText(
384 AttachmentsTab,
385 i18nc( "@title:tab Tab to modify attachments of an event or todo",
386 "Attac&hments" ) );
390 void EventOrTodoDialogPrivate::updateAttendeeCount( int newCount )
392 if ( newCount > 0 ) {
393 mUi->mTabWidget->setTabText(
394 AttendeesTab,
395 i18nc( "@title:tab Tab to modify attendees of an event or todo",
396 "&Attendees (%1)", newCount ) );
397 } else {
398 mUi->mTabWidget->setTabText(
399 AttendeesTab,
400 i18nc( "@title:tab Tab to modify attendees of an event or todo",
401 "&Attendees" ) );
405 void EventOrTodoDialogPrivate::updateButtonStatus( bool isDirty )
407 Q_Q( EventOrTodoDialog );
408 q->enableButton( KDialog::Apply, isDirty || mInitiallyDirty );
411 bool EventOrTodoDialogPrivate::containsPayloadIdentifiers(
412 const QSet<QByteArray> &partIdentifiers ) const
414 return partIdentifiers.contains( QByteArray( "PLD:RFC822" ) );
417 void EventOrTodoDialogPrivate::handleItemSaveFail( EditorItemManager::SaveAction,
418 const QString &errorMessage )
420 Q_Q( EventOrTodoDialog );
422 bool retry = false;
424 if ( !errorMessage.isEmpty() ) {
425 const QString message = i18nc( "@info",
426 "Unable to store the incidence in the calendar. Try again?\n\n "
427 "Reason: %1", errorMessage );
428 retry = ( KMessageBox::warningYesNo( q, message ) == KMessageBox::Yes );
431 if ( retry ) {
432 mItemManager->save();
433 } else {
434 updateButtonStatus( isDirty() );
435 q->enableButtonOk( true );
436 q->enableButtonCancel( true );
440 void EventOrTodoDialogPrivate::handleItemSaveFinish( EditorItemManager::SaveAction )
442 Q_Q( EventOrTodoDialog );
444 if ( mCloseOnSave ) {
445 q->accept();
446 } else {
447 const Akonadi::Item item = mItemManager->item();
448 Q_ASSERT( item.isValid() );
449 Q_ASSERT( item.hasPayload() );
450 Q_ASSERT( item.hasPayload<KCalCore::Incidence::Ptr>() );
451 // Now the item is succesfull saved, reload it in the editor in order to
452 // reset the dirty status of the editor.
453 mEditor->load( item.payload<KCalCore::Incidence::Ptr>() );
455 // Set the buttons to a reasonable state as well (ok and apply should be
456 // disabled at this point).
457 q->enableButtonOk( true );
458 q->enableButtonCancel( true );
459 q->enableButtonApply( isDirty() );
463 bool EventOrTodoDialogPrivate::hasSupportedPayload( const Akonadi::Item &item ) const
465 return CalendarSupport::incidence( item );
468 bool EventOrTodoDialogPrivate::isDirty() const
470 if ( mItem.isValid() ) {
471 return mEditor->isDirty() ||
472 mCalSelector->currentCollection().id() != mItem.storageCollectionId();
473 } else {
474 return mEditor->isDirty();
478 bool EventOrTodoDialogPrivate::isValid() const
480 if ( mEditor->isValid() ) {
481 // Check if there's a selected collection.
482 if ( mCalSelector->currentCollection().isValid() ) {
483 return true;
484 } else {
485 kWarning() << "Select a collection first";
489 return false;
492 void EventOrTodoDialogPrivate::load( const Akonadi::Item &item )
494 Q_Q( EventOrTodoDialog );
496 Q_ASSERT( hasSupportedPayload( item ) );
498 if ( CalendarSupport::hasJournal( item ) ) {
499 //mUi->mTabWidget->removeTab( 5 );
500 mUi->mTabWidget->removeTab( AttachmentsTab );
501 mUi->mTabWidget->removeTab( RecurrenceTab );
502 mUi->mTabWidget->removeTab( AlarmsTab );
505 mEditor->load( CalendarSupport::incidence( item ) );
507 const KCalCore::Incidence::Ptr incidence = CalendarSupport::incidence( item );
508 const QStringList allEmails = IncidenceEditorNG::EditorConfig::instance()->allEmails();
509 KCalCore::Attendee::Ptr me = incidence->attendeeByMails( allEmails );
511 if ( incidence->attendeeCount() > 1 && // >1 because you won't drink alone
512 me && ( me->status() == KCalCore::Attendee::NeedsAction ||
513 me->status() == KCalCore::Attendee::Tentative ||
514 me->status() == KCalCore::Attendee::InProcess ) ) {
515 // Show the invitation bar: "You are invited [accept] [decline]"
516 mUi->mInvitationBar->show();
517 } else {
518 mUi->mInvitationBar->hide();
521 kDebug() << "Loading item " << item.id() << "; parent " << item.parentCollection().id()
522 << "; storage " << item.storageCollectionId();
524 if ( item.parentCollection().isValid() ) {
525 mCalSelector->setDefaultCollection( item.parentCollection() );
528 if ( !mCalSelector->mimeTypeFilter().contains( "text/calendar" ) ||
529 !mCalSelector->mimeTypeFilter().contains( incidence->mimeType() ) )
531 mCalSelector->setMimeTypeFilter( QStringList() << incidence->mimeType() << "text/calendar" );
534 if ( mEditor->type() == KCalCore::Incidence::TypeTodo ) {
535 q->setWindowIcon( SmallIcon( "view-calendar-tasks" ) );
536 } else if ( mEditor->type() == KCalCore::Incidence::TypeEvent ) {
537 q->setWindowIcon( SmallIcon( "view-calendar-day" ) );
538 } else if ( mEditor->type() == KCalCore::Incidence::TypeJournal ) {
539 q->setWindowIcon( SmallIcon( "view-pim-journal" ) );
542 // Initialize tab's titles
543 updateAttachmentCount( incidence->attachments().size() );
544 handleRecurrenceChange( mIeRecurrence->currentRecurrenceType() );
545 handleAlarmCountChange( incidence->alarms().count() );
547 mItem = item;
549 q->show();
552 Akonadi::Item EventOrTodoDialogPrivate::save( const Akonadi::Item &item )
554 Q_ASSERT( mEditor->incidence<KCalCore::Incidence>() );
556 KCalCore::Incidence::Ptr incidenceInEditor = mEditor->incidence<KCalCore::Incidence>();
557 KCalCore::Incidence::Ptr newIncidence( incidenceInEditor->clone() );
559 Akonadi::Item result = item;
560 result.setMimeType( newIncidence->mimeType() );
562 // There's no editor that has the relatedTo property. We must set it here, by hand.
563 // Otherwise it gets lost.
564 // FIXME: Why don't we clone() incidenceInEditor then pass the clone to save(),
565 // I wonder if we're not leaking other properties.
566 newIncidence->setRelatedTo( incidenceInEditor->relatedTo() );
568 mEditor->save( newIncidence );
570 // TODO: Remove this once we support moving of events/todo's
571 mCalSelector->setEnabled( false );
573 // Make sure that we don't loose uid for existing incidence
574 newIncidence->setUid( mEditor->incidence<KCalCore::Incidence>()->uid() );
576 // Mark the incidence as changed
577 if ( mItem.isValid() ) {
578 newIncidence->setRevision( newIncidence->revision() + 1 );
581 result.setPayload<KCalCore::Incidence::Ptr>( newIncidence );
582 return result;
585 Akonadi::Collection EventOrTodoDialogPrivate::selectedCollection() const
587 return mCalSelector->currentCollection();
590 void EventOrTodoDialogPrivate::reject( RejectReason reason, const QString &errorMessage )
592 Q_UNUSED( reason );
594 Q_Q( EventOrTodoDialog );
595 kError() << "Rejecting:" << errorMessage;
596 q->deleteLater();
599 /// EventOrTodoDialog
601 EventOrTodoDialog::EventOrTodoDialog( QWidget *parent, Qt::WFlags flags )
602 : IncidenceDialog( parent, flags ), d_ptr( new EventOrTodoDialogPrivate( this ) )
604 Q_D( EventOrTodoDialog );
606 resize( QSize( 600, 500 ).expandedTo( minimumSizeHint() ) );
607 d->mUi->mTabWidget->setCurrentIndex( 0 );
608 d->mUi->mSummaryEdit->setFocus();
610 setButtons( KDialog::Ok | KDialog::Apply | KDialog::Cancel | KDialog::Default );
611 setButtonToolTip( KDialog::Apply,
612 i18nc( "@info:tooltip", "Save current changes" ) );
613 setButtonToolTip( KDialog::Ok,
614 i18nc( "@action:button", "Save changes and close dialog" ) );
615 setButtonToolTip( KDialog::Cancel,
616 i18nc( "@action:button", "Discard changes and close dialog" ) );
617 setDefaultButton( Ok );
618 enableButton( Apply, false );
620 setButtonText( Default, i18nc( "@action:button", "Manage &Templates..." ) );
621 setButtonToolTip( Default,
622 i18nc( "@info:tooltip",
623 "Apply or create templates for this item" ) );
624 setButtonWhatsThis( Default,
625 i18nc( "@info:whatsthis",
626 "Push this button to run a tool that helps "
627 "you manage a set of templates. Templates "
628 "can make creating new items easier and faster "
629 "by putting your favorite default values into "
630 "the editor automatically." ) );
632 setModal( false );
633 showButtonSeparator( false );
635 connect( d->mUi->mAcceptInvitationButton, SIGNAL(clicked()),
636 d->mIeAttendee, SLOT(acceptForMe()) );
637 connect( d->mUi->mAcceptInvitationButton, SIGNAL(clicked()),
638 d->mUi->mInvitationBar, SLOT(hide()) );
639 connect( d->mUi->mDeclineInvitationButton, SIGNAL(clicked()),
640 d->mIeAttendee, SLOT(declineForMe()) );
641 connect( d->mUi->mDeclineInvitationButton, SIGNAL(clicked()),
642 d->mUi->mInvitationBar, SLOT(hide()) );
645 EventOrTodoDialog::~EventOrTodoDialog()
647 delete d_ptr;
650 void EventOrTodoDialog::load( const Akonadi::Item &item, const QDate &activeDate )
652 Q_D( EventOrTodoDialog );
653 d->mIeDateTime->setActiveDate( activeDate );
654 if ( item.isValid() ) { // We're editing
655 d->mItemManager->load( item );
656 // TODO: Remove this once we support moving of events/todo's
657 d->mCalSelector->setEnabled( false );
658 } else { // We're creating
659 Q_ASSERT( d->hasSupportedPayload( item ) );
660 d->load( item );
661 show();
665 void EventOrTodoDialog::selectCollection( const Akonadi::Collection &collection )
667 Q_D( EventOrTodoDialog );
668 if ( collection.isValid() ) {
669 d->mCalSelector->setDefaultCollection( collection );
670 } else {
671 d->mCalSelector->setCurrentIndex( 0 );
675 void EventOrTodoDialog::setIsCounterProposal( bool isCounterProposal )
677 Q_D( EventOrTodoDialog );
678 d->mInvitationDispatcher->setIsCounterProposal( isCounterProposal );
681 QObject *EventOrTodoDialog::typeAheadReceiver() const
683 Q_D( const EventOrTodoDialog );
684 return d->mUi->mSummaryEdit;
687 void EventOrTodoDialog::slotButtonClicked( int button )
689 Q_D( EventOrTodoDialog );
691 switch( button ) {
692 case KDialog::Ok:
694 if ( d->isDirty() || d->mInitiallyDirty ) {
695 enableButtonOk( false );
696 enableButtonCancel( false );
697 enableButtonApply( false );
698 d->mCloseOnSave = true;
699 d->mInitiallyDirty = false;
700 d->mItemManager->save();
701 } else {
702 close();
704 break;
706 case KDialog::Apply:
708 enableButtonOk( false );
709 enableButtonCancel( false );
710 enableButtonApply( false );
712 d->mCloseOnSave = false;
713 d->mInitiallyDirty = false;
714 d->mItemManager->save();
715 break;
717 case KDialog::Cancel:
718 if ( d->isDirty() &&
719 KMessageBox::questionYesNo(
720 this,
721 i18nc( "@info", "Do you really want to cancel?" ),
722 i18nc( "@title:window", "KOrganizer Confirmation" ) ) == KMessageBox::Yes ) {
723 KDialog::reject(); // Discard current changes
724 } else if ( !d->isDirty() ) {
725 KDialog::reject(); // No pending changes, just close the dialog.
726 } // else { // the user wasn't finished editting after all }
727 break;
728 case KDialog::Default:
729 d->manageTemplates();
730 break;
731 default:
732 Q_ASSERT( false ); // Shouldn't happen
733 break;
737 void EventOrTodoDialog::setInitiallyDirty( bool initiallyDirty )
739 Q_D( EventOrTodoDialog );
740 d->mInitiallyDirty = initiallyDirty;
743 void EventOrTodoDialog::handleSelectedCollectionChange( const Akonadi::Collection &collection )
745 Q_D( EventOrTodoDialog );
746 if ( d->mItem.parentCollection().isValid() ) {
747 enableButton( Apply, collection.id() != d->mItem.parentCollection().id() );
751 #include "eventortododialog.moc"