Fix show ical2vcal error
[kdepim.git] / korganizer / actionmanager.cpp
blob176ad7a8090ba61c28ec300b64e61cf146f072fc
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-2016 Laurent Montel <montel@kde.org>
10 Copyright (c) 2012 Allen Winter <winter@kde.org>
12 This program is free software; you can redistribute it and/or modify
13 it under the terms of the GNU General Public License as published by
14 the Free Software Foundation; either version 2 of the License, or
15 (at your option) any later version.
17 This program is distributed in the hope that it will be useful,
18 but WITHOUT ANY WARRANTY; without even the implied warranty of
19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 GNU General Public License for more details.
22 You should have received a copy of the GNU General Public License along
23 with this program; if not, write to the Free Software Foundation, Inc.,
24 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
26 As a special exception, permission is given to link this program
27 with any edition of Qt, and distribute the resulting executable,
28 without including the source code for Qt in the source distribution.
30 #include "config-kdepim.h"
31 #include "actionmanager.h"
32 #include "akonadicollectionview.h"
33 #include "calendaradaptor.h"
34 #include "calendarview.h"
35 #include "job/htmlexportjob.h"
36 #include "htmlexportsettings.h"
37 #include "kocore.h"
38 #include "kodialogmanager.h"
39 #include "korganizeradaptor.h"
40 #include "koglobals.h"
41 #include "prefs/koprefs.h"
42 #include "koviewmanager.h"
43 #include "kowindowlist.h"
44 #include "KdepimDBusInterfaces/ReminderClient"
45 #include "kocheckableproxymodel.h"
47 #include <KHolidays/HolidayRegion>
49 #include <CalendarSupport/CollectionSelection>
50 #include <CalendarSupport/EventArchiver>
51 #include <CalendarSupport/KCalPrefs>
52 #include <CalendarSupport/Utils>
54 #include <IncidenceEditor/IncidenceEditorSettings>
56 #include <AkonadiCore/EntityDisplayAttribute>
57 #include <AkonadiWidgets/EntityTreeView>
58 #include <AkonadiCore/EntityTreeModel>
59 #include <AkonadiWidgets/ETMViewStateSaver>
60 #include <Akonadi/Calendar/History>
61 #include <Akonadi/Calendar/ICalImporter>
63 #include <KCalCore/FileStorage>
64 #include <KCalCore/ICalFormat>
65 #include <KCalCore/Person>
67 #include <KMime/KMimeMessage>
68 #include <KJobWidgets>
69 #include <KIO/StatJob>
70 #include <KIO/FileCopyJob>
72 #include <QAction>
73 #include <KActionCollection>
74 #include <QFileDialog>
75 #include <QFileDialog>
76 #include <QMenu>
77 #include <QMenuBar>
78 #include <KMessageBox>
79 #include <KMimeTypeTrader>
80 #include <KProcess>
81 #include <KSelectAction>
82 #include <KShortcutsDialog>
83 #include <KStandardAction>
85 #include <QTemporaryFile>
86 #include <KToggleAction>
87 #include <KWindowSystem>
88 #include <KIO/NetAccess>
89 #include <KNS3/DownloadDialog>
90 #include <QIcon>
91 #include "korganizer_debug.h"
92 #include "korganizer_options.h"
94 #include <QApplication>
95 #include <QTimer>
96 #include <KSharedConfig>
97 #include <KLocale>
98 #include <QStandardPaths>
100 KOWindowList *ActionManager::mWindowList = Q_NULLPTR;
102 ActionManager::ActionManager(KXMLGUIClient *client, CalendarView *widget,
103 QObject *parent, KOrg::MainWindow *mainWindow,
104 bool isPart, QMenuBar *menuBar)
105 : QObject(parent),
106 mCollectionViewShowAction(Q_NULLPTR),
107 mCollectionView(Q_NULLPTR), mCollectionViewStateSaver(Q_NULLPTR),
108 mCollectionSelectionModelStateSaver(Q_NULLPTR)
110 new KOrgCalendarAdaptor(this);
111 QDBusConnection::sessionBus().registerObject(QStringLiteral("/Calendar"), this);
113 mGUIClient = client;
114 mACollection = mGUIClient->actionCollection();
115 mCalendarView = widget;
116 mIsPart = isPart;
117 mTempFile = Q_NULLPTR;
118 mHtmlExportSync = false;
119 mMainWindow = mainWindow;
120 mMenuBar = menuBar;
123 ActionManager::~ActionManager()
125 // Remove Part plugins
126 KOCore::self()->unloadParts(mMainWindow, mParts);
128 delete mTempFile;
130 // Take this window out of the window list.
131 mWindowList->removeWindow(mMainWindow);
133 delete mCollectionSelectionModelStateSaver;
134 delete mCollectionViewStateSaver;
136 delete mCalendarView;
139 void ActionManager::toggleMenubar(bool dontShowWarning)
141 if (mMenuBar) {
142 if (mHideMenuBarAction->isChecked()) {
143 mMenuBar->show();
144 } else {
145 if (!dontShowWarning) {
146 QString accel = mHideMenuBarAction->shortcut().toString();
147 KMessageBox::information(mCalendarView,
148 i18n("<qt>This will hide the menu bar completely."
149 " You can show it again by typing %1.</qt>", accel),
150 i18n("Hide menu bar"), QStringLiteral("HideMenuBarWarning"));
152 mMenuBar->hide();
154 KOPrefs::instance()->setShowMenuBar(mHideMenuBarAction->isChecked());
157 // see the Note: below for why this method is necessary
158 void ActionManager::init()
160 // add this instance of the window to the static list.
161 if (!mWindowList) {
162 mWindowList = new KOWindowList;
165 // Note: We need this ActionManager to be fully constructed, and
166 // parent() to have a valid reference to it before the following
167 // addWindow is called.
168 mWindowList->addWindow(mMainWindow);
170 // initialize the QAction instances
171 initActions();
173 // set up autoExporting stuff
174 mAutoExportTimer = new QTimer(this);
175 connect(mAutoExportTimer, &QTimer::timeout, this, &ActionManager::checkAutoExport);
176 if (KOPrefs::instance()->mAutoExport &&
177 KOPrefs::instance()->mAutoExportInterval > 0) {
178 mAutoExportTimer->start(1000 * 60 * KOPrefs::instance()->mAutoExportInterval);
181 // set up autoSaving stuff
182 mAutoArchiveTimer = new QTimer(this);
183 mAutoArchiveTimer->setSingleShot(true);
184 connect(mAutoArchiveTimer, &QTimer::timeout, this, &ActionManager::slotAutoArchive);
186 // First auto-archive should be in 5 minutes (like in kmail).
187 if (CalendarSupport::KCalPrefs::instance()->mAutoArchive) {
188 mAutoArchiveTimer->start(5 * 60 * 1000); // singleshot
191 setTitle();
193 connect(mCalendarView, &CalendarView::modifiedChanged, this, &ActionManager::setTitle);
194 connect(mCalendarView, &CalendarView::configChanged, this, &ActionManager::updateConfig);
196 connect(mCalendarView, &CalendarView::incidenceSelected,
197 this, &ActionManager::processIncidenceSelection);
198 connect(mCalendarView, SIGNAL(exportHTML(KOrg::HTMLExportSettings*)),
199 this, SLOT(exportHTML(KOrg::HTMLExportSettings*)));
201 processIncidenceSelection(Akonadi::Item(), QDate());
203 // Update state of paste action
204 mCalendarView->checkClipboard();
207 Akonadi::ETMCalendar::Ptr ActionManager::calendar() const
209 return mCalendarView->calendar();
212 void ActionManager::createCalendarAkonadi()
214 Q_ASSERT(calendar());
216 KSharedConfig::Ptr config = KSharedConfig::openConfig();
217 mCollectionSelectionModelStateSaver =
218 new KViewStateMaintainer<Akonadi::ETMViewStateSaver>(
219 config->group("GlobalCollectionSelection"));
220 mCollectionSelectionModelStateSaver->setSelectionModel(calendar()->checkableProxyModel()->selectionModel());
222 AkonadiCollectionViewFactory factory(mCalendarView);
223 mCalendarView->addExtension(&factory);
224 mCollectionView = factory.collectionView();
225 mCollectionView->setObjectName(QStringLiteral("Resource View"));
226 connect(mCollectionView, &AkonadiCollectionView::resourcesAddedRemoved, this, &ActionManager::slotResourcesAddedRemoved);
227 connect(mCollectionView, &AkonadiCollectionView::defaultResourceChanged,
228 this, &ActionManager::slotDefaultResourceChanged);
229 connect(mCollectionView, SIGNAL(colorsChanged()),
230 mCalendarView, SLOT(updateConfig()));
232 mCollectionViewStateSaver = new KViewStateMaintainer<Akonadi::ETMViewStateSaver>(config->group("GlobalCollectionView"));
233 mCollectionViewStateSaver->setView(mCollectionView->view());
235 KCheckableProxyModel *checkableProxy = calendar()->checkableProxyModel();
236 QItemSelectionModel *selectionModel = checkableProxy->selectionModel();
238 mCollectionView->setCollectionSelectionProxyModel(checkableProxy);
240 CalendarSupport::CollectionSelection *collectionSelection = new CalendarSupport::CollectionSelection(selectionModel);
241 EventViews::EventView::setGlobalCollectionSelection(collectionSelection);
243 mCalendarView->readSettings();
245 connect(calendar().data(), &Akonadi::ETMCalendar::calendarChanged,
246 mCalendarView, &CalendarView::resourcesChanged);
247 connect(mCalendarView, &CalendarView::configChanged, this, &ActionManager::updateConfig);
249 calendar()->setOwner(KCalCore::Person::Ptr(new KCalCore::Person(CalendarSupport::KCalPrefs::instance()->fullName(),
250 CalendarSupport::KCalPrefs::instance()->email())));
254 void ActionManager::initActions()
256 QAction *action;
258 /*************************** FILE MENU **********************************/
260 //~~~~~~~~~~~~~~~~~~~~~~~ LOADING / SAVING ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
261 if (mIsPart) {
262 if (mMainWindow->hasDocument()) {
263 QAction *a = mACollection->addAction(KStandardAction::Open, this, SLOT(file_open()));
264 mACollection->addAction(QStringLiteral("korganizer_open"), a);
267 QAction *a = mACollection->addAction(KStandardAction::Print, mCalendarView, SLOT(print()));
268 mACollection->addAction(QStringLiteral("korganizer_print"), a);
269 a = mACollection->addAction(KStandardAction::PrintPreview, mCalendarView, SLOT(printPreview()));
270 mACollection->addAction(QStringLiteral("korganizer_print_preview"), a);
271 } else {
272 KStandardAction::open(this, SLOT(file_open()), mACollection);
273 KStandardAction::print(mCalendarView, SLOT(print()), mACollection);
274 KStandardAction::printPreview(mCalendarView, SLOT(printPreview()), mACollection);
277 //~~~~~~~~~~~~~~~~~~~~~~~~ IMPORT / EXPORT ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
278 mImportAction = new QAction(i18n("Import &Calendar..."), this);
279 setHelpText(mImportAction, i18n("Merge the contents of another iCalendar"));
280 mImportAction->setWhatsThis(
281 i18n("Select this menu entry if you would like to merge the contents "
282 "of another iCalendar into your current calendar."));
283 mACollection->addAction(QStringLiteral("import_icalendar"), mImportAction);
284 connect(mImportAction, &QAction::triggered, this, &ActionManager::file_import);
286 QAction *importAction = new QAction(i18n("&Import From UNIX Ical Tool"), this);
287 setHelpText(importAction, i18n("Import a calendar in another format"));
288 importAction->setWhatsThis(
289 i18n("Select this menu entry if you would like to import the contents "
290 "of a non-iCalendar formatted file into your current calendar."));
291 mACollection->addAction(QStringLiteral("import_ical"), importAction);
292 connect(importAction, &QAction::triggered, this, &ActionManager::file_icalimport);
294 action = new QAction(i18n("Get &Hot New Stuff..."), this);
295 mACollection->addAction(QStringLiteral("downloadnewstuff"), action);
296 connect(action, &QAction::triggered, this, &ActionManager::downloadNewStuff);
298 action = new QAction(i18n("Export &Web Page..."), this);
299 mACollection->addAction(QStringLiteral("export_web"), action);
300 connect(action, &QAction::triggered, mCalendarView, &CalendarView::exportWeb);
302 action = new QAction(i18n("Export as &iCalendar..."), this);
303 mACollection->addAction(QStringLiteral("export_icalendar"), action);
304 connect(action, &QAction::triggered, mCalendarView, &CalendarView::exportICalendar);
306 action = new QAction(i18n("Export as &vCalendar..."), this);
307 mACollection->addAction(QStringLiteral("export_vcalendar"), action);
308 connect(action, &QAction::triggered, mCalendarView, &CalendarView::exportVCalendar);
310 //Laurent: 2009-03-24 comment it until upload will implement
311 //action = new QAction( i18n( "Upload &Hot New Stuff..." ), this );
312 //mACollection->addAction( "uploadnewstuff", action );
313 //connect( action, SIGNAL(triggered(bool)), SLOT(uploadNewStuff()) );
315 action = new QAction(i18n("Archive O&ld Entries..."), this);
316 mACollection->addAction(QStringLiteral("file_archive"), action);
317 connect(action, &QAction::triggered, this, &ActionManager::file_archive);
319 action = new QAction(i18n("Pur&ge Completed To-dos"), mACollection);
320 mACollection->addAction(QStringLiteral("purge_completed"), action);
321 connect(action, &QAction::triggered, mCalendarView, &CalendarView::purgeCompleted);
323 /************************** EDIT MENU *********************************/
325 QAction *pasteAction;
326 Akonadi::History *history = mCalendarView->history();
327 if (mIsPart) {
328 // edit menu
329 mCutAction = mACollection->addAction(KStandardAction::Cut, QStringLiteral("korganizer_cut"),
330 mCalendarView, SLOT(edit_cut()));
331 mCopyAction = mACollection->addAction(KStandardAction::Copy, QStringLiteral("korganizer_copy"),
332 mCalendarView, SLOT(edit_copy()));
333 pasteAction = mACollection->addAction(KStandardAction::Paste, QStringLiteral("korganizer_paste"),
334 mCalendarView, SLOT(edit_paste()));
335 mUndoAction = mACollection->addAction(KStandardAction::Undo, QStringLiteral("korganizer_undo"),
336 history, SLOT(undo()));
337 mRedoAction = mACollection->addAction(KStandardAction::Redo, QStringLiteral("korganizer_redo"),
338 history, SLOT(redo()));
339 } else {
340 mCutAction = KStandardAction::cut(mCalendarView, SLOT(edit_cut()), mACollection);
341 mCopyAction = KStandardAction::copy(mCalendarView, SLOT(edit_copy()), mACollection);
342 pasteAction = KStandardAction::paste(mCalendarView, SLOT(edit_paste()), mACollection);
343 mUndoAction = KStandardAction::undo(history, SLOT(undo()), mACollection);
344 mRedoAction = KStandardAction::redo(history, SLOT(redo()), mACollection);
346 mDeleteAction = new QAction(QIcon::fromTheme(QStringLiteral("edit-delete")), i18n("&Delete"), this);
347 mACollection->addAction(QStringLiteral("edit_delete"), mDeleteAction);
348 connect(mDeleteAction, &QAction::triggered, mCalendarView, &CalendarView::appointment_delete);
349 if (mIsPart) {
350 QAction *a =
351 KStandardAction::find(mCalendarView->dialogManager(),
352 SLOT(showSearchDialog()), mACollection);
353 mACollection->addAction(QStringLiteral("korganizer_find"), a);
354 } else {
355 KStandardAction::find(mCalendarView->dialogManager(),
356 SLOT(showSearchDialog()), mACollection);
358 pasteAction->setEnabled(false);
359 mUndoAction->setEnabled(false);
360 mRedoAction->setEnabled(false);
361 connect(mCalendarView, &CalendarView::pasteEnabled, pasteAction, &QAction::setEnabled);
362 connect(history, &Akonadi::History::changed, this, &ActionManager::updateUndoRedoActions);
364 /************************** VIEW MENU *********************************/
366 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~ VIEWS ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
367 action = new QAction(QIcon::fromTheme(QStringLiteral("view-calendar-upcoming-events")), i18n("What's &Next"), this);
368 mACollection->addAction(QStringLiteral("view_whatsnext"), action);
369 connect(action, &QAction::triggered, mCalendarView->viewManager(),
370 &KOViewManager::showWhatsNextView);
372 action = new QAction(QIcon::fromTheme(QStringLiteral("view-calendar-month")), i18n("&Month"), this);
373 mACollection->addAction(QStringLiteral("view_month"), action);
374 connect(action, &QAction::triggered,
375 mCalendarView->viewManager(), &KOViewManager::showMonthView);
377 action = new QAction(QIcon::fromTheme(QStringLiteral("view-calendar-agenda")), i18n("&Agenda"), this);
378 mACollection->addAction(QStringLiteral("view_agenda"), action);
379 connect(action, &QAction::triggered,
380 mCalendarView->viewManager(), &KOViewManager::showAgendaView);
382 action = new QAction(QIcon::fromTheme(QStringLiteral("view-calendar-list")), i18n("&Event List"), this);
383 mACollection->addAction(QStringLiteral("view_list"), action);
384 connect(action, &QAction::triggered, mCalendarView->viewManager(),
385 &KOViewManager::showListView);
387 action = new QAction(QIcon::fromTheme(QStringLiteral("view-calendar-tasks")), i18n("&To-do List"), this);
388 mACollection->addAction(QStringLiteral("view_todo"), action);
389 connect(action, &QAction::triggered, mCalendarView->viewManager(),
390 &KOViewManager::showTodoView);
392 action = new QAction(QIcon::fromTheme(QStringLiteral("view-calendar-journal")), i18n("&Journal"), this);
393 mACollection->addAction(QStringLiteral("view_journal"), action);
394 connect(action, &QAction::triggered, mCalendarView->viewManager(),
395 &KOViewManager::showJournalView);
397 action = new QAction(QIcon::fromTheme(QStringLiteral("view-calendar-timeline")), i18n("Time&line"), this);
398 mACollection->addAction(QStringLiteral("view_timeline"), action);
399 connect(action, &QAction::triggered, mCalendarView->viewManager(),
400 &KOViewManager::showTimeLineView);
402 action = new QAction(QIcon::fromTheme(QStringLiteral("view-calendar-time-spent")), i18n("Time&spent"), this);
403 mACollection->addAction(QStringLiteral("view_timespent"), action);
404 connect(action, &QAction::triggered, mCalendarView->viewManager(),
405 &KOViewManager::showTimeSpentView);
407 //~~~~~~~~~~~~~~~~~~~~~~~~~~~ REFRESH ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
408 action = new QAction(i18n("&Refresh"), this);
409 mACollection->addAction(QStringLiteral("update"), action);
410 connect(action, SIGNAL(triggered(bool)), mCalendarView, SLOT(updateView()));
412 //~~~~~~~~~~~~~~~~~~~~~~~~~~~ FILTER ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
414 mFilterAction = new KSelectAction(i18n("F&ilter"), this);
415 mFilterAction->setToolBarMode(KSelectAction::MenuMode);
416 mACollection->addAction(QStringLiteral("filter_select"), mFilterAction);
417 mFilterAction->setEditable(false);
418 connect(mFilterAction, SIGNAL(triggered(int)),
419 mCalendarView, SLOT(filterActivated(int)));
420 connect(mCalendarView, &CalendarView::filtersUpdated,
421 this, &ActionManager::setItems);
422 connect(mCalendarView, &CalendarView::filterChanged,
423 this, &ActionManager::setTitle);
425 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ZOOM ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
426 // TODO: try to find / create better icons for the following 4 actions
427 action = new QAction(QIcon::fromTheme(QStringLiteral("zoom-in")), i18n("In Horizontally"), this);
428 action->setEnabled(mCalendarView->currentView()->supportsZoom());
429 mACollection->addAction(QStringLiteral("zoom_in_horizontally"), action);
430 connect(action, &QAction::triggered, mCalendarView->viewManager(),
431 &KOViewManager::zoomInHorizontally);
433 action = new QAction(QIcon::fromTheme(QStringLiteral("zoom-out")), i18n("Out Horizontally"), this);
434 action->setEnabled(mCalendarView->currentView()->supportsZoom());
435 mACollection->addAction(QStringLiteral("zoom_out_horizontally"), action);
436 connect(action, &QAction::triggered, mCalendarView->viewManager(),
437 &KOViewManager::zoomOutHorizontally);
439 action = new QAction(QIcon::fromTheme(QStringLiteral("zoom-in")), i18n("In Vertically"), this);
440 action->setEnabled(mCalendarView->currentView()->supportsZoom());
441 mACollection->addAction(QStringLiteral("zoom_in_vertically"), action);
442 connect(action, &QAction::triggered, mCalendarView->viewManager(),
443 &KOViewManager::zoomInVertically);
445 action = new QAction(QIcon::fromTheme(QStringLiteral("zoom-out")), i18n("Out Vertically"), this);
446 action->setEnabled(mCalendarView->currentView()->supportsZoom());
447 mACollection->addAction(QStringLiteral("zoom_out_vertically"), action);
448 connect(action, &QAction::triggered, mCalendarView->viewManager(),
449 &KOViewManager::zoomOutVertically);
451 /************************** Actions MENU *********************************/
452 bool isRTL = QApplication::isRightToLeft();
454 action = new QAction(QIcon::fromTheme(QStringLiteral("go-jump-today")),
455 i18nc("@action Jump to today", "To &Today"), this);
456 action->setIconText(i18n("Today"));
457 setHelpText(action, i18n("Scroll to Today"));
458 mACollection->addAction(QStringLiteral("go_today"), action);
459 connect(action, &QAction::triggered, mCalendarView, &CalendarView::goToday);
461 action = new QAction(QIcon::fromTheme(isRTL ? QStringLiteral("go-next") : QStringLiteral("go-previous")),
462 i18nc("scroll backward", "&Backward"), this);
463 action->setIconText(i18nc("scroll backward", "Back"));
464 setHelpText(action, i18n("Scroll Backward"));
465 mACollection->addAction(QStringLiteral("go_previous"), action);
466 connect(action, &QAction::triggered, mCalendarView, &CalendarView::goPrevious);
468 // Changing the action text by setText makes the toolbar button disappear.
469 // This has to be fixed first, before the connects below can be reenabled.
471 connect( mCalendarView, SIGNAL(changeNavStringPrev(QString)),
472 action, SLOT(setText(QString)) );
473 connect( mCalendarView, SIGNAL(changeNavStringPrev(QString)),
474 this, SLOT(dumpText(QString)) );*/
476 action = new QAction(QIcon::fromTheme(isRTL ? QStringLiteral("go-previous") : QStringLiteral("go-next")),
477 i18nc("scroll forward", "&Forward"), this);
478 action->setIconText(i18nc("scoll forward", "Forward"));
479 setHelpText(action, i18n("Scroll Forward"));
480 mACollection->addAction(QStringLiteral("go_next"), action);
481 connect(action, &QAction::triggered, mCalendarView, &CalendarView::goNext);
483 connect( mCalendarView,SIGNAL(changeNavStringNext(QString)),
484 action,SLOT(setText(QString)) );
487 action = new QAction(QIcon::fromTheme(QStringLiteral("view-calendar-day")), i18n("&Day"), this);
488 mACollection->addAction(QStringLiteral("select_day"), action);
489 action->setEnabled(mCalendarView->currentView()->supportsDateRangeSelection());
490 connect(action, &QAction::triggered, mCalendarView->viewManager(),
491 &KOViewManager::selectDay);
493 mNextXDays = new QAction(QIcon::fromTheme(QStringLiteral("view-calendar-upcoming-days")), QString(), this);
494 mNextXDays->setEnabled(mCalendarView->currentView()->supportsDateRangeSelection());
495 mACollection->addAction(QStringLiteral("select_nextx"), mNextXDays);
496 connect(mNextXDays, &QAction::triggered, mCalendarView->viewManager(),
497 &KOViewManager::selectNextX);
498 mNextXDays->setText(i18np("&Next Day", "&Next %1 Days", KOPrefs::instance()->mNextXDays));
500 action = new QAction(QIcon::fromTheme(QStringLiteral("view-calendar-workweek")), i18n("W&ork Week"), this);
501 action->setEnabled(mCalendarView->currentView()->supportsDateRangeSelection());
502 mACollection->addAction(QStringLiteral("select_workweek"), action);
503 connect(action, &QAction::triggered, mCalendarView->viewManager(),
504 &KOViewManager::selectWorkWeek);
506 action = new QAction(QIcon::fromTheme(QStringLiteral("view-calendar-week")), i18n("&Week"), this);
507 action->setEnabled(mCalendarView->currentView()->supportsDateRangeSelection());
508 mACollection->addAction(QStringLiteral("select_week"), action);
509 connect(action, &QAction::triggered, mCalendarView->viewManager(),
510 &KOViewManager::selectWeek);
512 /************************** Actions MENU *********************************/
513 mNewEventAction = new QAction(QIcon::fromTheme(QStringLiteral("appointment-new")), i18n("New E&vent..."), this);
514 //mNewEventAction->setIconText( i18nc( "@action:intoolbar create a new event", "Event" ) );
515 setHelpText(mNewEventAction, i18n("Create a new Event"));
517 mACollection->addAction(QStringLiteral("new_event"), mNewEventAction);
518 connect(mNewEventAction, &QAction::triggered, this,
519 &ActionManager::slotNewEvent);
521 mNewTodoAction = new QAction(QIcon::fromTheme(QStringLiteral("task-new")), i18n("New &To-do..."), this);
522 //mNewTodoAction->setIconText( i18n( "To-do" ) );
523 setHelpText(mNewTodoAction, i18n("Create a new To-do"));
524 mACollection->addAction(QStringLiteral("new_todo"), mNewTodoAction);
525 connect(mNewTodoAction, &QAction::triggered, this,
526 &ActionManager::slotNewTodo);
528 mNewSubtodoAction = new QAction(i18n("New Su&b-to-do..."), this);
529 mACollection->addAction(QStringLiteral("new_subtodo"), mNewSubtodoAction);
530 connect(mNewSubtodoAction, &QAction::triggered, this,
531 &ActionManager::slotNewSubTodo);
532 mNewSubtodoAction->setEnabled(false);
533 connect(mCalendarView, &CalendarView::todoSelected, mNewSubtodoAction,
534 &QAction::setEnabled);
536 mNewJournalAction = new QAction(QIcon::fromTheme(QStringLiteral("journal-new")), i18n("New &Journal..."), this);
537 //mNewJournalAction->setIconText( i18n( "Journal" ) );
538 setHelpText(mNewJournalAction, i18n("Create a new Journal"));
539 mACollection->addAction(QStringLiteral("new_journal"), mNewJournalAction);
540 connect(mNewJournalAction, &QAction::triggered, this,
541 &ActionManager::slotNewJournal);
543 mConfigureViewAction = new QAction(QIcon::fromTheme(QStringLiteral("configure")), i18n("Configure View..."), this);
544 mConfigureViewAction->setIconText(i18n("Configure"));
545 setHelpText(mConfigureViewAction, i18n("Configure the view"));
546 mConfigureViewAction->setEnabled(mCalendarView->currentView() &&
547 mCalendarView->currentView()->hasConfigurationDialog());
548 mACollection->addAction(QStringLiteral("configure_view"), mConfigureViewAction);
549 connect(mConfigureViewAction, &QAction::triggered, mCalendarView,
550 &CalendarView::configureCurrentView);
552 mShowIncidenceAction = new QAction(i18n("&Show"), this);
553 mACollection->addAction(QStringLiteral("show_incidence"), mShowIncidenceAction);
554 connect(mShowIncidenceAction, SIGNAL(triggered(bool)), mCalendarView,
555 SLOT(showIncidence()));
557 mEditIncidenceAction = new QAction(i18n("&Edit..."), this);
558 mACollection->addAction(QStringLiteral("edit_incidence"), mEditIncidenceAction);
559 connect(mEditIncidenceAction, SIGNAL(triggered(bool)), mCalendarView,
560 SLOT(editIncidence()));
562 mDeleteIncidenceAction = new QAction(i18n("&Delete"), this);
563 mACollection->addAction(QStringLiteral("delete_incidence"), mDeleteIncidenceAction);
564 connect(mDeleteIncidenceAction, SIGNAL(triggered(bool)), mCalendarView,
565 SLOT(deleteIncidence()));
566 mACollection->setDefaultShortcut(mDeleteIncidenceAction, QKeySequence(Qt::Key_Delete));
568 action = new QAction(i18n("&Make Sub-to-do Independent"), this);
569 mACollection->addAction(QStringLiteral("unsub_todo"), action);
570 connect(action, &QAction::triggered, mCalendarView,
571 &CalendarView::todo_unsub);
572 action->setEnabled(false);
573 connect(mCalendarView, &CalendarView::subtodoSelected, action,
574 &QAction::setEnabled);
576 // TODO: Add item to quickly toggle the reminder of a given incidence
577 // mToggleAlarmAction = new KToggleAction( i18n( "&Activate Reminder" ), 0,
578 // mCalendarView, SLOT(toggleAlarm()),
579 // mACollection, "activate_alarm" );
581 /************************** SCHEDULE MENU ********************************/
582 mPublishEvent = new QAction(QIcon::fromTheme(QStringLiteral("mail-send")), i18n("&Publish Item Information..."), this);
583 mACollection->addAction(QStringLiteral("schedule_publish"), mPublishEvent);
584 connect(mPublishEvent, SIGNAL(triggered(bool)), mCalendarView, SLOT(schedule_publish()));
585 mPublishEvent->setEnabled(false);
587 mSendInvitation =
588 new QAction(QIcon::fromTheme(QStringLiteral("mail-send")), i18n("Send &Invitation to Attendees"), this);
589 mACollection->addAction(QStringLiteral("schedule_request"), mSendInvitation);
590 connect(mSendInvitation, SIGNAL(triggered(bool)), mCalendarView, SLOT(schedule_request()));
591 mSendInvitation->setEnabled(false);
592 connect(mCalendarView, &CalendarView::organizerEventsSelected,
593 mSendInvitation, &QAction::setEnabled);
595 mRequestUpdate = new QAction(i18n("Re&quest Update"), this);
596 mACollection->addAction(QStringLiteral("schedule_refresh"), mRequestUpdate);
597 connect(mRequestUpdate, SIGNAL(triggered(bool)), mCalendarView, SLOT(schedule_refresh()));
598 mRequestUpdate->setEnabled(false);
599 connect(mCalendarView, &CalendarView::groupEventsSelected,
600 mRequestUpdate, &QAction::setEnabled);
602 mSendCancel = new QAction(i18n("Send &Cancellation to Attendees"), this);
603 mACollection->addAction(QStringLiteral("schedule_cancel"), mSendCancel);
604 connect(mSendCancel, SIGNAL(triggered(bool)), mCalendarView, SLOT(schedule_cancel()));
605 mSendCancel->setEnabled(false);
606 connect(mCalendarView, &CalendarView::organizerEventsSelected,
607 mSendCancel, &QAction::setEnabled);
609 mSendStatusUpdate =
610 new QAction(QIcon::fromTheme(QStringLiteral("mail-reply-sender")), i18n("Send Status &Update"), this);
611 mACollection->addAction(QStringLiteral("schedule_reply"), mSendStatusUpdate);
612 connect(mSendStatusUpdate, SIGNAL(triggered(bool)), mCalendarView, SLOT(schedule_reply()));
613 mSendStatusUpdate->setEnabled(false);
614 connect(mCalendarView, &CalendarView::groupEventsSelected,
615 mSendStatusUpdate, &QAction::setEnabled);
617 mRequestChange = new QAction(i18nc("counter proposal", "Request Chan&ge"), this);
618 mACollection->addAction(QStringLiteral("schedule_counter"), mRequestChange);
619 connect(mRequestChange, SIGNAL(triggered(bool)), mCalendarView, SLOT(schedule_counter()));
620 mRequestChange->setEnabled(false);
621 connect(mCalendarView, &CalendarView::groupEventsSelected,
622 mRequestChange, &QAction::setEnabled);
624 action = new QAction(i18n("&Mail Free Busy Information..."), this);
625 mACollection->addAction(QStringLiteral("mail_freebusy"), action);
626 connect(action, &QAction::triggered, mCalendarView, &CalendarView::mailFreeBusy);
627 action->setEnabled(true);
629 mForwardEvent = new QAction(QIcon::fromTheme(QStringLiteral("mail-forward")), i18n("&Send as iCalendar..."), this);
630 mACollection->addAction(QStringLiteral("schedule_forward"), mForwardEvent);
631 connect(mForwardEvent, SIGNAL(triggered(bool)), mCalendarView, SLOT(schedule_forward()));
632 mForwardEvent->setEnabled(false);
634 action = new QAction(i18n("&Upload Free Busy Information"), this);
635 mACollection->addAction(QStringLiteral("upload_freebusy"), action);
636 connect(action, &QAction::triggered, mCalendarView, &CalendarView::uploadFreeBusy);
637 action->setEnabled(true);
639 if (!mIsPart) {
640 action = new QAction(QIcon::fromTheme(QStringLiteral("help-contents")), i18n("&Address Book"), this);
641 mACollection->addAction(QStringLiteral("addressbook"), action);
642 connect(action, &QAction::triggered, mCalendarView, &CalendarView::openAddressbook);
645 /************************** SETTINGS MENU ********************************/
647 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~ SIDEBAR ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
648 mDateNavigatorShowAction = new KToggleAction(i18n("Show Date Navigator"), this);
649 mACollection->addAction(QStringLiteral("show_datenavigator"), mDateNavigatorShowAction);
650 connect(mDateNavigatorShowAction, &KToggleAction::triggered, this, &ActionManager::toggleDateNavigator);
652 mTodoViewShowAction = new KToggleAction(i18n("Show To-do View"), this);
653 mACollection->addAction(QStringLiteral("show_todoview"), mTodoViewShowAction);
654 connect(mTodoViewShowAction, &KToggleAction::triggered, this, &ActionManager::toggleTodoView);
656 mEventViewerShowAction = new KToggleAction(i18n("Show Item Viewer"), this);
657 mACollection->addAction(QStringLiteral("show_eventviewer"), mEventViewerShowAction);
658 connect(mEventViewerShowAction, &KToggleAction::triggered, this, &ActionManager::toggleEventViewer);
660 KConfigGroup config(KSharedConfig::openConfig(), "Settings");
661 mDateNavigatorShowAction->setChecked(config.readEntry("DateNavigatorVisible", true));
662 // if we are a kpart, then let's not show the todo in the left pane by
663 // default since there's also a Todo part and we'll assume they'll be
664 // using that as well, so let's not duplicate it (by default) here
665 mTodoViewShowAction->setChecked(
666 config.readEntry("TodoViewVisible", false)); //mIsPart ? false : true ) );
667 mEventViewerShowAction->setChecked(config.readEntry("EventViewerVisible", true));
668 toggleDateNavigator();
669 toggleTodoView();
670 toggleEventViewer();
672 if (!mMainWindow->hasDocument()) {
673 mCollectionViewShowAction = new KToggleAction(i18n("Show Calendar Manager"), this);
674 mACollection->addAction(QStringLiteral("show_resourceview"), mCollectionViewShowAction);
675 connect(mCollectionViewShowAction, &KToggleAction::triggered, this, &ActionManager::toggleResourceView);
676 mCollectionViewShowAction->setChecked(config.readEntry("ResourceViewVisible", true));
678 toggleResourceView();
681 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~ SIDEBAR ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
682 mHideMenuBarAction = KStandardAction::showMenubar(this, SLOT(toggleMenubar()), mACollection);
683 mHideMenuBarAction->setChecked(KOPrefs::instance()->showMenuBar());
684 toggleMenubar(true);
686 action = new QAction(i18n("Configure &Date && Time..."), this);
687 mACollection->addAction(QStringLiteral("conf_datetime"), action);
688 connect(action, &QAction::triggered,
689 this, &ActionManager::configureDateTime);
690 // TODO: Add an item to show the resource management dlg
691 // new QAction( i18n( "Manage &Calendars..." ), 0,
692 // this, SLOT(manageResources()),
693 // mACollection, "conf_resources" );
695 action = new QAction(QIcon::fromTheme(QStringLiteral("view-filter")), i18n("Manage View &Filters..."), this);
696 mACollection->addAction(QStringLiteral("edit_filters"), action);
697 connect(action, &QAction::triggered, mCalendarView,
698 &CalendarView::editFilters);
700 action = new QAction(i18n("Manage C&ategories..."), this);
701 mACollection->addAction(QStringLiteral("edit_categories"), action);
702 connect(action, &QAction::triggered, mCalendarView->dialogManager(),
703 &KODialogManager::showCategoryEditDialog);
705 if (mIsPart) {
706 action = new QAction(QIcon::fromTheme(QStringLiteral("configure")), i18n("&Configure KOrganizer..."), this);
707 mACollection->addAction(QStringLiteral("korganizer_configure"), action);
708 connect(action, &QAction::triggered, mCalendarView,
709 &CalendarView::edit_options);
710 mACollection->addAction(KStandardAction::KeyBindings, QStringLiteral("korganizer_configure_shortcuts"),
711 this, SLOT(keyBindings()));
712 } else {
713 KStandardAction::preferences(mCalendarView, SLOT(edit_options()), mACollection);
714 KStandardAction::keyBindings(this, SLOT(keyBindings()), mACollection);
718 void ActionManager::setItems(const QStringList &lst, int idx)
720 mFilterAction->setItems(lst);
721 mFilterAction->setCurrentItem(idx);
724 void ActionManager::slotResourcesAddedRemoved()
726 restoreCollectionViewSetting();
729 void ActionManager::slotDefaultResourceChanged(const Akonadi::Collection &collection)
731 mCalendarView->incidenceChanger()->setDefaultCollection(collection);
734 void ActionManager::slotNewEvent()
736 mCalendarView->newEvent();
739 void ActionManager::slotNewTodo()
741 mCalendarView->newTodo(selectedCollection());
744 void ActionManager::slotNewSubTodo()
746 mCalendarView->newSubTodo(selectedCollection());
749 void ActionManager::slotNewJournal()
751 mCalendarView->newJournal(selectedCollection());
754 void ActionManager::slotMergeFinished(bool success, int total)
756 Q_ASSERT(sender());
757 sender()->deleteLater();
758 mImportAction->setEnabled(true);
759 Akonadi::ICalImporter *importer = qobject_cast<Akonadi::ICalImporter *>(sender());
761 if (success) {
762 mCalendarView->showMessage(i18np("1 incidence was imported successfully.", "%1 incidences were imported successfully.", total), KMessageWidget::Information);
763 } else {
764 mCalendarView->showMessage(i18n("There was an error while merging the calendar: %1", importer->errorMessage()), KMessageWidget::Error);
768 void ActionManager::slotNewResourceFinished(bool success)
770 Q_ASSERT(sender());
771 sender()->deleteLater();
772 Akonadi::ICalImporter *importer = qobject_cast<Akonadi::ICalImporter *>(sender());
773 mImportAction->setEnabled(true);
774 if (success) {
775 mCalendarView->showMessage(i18n("New calendar added successfully"), KMessageWidget::Information);
776 } else {
777 mCalendarView->showMessage(i18n("Could not add a calendar. Error: %1", importer->errorMessage()), KMessageWidget::Error);
781 void ActionManager::readSettings()
783 // read settings from the KConfig, supplying reasonable
784 // defaults where none are to be found
786 mCalendarView->readSettings();
787 restoreCollectionViewSetting();
790 void ActionManager::restoreCollectionViewSetting()
792 mCollectionSelectionModelStateSaver->restoreState();
793 mCollectionViewStateSaver->restoreState();
796 void ActionManager::writeSettings()
798 KSharedConfig::Ptr config = KSharedConfig::openConfig();
799 KConfigGroup group = config->group("Settings");
800 mCalendarView->writeSettings();
802 if (mDateNavigatorShowAction) {
803 group.writeEntry("DateNavigatorVisible", mDateNavigatorShowAction->isChecked());
806 if (mTodoViewShowAction) {
807 group.writeEntry("TodoViewVisible", mTodoViewShowAction->isChecked());
810 if (mCollectionViewShowAction) {
811 group.writeEntry("ResourceViewVisible", mCollectionViewShowAction->isChecked());
814 if (mEventViewerShowAction) {
815 group.writeEntry("EventViewerVisible", mEventViewerShowAction->isChecked());
818 mCollectionViewStateSaver->saveState();
819 mCollectionSelectionModelStateSaver->saveState();
821 KConfigGroup selectionViewGroup = config->group("GlobalCollectionView");
822 KConfigGroup selectionGroup = config->group("GlobalCollectionSelection");
823 selectionGroup.sync();
824 selectionViewGroup.sync();
825 config->sync();
829 void ActionManager::file_new()
831 Q_EMIT actionNewMainWindow();
835 void ActionManager::file_open()
837 const QString defaultPath = QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation) + QLatin1String("/korganizer/");
838 const QUrl url = QFileDialog::getOpenFileUrl(dialogParent(), QString(), QUrl::fromLocalFile(defaultPath), QStringLiteral("text/calendar"));
840 file_open(url);
843 void ActionManager::file_open(const QUrl &url)
845 if (url.isEmpty()) {
846 return;
849 // is that URL already opened somewhere else? Activate that window
850 KOrg::MainWindow *korg = ActionManager::findInstance(url);
851 if ((Q_NULLPTR != korg) && (korg != mMainWindow)) {
852 #if KDEPIM_HAVE_X11
853 KWindowSystem::activateWindow(korg->topLevelWidget()->winId());
854 #endif
855 return;
858 qCDebug(KORGANIZER_LOG) << url.toDisplayString();
860 importCalendar(url);
863 void ActionManager::file_icalimport()
865 // FIXME: eventually, we will need a dialog box to select import type, etc.
866 // for now, hard-coded to ical file, $HOME/.calendar.
867 int retVal = -1;
868 QTemporaryFile tmpfn;
869 tmpfn.open();
871 QString homeDir = QDir::homePath() + QLatin1String("/.calendar");
873 if (!QFile::exists(homeDir)) {
874 KMessageBox::error(dialogParent(),
875 i18n("You have no ical file in your home directory.\n"
876 "Import cannot proceed.\n"));
877 return;
880 KProcess proc;
881 proc << QStringLiteral("ical2vcal") << tmpfn.fileName();
882 retVal = proc.execute();
884 qCDebug(KORGANIZER_LOG) << "ical2vcal return value:" << retVal;
886 if (retVal >= 0 && retVal <= 2) {
887 // now we need to MERGE what is in the iCal to the current calendar.
888 const bool success = importURL(QUrl::fromLocalFile(tmpfn.fileName()), /*merge=*/ true);
889 if (!success) {
890 mCalendarView->showMessage(i18n("KOrganizer encountered some unknown fields while "
891 "parsing your .calendar ical file, and had to "
892 "discard them; please check to see that all "
893 "your relevant data was correctly imported."), KMessageWidget::Warning);
895 } else {
896 // else nothing, the operation is async and the use will se a message widget when the operation finishes, not now.
898 } else if (retVal == -1) { // XXX this is bogus
899 mCalendarView->showMessage(i18n("KOrganizer encountered an error parsing your "
900 ".calendar file from ical; import has failed."), KMessageWidget::Error);
901 } else if (retVal == -2) { // XXX this is bogus
902 mCalendarView->showMessage(i18n("KOrganizer does not think that your .calendar "
903 "file is a valid ical calendar; import has failed."), KMessageWidget::Error);
907 void ActionManager::file_import()
909 const QUrl url = QFileDialog::getOpenFileUrl(dialogParent(), QString(), QUrl::fromLocalFile(QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation) + QLatin1String("/korganizer/")),
910 QStringLiteral("text/calendar"));
911 if (!url.isEmpty()) { // isEmpty if user canceled the dialog
912 importCalendar(url);
916 void ActionManager::file_archive()
918 mCalendarView->archiveCalendar();
921 bool ActionManager::importURL(const QUrl &url, bool merge)
923 Akonadi::ICalImporter *importer = new Akonadi::ICalImporter();
924 bool jobStarted;
925 if (merge) {
926 connect(importer, &Akonadi::ICalImporter::importIntoExistingFinished, this, &ActionManager::slotMergeFinished),
927 jobStarted = importer->importIntoExistingResource(url, Akonadi::Collection());
928 } else {
929 connect(importer, &Akonadi::ICalImporter::importIntoNewFinished, this, &ActionManager::slotNewResourceFinished);
930 jobStarted = importer->importIntoNewResource(url.path());
933 if (jobStarted) {
934 mImportAction->setEnabled(false);
935 } else {
936 // empty error message means user canceled.
937 if (!importer->errorMessage().isEmpty()) {
938 mCalendarView->showMessage(i18n("An error occurred: %1", importer->errorMessage()), KMessageWidget::Error);
942 return jobStarted;
945 bool ActionManager::saveURL()
947 QString ext;
949 if (mURL.isLocalFile()) {
950 ext = mFile.right(4);
951 } else {
952 ext = mURL.fileName().right(4);
955 if (ext == QLatin1String(".vcs")) {
956 int result = KMessageBox::warningContinueCancel(
957 dialogParent(),
958 i18n("Your calendar will be saved in iCalendar format. Use "
959 "'Export vCalendar' to save in vCalendar format."),
960 i18n("Format Conversion"), KGuiItem(i18n("Proceed")),
961 KStandardGuiItem::cancel(),
962 QStringLiteral("dontaskFormatConversion"), KMessageBox::Notify);
963 if (result != KMessageBox::Continue) {
964 return false;
967 QString filename = mURL.fileName();
968 filename.replace(filename.length() - 4, 4, QStringLiteral(".ics"));
969 mURL = mURL.adjusted(QUrl::RemoveFilename);
970 mURL.setPath(mURL.path() + filename);
971 if (mURL.isLocalFile()) {
972 mFile = mURL.toLocalFile();
974 setTitle();
977 if (!mCalendarView->saveCalendar(mFile)) {
978 qCDebug(KORGANIZER_LOG) << "calendar view save failed.";
979 return false;
982 if (!mURL.isLocalFile()) {
983 auto job = KIO::file_copy(QUrl::fromLocalFile(mFile), mURL);
984 KJobWidgets::setWindow(job, view());
985 if (!job->exec()) {
986 QString msg = i18n("Cannot upload calendar to '%1'",
987 mURL.toDisplayString());
988 KMessageBox::error(dialogParent(), msg);
989 return false;
993 mMainWindow->showStatusMessage(i18n("Saved calendar '%1'.", mURL.toDisplayString()));
995 return true;
998 void ActionManager::exportHTML()
1000 HTMLExportSettings *settings = new HTMLExportSettings(QStringLiteral("KOrganizer"));
1001 mSettingsToFree.insert(settings);
1002 // Manually read in the config, because parametrized kconfigxt objects don't
1003 // seem to load the config theirselves
1004 settings->load();
1006 const QDate qd1 = QDate::currentDate();
1007 QDate qd2 = qd1;
1009 if (settings->monthView()) {
1010 qd2 = qd2.addMonths(1);
1011 } else {
1012 qd2 = qd2.addDays(7);
1014 settings->setDateStart(QDateTime(qd1));
1015 settings->setDateEnd(QDateTime(qd2));
1017 exportHTML(settings, true/*autoMode*/);
1020 void ActionManager::exportHTML(KOrg::HTMLExportSettings *settings, bool autoMode)
1022 if (!settings) {
1023 qCWarning(KORGANIZER_LOG) << "Settings is null" << settings;
1024 return;
1027 if (settings->outputFile().isEmpty()) {
1028 int result = KMessageBox::questionYesNo(
1029 dialogParent(),
1030 i18n("The HTML calendar export file has not been specified yet.\n"
1031 "Do you want to set it now?\n\n"
1032 "If you answer \"no\" then this export operation will be canceled"),
1033 QString());
1034 if (result == KMessageBox::No) {
1035 mMainWindow->showStatusMessage(
1036 i18nc("@info:status",
1037 "Calendar HTML operation canceled due to unspecified output file name"));
1038 return;
1041 const QString fileName =
1042 QFileDialog::getSaveFileName(dialogParent(), i18n("Select path for HTML calendar export"),
1043 QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation),
1044 i18n("HTML Files (*.html)"));
1045 settings->setOutputFile(fileName);
1046 settings->save();
1049 if (!autoMode && QFileInfo(settings->outputFile()).exists()) {
1050 if (KMessageBox::warningContinueCancel(
1051 dialogParent(),
1052 i18n("Do you want to overwrite file \"%1\"?",
1053 settings->outputFile()),
1054 QString(),
1055 KStandardGuiItem::overwrite()) == KMessageBox::Cancel) {
1056 mMainWindow->showStatusMessage(
1057 i18nc("@info:status",
1058 "Calendar HTML operation canceled due to output file overwrite"));
1059 return;
1063 settings->setEMail(CalendarSupport::KCalPrefs::instance()->email());
1064 settings->setName(CalendarSupport::KCalPrefs::instance()->fullName());
1066 settings->setCreditName(QStringLiteral("KOrganizer"));
1067 settings->setCreditURL(QStringLiteral("http://korganizer.kde.org"));
1069 KOrg::HtmlExportJob *exportJob = new KOrg::HtmlExportJob(calendar(), settings, autoMode, mMainWindow, view());
1071 if (KOGlobals::self()->holidays()) {
1072 KHolidays::Holiday::List holidays = KOGlobals::self()->holidays()->holidays(
1073 settings->dateStart().date(), settings->dateEnd().date());
1074 foreach (const KHolidays::Holiday &holiday, holidays) {
1075 exportJob->addHoliday(holiday.observedStartDate(), holiday.name());
1079 connect(exportJob, &KOrg::HtmlExportJob::result, this, &ActionManager::handleExportJobResult);
1080 exportJob->start();
1083 bool ActionManager::saveAsURL(const QUrl &url)
1085 qCDebug(KORGANIZER_LOG) << url.toDisplayString();
1087 if (url.isEmpty()) {
1088 qCDebug(KORGANIZER_LOG) << "Empty URL.";
1089 return false;
1091 if (!url.isValid()) {
1092 qCDebug(KORGANIZER_LOG) << "Malformed URL.";
1093 return false;
1096 QString fileOrig = mFile;
1097 QUrl URLOrig = mURL;
1099 QTemporaryFile *tempFile = Q_NULLPTR;
1100 if (url.isLocalFile()) {
1101 mFile = url.toLocalFile();
1102 } else {
1103 tempFile = new QTemporaryFile;
1104 tempFile->setAutoRemove(false);
1105 tempFile->open();
1106 mFile = tempFile->fileName();
1108 mURL = url;
1110 bool success = saveURL(); // Save local file and upload local file
1111 if (success) {
1112 delete mTempFile;
1113 mTempFile = tempFile;
1114 KIO::NetAccess::removeTempFile(fileOrig);
1115 setTitle();
1116 } else {
1117 KMessageBox::sorry(dialogParent(),
1118 i18n("Unable to save calendar to the file %1.", mFile),
1119 i18n("Error"));
1120 qCDebug(KORGANIZER_LOG) << "failed";
1121 mURL = URLOrig;
1122 mFile = fileOrig;
1123 delete tempFile;
1126 return success;
1129 #ifdef AKONADI_PORT_DISABLED // can go away, kept for reference
1130 bool ActionManager::saveModifiedURL()
1132 qCDebug(KORGANIZER_LOG);
1134 // If calendar isn't modified do nothing.
1135 if (!mCalendarView->isModified()) {
1136 return true;
1139 mHtmlExportSync = true;
1140 if (KOPrefs::instance()->mAutoSave && !mURL.isEmpty()) {
1141 // Save automatically, when auto save is enabled.
1142 return saveURL();
1143 } else {
1144 int result = KMessageBox::warningYesNoCancel(
1145 dialogParent(),
1146 i18n("The calendar has been modified.\nDo you want to save it?"),
1147 QString(),
1148 KStandardGuiItem::save(), KStandardGuiItem::discard());
1149 switch (result) {
1150 case KMessageBox::Yes:
1151 if (mURL.isEmpty()) {
1152 QUrl url = getSaveURL();
1153 return saveAsURL(url);
1154 } else {
1155 return saveURL();
1157 case KMessageBox::No:
1158 return true;
1159 case KMessageBox::Cancel:
1160 default: {
1161 mHtmlExportSync = false;
1162 return false;
1167 #endif
1169 QUrl ActionManager::getSaveURL()
1171 QUrl url =
1172 QFileDialog::getSaveFileUrl(dialogParent(), QString(), QString(QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation) + QLatin1String("/korganizer/")),
1173 i18n("*.ics *.vcs|Calendar Files")
1176 if (!url.isValid()) {
1177 return url;
1180 QString filename = url.fileName();
1182 QString e = filename.right(4);
1183 if (e != QLatin1String(".vcs") && e != QLatin1String(".ics")) {
1184 // Default save format is iCalendar
1185 filename += QLatin1String(".ics");
1187 url = url.adjusted(QUrl::RemoveFilename);
1188 url.setPath(url.path() + filename);
1190 qCDebug(KORGANIZER_LOG) << "url:" << url.url();
1192 return url;
1195 void ActionManager::saveProperties(KConfigGroup &config)
1197 qCDebug(KORGANIZER_LOG);
1199 config.writeEntry("UseResourceCalendar", !mMainWindow->hasDocument());
1200 if (mMainWindow->hasDocument()) {
1201 config.writePathEntry("Calendar", mURL.url());
1205 void ActionManager::readProperties(const KConfigGroup &)
1207 mMainWindow->init(false);
1210 // Configuration changed as a result of the options dialog.
1211 void ActionManager::updateConfig()
1213 qCDebug(KORGANIZER_LOG);
1214 mNextXDays->setText(i18np("&Next Day", "&Next %1 Days",
1215 KOPrefs::instance()->mNextXDays));
1217 KOCore::self()->reloadPlugins();
1219 /* Hide/Show the Reminder Daemon */
1220 if (!KOPrefs::instance()->mShowReminderDaemon) {
1221 KPIM::ReminderClient::hideDaemon();
1222 } else {
1223 KPIM::ReminderClient::showDaemon();
1226 // Commented out because it crashes KOrganizer.
1227 // mParts = KOCore::self()->reloadParts( mMainWindow, mParts );
1228 #ifdef AKONADI_PORT_DISABLED // shouldn't be required anymore
1229 if (mCollectionView) {
1230 mCollectionView->updateView();
1232 #endif
1235 void ActionManager::configureDateTime()
1237 KProcess proc;
1238 proc << QStringLiteral("kcmshell5") << QStringLiteral("formats") << QStringLiteral("translations") << QStringLiteral("clock");
1240 if (!proc.startDetached()) {
1241 KMessageBox::sorry(dialogParent(),
1242 i18n("Could not start control module for date and time format."));
1246 KOrg::MainWindow *ActionManager::findInstance(const QUrl &url)
1248 if (mWindowList) {
1249 if (url.isEmpty()) {
1250 return mWindowList->defaultInstance();
1251 } else {
1252 return mWindowList->findInstance(url);
1254 } else {
1255 return Q_NULLPTR;
1259 bool ActionManager::openURL(const QString &url)
1261 importCalendar(QUrl::fromLocalFile(url));
1262 return true;
1265 void ActionManager::dumpText(const QString &str)
1267 qCDebug(KORGANIZER_LOG) << str;
1270 void ActionManager::toggleDateNavigator()
1272 bool visible = mDateNavigatorShowAction->isChecked();
1273 if (mCalendarView) {
1274 mCalendarView->showDateNavigator(visible);
1278 void ActionManager::toggleTodoView()
1280 bool visible = mTodoViewShowAction->isChecked();
1281 if (mCalendarView) {
1282 mCalendarView->showTodoView(visible);
1286 void ActionManager::toggleEventViewer()
1288 bool visible = mEventViewerShowAction->isChecked();
1289 if (mCalendarView) {
1290 mCalendarView->showEventViewer(visible);
1294 void ActionManager::toggleResourceView()
1296 const bool visible = mCollectionViewShowAction->isChecked();
1297 if (mCollectionView) {
1298 if (visible) {
1299 mCollectionView->show();
1300 } else {
1301 mCollectionView->hide();
1306 bool ActionManager::mergeURL(const QString &url)
1308 return importURL(QUrl::fromLocalFile(url), true);
1311 bool ActionManager::saveAsURL(const QString &url)
1313 return saveAsURL(QUrl::fromLocalFile(url));
1316 QString ActionManager::getCurrentURLasString() const
1318 return mURL.url();
1321 bool ActionManager::editIncidence(Akonadi::Item::Id id)
1323 return mCalendarView->editIncidence(id);
1326 bool ActionManager::showIncidence(Akonadi::Item::Id id)
1328 return mCalendarView->showIncidence(id);
1331 bool ActionManager::showIncidenceContext(Akonadi::Item::Id id)
1333 return mCalendarView->showIncidenceContext(id);
1336 bool ActionManager::handleCommandLine(const QStringList &args)
1338 QCommandLineParser parser;
1339 korganizer_options(&parser);
1340 parser.process(args);
1342 KOrg::MainWindow *mainWindow = ActionManager::findInstance(QUrl());
1344 bool ret = true;
1346 if (!mainWindow) {
1347 qCCritical(KORGANIZER_LOG) << "Unable to find default calendar resources view.";
1348 ret = false;
1349 } else if (parser.positionalArguments().isEmpty()) {
1350 // No filenames given => all other args are meaningless, show main Window
1351 mainWindow->topLevelWidget()->show();
1352 } else {
1353 // Import, merge, or ask => we need the resource calendar window anyway.
1354 mainWindow->topLevelWidget()->show();
1356 // Check for import, merge or ask
1357 if (parser.isSet(QStringLiteral("import"))) {
1358 for (const QString &url : parser.positionalArguments()) {
1359 importURL(QUrl::fromUserInput(url), /*merge=*/false);
1361 } else if (parser.isSet(QStringLiteral("merge"))) {
1362 for (const QString &url : parser.positionalArguments()) {
1363 importURL(QUrl::fromUserInput(url), /*merge=*/true);
1365 } else {
1366 for (const QString &url : parser.positionalArguments()) {
1367 mainWindow->actionManager()->importCalendar(QUrl::fromUserInput(url));
1371 return ret;
1374 bool ActionManager::deleteIncidence(Akonadi::Item::Id id, bool force)
1376 return mCalendarView->deleteIncidence(id, force);
1379 bool ActionManager::addIncidence(const QString &ical)
1381 return mCalendarView->addIncidence(ical);
1384 void ActionManager::downloadNewStuff()
1386 qCDebug(KORGANIZER_LOG);
1387 KNS3::DownloadDialog dialog(mCalendarView);
1388 dialog.exec();
1389 foreach (const KNS3::Entry &e, dialog.installedEntries()) {
1390 qCDebug(KORGANIZER_LOG) << " downloadNewStuff :";
1391 const QStringList lstFile = e.installedFiles();
1392 if (lstFile.count() != 1) {
1393 continue;
1395 const QString file = lstFile.at(0);
1396 const QUrl filename = QUrl::fromLocalFile(file);
1397 qCDebug(KORGANIZER_LOG) << "filename :" << filename;
1398 if (! filename.isValid()) {
1399 continue;
1402 KCalCore::FileStorage storage(calendar());
1403 storage.setFileName(file);
1404 storage.setSaveFormat(new KCalCore::ICalFormat);
1405 if (!storage.load()) {
1406 KMessageBox::error(mCalendarView, i18n("Could not load calendar %1.", file));
1407 } else {
1408 QStringList eventSummaries;
1409 KCalCore::Event::List events = calendar()->events();
1410 eventSummaries.reserve(events.count());
1411 foreach (const KCalCore::Event::Ptr &event, events) {
1412 eventSummaries.append(event->summary());
1415 const int result = KMessageBox::warningContinueCancelList(mCalendarView,
1416 i18n("The downloaded events will be merged into your current calendar."),
1417 eventSummaries);
1419 if (result != KMessageBox::Continue) {
1420 // FIXME (KNS2): hm, no way out here :-)
1423 if (importURL(QUrl::fromLocalFile(file), true)) {
1424 // FIXME (KNS2): here neither
1430 QString ActionManager::localFileName()
1432 return mFile;
1435 class ActionManager::ActionStringsVisitor : public KCalCore::Visitor
1437 public:
1438 ActionStringsVisitor() : mShow(Q_NULLPTR), mEdit(Q_NULLPTR), mDelete(Q_NULLPTR) {}
1440 bool act(KCalCore::IncidenceBase::Ptr incidence, QAction *show, QAction *edit, QAction *del)
1442 mShow = show;
1443 mEdit = edit;
1444 mDelete = del;
1445 return incidence->accept(*this, incidence);
1448 protected:
1449 bool visit(const KCalCore::Event::Ptr &) Q_DECL_OVERRIDE {
1450 if (mShow)
1452 mShow->setText(i18n("&Show Event"));
1454 if (mEdit)
1456 mEdit->setText(i18n("&Edit Event..."));
1458 if (mDelete)
1460 mDelete->setText(i18n("&Delete Event"));
1462 return true;
1465 bool visit(const KCalCore::Todo::Ptr &) Q_DECL_OVERRIDE {
1466 if (mShow)
1468 mShow->setText(i18n("&Show To-do"));
1470 if (mEdit)
1472 mEdit->setText(i18n("&Edit To-do..."));
1474 if (mDelete)
1476 mDelete->setText(i18n("&Delete To-do"));
1478 return true;
1481 bool visit(const KCalCore::Journal::Ptr &) Q_DECL_OVERRIDE {
1482 return assignDefaultStrings();
1485 bool visit(const KCalCore::FreeBusy::Ptr &) Q_DECL_OVERRIDE { // to inhibit hidden virtual compile warning
1486 return false;
1489 protected:
1490 bool assignDefaultStrings()
1492 if (mShow) {
1493 mShow->setText(i18n("&Show"));
1495 if (mEdit) {
1496 mEdit->setText(i18n("&Edit..."));
1498 if (mDelete) {
1499 mDelete->setText(i18n("&Delete"));
1501 return true;
1503 QAction *mShow;
1504 QAction *mEdit;
1505 QAction *mDelete;
1508 void ActionManager::processIncidenceSelection(const Akonadi::Item &item, const QDate &date)
1510 //qCDebug(KORGANIZER_LOG) << "ActionManager::processIncidenceSelection()";
1511 Q_UNUSED(date);
1513 const KCalCore::Incidence::Ptr incidence = CalendarSupport::incidence(item);
1514 if (!incidence) {
1515 enableIncidenceActions(false);
1516 return;
1519 enableIncidenceActions(true);
1521 if (!mCalendarView->calendar()->hasRight(item, Akonadi::Collection::CanDeleteItem)) {
1522 mCutAction->setEnabled(false);
1523 mDeleteAction->setEnabled(false);
1526 ActionStringsVisitor v;
1527 if (!v.act(incidence, mShowIncidenceAction, mEditIncidenceAction, mDeleteIncidenceAction)) {
1528 mShowIncidenceAction->setText(i18n("&Show"));
1529 mEditIncidenceAction->setText(i18n("&Edit..."));
1530 mDeleteIncidenceAction->setText(i18n("&Delete"));
1534 void ActionManager::enableIncidenceActions(bool enabled)
1536 mShowIncidenceAction->setEnabled(enabled);
1537 mEditIncidenceAction->setEnabled(enabled);
1538 mDeleteIncidenceAction->setEnabled(enabled);
1540 mCutAction->setEnabled(enabled);
1541 mCopyAction->setEnabled(enabled);
1542 mDeleteAction->setEnabled(enabled);
1543 mPublishEvent->setEnabled(enabled);
1544 mForwardEvent->setEnabled(enabled);
1545 mSendInvitation->setEnabled(enabled);
1546 mSendCancel->setEnabled(enabled);
1547 mSendStatusUpdate->setEnabled(enabled);
1548 mRequestChange->setEnabled(enabled);
1549 mRequestUpdate->setEnabled(enabled);
1552 Akonadi::Collection ActionManager::selectedCollection() const
1554 const QModelIndex index = mCollectionView->view()->currentIndex();
1555 if (!index.isValid()) {
1556 return Akonadi::Collection();
1559 return index.data(Akonadi::EntityTreeModel::CollectionRole).value<Akonadi::Collection>();
1562 void ActionManager::keyBindings()
1564 KShortcutsDialog dlg(KShortcutsEditor::AllActions,
1565 KShortcutsEditor::LetterShortcutsDisallowed, view());
1566 if (mMainWindow) {
1567 dlg.addCollection(mMainWindow->getActionCollection());
1570 foreach (KOrg::Part *part, mParts) {
1571 if (part) {
1572 dlg.addCollection(part->actionCollection(), part->shortInfo());
1575 dlg.configure();
1578 void ActionManager::loadParts()
1580 mParts = KOCore::self()->loadParts(mMainWindow);
1583 void ActionManager::setTitle()
1585 mMainWindow->setTitle();
1588 void ActionManager::openEventEditor(const QString &text)
1590 mCalendarView->newEvent(text);
1593 void ActionManager::openEventEditor(const QString &summary,
1594 const QString &description,
1595 const QStringList &attachments)
1597 mCalendarView->newEvent(summary, description, attachments);
1600 void ActionManager::openEventEditor(const QString &summary,
1601 const QString &description,
1602 const QStringList &attachments,
1603 const QStringList &attendees)
1605 mCalendarView->newEvent(summary, description, attachments, attendees);
1608 void ActionManager::openEventEditor(const QString &summary,
1609 const QString &description,
1610 const QString &uri,
1611 const QString &file,
1612 const QStringList &attendees,
1613 const QString &attachmentMimetype)
1615 int action = IncidenceEditorNG::IncidenceEditorSettings::self()->defaultEmailAttachMethod();
1616 if (attachmentMimetype != QLatin1String("message/rfc822")) {
1617 action = IncidenceEditorNG::IncidenceEditorSettings::Link;
1618 } else if (IncidenceEditorNG::IncidenceEditorSettings::self()->defaultEmailAttachMethod() ==
1619 IncidenceEditorNG::IncidenceEditorSettings::Ask) {
1620 QMenu *menu = new QMenu(Q_NULLPTR);
1621 QAction *attachLink = menu->addAction(i18n("Attach as &link"));
1622 QAction *attachInline = menu->addAction(i18n("Attach &inline"));
1623 QAction *attachBody = menu->addAction(i18n("Attach inline &without attachments"));
1624 menu->addSeparator();
1625 menu->addAction(QIcon::fromTheme(QStringLiteral("dialog-cancel")), i18n("C&ancel"));
1627 QAction *ret = menu->exec(QCursor::pos());
1628 delete menu;
1630 if (ret == attachLink) {
1631 action = IncidenceEditorNG::IncidenceEditorSettings::Link;
1632 } else if (ret == attachInline) {
1633 action = IncidenceEditorNG::IncidenceEditorSettings::InlineFull;
1634 } else if (ret == attachBody) {
1635 action = IncidenceEditorNG::IncidenceEditorSettings::InlineBody;
1636 } else {
1637 return;
1641 QString attData;
1642 QTemporaryFile tf;
1643 tf.setAutoRemove(true);
1644 switch (action) {
1645 case IncidenceEditorNG::IncidenceEditorSettings::Link:
1646 attData = uri;
1647 break;
1648 case IncidenceEditorNG::IncidenceEditorSettings::InlineFull:
1649 attData = file;
1650 break;
1651 case IncidenceEditorNG::IncidenceEditorSettings::InlineBody: {
1652 QFile f(file);
1653 if (!f.open(QFile::ReadOnly)) {
1654 return;
1656 KMime::Message *msg = new KMime::Message();
1657 msg->setContent(f.readAll());
1658 msg->parse();
1659 if (msg == msg->textContent() || msg->textContent() == Q_NULLPTR) { // no attachments
1660 attData = file;
1661 } else {
1662 if (KMessageBox::warningContinueCancel(
1663 Q_NULLPTR,
1664 i18n("Removing attachments from an email might invalidate its signature."),
1665 i18n("Remove Attachments"), KStandardGuiItem::cont(), KStandardGuiItem::cancel(),
1666 QStringLiteral("BodyOnlyInlineAttachment")) != KMessageBox::Continue) {
1667 delete msg;
1668 return;
1670 KMime::Message *newMsg = new KMime::Message();
1671 newMsg->setHead(msg->head());
1672 newMsg->setBody(msg->textContent()->body());
1673 newMsg->parse();
1674 newMsg->contentTransferEncoding()->from7BitString(
1675 msg->textContent()->contentTransferEncoding()->as7BitString());
1676 newMsg->contentType()->from7BitString(msg->textContent()->contentType()->as7BitString());
1677 newMsg->assemble();
1678 tf.write(newMsg->encodedContent());
1679 attData = tf.fileName();
1681 tf.close();
1682 delete msg;
1683 break;
1685 default:
1686 return;
1689 mCalendarView->newEvent(summary, description, QStringList(attData),
1690 attendees, QStringList(attachmentMimetype),
1691 action != IncidenceEditorNG::IncidenceEditorSettings::Link);
1694 void ActionManager::openTodoEditor(const QString &text)
1696 mCalendarView->newTodo(text);
1699 void ActionManager::openTodoEditor(const QString &summary,
1700 const QString &description,
1701 const QStringList &attachments)
1703 mCalendarView->newTodo(summary, description, attachments);
1705 void ActionManager::openTodoEditor(const QString &summary,
1706 const QString &description,
1707 const QStringList &attachments,
1708 const QStringList &attendees)
1710 mCalendarView->newTodo(summary, description, attachments, attendees);
1713 void ActionManager::openTodoEditor(const QString &summary,
1714 const QString &description,
1715 const QString &uri,
1716 const QString &file,
1717 const QStringList &attendees,
1718 const QString &attachmentMimetype)
1720 int action = KOPrefs::instance()->defaultTodoAttachMethod();
1721 if (attachmentMimetype != QLatin1String("message/rfc822")) {
1722 action = KOPrefs::TodoAttachLink;
1723 } else if (KOPrefs::instance()->defaultTodoAttachMethod() == KOPrefs::TodoAttachAsk) {
1724 QMenu *menu = new QMenu(Q_NULLPTR);
1725 QAction *attachLink = menu->addAction(i18n("Attach as &link"));
1726 QAction *attachInline = menu->addAction(i18n("Attach &inline"));
1727 menu->addSeparator();
1728 menu->addAction(QIcon::fromTheme(QStringLiteral("dialog-cancel")), i18n("C&ancel"));
1730 QAction *ret = menu->exec(QCursor::pos());
1731 delete menu;
1733 if (ret == attachLink) {
1734 action = KOPrefs::TodoAttachLink;
1735 } else if (ret == attachInline) {
1736 action = KOPrefs::TodoAttachInlineFull;
1737 } else {
1738 return;
1742 QString attData;
1743 switch (action) {
1744 case KOPrefs::TodoAttachLink:
1745 attData = uri;
1746 break;
1747 case KOPrefs::TodoAttachInlineFull:
1748 attData = file;
1749 break;
1750 default:
1751 return;
1754 mCalendarView->newTodo(summary, description, QStringList(attData),
1755 attendees, QStringList(attachmentMimetype),
1756 action != KOPrefs::TodoAttachLink);
1759 void ActionManager::openJournalEditor(const QDate &date)
1761 mCalendarView->newJournal(date);
1764 void ActionManager::openJournalEditor(const QString &text, const QDate &date)
1766 mCalendarView->newJournal(text, date);
1769 void ActionManager::openJournalEditor(const QString &text)
1771 mCalendarView->newJournal(text);
1774 void ActionManager::showJournalView()
1776 mCalendarView->viewManager()->showJournalView();
1779 void ActionManager::showTodoView()
1781 mCalendarView->viewManager()->showTodoView();
1784 void ActionManager::showEventView()
1786 mCalendarView->viewManager()->showEventView();
1789 void ActionManager::goDate(const QDate &date)
1791 mCalendarView->goDate(date);
1794 void ActionManager::goDate(const QString &date)
1796 goDate(KLocale::global()->readDate(date));
1799 void ActionManager::showDate(const QDate &date)
1801 mCalendarView->showDate(date);
1804 void ActionManager::updateUndoRedoActions()
1806 Akonadi::History *history = mCalendarView->incidenceChanger()->history();
1808 if (history->undoAvailable()) {
1809 mUndoAction->setEnabled(true);
1810 mUndoAction->setText(i18n("Undo: %1", history->nextUndoDescription()));
1811 } else {
1812 mUndoAction->setEnabled(false);
1813 mUndoAction->setText(i18n("Undo"));
1816 if (history->redoAvailable()) {
1817 mRedoAction->setEnabled(true);
1818 mRedoAction->setText(i18n("Redo: %1", history->nextRedoDescription()));
1819 } else {
1820 mRedoAction->setEnabled(false);
1821 mRedoAction->setText(i18n("Redo"));
1824 mUndoAction->setIconText(i18n("Undo"));
1827 bool ActionManager::queryClose()
1829 return true;
1832 void ActionManager::importCalendar(const QUrl &url)
1834 if (!url.isValid()) {
1835 KMessageBox::error(dialogParent(),
1836 i18n("URL '%1' is invalid.", url.toDisplayString()));
1837 return;
1840 const QString questionText =
1841 i18nc("@info",
1842 "<p>Would you like to merge this calendar item into an existing calendar "
1843 "or use it to create a brand new calendar?</p>"
1844 "<p>If you select merge, then you will be given the opportunity to select "
1845 "the destination calendar.</p>"
1846 "<p>If you select add, then a new calendar will be created for you automatically.</p>");
1848 const int answer =
1849 KMessageBox::questionYesNoCancel(
1850 dialogParent(),
1851 questionText,
1852 i18nc("@title:window", "Import Calendar"),
1853 KGuiItem(i18n("Merge into existing calendar")),
1854 KGuiItem(i18n("Add as new calendar")));
1856 switch (answer) {
1857 case KMessageBox::Yes: //merge
1858 importURL(url, true);
1859 break;
1860 case KMessageBox::No: //import
1861 importURL(url, false);
1862 break;
1863 default:
1864 return;
1868 void ActionManager::slotAutoArchivingSettingsModified()
1870 if (CalendarSupport::KCalPrefs::instance()->mAutoArchive) {
1871 mAutoArchiveTimer->start(4 * 60 * 60 * 1000); // check again in 4 hours
1872 } else {
1873 mAutoArchiveTimer->stop();
1877 void ActionManager::slotAutoArchive()
1879 if (!mCalendarView->calendar()) { // can this happen?
1880 return;
1883 mAutoArchiveTimer->stop();
1884 CalendarSupport::EventArchiver archiver;
1886 archiver.runAuto(calendar(), mCalendarView->incidenceChanger(), mCalendarView, false /*no gui*/);
1888 // restart timer with the correct delay ( especially useful for the first time )
1889 slotAutoArchivingSettingsModified();
1892 QWidget *ActionManager::dialogParent()
1894 return mCalendarView->topLevelWidget();
1897 void ActionManager::checkAutoExport()
1899 // Don't save if auto save interval is zero
1900 if (KOPrefs::instance()->mAutoExportInterval == 0) {
1901 return;
1904 // has this calendar been saved before? If yes automatically save it.
1905 if (KOPrefs::instance()->mAutoExport) {
1906 exportHTML();
1910 void ActionManager::openTodoEditor(const QString &summary,
1911 const QString &description,
1912 const QStringList &attachmentUris,
1913 const QStringList &attendees,
1914 const QStringList &attachmentMimetypes,
1915 bool attachmentIsInline)
1917 Q_UNUSED(summary);
1918 Q_UNUSED(description);
1919 Q_UNUSED(attachmentUris);
1920 Q_UNUSED(attendees);
1921 Q_UNUSED(attachmentMimetypes);
1922 Q_UNUSED(attachmentIsInline);
1923 qCWarning(KORGANIZER_LOG) << "Not implemented in korg-desktop";
1926 void ActionManager::openEventEditor(const QString &summary,
1927 const QString &description,
1928 const QStringList &attachmentUris,
1929 const QStringList &attendees,
1930 const QStringList &attachmentMimetypes,
1931 bool attachmentIsInline)
1933 Q_UNUSED(summary);
1934 Q_UNUSED(description);
1935 Q_UNUSED(attachmentUris);
1936 Q_UNUSED(attendees);
1937 Q_UNUSED(attachmentMimetypes);
1938 Q_UNUSED(attachmentIsInline);
1939 qCWarning(KORGANIZER_LOG) << "Not implemented in korg-desktop";
1942 void ActionManager::handleExportJobResult(KJob *job)
1944 HtmlExportJob *htmlExportJob = qobject_cast<HtmlExportJob *>(job);
1945 Q_ASSERT(htmlExportJob);
1947 if (mSettingsToFree.contains(htmlExportJob->settings())) {
1948 mSettingsToFree.remove(htmlExportJob->settings());
1949 delete htmlExportJob->settings();
1953 void ActionManager::setHelpText(QAction *act, const QString &text)
1955 act->setStatusTip(text);
1956 act->setToolTip(text);
1957 if (act->whatsThis().isEmpty()) {
1958 act->setWhatsThis(text);