Add another crash guard, should cover Andy's LDAP crashes.
[kdepim.git] / korganizer / actionmanager.cpp
blobab564439e95adb2bff081f4bc707b0b2799d90f0
1 /*
2 This file is part of KOrganizer.
4 Copyright (c) 2002 Mike Pilone <mpilone@slac.com>
5 Copyright (c) 2002 Don Sanders <sanders@kde.org>
6 Copyright (c) 2004 Cornelius Schumacher <schumacher@kde.org>
7 Copyright (C) 2004 Reinhold Kainhofer <reinhold@kainhofer.com>
8 Copyright (c) 2005 Rafal Rzepecki <divide@users.sourceforge.net>
9 Copyright (c) 2010 Laurent Montel <montel@kde.org>
11 This program is free software; you can redistribute it and/or modify
12 it under the terms of the GNU General Public License as published by
13 the Free Software Foundation; either version 2 of the License, or
14 (at your option) any later version.
16 This program is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 GNU General Public License for more details.
21 You should have received a copy of the GNU General Public License along
22 with this program; if not, write to the Free Software Foundation, Inc.,
23 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
25 As a special exception, permission is given to link this program
26 with any edition of Qt, and distribute the resulting executable,
27 without including the source code for Qt in the source distribution.
30 #include "actionmanager.h"
31 #include "calendaradaptor.h"
32 #include "calendarview.h"
33 #include "history.h"
34 #include "importdialog.h"
35 #include "kocore.h"
36 #include "kodialogmanager.h"
37 #include "koglobals.h"
38 #include "koprefs.h"
39 #include "koviewmanager.h"
40 #include "kowindowlist.h"
41 #include "reminderclient.h"
42 #include "akonadicollectionview.h"
43 #include "htmlexportjob.h"
44 #include "htmlexportsettings.h"
46 #include <KCalCore/FileStorage>
48 #include <KMime/KMimeMessage>
50 #include <calendarviews/eventviews/eventview.h>
51 #include <calendarsupport/calendar.h>
52 #include <calendarsupport/calendaradaptor.h>
53 #include <calendarsupport/calendarmodel.h>
54 #include <calendarsupport/collectionselection.h>
55 #include <calendarsupport/eventarchiver.h>
56 #include <calendarsupport/freebusymanager.h>
57 #include <calendarsupport/groupware.h>
58 #include <calendarsupport/incidencechanger.h>
59 #include <calendarsupport/kcalprefs.h>
60 #include <calendarsupport/utils.h>
62 #include <incidenceeditor-ng/globalsettings.h>
63 #include <incidenceeditor-ng/groupwareintegration.h>
65 #include <akonadi_next/kcheckableproxymodel.h>
66 #include <akonadi_next/kcolumnfilterproxymodel.h>
68 #include <Akonadi/EntityTreeModel>
69 #include <Akonadi/ChangeRecorder>
70 #include <Akonadi/Session>
71 #include <akonadi/entitymimetypefiltermodel.h>
72 #include <akonadi/entitydisplayattribute.h>
73 #include <Akonadi/ItemFetchScope>
74 #include <Akonadi/AgentManager>
75 #include <Akonadi/AgentInstanceCreateJob>
76 #include <akonadi/etmviewstatesaver.h>
78 #include <KHolidays/Holidays>
79 #include <kmimetypetrader.h>
80 #include <kio/job.h>
81 #include <KAction>
82 #include <KActionCollection>
83 #include <KFileDialog>
84 #include <KMenu>
85 #include <KNotification>
86 #include <KProcess>
87 #include <KRecentFilesAction>
88 #include <KSelectAction>
89 #include <KShortcutsDialog>
90 #include <KStandardAction>
91 #include <KStandardDirs>
92 #include <KSystemTimeZone>
93 #include <KTemporaryFile>
94 #include <KTipDialog>
95 #include <KMenuBar>
96 #include <KToggleAction>
97 #include <KWindowSystem>
98 #include <KIO/NetAccess>
99 #include <kcmdlineargs.h>
100 #include <knewstuff3/downloaddialog.h>
102 #include <kselectionproxymodel.h>
104 #include <QApplication>
105 #include <QTimer>
106 #include <QDebug>
107 #include <QTemporaryFile>
109 #include <akonadi/entitytreeview.h>
110 #include <QVBoxLayout>
112 using namespace Future;
113 using namespace KCalCore;
115 KOWindowList *ActionManager::mWindowList = 0;
117 ActionManager::ActionManager( KXMLGUIClient *client, CalendarView *widget,
118 QObject *parent, KOrg::MainWindow *mainWindow,
119 bool isPart, KMenuBar *menuBar )
120 : QObject( parent ),
121 mCollectionViewShowAction( 0 ), mCalendarModel( 0 ), mCalendar( 0 ),
122 mCollectionView( 0 ), mCollectionViewStateSaver( 0 ),
123 mCollectionSelectionModelStateSaver( 0 ), mIsClosing( false )
125 new KOrgCalendarAdaptor( this );
126 QDBusConnection::sessionBus().registerObject( "/Calendar", this );
128 // Construct the groupware object, it'll take care of the IncidenceEditors::EditorConfig as well
129 if ( !IncidenceEditorNG::GroupwareIntegration::isActive() ) {
130 IncidenceEditorNG::GroupwareIntegration::activate();
133 mGUIClient = client;
134 mACollection = mGUIClient->actionCollection();
135 mCalendarView = widget;
136 mIsPart = isPart;
137 mTempFile = 0;
138 mHtmlExportSync = false;
139 mMainWindow = mainWindow;
140 mMenuBar = menuBar;
143 ActionManager::~ActionManager()
145 // Remove Part plugins
146 KOCore::self()->unloadParts( mMainWindow, mParts );
148 delete mTempFile;
150 // Take this window out of the window list.
151 mWindowList->removeWindow( mMainWindow );
153 delete mCollectionSelectionModelStateSaver;
154 delete mCollectionViewStateSaver;
156 delete mCalendarView;
157 delete mCalendar;
160 void ActionManager::toggleMenubar( bool dontShowWarning )
162 if ( mMenuBar ) {
163 if ( mHideMenuBarAction->isChecked() ) {
164 mMenuBar->show();
165 } else {
166 if ( !dontShowWarning ) {
167 QString accel = mHideMenuBarAction->shortcut().toString();
168 KMessageBox::information( mCalendarView,
169 i18n( "<qt>This will hide the menu bar completely."
170 " You can show it again by typing %1.</qt>", accel ),
171 "Hide menu bar", "HideMenuBarWarning" );
173 mMenuBar->hide();
175 KOPrefs::instance()->setShowMenuBar( mHideMenuBarAction->isChecked() );
178 // see the Note: below for why this method is necessary
179 void ActionManager::init()
181 // add this instance of the window to the static list.
182 if ( !mWindowList ) {
183 mWindowList = new KOWindowList;
184 // Show tip of the day, when the first calendar is shown.
185 if ( !mIsPart ) {
186 QTimer::singleShot( 0, this, SLOT(showTipOnStart()) );
190 // Note: We need this ActionManager to be fully constructed, and
191 // parent() to have a valid reference to it before the following
192 // addWindow is called.
193 mWindowList->addWindow( mMainWindow );
195 // initialize the KAction instances
196 initActions();
198 // set up autoExporting stuff
199 mAutoExportTimer = new QTimer( this );
200 connect( mAutoExportTimer, SIGNAL(timeout()), SLOT(checkAutoExport()) );
201 if ( KOPrefs::instance()->mAutoExport &&
202 KOPrefs::instance()->mAutoExportInterval > 0 ) {
203 mAutoExportTimer->start( 1000 * 60 * KOPrefs::instance()->mAutoExportInterval );
207 // per default (no calendars activated) disable actions
208 slotResourcesChanged( false );
210 // set up autoSaving stuff
212 mAutoArchiveTimer = new QTimer( this );
213 mAutoArchiveTimer->setSingleShot( true );
214 connect( mAutoArchiveTimer, SIGNAL(timeout()), SLOT(slotAutoArchive()) );
216 // First auto-archive should be in 5 minutes (like in kmail).
217 if ( CalendarSupport::KCalPrefs::instance()->mAutoArchive ) {
218 mAutoArchiveTimer->start( 5 * 60 * 1000 ); // singleshot
221 setTitle();
223 connect( mCalendarView, SIGNAL(modifiedChanged(bool)), SLOT(setTitle()) );
224 connect( mCalendarView, SIGNAL(configChanged()), SLOT(updateConfig()) );
226 connect( mCalendarView, SIGNAL(incidenceSelected(const Akonadi::Item &, const QDate &)),
227 this, SLOT(processIncidenceSelection(const Akonadi::Item &, const QDate &)) );
228 connect( mCalendarView, SIGNAL(exportHTML(KOrg::HTMLExportSettings *)),
229 this, SLOT(exportHTML(KOrg::HTMLExportSettings *)) );
231 processIncidenceSelection( Akonadi::Item(), QDate() );
233 // Update state of paste action
234 mCalendarView->checkClipboard();
237 void ActionManager::slotCollectionChanged( const Akonadi::Collection &collection,
238 const QSet<QByteArray> &changedAttributes )
240 Q_UNUSED( collection );
242 if ( changedAttributes.contains( "AccessRights" ) ) {
243 mCalendarView->viewManager()->addChange( EventViews::EventView::ResourcesChanged );
244 mCalendarView->updateView();
248 void ActionManager::createCalendarAkonadi()
250 Akonadi::Session *session = new Akonadi::Session( "KOrganizerETM", this );
251 Akonadi::ChangeRecorder *monitor = new Akonadi::ChangeRecorder( this );
252 connect( monitor, SIGNAL(collectionChanged(Akonadi::Collection,QSet<QByteArray>) ),
253 this, SLOT(slotCollectionChanged(Akonadi::Collection,QSet<QByteArray>) ) );
255 Akonadi::ItemFetchScope scope;
256 scope.fetchFullPayload( true );
257 scope.fetchAttribute<Akonadi::EntityDisplayAttribute>();
259 monitor->setSession( session );
260 monitor->setCollectionMonitored( Akonadi::Collection::root() );
261 monitor->fetchCollection( true );
262 monitor->setItemFetchScope( scope );
263 monitor->setMimeTypeMonitored( "text/calendar", true );
264 monitor->setMimeTypeMonitored( KCalCore::Event::eventMimeType(), true );
265 monitor->setMimeTypeMonitored( KCalCore::Todo::todoMimeType(), true );
266 monitor->setMimeTypeMonitored( KCalCore::Journal::journalMimeType(), true );
267 mCalendarModel = new CalendarSupport::CalendarModel( monitor, this );
268 //mCalendarModel->setItemPopulationStrategy( Akonadi::EntityTreeModel::LazyPopulation );
270 // Our calendar tree must be sorted.
271 QSortFilterProxyModel *sortFilterProxy = new QSortFilterProxyModel( this );
272 sortFilterProxy->setDynamicSortFilter( true );
273 sortFilterProxy->setSortCaseSensitivity( Qt::CaseInsensitive );
274 sortFilterProxy->setSourceModel( mCalendarModel );
276 // We're only interested in the CollectionTitle column
277 KColumnFilterProxyModel *columnFilterProxy = new KColumnFilterProxyModel( this );
278 columnFilterProxy->setSourceModel( sortFilterProxy );
279 columnFilterProxy->setVisibleColumn( CalendarSupport::CalendarModel::CollectionTitle );
281 // Keep track of selected items.
282 QItemSelectionModel* selectionModel = new QItemSelectionModel( columnFilterProxy );
284 // Make item selection work by means of checkboxes.
285 KCheckableProxyModel *checkableProxy = new KCheckableProxyModel( this );
286 checkableProxy->setSelectionModel( selectionModel );
287 checkableProxy->setSourceModel( columnFilterProxy );
289 KConfig *config = KOGlobals::self()->config();
290 mCollectionSelectionModelStateSaver = new KViewStateMaintainer<Akonadi::ETMViewStateSaver>( config->group( "GlobalCollectionSelection" ) );
291 mCollectionSelectionModelStateSaver->setSelectionModel( checkableProxy->selectionModel() );
293 AkonadiCollectionViewFactory factory( mCalendarView );
294 mCalendarView->addExtension( &factory );
295 mCollectionView = factory.collectionView();
296 connect( mCollectionView, SIGNAL(resourcesChanged(bool)), SLOT(slotResourcesChanged(bool)));
297 connect( mCollectionView, SIGNAL(resourcesAddedRemoved()), SLOT(slotResourcesAddedRemoved()));
298 connect( mCollectionView, SIGNAL(defaultResourceChanged(Akonadi::Collection)),
299 SLOT(slotDefaultResourceChanged(Akonadi::Collection)) );
300 connect( mCollectionView, SIGNAL(colorsChanged()),
301 mCalendarView, SLOT(updateConfig()) );
303 mCollectionViewStateSaver = new KViewStateMaintainer<Akonadi::ETMViewStateSaver>( config->group( "GlobalCollectionView" ) );
304 mCollectionViewStateSaver->setView( mCollectionView->view() );
306 mCollectionView->setCollectionSelectionProxyModel( checkableProxy );
308 CalendarSupport::CollectionSelection *colSel = new CalendarSupport::CollectionSelection( selectionModel );
309 EventViews::EventView::setGlobalCollectionSelection( colSel );
310 KSelectionProxyModel* selectionProxy = new KSelectionProxyModel( selectionModel );
311 selectionProxy->setFilterBehavior( KSelectionProxyModel::ChildrenOfExactSelection );
312 selectionProxy->setSourceModel( mCalendarModel );
314 Akonadi::EntityMimeTypeFilterModel* filterProxy2 = new Akonadi::EntityMimeTypeFilterModel( this );
316 filterProxy2->setHeaderGroup( Akonadi::EntityTreeModel::ItemListHeaders );
317 filterProxy2->setSourceModel( selectionProxy );
318 filterProxy2->setSortRole( CalendarSupport::CalendarModel::SortRole );
320 mCalendar = new CalendarSupport::Calendar( mCalendarModel, filterProxy2, KSystemTimeZones::local() );
322 mCalendarView->setCalendar( mCalendar );
323 mCalendarView->readSettings();
325 connect( mCalendar, SIGNAL(calendarChanged()),
326 mCalendarView, SLOT(resourcesChanged()) );
327 connect( mCalendar, SIGNAL(signalErrorMessage(const QString &)),
328 mCalendarView, SLOT(showErrorMessage(const QString &)) );
329 connect( mCalendarView, SIGNAL(configChanged()), SLOT(updateConfig()) );
331 mCalendar->setOwner( Person( CalendarSupport::KCalPrefs::instance()->fullName(),
332 CalendarSupport::KCalPrefs::instance()->email() ) );
337 void ActionManager::initActions()
339 KAction *action;
341 /*************************** FILE MENU **********************************/
343 //~~~~~~~~~~~~~~~~~~~~~~~ LOADING / SAVING ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
344 if ( mIsPart ) {
345 if ( mMainWindow->hasDocument() ) {
346 KAction *a = mACollection->addAction( KStandardAction::Open, this, SLOT(file_open()) );
347 mACollection->addAction( "korganizer_open", a );
350 QAction *a = mACollection->addAction( KStandardAction::Print, mCalendarView, SLOT(print()) );
351 mACollection->addAction( "korganizer_print", a );
352 a = mACollection->addAction( KStandardAction::PrintPreview, mCalendarView, SLOT(print()) );
353 mACollection->addAction( "korganizer_print_preview", a );
354 a->setEnabled( !KMimeTypeTrader::self()->query("application/pdf", "KParts/ReadOnlyPart").isEmpty() );
355 } else {
356 KStandardAction::open( this, SLOT(file_open()), mACollection );
357 KStandardAction::print( mCalendarView, SLOT(print()), mACollection );
358 QAction * preview = KStandardAction::printPreview( mCalendarView, SLOT(printPreview()), mACollection );
359 preview->setEnabled( !KMimeTypeTrader::self()->query("application/pdf", "KParts/ReadOnlyPart").isEmpty() );
362 //~~~~~~~~~~~~~~~~~~~~~~~~ IMPORT / EXPORT ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
363 KAction *mergeAction = new KAction( i18n( "Import &Calendar..." ), this );
364 mergeAction->setHelpText(
365 i18n( "Merge the contents of another iCalendar" ) );
366 mergeAction->setWhatsThis(
367 i18n( "Select this menu entry if you would like to merge the contents "
368 "of another iCalendar into your current calendar." ) );
369 mACollection->addAction( "import_icalendar", mergeAction );
370 connect( mergeAction, SIGNAL(triggered(bool)), SLOT(file_merge()) );
372 KAction *importAction = new KAction( i18n( "&Import From UNIX Ical Tool" ), this );
373 importAction->setHelpText(
374 i18n( "Import a calendar in another format" ) );
375 importAction->setWhatsThis(
376 i18n( "Select this menu entry if you would like to import the contents "
377 "of a non-iCalendar formatted file into your current calendar." ) );
378 mACollection->addAction( "import_ical", importAction );
379 connect( importAction, SIGNAL(triggered(bool)), SLOT(file_icalimport()) );
381 action = new KAction( i18n( "Get &Hot New Stuff..." ), this );
382 mACollection->addAction( "downloadnewstuff", action );
383 connect( action, SIGNAL(triggered(bool)), SLOT(downloadNewStuff()) );
385 action = new KAction( i18n( "Export &Web Page..." ), this );
386 mACollection->addAction( "export_web", action );
387 connect( action, SIGNAL(triggered(bool)), mCalendarView, SLOT(exportWeb()) );
389 action = new KAction( i18n( "Export as &iCalendar..." ), this );
390 mACollection->addAction( "export_icalendar", action );
391 connect( action, SIGNAL(triggered(bool)), mCalendarView, SLOT(exportICalendar()) );
393 action = new KAction( i18n( "Export as &vCalendar..." ), this );
394 mACollection->addAction( "export_vcalendar", action );
395 connect( action, SIGNAL(triggered(bool)), mCalendarView, SLOT(exportVCalendar()) );
397 //Laurent: 2009-03-24 comment it until upload will implement
398 //action = new KAction( i18n( "Upload &Hot New Stuff..." ), this );
399 //mACollection->addAction( "uploadnewstuff", action );
400 //connect( action, SIGNAL(triggered(bool)), SLOT(uploadNewStuff()) );
402 action = new KAction( i18n( "Archive O&ld Entries..." ), this );
403 mACollection->addAction( "file_archive", action );
404 connect( action, SIGNAL(triggered(bool)), SLOT(file_archive()) );
406 action = new KAction( i18n( "Pur&ge Completed To-dos" ), mACollection );
407 mACollection->addAction( "purge_completed", action );
408 connect( action, SIGNAL(triggered(bool)), mCalendarView, SLOT(purgeCompleted()) );
410 /************************** EDIT MENU *********************************/
412 QAction *pasteAction;
413 KOrg::History *h = mCalendarView->history();
414 if ( mIsPart ) {
415 // edit menu
416 mCutAction = mACollection->addAction( KStandardAction::Cut, "korganizer_cut",
417 mCalendarView, SLOT(edit_cut()) );
418 mCopyAction = mACollection->addAction( KStandardAction::Copy, "korganizer_copy",
419 mCalendarView, SLOT(edit_copy()) );
420 pasteAction = mACollection->addAction( KStandardAction::Paste, "korganizer_paste",
421 mCalendarView, SLOT(edit_paste()) );
422 mUndoAction = mACollection->addAction( KStandardAction::Undo, "korganizer_undo",
423 h, SLOT(undo()) );
424 mRedoAction = mACollection->addAction( KStandardAction::Redo, "korganizer_redo",
425 h, SLOT(redo()) );
426 } else {
427 mCutAction = KStandardAction::cut( mCalendarView, SLOT(edit_cut()), mACollection );
428 mCopyAction = KStandardAction::copy( mCalendarView, SLOT(edit_copy()), mACollection );
429 pasteAction = KStandardAction::paste( mCalendarView, SLOT(edit_paste()), mACollection );
430 mUndoAction = KStandardAction::undo( h, SLOT(undo()), mACollection );
431 mRedoAction = KStandardAction::redo( h, SLOT(redo()), mACollection );
433 mDeleteAction = new KAction( KIcon( "edit-delete" ), i18n( "&Delete" ), this );
434 mACollection->addAction( "edit_delete", mDeleteAction );
435 connect( mDeleteAction, SIGNAL(triggered(bool)), mCalendarView, SLOT(appointment_delete()) );
436 if ( mIsPart ) {
437 QAction *a =
438 KStandardAction::find( mCalendarView->dialogManager(),
439 SLOT(showSearchDialog()), mACollection );
440 mACollection->addAction( "korganizer_find", a );
441 } else {
442 KStandardAction::find( mCalendarView->dialogManager(),
443 SLOT(showSearchDialog()), mACollection );
445 pasteAction->setEnabled( false );
446 mUndoAction->setEnabled( false );
447 mRedoAction->setEnabled( false );
448 connect( mCalendarView, SIGNAL(pasteEnabled(bool)), pasteAction, SLOT(setEnabled(bool)) );
449 connect( h, SIGNAL(undoAvailable(const QString &)), SLOT(updateUndoAction(const QString &)) );
450 connect( h, SIGNAL(redoAvailable(const QString &)), SLOT(updateRedoAction(const QString &)) );
452 /************************** VIEW MENU *********************************/
454 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~ VIEWS ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
455 action = new KAction( KIcon( "view-calendar-upcoming-events" ), i18n( "What's &Next" ), this );
456 mACollection->addAction( "view_whatsnext", action );
457 connect( action, SIGNAL(triggered(bool)), mCalendarView->viewManager(),
458 SLOT(showWhatsNextView()) );
460 action = new KAction( KIcon( "view-calendar-month" ), i18n( "&Month View" ), this );
461 mACollection->addAction( "view_month", action );
462 connect( action, SIGNAL(triggered(bool)),
463 mCalendarView->viewManager(), SLOT(showMonthView()) );
465 action = new KAction( KIcon( "view-calendar-agenda" ), i18n( "&Agenda" ), this );
466 mACollection->addAction( "view_agenda", action );
467 connect( action, SIGNAL(triggered(bool)),
468 mCalendarView->viewManager(), SLOT(showAgendaView()) );
470 action = new KAction( KIcon( "view-calendar-list" ), i18n( "&Event List" ), this );
471 mACollection->addAction( "view_list", action );
472 connect( action, SIGNAL(triggered(bool)), mCalendarView->viewManager(),
473 SLOT(showListView()) );
475 action = new KAction( KIcon( "view-calendar-tasks" ), i18n( "&To-do List" ), this );
476 mACollection->addAction( "view_todo", action );
477 connect( action, SIGNAL(triggered(bool)), mCalendarView->viewManager(),
478 SLOT(showTodoView()) );
480 action = new KAction( KIcon( "view-calendar-journal" ), i18n( "&Journal" ), this );
481 mACollection->addAction( "view_journal", action );
482 connect( action, SIGNAL(triggered(bool)), mCalendarView->viewManager(),
483 SLOT(showJournalView()) );
485 action = new KAction( KIcon( "view-calendar-timeline" ), i18n( "Time&line" ), this );
486 mACollection->addAction( "view_timeline", action );
487 connect( action, SIGNAL(triggered(bool)), mCalendarView->viewManager(),
488 SLOT(showTimeLineView()) );
490 action = new KAction( KIcon( "view-calendar-time-spent" ), i18n( "Time&spent" ), this );
491 mACollection->addAction( "view_timespent", action );
492 connect( action, SIGNAL(triggered(bool)), mCalendarView->viewManager(),
493 SLOT(showTimeSpentView()) );
495 //~~~~~~~~~~~~~~~~~~~~~~~~~~~ REFRESH ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
496 action = new KAction( i18n( "&Refresh" ), this );
497 mACollection->addAction( "update", action );
498 connect( action, SIGNAL(triggered(bool)), mCalendarView, SLOT(updateView()) );
500 //~~~~~~~~~~~~~~~~~~~~~~~~~~~ FILTER ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
502 mFilterAction = new KSelectAction( i18n( "F&ilter" ), this );
503 mFilterAction->setToolBarMode( KSelectAction::MenuMode );
504 mACollection->addAction( "filter_select", mFilterAction );
505 mFilterAction->setEditable( false );
506 connect( mFilterAction, SIGNAL(triggered(int)),
507 mCalendarView, SLOT(filterActivated(int)) );
508 connect( mCalendarView, SIGNAL(filtersUpdated(const QStringList &, int)),
509 this, SLOT(setItems(const QStringList &, int)) );
510 connect( mCalendarView, SIGNAL(filterChanged()),
511 this, SLOT(setTitle()) );
513 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ZOOM ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
514 // TODO: try to find / create better icons for the following 4 actions
515 action = new KAction( KIcon( "zoom-in" ), i18n( "In Horizontally" ), this );
516 action->setEnabled( mCalendarView->currentView()->supportsZoom() );
517 mACollection->addAction( "zoom_in_horizontally", action );
518 connect( action, SIGNAL(triggered(bool)), mCalendarView->viewManager(),
519 SLOT(zoomInHorizontally()) );
521 action = new KAction( KIcon( "zoom-out" ), i18n( "Out Horizontally" ), this );
522 action->setEnabled( mCalendarView->currentView()->supportsZoom() );
523 mACollection->addAction( "zoom_out_horizontally", action );
524 connect( action, SIGNAL(triggered(bool)), mCalendarView->viewManager(),
525 SLOT(zoomOutHorizontally()) );
527 action = new KAction( KIcon( "zoom-in" ), i18n( "In Vertically" ), this );
528 action->setEnabled( mCalendarView->currentView()->supportsZoom() );
529 mACollection->addAction( "zoom_in_vertically", action );
530 connect( action, SIGNAL(triggered(bool)), mCalendarView->viewManager(),
531 SLOT(zoomInVertically()) );
533 action = new KAction( KIcon( "zoom-out" ), i18n( "Out Vertically" ), this );
534 action->setEnabled( mCalendarView->currentView()->supportsZoom() );
535 mACollection->addAction( "zoom_out_vertically", action );
536 connect( action, SIGNAL(triggered(bool)), mCalendarView->viewManager(),
537 SLOT(zoomOutVertically()) );
540 /************************** Actions MENU *********************************/
541 bool isRTL = QApplication::isRightToLeft();
543 action = new KAction( KIcon( "go-jump-today" ),
544 i18nc( "@action Jump to today", "To &Today" ), this );
545 action->setIconText( i18n( "Today" ) );
546 action->setHelpText( i18n( "Scroll to Today" ) );
547 mACollection->addAction( "go_today", action );
548 connect( action, SIGNAL(triggered(bool)), mCalendarView, SLOT(goToday()) );
550 action = new KAction( KIcon( isRTL ? "go-next" : "go-previous" ),
551 i18nc( "scroll backward", "&Backward" ), this );
552 action->setIconText( i18nc( "scroll backward", "Back" ) );
553 action->setHelpText( i18n( "Scroll Backward" ) );
554 mACollection->addAction( "go_previous", action );
555 connect( action, SIGNAL(triggered(bool)), mCalendarView, SLOT(goPrevious()) );
557 // Changing the action text by setText makes the toolbar button disappear.
558 // This has to be fixed first, before the connects below can be reenabled.
560 connect( mCalendarView, SIGNAL(changeNavStringPrev(const QString &)),
561 action, SLOT(setText(const QString &)) );
562 connect( mCalendarView, SIGNAL(changeNavStringPrev(const QString &)),
563 this, SLOT(dumpText(const QString &)) );*/
565 action = new KAction( KIcon( isRTL ? "go-previous" : "go-next" ),
566 i18nc( "scroll forward", "&Forward" ), this );
567 action->setIconText( i18nc( "scoll forward", "Forward" ) );
568 action->setHelpText( i18n( "Scroll Forward" ) );
569 mACollection->addAction( "go_next", action );
570 connect( action, SIGNAL(triggered(bool)), mCalendarView, SLOT(goNext()) );
572 connect( mCalendarView,SIGNAL(changeNavStringNext(const QString &)),
573 action,SLOT(setText(const QString &)) );
576 action = new KAction( KIcon( "view-calendar-day" ), i18n( "&Day" ), this );
577 mACollection->addAction( "select_day", action );
578 action->setEnabled( mCalendarView->currentView()->supportsDateRangeSelection() );
579 connect( action, SIGNAL(triggered(bool)), mCalendarView->viewManager(),
580 SLOT(selectDay()) );
582 mNextXDays = new KAction( KIcon( "view-calendar-upcoming-days" ), QString(), this );
583 mNextXDays->setEnabled( mCalendarView->currentView()->supportsDateRangeSelection() );
584 mACollection->addAction( "select_nextx", mNextXDays );
585 connect( mNextXDays, SIGNAL(triggered(bool)), mCalendarView->viewManager(),
586 SLOT(selectNextX()) );
587 mNextXDays->setText( i18np( "&Next Day", "&Next %1 Days", KOPrefs::instance()->mNextXDays ) );
589 action = new KAction( KIcon( "view-calendar-workweek" ), i18n( "W&ork Week" ), this );
590 action->setEnabled( mCalendarView->currentView()->supportsDateRangeSelection() );
591 mACollection->addAction( "select_workweek", action );
592 connect( action, SIGNAL(triggered(bool)), mCalendarView->viewManager(),
593 SLOT(selectWorkWeek()) );
595 action = new KAction( KIcon( "view-calendar-week" ), i18n( "&Week" ), this );
596 action->setEnabled( mCalendarView->currentView()->supportsDateRangeSelection() );
597 mACollection->addAction( "select_week", action );
598 connect( action, SIGNAL(triggered(bool)), mCalendarView->viewManager(),
599 SLOT(selectWeek()) );
601 /************************** Actions MENU *********************************/
602 mNewEventAction = new KAction( KIcon( "appointment-new" ), i18n( "New E&vent..." ), this );
603 //mNewEventAction->setIconText( i18nc( "@action:intoolbar create a new event", "Event" ) );
604 mNewEventAction->setHelpText( i18n( "Create a new Event" ) );
606 mACollection->addAction( "new_event", mNewEventAction );
607 connect( mNewEventAction, SIGNAL(triggered(bool)), this,
608 SLOT(slotNewEvent()) );
610 mNewTodoAction = new KAction( KIcon( "task-new" ), i18n( "New &To-do..." ), this );
611 //mNewTodoAction->setIconText( i18n( "To-do" ) );
612 mNewTodoAction->setHelpText( i18n( "Create a new To-do" ) );
613 mACollection->addAction( "new_todo", mNewTodoAction );
614 connect( mNewTodoAction, SIGNAL(triggered(bool)), this,
615 SLOT(slotNewTodo()) );
617 mNewSubtodoAction = new KAction( i18n( "New Su&b-to-do..." ), this );
618 mACollection->addAction( "new_subtodo", mNewSubtodoAction );
619 connect( mNewSubtodoAction, SIGNAL(triggered(bool)), this,
620 SLOT(slotNewSubTodo() ));
621 mNewSubtodoAction->setEnabled( false );
622 connect( mCalendarView,SIGNAL(todoSelected(bool)), mNewSubtodoAction,
623 SLOT(setEnabled(bool)) );
625 mNewJournalAction = new KAction( KIcon( "journal-new" ), i18n( "New &Journal..." ), this );
626 //mNewJournalAction->setIconText( i18n( "Journal" ) );
627 mNewJournalAction->setHelpText( i18n( "Create a new Journal" ) );
628 mACollection->addAction( "new_journal", mNewJournalAction );
629 connect( mNewJournalAction, SIGNAL(triggered(bool)), this,
630 SLOT(slotNewJournal()) );
632 mConfigureViewAction = new KAction( KIcon( "configure" ), i18n( "Configure View..." ), this );
633 mConfigureViewAction->setIconText( i18n( "Configure" ) );
634 mConfigureViewAction->setHelpText( i18n( "Configure the view" ) );
635 mConfigureViewAction->setEnabled( mCalendarView->currentView() &&
636 mCalendarView->currentView()->hasConfigurationDialog() );
637 mACollection->addAction( "configure_view", mConfigureViewAction );
638 connect( mConfigureViewAction, SIGNAL(triggered(bool)), mCalendarView,
639 SLOT(configureCurrentView()) );
641 mShowIncidenceAction = new KAction( i18n( "&Show" ), this );
642 mACollection->addAction( "show_incidence", mShowIncidenceAction );
643 connect( mShowIncidenceAction, SIGNAL(triggered(bool)), mCalendarView,
644 SLOT(showIncidence()) );
646 mEditIncidenceAction = new KAction( i18n( "&Edit..." ), this );
647 mACollection->addAction( "edit_incidence", mEditIncidenceAction );
648 connect( mEditIncidenceAction, SIGNAL(triggered(bool)), mCalendarView,
649 SLOT(editIncidence()) );
651 mDeleteIncidenceAction = new KAction( i18n( "&Delete" ), this );
652 mACollection->addAction( "delete_incidence", mDeleteIncidenceAction );
653 connect( mDeleteIncidenceAction, SIGNAL(triggered(bool)), mCalendarView,
654 SLOT(deleteIncidence()) );
655 mDeleteIncidenceAction->setShortcut( QKeySequence( Qt::Key_Delete ) );
657 action = new KAction( i18n( "&Make Sub-to-do Independent" ), this );
658 mACollection->addAction( "unsub_todo", action );
659 connect( action, SIGNAL(triggered(bool)), mCalendarView,
660 SLOT(todo_unsub()) );
661 action->setEnabled( false );
662 connect( mCalendarView, SIGNAL(subtodoSelected(bool)), action,
663 SLOT(setEnabled(bool)) );
665 // TODO: Add item to quickly toggle the reminder of a given incidence
666 // mToggleAlarmAction = new KToggleAction( i18n( "&Activate Reminder" ), 0,
667 // mCalendarView, SLOT(toggleAlarm()),
668 // mACollection, "activate_alarm" );
670 /************************** SCHEDULE MENU ********************************/
671 mPublishEvent = new KAction( KIcon( "mail-send" ), i18n( "&Publish Item Information..." ), this );
672 mACollection->addAction( "schedule_publish", mPublishEvent );
673 connect( mPublishEvent, SIGNAL(triggered(bool)), mCalendarView, SLOT(schedule_publish()) );
674 mPublishEvent->setEnabled( false );
676 mSendInvitation = new KAction( KIcon( "mail-send" ), i18n( "Send &Invitation to Attendees" ), this );
677 mACollection->addAction( "schedule_request", mSendInvitation );
678 connect( mSendInvitation, SIGNAL(triggered(bool)), mCalendarView, SLOT(schedule_request()) );
679 mSendInvitation->setEnabled( false );
680 connect( mCalendarView, SIGNAL(organizerEventsSelected(bool)),
681 mSendInvitation, SLOT(setEnabled(bool)) );
683 mRequestUpdate = new KAction( i18n( "Re&quest Update" ), this );
684 mACollection->addAction( "schedule_refresh", mRequestUpdate );
685 connect( mRequestUpdate, SIGNAL(triggered(bool)), mCalendarView, SLOT(schedule_refresh()) );
686 mRequestUpdate->setEnabled( false );
687 connect( mCalendarView, SIGNAL(groupEventsSelected(bool)),
688 mRequestUpdate, SLOT(setEnabled(bool)) );
690 mSendCancel = new KAction( i18n( "Send &Cancellation to Attendees" ), this );
691 mACollection->addAction( "schedule_cancel", mSendCancel );
692 connect( mSendCancel, SIGNAL(triggered(bool)), mCalendarView, SLOT(schedule_cancel()) );
693 mSendCancel->setEnabled( false );
694 connect( mCalendarView, SIGNAL(organizerEventsSelected(bool)),
695 mSendCancel, SLOT(setEnabled(bool)) );
697 mSendStatusUpdate = new KAction( KIcon( "mail-reply-sender" ), i18n( "Send Status &Update" ), this );
698 mACollection->addAction( "schedule_reply", mSendStatusUpdate );
699 connect( mSendStatusUpdate, SIGNAL(triggered(bool)), mCalendarView, SLOT(schedule_reply()) );
700 mSendStatusUpdate->setEnabled( false );
701 connect( mCalendarView, SIGNAL(groupEventsSelected(bool)),
702 mSendStatusUpdate, SLOT(setEnabled(bool)) );
704 mRequestChange = new KAction( i18nc( "counter proposal", "Request Chan&ge" ), this );
705 mACollection->addAction( "schedule_counter", mRequestChange );
706 connect( mRequestChange, SIGNAL(triggered(bool)), mCalendarView, SLOT(schedule_counter()) );
707 mRequestChange->setEnabled( false );
708 connect( mCalendarView, SIGNAL(groupEventsSelected(bool)),
709 mRequestChange, SLOT(setEnabled(bool)) );
711 action = new KAction( i18n( "&Mail Free Busy Information..." ), this );
712 mACollection->addAction( "mail_freebusy", action );
713 connect( action, SIGNAL(triggered(bool)), mCalendarView, SLOT(mailFreeBusy()) );
714 action->setEnabled( true );
716 mForwardEvent = new KAction( KIcon( "mail-forward" ), i18n( "&Send as iCalendar..." ), this );
717 mACollection->addAction( "schedule_forward", mForwardEvent );
718 connect( mForwardEvent, SIGNAL(triggered(bool)), mCalendarView, SLOT(schedule_forward()) );
719 mForwardEvent->setEnabled( false );
721 action = new KAction( i18n( "&Upload Free Busy Information" ), this );
722 mACollection->addAction( "upload_freebusy", action );
723 connect( action, SIGNAL(triggered(bool)), mCalendarView, SLOT(uploadFreeBusy()) );
724 action->setEnabled( true );
726 if ( !mIsPart ) {
727 action = new KAction( KIcon( "help-contents" ), i18n( "&Address Book" ), this );
728 mACollection->addAction( "addressbook", action );
729 connect( action, SIGNAL(triggered(bool)), mCalendarView, SLOT(openAddressbook()) );
732 /************************** SETTINGS MENU ********************************/
734 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~ SIDEBAR ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
735 mDateNavigatorShowAction = new KToggleAction( i18n( "Show Date Navigator" ), this );
736 mACollection->addAction( "show_datenavigator", mDateNavigatorShowAction );
737 connect( mDateNavigatorShowAction, SIGNAL(triggered(bool)), SLOT(toggleDateNavigator()) );
739 mTodoViewShowAction = new KToggleAction( i18n( "Show To-do View" ), this );
740 mACollection->addAction( "show_todoview", mTodoViewShowAction );
741 connect( mTodoViewShowAction, SIGNAL(triggered(bool)), SLOT(toggleTodoView()) );
743 mEventViewerShowAction = new KToggleAction( i18n( "Show Item Viewer" ), this );
744 mACollection->addAction( "show_eventviewer", mEventViewerShowAction );
745 connect( mEventViewerShowAction, SIGNAL(triggered(bool)), SLOT(toggleEventViewer()) );
746 KConfigGroup config( KOGlobals::self()->config(), "Settings" );
747 mDateNavigatorShowAction->setChecked( config.readEntry( "DateNavigatorVisible", true ) );
748 // if we are a kpart, then let's not show the todo in the left pane by
749 // default since there's also a Todo part and we'll assume they'll be
750 // using that as well, so let's not duplicate it (by default) here
751 mTodoViewShowAction->setChecked( config.readEntry( "TodoViewVisible", false ) ); //mIsPart ? false : true ) );
752 mEventViewerShowAction->setChecked( config.readEntry( "EventViewerVisible", true ) );
753 toggleDateNavigator();
754 toggleTodoView();
755 toggleEventViewer();
757 if ( !mMainWindow->hasDocument() ) {
758 mCollectionViewShowAction = new KToggleAction( i18n( "Show Calendar Manager" ), this );
759 mACollection->addAction( "show_resourceview", mCollectionViewShowAction );
760 connect( mCollectionViewShowAction, SIGNAL(triggered(bool)), SLOT(toggleResourceView()) );
761 mCollectionViewShowAction->setChecked( config.readEntry( "ResourceViewVisible", true ) );
763 toggleResourceView();
766 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~ SIDEBAR ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
767 mHideMenuBarAction = KStandardAction::showMenubar( this, SLOT(toggleMenubar()), mACollection );
768 mHideMenuBarAction->setChecked( KOPrefs::instance()->showMenuBar() );
769 toggleMenubar( true );
771 action = new KAction( i18n( "Configure &Date && Time..." ), this );
772 mACollection->addAction( "conf_datetime", action );
773 connect( action, SIGNAL(triggered(bool)),
774 SLOT(configureDateTime()) );
775 // TODO: Add an item to show the resource management dlg
776 // new KAction( i18n( "Manage &Calendars..." ), 0,
777 // this, SLOT(manageResources()),
778 // mACollection, "conf_resources" );
780 action = new KAction( KIcon( "view-filter" ), i18n( "Manage View &Filters..." ), this );
781 mACollection->addAction( "edit_filters", action );
782 connect( action, SIGNAL(triggered(bool)), mCalendarView,
783 SLOT(editFilters()) );
785 action = new KAction( i18n( "Manage C&ategories..." ), this );
786 mACollection->addAction( "edit_categories", action );
787 connect( action, SIGNAL(triggered(bool)), mCalendarView->dialogManager(),
788 SLOT(showCategoryEditDialog()) );
790 if ( mIsPart ) {
791 action = new KAction( KIcon( "configure" ), i18n( "&Configure Calendar..." ), this );
792 mACollection->addAction( "korganizer_configure", action );
793 connect( action, SIGNAL(triggered(bool)), mCalendarView,
794 SLOT(edit_options()) );
795 mACollection->addAction( KStandardAction::KeyBindings, "korganizer_configure_shortcuts",
796 this, SLOT(keyBindings()) );
797 } else {
798 KStandardAction::preferences( mCalendarView, SLOT(edit_options()), mACollection );
799 KStandardAction::keyBindings( this, SLOT(keyBindings()), mACollection );
802 /**************************** HELP MENU **********************************/
803 QAction *a = mACollection->addAction( KStandardAction::TipofDay, this,
804 SLOT(showTip()) );
805 mACollection->addAction( "help_tipofday", a );
808 void ActionManager::slotResourcesChanged( bool enabled )
810 mNewEventAction->setEnabled( enabled );
811 mNewTodoAction->setEnabled( enabled );
813 Akonadi::Item item = mCalendarView->currentSelection();
814 mNewSubtodoAction->setEnabled( enabled && CalendarSupport::hasTodo( item ) );
816 mNewJournalAction->setEnabled( enabled );
818 mCalendarView->setCreatingEnabled( enabled );
821 void ActionManager::setItems( const QStringList &lst, int idx )
823 mFilterAction->setItems( lst );
824 mFilterAction->setCurrentItem( idx );
827 void ActionManager::slotResourcesAddedRemoved()
829 restoreCollectionViewSetting();
832 void ActionManager::slotDefaultResourceChanged( const Akonadi::Collection &collection )
834 mCalendarView->incidenceChanger()->setDefaultCollectionId( collection.id() );
837 void ActionManager::slotNewEvent()
839 mCalendarView->newEvent();
842 void ActionManager::slotNewTodo()
844 mCalendarView->newTodo( selectedCollection() );
847 void ActionManager::slotNewSubTodo()
849 mCalendarView->newSubTodo( selectedCollection() );
852 void ActionManager::slotNewJournal()
854 mCalendarView->newJournal( selectedCollection() );
857 void ActionManager::readSettings()
859 // read settings from the KConfig, supplying reasonable
860 // defaults where none are to be found
862 mCalendarView->readSettings();
863 restoreCollectionViewSetting();
866 void ActionManager::restoreCollectionViewSetting()
868 mCollectionSelectionModelStateSaver->restoreState();
869 mCollectionViewStateSaver->restoreState();
872 void ActionManager::writeSettings()
874 KConfigGroup config = KOGlobals::self()->config()->group( "Settings" );
875 mCalendarView->writeSettings();
877 if ( mDateNavigatorShowAction ) {
878 config.writeEntry( "DateNavigatorVisible", mDateNavigatorShowAction->isChecked() );
881 if ( mTodoViewShowAction ) {
882 config.writeEntry( "TodoViewVisible", mTodoViewShowAction->isChecked() );
885 if ( mCollectionViewShowAction ) {
886 config.writeEntry( "ResourceViewVisible", mCollectionViewShowAction->isChecked() );
889 if ( mEventViewerShowAction ) {
890 config.writeEntry( "EventViewerVisible", mEventViewerShowAction->isChecked() );
893 mCollectionViewStateSaver->saveState();
894 mCollectionSelectionModelStateSaver->saveState();
896 KConfigGroup selectionViewGroup = KOGlobals::self()->config()->group( "GlobalCollectionView" );
897 KConfigGroup selectionGroup = KOGlobals::self()->config()->group( "GlobalCollectionSelection" );
898 selectionGroup.sync();
899 selectionViewGroup.sync();
900 config.sync();
903 void ActionManager::file_new()
905 emit actionNew();
908 void ActionManager::file_open()
910 KUrl url;
911 const QString defaultPath = KStandardDirs::locateLocal( "data","korganizer/" );
912 url = KFileDialog::getOpenUrl( defaultPath, "text/calendar", dialogParent() );
914 file_open( url );
917 void ActionManager::file_open( const KUrl &url )
919 if ( url.isEmpty() ) {
920 return;
923 // is that URL already opened somewhere else? Activate that window
924 KOrg::MainWindow *korg = ActionManager::findInstance( url );
925 if ( ( 0 != korg )&&( korg != mMainWindow ) ) {
926 #ifdef Q_WS_X11
927 KWindowSystem::activateWindow( korg->topLevelWidget()->winId() );
928 #endif
929 return;
932 kDebug() << url.prettyUrl();
934 emit actionNew( url );
937 void ActionManager::file_icalimport()
939 // FIXME: eventually, we will need a dialog box to select import type, etc.
940 // for now, hard-coded to ical file, $HOME/.calendar.
941 int retVal = -1;
942 QString progPath;
943 KTemporaryFile tmpfn;
944 tmpfn.open();
946 QString homeDir = QDir::homePath() + QString::fromLatin1( "/.calendar" );
948 if ( !QFile::exists( homeDir ) ) {
949 KMessageBox::error( dialogParent(),
950 i18n( "You have no ical file in your home directory.\n"
951 "Import cannot proceed.\n" ) );
952 return;
955 KProcess proc;
956 proc << "ical2vcal" << tmpfn.fileName();
957 retVal = proc.execute();
959 if ( retVal < 0 ) {
960 kDebug() << "Error executing ical2vcal.";
961 return;
964 kDebug() << "ical2vcal return value:" << retVal;
966 if ( retVal >= 0 && retVal <= 2 ) {
967 // now we need to MERGE what is in the iCal to the current calendar.
968 mCalendarView->openCalendar( tmpfn.fileName(), 1 );
969 if ( !retVal ) {
970 KMessageBox::information( dialogParent(),
971 i18n( "KOrganizer successfully imported and "
972 "merged your .calendar file from ical "
973 "into the currently opened calendar." ),
974 "dotCalendarImportSuccess" );
975 } else {
976 KMessageBox::information( dialogParent(),
977 i18n( "KOrganizer encountered some unknown fields while "
978 "parsing your .calendar ical file, and had to "
979 "discard them; please check to see that all "
980 "your relevant data was correctly imported." ),
981 i18n( "ICal Import Successful with Warning" ) );
983 } else if ( retVal == -1 ) { // XXX this is bogus
984 KMessageBox::error( dialogParent(),
985 i18n( "KOrganizer encountered an error parsing your "
986 ".calendar file from ical; import has failed." ) );
987 } else if ( retVal == -2 ) { // XXX this is bogus
988 KMessageBox::error( dialogParent(),
989 i18n( "KOrganizer does not think that your .calendar "
990 "file is a valid ical calendar; import has failed." ) );
994 void ActionManager::file_merge()
996 const KUrl url = KFileDialog::getOpenUrl( KStandardDirs::locateLocal( "data","korganizer/" ),
997 "text/calendar",
998 dialogParent() );
999 if ( !url.isEmpty() ) { // isEmpty if user canceled the dialog
1000 importCalendar( url );
1004 void ActionManager::file_archive()
1006 mCalendarView->archiveCalendar();
1009 void ActionManager::file_close()
1011 #ifdef AKONADI_PORT_DISABLED
1012 if ( !saveModifiedURL() ) {
1013 return;
1015 #endif
1016 mCalendarView->closeCalendar();
1017 KIO::NetAccess::removeTempFile( mFile );
1018 mURL = "";
1019 mFile = "";
1021 setTitle();
1024 bool ActionManager::openURL( const KUrl &url, bool merge )
1026 kDebug();
1028 if ( url.isEmpty() ) {
1029 kDebug() << "Error! Empty URL.";
1030 return false;
1032 if ( !url.isValid() ) {
1033 kDebug() << "Error! URL is malformed.";
1034 return false;
1037 if ( url.isLocalFile() ) {
1038 mURL = url;
1039 mFile = url.toLocalFile();
1040 if ( !KStandardDirs::exists( mFile ) ) {
1041 mMainWindow->showStatusMessage( i18n( "New calendar '%1'.", url.prettyUrl() ) );
1042 } else {
1043 bool success = mCalendarView->openCalendar( mFile, merge );
1044 if ( success ) {
1045 showStatusMessageOpen( url, merge );
1048 setTitle();
1049 } else {
1050 QString tmpFile;
1051 if ( KIO::NetAccess::download( url, tmpFile, view() ) ) {
1052 kDebug() << "--- Downloaded to" << tmpFile;
1053 bool success = mCalendarView->openCalendar( tmpFile, merge );
1054 if ( merge ) {
1055 KIO::NetAccess::removeTempFile( tmpFile );
1056 if ( success ) {
1057 showStatusMessageOpen( url, merge );
1059 } else {
1060 if ( success ) {
1061 KIO::NetAccess::removeTempFile( mFile );
1062 mURL = url;
1063 mFile = tmpFile;
1064 setTitle();
1065 kDebug() << "-- Add recent URL:" << url.prettyUrl();
1066 showStatusMessageOpen( url, merge );
1069 return success;
1070 } else {
1071 QString msg;
1072 msg = i18n( "Cannot download calendar from '%1'.", url.prettyUrl() );
1073 KMessageBox::error( dialogParent(), msg );
1074 return false;
1077 return true;
1080 bool ActionManager::addResource( const KUrl &url )
1082 kDebug()<< url;
1083 Akonadi::AgentType type = Akonadi::AgentManager::self()->type( QLatin1String("akonadi_ical_resource") );
1084 Akonadi::AgentInstanceCreateJob *job = new Akonadi::AgentInstanceCreateJob( type, this );
1085 job->setProperty("path", url.path());
1086 connect( job, SIGNAL( result( KJob * ) ), this, SLOT( agentCreated( KJob * ) ) );
1087 job->start();
1088 return true;
1091 void ActionManager::agentCreated( KJob *job )
1093 kDebug();
1094 Akonadi::AgentInstanceCreateJob *createjob = qobject_cast<Akonadi::AgentInstanceCreateJob*>( job );
1095 Q_ASSERT( createjob );
1096 if ( createjob->error() ) {
1097 mCalendarView->showErrorMessage( createjob->errorString() );
1098 return;
1100 Akonadi::AgentInstance instance = createjob->instance();
1101 //instance.setName( CalendarName );
1102 QDBusInterface iface( QString::fromLatin1("org.freedesktop.Akonadi.Resource.%1").arg( instance.identifier() ), QLatin1String("/Settings") );
1103 if( ! iface.isValid() ) {
1104 mCalendarView->showErrorMessage( i18n("Failed to obtain D-Bus interface for remote configuration.") );
1105 return;
1107 QString path = createjob->property( "path" ).toString();
1108 Q_ASSERT( ! path.isEmpty() );
1109 iface.call(QLatin1String("setPath"), path);
1110 instance.reconfigure();
1113 void ActionManager::showStatusMessageOpen( const KUrl &url, bool merge )
1115 if ( merge ) {
1116 mMainWindow->showStatusMessage( i18n( "Merged calendar '%1'.",
1117 url.prettyUrl() ) );
1118 } else {
1119 mMainWindow->showStatusMessage( i18n( "Opened calendar '%1'.",
1120 url.prettyUrl() ) );
1124 void ActionManager::closeUrl()
1126 kDebug();
1128 file_close();
1131 bool ActionManager::saveURL()
1133 QString ext;
1135 if ( mURL.isLocalFile() ) {
1136 ext = mFile.right( 4 );
1137 } else {
1138 ext = mURL.fileName().right( 4 );
1141 if ( ext == QLatin1String( ".vcs" ) ) {
1142 int result = KMessageBox::warningContinueCancel(
1143 dialogParent(),
1144 i18n( "Your calendar will be saved in iCalendar format. Use "
1145 "'Export vCalendar' to save in vCalendar format." ),
1146 i18n( "Format Conversion" ), KGuiItem( i18n( "Proceed" ) ),
1147 KStandardGuiItem::cancel(),
1148 QString( "dontaskFormatConversion" ), KMessageBox::Notify );
1149 if ( result != KMessageBox::Continue ) {
1150 return false;
1153 QString filename = mURL.fileName();
1154 filename.replace( filename.length() - 4, 4, ".ics" );
1155 mURL.setFileName( filename );
1156 if ( mURL.isLocalFile() ) {
1157 mFile = mURL.toLocalFile();
1159 setTitle();
1162 if ( !mCalendarView->saveCalendar( mFile ) ) {
1163 kDebug() << "calendar view save failed.";
1164 return false;
1167 if ( !mURL.isLocalFile() ) {
1168 if ( !KIO::NetAccess::upload( mFile, mURL, view() ) ) {
1169 QString msg = i18n( "Cannot upload calendar to '%1'",
1170 mURL.prettyUrl() );
1171 KMessageBox::error( dialogParent(), msg );
1172 return false;
1176 mMainWindow->showStatusMessage( i18n( "Saved calendar '%1'.", mURL.prettyUrl() ) );
1178 return true;
1181 void ActionManager::exportHTML()
1183 HTMLExportSettings settings( "KOrganizer" );
1184 // Manually read in the config, because parametrized kconfigxt objects don't
1185 // seem to load the config theirselves
1186 settings.readConfig();
1188 const QDate qd1 = QDate::currentDate();
1189 QDate qd2 = qd1;
1191 if ( settings.monthView() ) {
1192 qd2.addMonths( 1 );
1193 } else {
1194 qd2.addDays( 7 );
1196 settings.setDateStart( QDateTime( qd1 ) );
1197 settings.setDateEnd( QDateTime( qd2 ) );
1198 exportHTML( &settings );
1201 void ActionManager::exportHTML( KOrg::HTMLExportSettings *settings )
1203 if ( !settings || settings->outputFile().isEmpty() ) {
1204 return;
1207 if ( QFileInfo( settings->outputFile() ).exists() ) {
1208 if( KMessageBox::warningContinueCancel(
1209 dialogParent(),
1210 i18n( "Do you want to overwrite file \"%1\"?",
1211 settings->outputFile() ),
1212 QString(),
1213 KStandardGuiItem::overwrite() ) == KMessageBox::Cancel ) {
1214 return;
1218 settings->setEMail( CalendarSupport::KCalPrefs::instance()->email() );
1219 settings->setName( CalendarSupport::KCalPrefs::instance()->fullName() );
1221 settings->setCreditName( "KOrganizer" );
1222 settings->setCreditURL( "http://korganizer.kde.org" );
1224 KOrg::HtmlExportJob *exportJob = new KOrg::HtmlExportJob( mCalendarView->calendar(), settings, view() );
1226 if( KOGlobals::self()->holidays() ) {
1227 KHolidays::Holiday::List holidays = KOGlobals::self()->holidays()->holidays(
1228 settings->dateStart().date(), settings->dateEnd().date() );
1229 foreach( KHolidays::Holiday holiday, holidays ) {
1230 exportJob->addHoliday( holiday.date(), holiday.text() );
1234 exportJob->start();
1237 bool ActionManager::saveAsURL( const KUrl &url )
1239 kDebug() << url.prettyUrl();
1241 if ( url.isEmpty() ) {
1242 kDebug() << "Empty URL.";
1243 return false;
1245 if ( !url.isValid() ) {
1246 kDebug() << "Malformed URL.";
1247 return false;
1250 QString fileOrig = mFile;
1251 KUrl URLOrig = mURL;
1253 KTemporaryFile *tempFile = 0;
1254 if ( url.isLocalFile() ) {
1255 mFile = url.toLocalFile();
1256 } else {
1257 tempFile = new KTemporaryFile;
1258 tempFile->setAutoRemove(false);
1259 tempFile->open();
1260 mFile = tempFile->fileName();
1262 mURL = url;
1264 bool success = saveURL(); // Save local file and upload local file
1265 if ( success ) {
1266 delete mTempFile;
1267 mTempFile = tempFile;
1268 KIO::NetAccess::removeTempFile( fileOrig );
1269 setTitle();
1270 } else {
1271 KMessageBox::sorry( dialogParent(),
1272 i18n( "Unable to save calendar to the file %1.", mFile ),
1273 i18n( "Error" ) );
1274 kDebug() << "failed";
1275 mURL = URLOrig;
1276 mFile = fileOrig;
1277 delete tempFile;
1280 return success;
1283 #ifdef AKONADI_PORT_DISABLED // can go away, kept for reference
1284 bool ActionManager::saveModifiedURL()
1286 kDebug();
1288 // If calendar isn't modified do nothing.
1289 if ( !mCalendarView->isModified() ) {
1290 return true;
1293 mHtmlExportSync = true;
1294 if ( KOPrefs::instance()->mAutoSave && !mURL.isEmpty() ) {
1295 // Save automatically, when auto save is enabled.
1296 return saveURL();
1297 } else {
1298 int result = KMessageBox::warningYesNoCancel(
1299 dialogParent(),
1300 i18n( "The calendar has been modified.\nDo you want to save it?" ),
1301 QString(),
1302 KStandardGuiItem::save(), KStandardGuiItem::discard() );
1303 switch( result ) {
1304 case KMessageBox::Yes:
1305 if ( mURL.isEmpty() ) {
1306 KUrl url = getSaveURL();
1307 return saveAsURL( url );
1308 } else {
1309 return saveURL();
1311 case KMessageBox::No:
1312 return true;
1313 case KMessageBox::Cancel:
1314 default:
1316 mHtmlExportSync = false;
1317 return false;
1322 #endif
1324 KUrl ActionManager::getSaveURL()
1326 KUrl url =
1327 KFileDialog::getSaveUrl( KStandardDirs::locateLocal( "data","korganizer/" ),
1328 i18n( "*.ics *.vcs|Calendar Files" ),
1329 dialogParent() );
1331 if ( url == KUrl() ) {
1332 return url;
1335 QString filename = url.fileName();
1337 QString e = filename.right( 4 );
1338 if ( e != QLatin1String( ".vcs" ) && e != QLatin1String( ".ics" ) ) {
1339 // Default save format is iCalendar
1340 filename += ".ics";
1343 url.setFileName( filename );
1345 kDebug() << "url:" << url.url();
1347 return url;
1350 void ActionManager::saveProperties( KConfigGroup &config )
1352 kDebug();
1354 config.writeEntry( "UseResourceCalendar", !mMainWindow->hasDocument() );
1355 if ( mMainWindow->hasDocument() ) {
1356 config.writePathEntry( "Calendar", mURL.url() );
1360 void ActionManager::readProperties( const KConfigGroup &config )
1362 kDebug();
1364 bool isResourceCalendar(
1365 config.readEntry( "UseResourceCalendar", true ) );
1366 QString calendarUrl = config.readPathEntry( "Calendar", QString() );
1368 if ( !isResourceCalendar && !calendarUrl.isEmpty() ) {
1369 mMainWindow->init( true );
1370 KUrl u( calendarUrl );
1371 openURL( u );
1372 } else {
1373 mMainWindow->init( false );
1377 // Configuration changed as a result of the options dialog.
1378 void ActionManager::updateConfig()
1380 kDebug();
1381 mNextXDays->setText( i18np( "&Next Day", "&Next %1 Days",
1382 KOPrefs::instance()->mNextXDays ) );
1384 KOCore::self()->reloadPlugins();
1386 /* Hide/Show the Reminder Daemon */
1387 if ( !KOPrefs::instance()->mShowReminderDaemon ) {
1388 KPIM::ReminderClient::hideDaemon();
1389 } else {
1390 KPIM::ReminderClient::showDaemon();
1393 // Commented out because it crashes KOrganizer.
1394 // mParts = KOCore::self()->reloadParts( mMainWindow, mParts );
1395 #ifdef AKONADI_PORT_DISABLED // shouldn't be required anymore
1396 if ( mCollectionView ) {
1397 mCollectionView->updateView();
1399 #endif
1402 void ActionManager::configureDateTime()
1404 KProcess proc;
1405 proc << "kcmshell4" << "language";
1407 if ( !proc.startDetached() ) {
1408 KMessageBox::sorry( dialogParent(),
1409 i18n( "Could not start control module for date and time format." ) );
1413 void ActionManager::showTip()
1415 KTipDialog::showTip( dialogParent(), QString(), true );
1418 void ActionManager::showTipOnStart()
1420 KConfigGroup config( KGlobal::config(), "TipOfDay" );
1421 KTipDialog::setShowOnStart( config.readEntry( "RunOnStart", false ) );
1422 KTipDialog::showTip( dialogParent() );
1425 KOrg::MainWindow *ActionManager::findInstance( const KUrl &url )
1427 if ( mWindowList ) {
1428 if ( url.isEmpty() ) {
1429 return mWindowList->defaultInstance();
1430 } else {
1431 return mWindowList->findInstance( url );
1433 } else {
1434 return 0;
1438 void ActionManager::dumpText( const QString &str )
1440 kDebug() << str;
1443 void ActionManager::toggleDateNavigator()
1445 bool visible = mDateNavigatorShowAction->isChecked();
1446 if ( mCalendarView ) {
1447 mCalendarView->showDateNavigator( visible );
1451 void ActionManager::toggleTodoView()
1453 bool visible = mTodoViewShowAction->isChecked();
1454 if ( mCalendarView ) {
1455 mCalendarView->showTodoView( visible );
1459 void ActionManager::toggleEventViewer()
1461 bool visible = mEventViewerShowAction->isChecked();
1462 if ( mCalendarView ) {
1463 mCalendarView->showEventViewer( visible );
1467 void ActionManager::toggleResourceView()
1469 const bool visible = mCollectionViewShowAction->isChecked();
1470 if ( mCollectionView ) {
1471 if ( visible ) {
1472 mCollectionView->show();
1473 } else {
1474 mCollectionView->hide();
1479 bool ActionManager::openURL( const QString &url )
1481 return openURL( KUrl( url ) );
1484 bool ActionManager::mergeURL( const QString &url )
1486 return openURL( KUrl( url ), true );
1489 bool ActionManager::saveAsURL( const QString &url )
1491 return saveAsURL( KUrl( url ) );
1494 QString ActionManager::getCurrentURLasString() const
1496 return mURL.url();
1499 bool ActionManager::editIncidence( const Akonadi::Item::Id &uid )
1501 return mCalendarView->editIncidence( uid );
1504 bool ActionManager::showIncidence( const Akonadi::Item::Id &uid )
1506 return mCalendarView->showIncidence( uid );
1509 bool ActionManager::showIncidenceContext( const Akonadi::Item::Id &uid )
1511 return mCalendarView->showIncidenceContext( uid );
1514 bool ActionManager::handleCommandLine()
1516 KCmdLineArgs *args = KCmdLineArgs::parsedArgs();
1517 KOrg::MainWindow *mainWindow = ActionManager::findInstance( KUrl() );
1519 bool ret = true;
1521 if ( !mainWindow ) {
1522 kError() << "Unable to find default calendar resources view.";
1523 ret = false;
1524 } else if ( args->count() <= 0 ) {
1525 // No filenames given => all other args are meaningless, show main Window
1526 mainWindow->topLevelWidget()->show();
1527 } else if ( !args->isSet( "open" ) ) {
1528 // Import, merge, or ask => we need the resource calendar window anyway.
1529 mainWindow->topLevelWidget()->show();
1531 // Check for import, merge or ask
1532 if ( args->isSet( "import" ) ) {
1533 for( int i = 0; i < args->count(); ++i ) {
1534 mainWindow->actionManager()->addResource( args->url( i ) );
1536 } else if ( args->isSet( "merge" ) ) {
1537 for( int i = 0; i < args->count(); ++i ) {
1538 mainWindow->actionManager()->mergeURL( args->url( i ).url() );
1540 } else {
1541 for( int i = 0; i < args->count(); ++i ) {
1542 mainWindow->actionManager()->importCalendar( args->url( i ) );
1546 return ret;
1549 bool ActionManager::deleteIncidence( const Akonadi::Item::Id &uid, bool force )
1551 return mCalendarView->deleteIncidence( uid, force );
1554 bool ActionManager::addIncidence( const QString &ical )
1556 return mCalendarView->addIncidence( ical );
1559 void ActionManager::downloadNewStuff()
1561 kDebug();
1562 KNS3::DownloadDialog dialog(mCalendarView);
1563 dialog.exec();
1564 foreach (const KNS3::Entry& e, dialog.installedEntries()) {
1565 kDebug()<<" downloadNewStuff :";
1566 const QStringList lstFile = e.installedFiles();
1567 if ( lstFile.count() != 1 ) {
1568 continue;
1570 const QString file = lstFile.at( 0 );
1571 const KUrl filename( file );
1572 kDebug()<< "filename :"<<filename;
1573 if( ! filename.isValid() ) {
1574 continue;
1577 //AKONADI_PORT avoid this local incidence changer copy...
1578 CalendarSupport::IncidenceChanger changer( mCalendar, 0, Akonadi::Collection().id() );
1580 CalendarSupport::CalendarAdaptor::Ptr cal(
1581 new CalendarSupport::CalendarAdaptor(
1582 mCalendar, mCalendarView, true /*use default collection*/ ) );
1584 FileStorage storage( cal );
1585 storage.setFileName( file );
1586 storage.setSaveFormat( new ICalFormat );
1587 if ( !storage.load() ) {
1588 KMessageBox::error( mCalendarView, i18n( "Could not load calendar %1.", file ) );
1589 } else {
1590 QStringList eventList;
1591 foreach( Event::Ptr e, cal->events() ) {
1592 eventList.append( e->summary() );
1595 const int result = KMessageBox::warningContinueCancelList( mCalendarView,
1596 i18n( "The downloaded events will be merged into your current calendar." ),
1597 eventList );
1599 if ( result != KMessageBox::Continue ) {
1600 // FIXME (KNS2): hm, no way out here :-)
1603 if ( mCalendarView->openCalendar( file, true ) ) {
1604 // FIXME (KNS2): here neither
1610 QString ActionManager::localFileName()
1612 return mFile;
1615 class ActionManager::ActionStringsVisitor : public Visitor
1617 public:
1618 ActionStringsVisitor() : mShow( 0 ), mEdit( 0 ), mDelete( 0 ) {}
1620 bool act( IncidenceBase::Ptr incidence, QAction *show, QAction *edit, QAction *del )
1622 mShow = show;
1623 mEdit = edit;
1624 mDelete = del;
1625 return incidence->accept( *this, incidence );
1628 protected:
1629 bool visit( Event::Ptr )
1631 if ( mShow ) {
1632 mShow->setText( i18n( "&Show Event" ) );
1634 if ( mEdit ) {
1635 mEdit->setText( i18n( "&Edit Event..." ) );
1637 if ( mDelete ) {
1638 mDelete->setText( i18n( "&Delete Event" ) );
1640 return true;
1642 bool visit( Todo::Ptr )
1644 if ( mShow ) {
1645 mShow->setText( i18n( "&Show To-do" ) );
1647 if ( mEdit ) {
1648 mEdit->setText( i18n( "&Edit To-do..." ) );
1650 if ( mDelete ) {
1651 mDelete->setText( i18n( "&Delete To-do" ) );
1653 return true;
1655 bool visit( Journal::Ptr )
1657 return assignDefaultStrings();
1659 bool visit( FreeBusy::Ptr ) // to inhibit hidden virtual compile warning
1661 return false;
1664 protected:
1665 bool assignDefaultStrings()
1667 if ( mShow ) {
1668 mShow->setText( i18n( "&Show" ) );
1670 if ( mEdit ) {
1671 mEdit->setText( i18n( "&Edit..." ) );
1673 if ( mDelete ) {
1674 mDelete->setText( i18n( "&Delete" ) );
1676 return true;
1678 QAction *mShow;
1679 QAction *mEdit;
1680 QAction *mDelete;
1683 void ActionManager::processIncidenceSelection( const Akonadi::Item &item, const QDate &date )
1685 //kDebug(5850) << "ActionManager::processIncidenceSelection()";
1686 Q_UNUSED( date );
1688 const KCalCore::Incidence::Ptr incidence = CalendarSupport::incidence( item );
1689 if ( !incidence ) {
1690 enableIncidenceActions( false );
1691 return;
1694 enableIncidenceActions( true );
1696 if ( !mCalendarView->calendar()->hasDeleteRights( item ) ) {
1697 mCutAction->setEnabled( false );
1698 mDeleteAction->setEnabled( false );
1701 ActionStringsVisitor v;
1702 if ( !v.act( incidence, mShowIncidenceAction, mEditIncidenceAction, mDeleteIncidenceAction ) ) {
1703 mShowIncidenceAction->setText( i18n( "&Show" ) );
1704 mEditIncidenceAction->setText( i18n( "&Edit..." ) );
1705 mDeleteIncidenceAction->setText( i18n( "&Delete" ) );
1709 void ActionManager::enableIncidenceActions( bool enabled )
1711 mShowIncidenceAction->setEnabled( enabled );
1712 mEditIncidenceAction->setEnabled( enabled );
1713 mDeleteIncidenceAction->setEnabled( enabled );
1715 mCutAction->setEnabled( enabled );
1716 mCopyAction->setEnabled( enabled );
1717 mDeleteAction->setEnabled( enabled );
1718 mPublishEvent->setEnabled( enabled );
1719 mForwardEvent->setEnabled( enabled );
1720 mSendInvitation->setEnabled( enabled );
1721 mSendCancel->setEnabled( enabled );
1722 mSendStatusUpdate->setEnabled( enabled );
1723 mRequestChange->setEnabled( enabled );
1724 mRequestUpdate->setEnabled( enabled );
1727 Akonadi::Collection ActionManager::selectedCollection() const
1729 const QModelIndex index = mCollectionView->view()->currentIndex();
1730 if ( !index.isValid() )
1731 return Akonadi::Collection();
1733 return index.data( Akonadi::EntityTreeModel::CollectionRole ).value<Akonadi::Collection>();
1736 void ActionManager::keyBindings()
1738 KShortcutsDialog dlg( KShortcutsEditor::AllActions,
1739 KShortcutsEditor::LetterShortcutsDisallowed, view() );
1740 if ( mMainWindow ) {
1741 dlg.addCollection( mMainWindow->getActionCollection() );
1744 foreach ( KOrg::Part *part, mParts ) {
1745 if ( part ) {
1746 dlg.addCollection( part->actionCollection(), part->shortInfo() );
1749 dlg.configure();
1752 void ActionManager::loadParts()
1754 mParts = KOCore::self()->loadParts( mMainWindow );
1757 void ActionManager::setTitle()
1759 mMainWindow->setTitle();
1762 void ActionManager::openEventEditor( const QString &text )
1764 mCalendarView->newEvent( text );
1767 void ActionManager::openEventEditor( const QString &summary,
1768 const QString &description,
1769 const QStringList &attachments )
1771 mCalendarView->newEvent( summary, description, attachments );
1774 void ActionManager::openEventEditor( const QString &summary,
1775 const QString &description,
1776 const QStringList &attachments,
1777 const QStringList &attendees )
1779 mCalendarView->newEvent( summary, description, attachments, attendees );
1782 void ActionManager::openEventEditor( const QString &summary,
1783 const QString &description,
1784 const QString &uri,
1785 const QString &file,
1786 const QStringList &attendees,
1787 const QString &attachmentMimetype )
1789 int action = IncidenceEditorNG::GlobalSettings::self()->defaultEmailAttachMethod();
1790 if ( attachmentMimetype != "message/rfc822" ) {
1791 action = IncidenceEditorNG::GlobalSettings::Link;
1792 } else if ( IncidenceEditorNG::GlobalSettings::self()->defaultEmailAttachMethod() == IncidenceEditorNG::GlobalSettings::Ask ) {
1793 KMenu *menu = new KMenu( 0 );
1794 QAction *attachLink = menu->addAction( i18n( "Attach as &link" ) );
1795 QAction *attachInline = menu->addAction( i18n( "Attach &inline" ) );
1796 QAction *attachBody = menu->addAction( i18n( "Attach inline &without attachments" ) );
1797 menu->addSeparator();
1798 menu->addAction( KIcon( "dialog-cancel" ), i18n( "C&ancel" ) );
1800 QAction *ret = menu->exec( QCursor::pos() );
1801 delete menu;
1803 if ( ret == attachLink ) {
1804 action = IncidenceEditorNG::GlobalSettings::Link;
1805 } else if ( ret == attachInline ) {
1806 action = IncidenceEditorNG::GlobalSettings::InlineFull;
1807 } else if ( ret == attachBody ) {
1808 action = IncidenceEditorNG::GlobalSettings::InlineBody;
1809 } else {
1810 return;
1814 QString attData;
1815 KTemporaryFile tf;
1816 tf.setAutoRemove( true );
1817 switch ( action ) {
1818 case IncidenceEditorNG::GlobalSettings::Link:
1819 attData = uri;
1820 break;
1821 case IncidenceEditorNG::GlobalSettings::InlineFull:
1822 attData = file;
1823 break;
1824 case IncidenceEditorNG::GlobalSettings::InlineBody:
1826 QFile f( file );
1827 if ( !f.open( QFile::ReadOnly ) ) {
1828 return;
1830 KMime::Message *msg = new KMime::Message();
1831 msg->setContent( f.readAll() );
1832 msg->parse();
1833 if ( msg == msg->textContent() || msg->textContent() == 0 ) { // no attachments
1834 attData = file;
1835 } else {
1836 if ( KMessageBox::warningContinueCancel(
1838 i18n( "Removing attachments from an email might invalidate its signature." ),
1839 i18n( "Remove Attachments" ), KStandardGuiItem::cont(), KStandardGuiItem::cancel(),
1840 "BodyOnlyInlineAttachment" ) != KMessageBox::Continue ) {
1841 delete msg;
1842 return;
1844 KMime::Message *newMsg = new KMime::Message();
1845 newMsg->setHead( msg->head() );
1846 newMsg->setBody( msg->textContent()->body() );
1847 newMsg->parse();
1848 newMsg->contentTransferEncoding()->from7BitString(
1849 msg->textContent()->contentTransferEncoding()->as7BitString() );
1850 newMsg->contentType()->from7BitString( msg->textContent()->contentType()->as7BitString() );
1851 newMsg->assemble();
1852 tf.write( newMsg->encodedContent() );
1853 attData = tf.fileName();
1855 tf.close();
1856 delete msg;
1857 break;
1859 default:
1860 return;
1863 mCalendarView->newEvent( summary, description, QStringList(attData),
1864 attendees, QStringList(attachmentMimetype),
1865 action != IncidenceEditorNG::GlobalSettings::Link );
1868 void ActionManager::openTodoEditor( const QString &text )
1870 mCalendarView->newTodo( text );
1873 void ActionManager::openTodoEditor( const QString &summary,
1874 const QString &description,
1875 const QStringList &attachments )
1877 mCalendarView->newTodo( summary, description, attachments );
1879 void ActionManager::openTodoEditor( const QString &summary,
1880 const QString &description,
1881 const QStringList &attachments,
1882 const QStringList &attendees )
1884 mCalendarView->newTodo( summary, description, attachments, attendees );
1887 void ActionManager::openTodoEditor( const QString &summary,
1888 const QString &description,
1889 const QString &uri,
1890 const QString &file,
1891 const QStringList &attendees,
1892 const QString &attachmentMimetype )
1894 int action = KOPrefs::instance()->defaultTodoAttachMethod();
1895 if ( attachmentMimetype != "message/rfc822" ) {
1896 action = KOPrefs::TodoAttachLink;
1897 } else if ( KOPrefs::instance()->defaultTodoAttachMethod() == KOPrefs::TodoAttachAsk ) {
1898 KMenu *menu = new KMenu( 0 );
1899 QAction *attachLink = menu->addAction( i18n( "Attach as &link" ) );
1900 QAction *attachInline = menu->addAction( i18n( "Attach &inline" ) );
1901 menu->addSeparator();
1902 menu->addAction( KIcon( "dialog-cancel" ), i18n( "C&ancel" ) );
1904 QAction *ret = menu->exec( QCursor::pos() );
1905 delete menu;
1907 if ( ret == attachLink ) {
1908 action = KOPrefs::TodoAttachLink;
1909 } else if ( ret == attachInline ) {
1910 action = KOPrefs::TodoAttachInlineFull;
1911 } else {
1912 return;
1916 QString attData;
1917 switch ( action ) {
1918 case KOPrefs::TodoAttachLink:
1919 attData = uri;
1920 break;
1921 case KOPrefs::TodoAttachInlineFull:
1922 attData = file;
1923 break;
1924 default:
1925 return;
1928 mCalendarView->newTodo( summary, description, QStringList( attData ),
1929 attendees, QStringList( attachmentMimetype ),
1930 action != KOPrefs::TodoAttachLink );
1933 void ActionManager::openJournalEditor( const QDate &date )
1935 mCalendarView->newJournal( date );
1938 void ActionManager::openJournalEditor( const QString &text, const QDate &date )
1940 mCalendarView->newJournal( text, date );
1943 void ActionManager::openJournalEditor( const QString &text )
1945 mCalendarView->newJournal( text );
1948 void ActionManager::showJournalView()
1950 mCalendarView->viewManager()->showJournalView();
1953 void ActionManager::showTodoView()
1955 mCalendarView->viewManager()->showTodoView();
1958 void ActionManager::showEventView()
1960 mCalendarView->viewManager()->showEventView();
1963 void ActionManager::goDate( const QDate &date )
1965 mCalendarView->goDate( date );
1968 void ActionManager::goDate( const QString &date )
1970 goDate( KGlobal::locale()->readDate( date ) );
1973 void ActionManager::showDate( const QDate &date )
1975 mCalendarView->showDate( date );
1978 void ActionManager::updateUndoAction( const QString &text )
1980 mUndoAction->setText( i18n( "Undo" ) );
1981 if ( text.isEmpty() ) {
1982 mUndoAction->setEnabled( false );
1983 } else {
1984 mUndoAction->setEnabled( true );
1985 if ( !text.isEmpty() ) {
1986 mUndoAction->setText( i18n( "Undo: %1", text ) );
1989 mUndoAction->setIconText( i18n( "Undo" ) );
1992 void ActionManager::updateRedoAction( const QString &text )
1994 if ( text.isEmpty() ) {
1995 mRedoAction->setEnabled( false );
1996 mRedoAction->setText( i18n( "Redo" ) );
1997 } else {
1998 mRedoAction->setEnabled( true );
1999 if ( text.isEmpty() ) {
2000 mRedoAction->setText( i18n( "Redo" ) );
2001 } else {
2002 mRedoAction->setText( i18n( "Redo (%1)", text ) );
2007 bool ActionManager::queryClose()
2009 return true;
2012 void ActionManager::importCalendar( const KUrl &url )
2014 if ( !url.isValid() ) {
2015 KMessageBox::error( dialogParent(),
2016 i18n( "URL '%1' is invalid.", url.prettyUrl() ) );
2017 return;
2020 ImportDialog *dialog;
2021 dialog = new ImportDialog( url, mMainWindow->topLevelWidget() );
2022 connect( dialog, SIGNAL(dialogFinished(ImportDialog *)),
2023 SLOT(slotImportDialogFinished(ImportDialog *)) );
2024 connect( dialog, SIGNAL(openURL(const KUrl &, bool)),
2025 SLOT(openURL(const KUrl &, bool)) );
2026 connect( dialog, SIGNAL(addResource(const KUrl &)),
2027 SLOT(addResource(const KUrl &)) );
2029 dialog->show();
2032 void ActionManager::slotImportDialogFinished( ImportDialog *dlg )
2034 dlg->deleteLater();
2035 mCalendarView->updateView();
2038 void ActionManager::slotAutoArchivingSettingsModified()
2040 if ( CalendarSupport::KCalPrefs::instance()->mAutoArchive ) {
2041 mAutoArchiveTimer->start( 4 * 60 * 60 * 1000 ); // check again in 4 hours
2042 } else {
2043 mAutoArchiveTimer->stop();
2047 void ActionManager::slotAutoArchive()
2049 if ( !mCalendarView->calendar() ) { // can this happen?
2050 return;
2053 mAutoArchiveTimer->stop();
2054 CalendarSupport::EventArchiver archiver;
2055 connect( &archiver, SIGNAL(eventsDeleted()), mCalendarView, SLOT(updateView()) ); //AKONADI_PORT this signal shouldn't be needed anymore?
2056 //AKONADI_PORT avoid this local incidence changer copy...
2057 CalendarSupport::IncidenceChanger changer( mCalendar, 0, Akonadi::Collection().id() );
2058 archiver.runAuto( mCalendarView->calendar(), &changer, mCalendarView, false /*no gui*/);
2060 // restart timer with the correct delay ( especially useful for the first time )
2061 slotAutoArchivingSettingsModified();
2064 QWidget *ActionManager::dialogParent()
2066 return mCalendarView->topLevelWidget();
2069 void ActionManager::checkAutoExport()
2071 // Don't save if auto save interval is zero
2072 if ( KOPrefs::instance()->mAutoExportInterval == 0 ) {
2073 return;
2076 // has this calendar been saved before? If yes automatically save it.
2077 if ( KOPrefs::instance()->mAutoExport ) {
2078 exportHTML();
2083 void ActionManager::openTodoEditor( const QString &summary,
2084 const QString &description,
2085 const QStringList &attachmentUris,
2086 const QStringList &attendees,
2087 const QStringList &attachmentMimetypes,
2088 bool attachmentIsInline )
2090 Q_UNUSED( summary );
2091 Q_UNUSED( description );
2092 Q_UNUSED( attachmentUris );
2093 Q_UNUSED( attendees );
2094 Q_UNUSED( attachmentMimetypes );
2095 Q_UNUSED( attachmentIsInline );
2096 kWarning() << "Not implemented in korg-desktop";
2099 void ActionManager::openEventEditor( const QString &summary,
2100 const QString &description,
2101 const QStringList &attachmentUris,
2102 const QStringList &attendees,
2103 const QStringList &attachmentMimetypes,
2104 bool attachmentIsInline )
2106 Q_UNUSED( summary );
2107 Q_UNUSED( description );
2108 Q_UNUSED( attachmentUris );
2109 Q_UNUSED( attendees );
2110 Q_UNUSED( attachmentMimetypes );
2111 Q_UNUSED( attachmentIsInline );
2112 kWarning() << "Not implemented in korg-desktop";
2115 #include "actionmanager.moc"